我正在阅读一篇文章,其中作者已经实现了这样的实体类:
@Entity
public class Product {
@OneToMany
private List<Part> parts; // note the missing "= new ArrayList<Part>();"
public Product() {
}
// getters and setters
}
我总是习惯实例化集合字段,在本例中是parts
,可以是内联(private List<Part> parts = new ArrayList<Part>();
),也可以是构造函数内部,因为据我记忆,不这样做会导致各种NPE
我认为JPA 2中的事情发生了变化,现在JPA运行时使用运行时字节码增强或反射自动实例化该字段,所以我再试一次,但是如果没有实例化{{{I}我仍然无法工作1}}字段,否则parts
将抛出NPE。
所以我的问题是,如果不使用Hibernate作为提供程序在Java SE和Java EE环境中实例化aProduct.getParts().add(aPart)
字段,是否可以使这项工作成为可能?如果是这样,怎么样?
答案 0 :(得分:9)
我的理解是JPA提供程序只能在从DB加载的实体中正确实例化该字段。但是,如果您创建一个新的(暂时的)实体,则必须确保所有字段都有效。请注意,在您实际将其附加到持久性上下文之前,Hibernate / JPA不知道新创建的瞬态实体。如果你考虑它,它是合乎逻辑的(至少对我来说):如果你依靠JPA / Hibernate来正确地实例化你的对象,你会建立一个强大的,侵入性的实现依赖,这将使它变得非常困难没有它就不可能再工作了。
因此,对于从未重新创建的实体,只保留未加初始化的集合属性可能没问题。对于您也创建新实例的类,解决此问题的最简单方法是提供两个构造函数:Hibernate / JPA的默认值,以及“手动”创建的参数化构造函数。如果您没有要设置的参数,您还可以创建一个静态工厂方法,以使用默认值初始化所有必填字段。
答案 1 :(得分:2)
如果从数据存储区加载实体,则不需要“实例化”该字段,因为它将从数据存储区加载(如果它存在于持久性中)。如果在persist()中集合为null,那么在检索它时,它可能也是null(因为这是使持久性机制透明的点)