우리는 Hibernate를 사용하는 웹 애플리케이션을 가지고있다. 코드베이스를 3.3.2에서 Hibernate 3.6으로 업그레이드 한 후, 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
}
이 최대 절전 모드 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을 반환했습니다. 데이터베이스의 실제 행에는 0이 아니거나 0이 아닌 값이 있습니다. 그러나 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 팀은 "테스트를 제공하여 증명하십시오"라고 대답합니다 :) – chris
일부 getter 및 setter가 'final'이기 때문에 나는 내 잘못이었습니다. 그러나 나는 Hibernate 문서에서 이것을 수행하는 것에 대한 경고를 찾을 수 없기 때문에 문서화 문제를보고 할 수도있다. 문서는 최종 클래스에 대해서는 경고하지만 최종 메소드에 대해서는 경고하지 않습니다 ... – gutch