У нас есть веб-приложение, которое использует Hibernate. После обновления кодовой базы до Hibernate 3.6 (из 3.3.2) я обнаружил, что прокси-объекты данных, сгенерированные Hibernate, возвращают правильное значение только для некоторых методов. Кажется, что методы в конкретном классе модели данных работают нормально, но методы в @MappedSuperclass
абстрактных суперклассах не работают.
Вот модель данных, которую мы имеем:
@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, но после обновления до Hibernate 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 или ноль. Фактическая строка в базе данных имеет ненулевые / ненулевые значения. Однако getName (), getPath () и наиболее любопытно getSecurityId () работали нормально.
Может кто-нибудь объяснить, почему это происходит? Это фундаментальная проблема с отображенными суперклассами, или есть другая причина, по которой это может произойти?
Обратите внимание, что объект Form
, возвращаемый Hibernate, является прокси-сервером Javassist - при просмотре в отладчике он обычно имеет имя класса, например Form_$$_javassist_15
и т. Д.
<ч />
Обновление:
Эта проблема, похоже, возникает в Hibernate, а не в Javassist. Я переключил генерацию байт-кода на CGLIB, установив hibernate.bytecode.provider=cglib
в hibernate.properties, но получил точно такие же ошибочные результаты с CGLIB (и подтвердил, что CGLIB работает, поскольку имя класса, возвращаемое Hibernate, становится Form$$EnhancerByCGLIB$$4f3b4523
).
Я все еще не могу определить, почему все идет не так.