请帮助我理解一下,为什么试图在Hibernate 5.x中加载记录时默认构造函数会多次执行
持久性类
public class Customer {
private int cid;
private String cphone;
private String ccity;
private String cemail;
public Customer() {
System.out.println("**Default Constructor**");
}
public Customer(String cphone, String ccity, String cemail) {
this.cphone = cphone;
this.ccity = ccity;
this.cemail = cemail;
}
public int getCid() {
return cid;
}
public void setCid(int cid) {
this.cid = cid;
}
public String getCphone() {
return cphone;
}
public void setCphone(String cphone) {
this.cphone = cphone;
}
public String getCcity() {
return ccity;
}
public void setCcity(String ccity) {
this.ccity = ccity;
}
public String getCemail() {
return cemail;
}
public void setCemail(String cemail) {
this.cemail = cemail;
}
}
注意:已尝试使用SQLServer 2014和Hibernate 5.3.7
答案 0 :(得分:1)
从Hibernate 5.3.7开始,第一个发生在SessionFactory
初始化过程中:
if ( identifierGetter != null && constructor != null ) {
// use the id value of a newly instantiated instance as the unsaved-value
final Serializable defaultValue = (Serializable) identifierGetter.get( instantiate( constructor ) );
return new IdentifierValue( defaultValue );
}
似乎可以弄清楚@Id
字段的哪个值指示@Entity
未保存。
您使用的是Session#load
,它会在实体存在的情况下返回该实体的代理。
代理类是@Entity
的子类
因此,代理类的构造函数调用了超级构造函数。因此,第二呼叫
然后,您将强制Hibernate
初始化实体(您调用getCemail()
)。
Hibernate
发出sql
语句,然后初始化AbstractLazyInitializer#target
。这是对构造函数的第三次调用
为了更好地了解发生了什么,我建议您对其进行调试。
在默认构造函数上放置一个断点,并查看堆栈跟踪。