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でOK働いたが、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を返しました。データベースの実際の行には、非ゼロ/非NULL値があります。しかし、getName()、getPath()、そして最も不思議なことにgetSecurityId()はうまくいきました。
これはなぜ起こっているのですか?それはマップされたスーパークラスの根本的な問題か、これが起こる別の理由がありますか?
Hibernateが返さForm
オブジェクトはJavassistのプロキシであることに注意してください - デバッガで見ると、それは一般的にForm_$$_javassist_15
のようなクラス名を持つなど
更新:この問題は、と思わ
Javassistではなく、Hibernateで発生している可能性があります。私は、hibernate.propertiesにhibernate.bytecode.provider=cglib
を設定してバイトコード生成をCGLIBに切り替えましたが、CGLIBを使って同じ結果を得ることができました(Hibernateから返されたクラス名がForm$$EnhancerByCGLIB$$4f3b4523
になったためCGLIBが動作しています)。
私はまだそれが間違っている理由を特定することにはまだ近いです。
おそらく、バグレポートを提出する必要があります。この予期しない動作を証明するテストがあり、そのテストをHibernateだけに分けた場合、これはバグレポートの良い候補です。通常、Hibernateのチームはあなたに "テストを提供して証明する"と挑戦します:) – chris
ゲッターとセッターの中には最終的なものがあったので、私は自分の責任でした。しかし、私はHibernateのドキュメントでこれを行うことに関する警告を見つけることができなかったので、ドキュメントの問題を報告するかもしれません。ドキュメントは最終的なクラスについて警告しますが、最終的なメソッドについては警告しません... – gutch