如何在建立强制关系时创建一个spring jpa / correct存储库?

时间:2016-12-13 20:54:50

标签: spring hibernate spring-data-jpa

我有以下数据库,允许用户在书店租书: enter image description here

实体类Book在保存时需要具有Category和BookDescription。

那些Book类看起来像这样:

@Entity
@Table(name = "books")
@Inheritance(strategy = InheritanceType.JOINED)
public abstract class Book {

@OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
@JoinColumn(name = "book_description_id")
private BookDescription bookDescription;

@ManyToOne(cascade = CascadeType.PERSIST, fetch = FetchType.LAZY)
private Category category;

//omitted fields, getters, setters & other relations
}

我正在查看Spring Data JPA。它有

的签名
CrudRepository<T, ID extends Serializable>

这意味着我将

CrudRepository<Book, String>

但我怎么会保存一本书?

所以,一般来说,用户将提交一个表单,我将绑定一个BookUIObject,它将包含保存书籍所需的所有细节,将其传递给BookService女巫将从中提取3个对象:Book(具体实现) ,类别和BookDescription。问题是服务是否会挂起书籍关系并调用常规repository.save(Book),否则它将调用repository.save(Book,Category,BookDescription)之类的方法?

另外,我应该将用户的数据直接绑定到实体类中,还是像我说的那样绑定到一般的BookUIObject并让服务从中提取实体类?

亲切的问候,

1 个答案:

答案 0 :(得分:2)

通常,您必须致电BookReporitory.save(书籍)。对于这两种关系,书籍都有级联,因此如果您在保存的书籍实例上设置了BookDescription和类别,它们也将被保留。如果你没有级联持久化,你必须使用他们的JPARepository保存它们(除非它们已经存在于Persistence上下文中)。

在此示例中要理解的一件事是,如果您创建新的类别对象并将其设置在书籍上并保存书籍,则会在数据库中创建一个新类别。因此,如果UI发布category = sic-fi,则必须检查该类别是否已存在,如果存在,则必须使用托管类别,并在书上设置该类别,而不是创建另一个“科幻”类别。这就是我不会在类别关系上保持级联的原因,因为我宁愿有一个约束违规,因为一个类别不存在,而不是一个新的类别sci-如果有人错过拼写它在UI中。

我不建议直接将表单绑定到JPA实体,因为您总是需要从JPA获取实体,因为您必须使用托管版本,因此根据我的经验,最好还有另一组bean用于表单绑定。

如果在@JoinColumn中缺少nullable = false,那么另一件事就会跳出来。如果一本书不在一个类别中就不能存在,那么将它传递给数据库是至关重要的,如果你从JPA元数据模型生成表格,这就是它的完成方式。如果我在使用数据库/ JPA时只能给出一个建议,那么使用NOT NULL会过于热心。插入时更容易获得约束违规100次,而不是稍后获取NullPointerException并且必须检查每个可能最终调用save并检查参数是否为null的代码路径。

此外,我建议您花一些时间来理解EntityManager和Persistence Context的概念,开发人员犯的大多数错误/假设都会回到持久化上下文以及4实体状态如何工作。