有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java在spring boot JPA中,如何正确地将实体表示具有外键关联的对象发布到不同的实体?

如果我有一个包含另一个类的对象的实体,例如一个Book实体,其中有一个Publisher实体,该实体关联如下:

@ManyToOne
@JoinColumn(name="PUB_CODE", referencedColumnName = "PUB_CODE")
private Publisher pub;

这是在数据库中发布具有外键关联的对象的安全/正确方法吗(在本例中,我在DB中看到了正确的数据,但不能100%确定它是否在所有情况下都有效)?我不知道在事务原子性或线程方面这样做是否安全,或者它是否有效。相关代码如下:

这本书。java

package app.domain;

/*imports*/

@Entity
public class Book implements Serializable{

    /**
     * 
     */
    private static final long serialVersionUID = -6902184723423514234L;

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;

    @Column(nullable = false, unique=true)
    private String bookName;

    @Column(nullable = false)
    private int pageCount;

    @ManyToOne
    @JoinColumn(name="PUB_CODE", referencedColumnName="PUB_CODE")
    private Publisher pub;


    /*public getters and setters*/

}

出版商。java

package app.domain;

/*imports*/

@Entity
public class Publisher implements Serializable {

    private static final long serialVersionUID = 4750079787174869458L;

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;

    @Column(name="PUB_CODE",nullable = false, unique = true)
    private String publisherCode;

    @Column(nullable = false)
    private String publisherName;

    /*public getters and setters*/

}

BookRepo。java

package app.service;

/*imports*/

public interface BookRepo extends JpaRepository<Book, Long>{

    @Query("SELECT pb FROM Publisher pb WHERE pb.publisherCode = TRIM(UPPER(:pubCode))")
    public Publisher findPublisherByPubCode(@Param("pubCode")String pubCode);
}

书籍控制器。java

package app.controller;

/*imports*/

@RestController
@RequestMapping(value = "/books")
public class BookController {

    private BookRepo bookRepo;

    @Autowired
    public BookController(BookRepo bookRepo) {
        this.bookRepo = bookRepo;
    }
    //The ApiPathParam is for JSONDOC purposes
    @RequestMapping(value = "/create", method = RequestMethod.POST)
    public List<Book> create(@ApiPathParam(name = "book") @RequestBody Book book, @ApiPathParam(name = "pubCode") @RequestParam("pubCode") String pubCode) {
        // Assume exception handling
        Publisher pbToAttachToThisBook = bookRepo.findPublisherByPubCode(pubCode);
        book.setPub(pbToAttachToThisBook);
        bookRepo.save(book);
        return bookRepo.findAll();
    }
}

发布对象主体(输入到发布工具):

{
  "bookName": "goosebumps",
  "id": 0,
  "pageCount": 332,
  "pub": {
    "id": 0,
    "publisherCode": "",
    "publisherName": "",
    "serialVersionUID": 0
  },
  "serialVersionUID": 0
}

在与上面相同的调用中,提供了pubCode参数输入,也输入到POST工具中:'SC'

执行上述代码后,在Book表中,有一个上面的Book条目,其PUB_CODE外键列用'SC'填充,调用的POST-controller方法返回的List<Book>表明新添加的图书包含了数据库中已经存在的出版商的Publisher实体信息(例如全名“Scholastic”)

多谢各位


共 (2) 个答案

  1. # 1 楼答案

    听起来你需要从你的Rest Resources/ API specs开始separate/decouple你的data layer's domain model,因为它们可能以不同的速度发展。此外,您对JPA的选择不应影响API specs

    如果你觉得这是你想要追求的东西,那么就有很多资源,包括Best Practices for Better RESTful API

  2. # 2 楼答案

    您最初发布的技术(传递FK ID,在控制器中手动检索,并在实体上显式设置)是有效和安全的

    我不知道有什么更干净的方法,除非您使用HATEOAS主体,它允许资源链接处理:http://projects.spring.io/spring-hateoas/