试图在Hibernate 5.x中加载记录时,默认构造函数被执行很多次

时间:2019-01-01 09:13:40

标签: hibernate

请帮助我理解一下,为什么试图在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;
    }
}

加载记录的步骤 enter image description here

日志 Console Logs Screenshot

注意:已尝试使用SQLServer 2014和Hibernate 5.3.7

1 个答案:

答案 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未保存。

请参见UnsavedValueFactory

第二次通话

您使用的是Session#load,它会在实体存在的情况下返回该实体的代理。

代理类是@Entity的子类

因此,代理类的构造函数调用了超级构造函数。因此,第二呼叫

第三个电话

然后,您将强制Hibernate初始化实体(您调用getCemail())。 Hibernate发出sql语句,然后初始化AbstractLazyInitializer#target。这是对构造函数的第三次调用


为了更好地了解发生了什么,我建议您对其进行调试。

在默认构造函数上放置一个断点,并查看堆栈跟踪。