我們有一個使用Hibernate的Web應用程序。將代碼庫升級到Hibernate 3.6(從3.3.2開始)後,我發現由Hibernate生成的代理數據對象僅爲某些方法返回正確的值。看起來,具體數據模型類中的方法工作正常,但抽象超類@MappedSuperclass
中的方法不起作用。Hibernate代理對象不適用於超類方法
這是我們擁有的數據模型:
@MappedSuperclass
public abstract class DataObject implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "ID", unique = true, columnDefinition = "serial")
private int id;
// getter, setter, equals, hashcode implementations here
}
@MappedSuperclass
public abstract class SecuredDataObject extends DataObject {
@Version
@Column(name = "Version")
private int version;
@Basic
@Column(name = "SecurityId", nullable = true)
private Integer securityId;
// getters, setters here
}
@MappedSuperclass
public abstract class AuditedDataObject extends SecuredDataObject {
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "CreatedDate", nullable = true)
private Date createdDate;
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "LastUpdateDate", nullable = true)
private Date lastUpdateDate;
// getters, setters here
}
@Entity
@Table(name = "Form")
public class Form extends AuditedDataObject {
@Basic
@Column(name = "Name", length = 200, nullable = false)
private String name;
@Basic
@Column(name = "Path", length = 80, nullable = true)
private String path;
// getters, setters, other properties and methods here
}
這在Hibernate中3.3.2的工作確定,但升級後休眠3.6應用程序出了問題。下面的測試代碼說明了此問題:
int formId = 1234;
Form form = (Form) sessionFactory.getCurrentSession().load(Form.class, formId);
System.out.print("id = ");
System.out.println(formId);
System.out.print("getId() = ");
System.out.println(form.getId());
System.out.print("getSecurityId() = ");
System.out.println(form.getSecurityId());
System.out.print("getVersion() = ");
System.out.println(form.getVersion());
System.out.print("getLastUpdateDate() = ");
System.out.println(form.getLastUpdateDate());
System.out.print("getCreatedDate() = ");
System.out.println(form.getCreatedDate());
System.out.print("getName() = ");
System.out.println(form.getName());
System.out.print("getPath() = ");
System.out.println(form.getPath());
該代碼的輸出是:
id = 1234
getId() = 0
getSecurityId() = 182
getVersion() = 0
getLastUpdateDate() = null
getCreatedDate() = null
getName() = Form name here
getPath() = /path/here
的那些方法四個已返回不正確的結果:的getId(),getVersion(),getLastUpdateDate()和getCreatedDate()返回0或null。數據庫中的實際行具有非零/非空值。然而getName(),getPath()和最好奇的getSecurityId()工作正常。
任何人都可以解釋爲什麼發生這種情況?它是映射超類的一個基本問題,還是有另一個原因爲什麼會出現這種情況?
注意,由Hibernate返回的Form
對象是一個Javassist進行代理 - 如果在調試器中查看它通常有一個像Form_$$_javassist_15
類名稱等
更新:
這個問題似乎發生在Hibernate中,而不是Javassist中。我通過在hibernate.properties中設置hibernate.bytecode.provider=cglib
來將字節碼生成轉換爲CGLIB,但是在CGLIB到位的情況下獲得完全相同的錯誤結果(並且由於Hibernate返回的類名稱變爲Form$$EnhancerByCGLIB$$4f3b4523
,所以確認CGLIB正在工作)。
儘管如此,我仍然沒有接近確定爲什麼會出錯。
也許你需要提交一份錯誤報告。如果你有一個可以證明這種意外行爲的測試,並且你只將測試隔離到Hibernate,那麼這是一個很好的候選bug報告。通常Hibernate團隊會挑戰你「通過提供一個測試來證明它」:) – chris 2011-01-13 23:51:48