在spring-boot JPA中,如何正确地将实体表示具有与不同实体的外键关联的对象POST



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

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

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

Book.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*/
}

Publisher.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);
}

BookController.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();
}
}

Post对象体(输入Post工具):

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

pubCode参数输入,也输入POST工具,与上述调用相同:'SC'

执行上述代码后,在Book表中,有一个用于上述Book的条目,其PUB_CODE外键列填充有'SC',被调用的POST控制器方法返回的CCD_ 5表明,新添加的图书包括数据库中已经存在的PUB_CODE='SC'出版商的Publisher实体信息(如全名"Scholastic")。

谢谢。

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

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

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

如果这感觉像是你想要追求的东西,那么有很多资源,包括更好的RESTful API 的最佳实践

最新更新