From: David Ng (JIRA) <no...@at...> - 2006-07-28 00:31:27
|
Problem with hibernate proxy object and ClassMetaData ----------------------------------------------------- Key: HHH-1953 URL: http://opensource.atlassian.com/projects/hibernate/browse/HHH-1953 Project: Hibernate3 Type: Bug Versions: 3.1.2 Environment: Tested environment: - Hibernate 3.1.2 - Hibernate 3.1.3 - Postgresql 8.1 - Jdk 1.5.0_06 - Windows XP SP2 and Linux Reporter: David Ng Priority: Critical Hi, The problem can be summarised as follow: - If an hibernate entity object has proxy attribute is defined inside class node of hbm.xml file, ClassMetaData.getPropertyValue() of any property will throw IllegalArgumentException; - Regardless whether Reflection API is used or hibernate.cglib.use_reflection_optimizer is either set to true or false; - If the proxy attribute is not defined, ClassMetaData::getPropertyValue() / ClassMetaData::getPropertyValues() returns the values successfully; and - Accessing the TsRecStat property by invoking TsPassword::getTsRecStat() does not cause exception to be thrown in any of the case. My question: - If reflection API should not be used to access the property value, shouldn't hibernate ClassMetaData API be used to access the property value? 2 postings have been made in regard to this on hibernate forum: http://forum.hibernate.org/viewtopic.php?t=955828 http://forum.hibernate.org/viewtopic.php?t=958029 ======================================================================================================================== THE TEST CODE: public void testAccessingTsPasswordProxyWithClassMetaDataAPI() { Session currentSession = null; Transaction transaction = null; try { ClassMetadata passwordClassMetaData = m_sessionFactory.getClassMetadata( TsPassword.class ); currentSession = m_sessionFactory.openSession(); transaction = currentSession.beginTransaction(); Query query = currentSession.createQuery( "FROM TsPassword AS p" ); Iterator it = query.iterate(); while( it.hasNext() ) { Object obj = it.next(); ITsPassword itspassword = (ITsPassword) obj; Date tsExpiryTimestamp = itspassword.getTsExpiryTimestamp(); passwordClassMetaData.getPropertyValue( itspassword, "TsRecStat", EntityMode.POJO ); Object expiryFromPasswordInterface = passwordClassMetaData.getPropertyValue( itspassword, "TsExpiryTimestamp", EntityMode.POJO ); assertEquals( "Expiry timestamp from interface", tsExpiryTimestamp, expiryFromPasswordInterface ); Object propertyValue = passwordClassMetaData.getPropertyValue( obj, "TsExpiryTimestamp", EntityMode.POJO ); assertEquals( "Expiry timestamp from raw object", tsExpiryTimestamp, propertyValue ); } transaction.commit(); } catch( HibernateException he ) { he.printStackTrace(); fail( "Hibernate exception occurred." ); if( transaction != null ) { transaction.rollback(); } } catch( Exception e ) { e.printStackTrace(); fail( "Something else exception occured." ); if( transaction != null ) { transaction.rollback(); } } finally { if( currentSession != null ) { currentSession.close(); } } } Line 78 is passwordClassMetaData.getPropertyValue( itspassword, "TsRecStat", EntityMode.POJO ); The exception: IllegalArgumentException in class: com.tokuii.baseapp.conf.redbull.v1.data.TsPassword, getter method of property: TsRecStat org.hibernate.PropertyAccessException: IllegalArgumentException occurred calling getter of com.tokuii.baseapp.conf.redbull.v1.data.TsPassword.TsRecStat at org.hibernate.property.BasicPropertyAccessor$BasicGetter.get(BasicPropertyAccessor.java:171) at org.hibernate.tuple.AbstractEntityTuplizer.getPropertyValue(AbstractEntityTuplizer.java:270) at org.hibernate.tuple.AbstractEntityTuplizer.getPropertyValue(AbstractEntityTuplizer.java:280) at org.hibernate.persister.entity.AbstractEntityPersister.getPropertyValue(AbstractEntityPersister.java:3252) at com.tokuii.tests.component.hibernate.HibernateProxyTest.testAccessingTsPasswordProxyWithClassMetaDataAPI(Hibe rnateProxyTest.java:78) Caused by: java.lang.IllegalArgumentException: object is not an instance of declaring class at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:585) at org.hibernate.property.BasicPropertyAccessor$BasicGetter.get(BasicPropertyAccessor.java:145) ... 50 more Hbm.xml: <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping> <class name="com.tokuii.baseapp.conf.redbull.v1.data.TsPassword" table="TsPassword" proxy="com.tokuii.system.ITsPassword"> <id name="Id" type="long" unsaved-value="0"> <generator class="native"/> </id> <version column="TsVersion" name="TsVersion"/> <many-to-one name="TsCreateUser" class="com.tokuii.baseapp.conf.redbull.v1.data.TsUser"/> <many-to-one name="TsModifyUser" class="com.tokuii.baseapp.conf.redbull.v1.data.TsUser"/> <property name="TsCreateTimestamp" type="timestamp" column="TsCreateTimestamp" not-null="false"/> <property name="TsModifyTimestamp" type="timestamp" column="TsModifyTimestamp" not-null="false"/> <property name="TsRecStat" type="java.lang.String" column="TsRecStat" not-null="false"/> <property name="TsSysRowState" type="java.lang.String" column="TsSysRowState" not-null="false"/> <property name="TsExpiryTimestamp" type="timestamp" column="TsExpiryTimestamp" not-null="false"/> <property name="TsPassword" type="java.lang.String" column="TsPassword" not-null="false" length="50"/> <property name="TsPwChangeRestriction" type="java.lang.Boolean" column="TsPwChangeRestriction" not-null="false"/> <property name="TsPwValidity" type="java.lang.String" column="TsPwValidity" not-null="false"/> </class> </hibernate-mapping> The TsPassword.java: public class TsPassword implements com.tokuii.system.ITsPassword { private java.lang.Long m_Id; private int m_TsVersion = 1; private com.tokuii.system.ITsUser m_TsCreateUser; private com.tokuii.system.ITsUser m_TsModifyUser; private java.util.Date m_TsCreateTimestamp; private java.util.Date m_TsModifyTimestamp; private java.lang.String m_TsRecStat = "A"; private java.lang.String m_TsSysRowState = "P"; private java.util.Date m_TsExpiryTimestamp; private java.lang.String m_TsPassword; // Natural Identifier private java.lang.Boolean m_TsPwChangeRestriction; private java.lang.String m_TsPwValidity; private com.tokuii.system.ITsUser m_TsUserId; // Natural Identifier private java.util.Set m_TsPasswordIdTsUser; /** Non-persistent field. */ private java.util.Map m_NonDBFields; public TsPassword() { } public java.lang.Long getId() { return m_Id; } public void setId(java.lang.Long newId) { m_Id = newId; } public int getTsVersion() { return m_TsVersion; } public void setTsVersion(int newTsVersion) { m_TsVersion = newTsVersion; } public Object getNonDBField(String fieldName) { synchronized (this) { if (m_NonDBFields == null) { return null; } return m_NonDBFields.get(fieldName); } } public void setNonDBField(String fieldName, Object value) { synchronized (this) { if (m_NonDBFields == null) { m_NonDBFields = new java.util.HashMap(); } m_NonDBFields.put(fieldName, value); } } public com.tokuii.system.ITsUser getTsCreateUser() { return m_TsCreateUser; } public void setTsCreateUser(com.tokuii.system.ITsUser newTsCreateUser) { m_TsCreateUser = newTsCreateUser; } public com.tokuii.system.ITsUser getTsModifyUser() { return m_TsModifyUser; } public void setTsModifyUser(com.tokuii.system.ITsUser newTsModifyUser) { m_TsModifyUser = newTsModifyUser; } public java.util.Date getTsCreateTimestamp() { return m_TsCreateTimestamp; } public void setTsCreateTimestamp(java.util.Date newTsCreateTimestamp) { m_TsCreateTimestamp = newTsCreateTimestamp; } public java.util.Date getTsModifyTimestamp() { return m_TsModifyTimestamp; } public void setTsModifyTimestamp(java.util.Date newTsModifyTimestamp) { m_TsModifyTimestamp = newTsModifyTimestamp; } public java.lang.String getTsRecStat() { return m_TsRecStat; } public void setTsRecStat(java.lang.String newTsRecStat) { m_TsRecStat = newTsRecStat; } public java.lang.String getTsSysRowState() { return m_TsSysRowState; } public void setTsSysRowState(java.lang.String newTsSysRowState) { m_TsSysRowState = newTsSysRowState; } public java.util.Date getTsExpiryTimestamp() { return m_TsExpiryTimestamp; } public void setTsExpiryTimestamp(java.util.Date newTsExpiryTimestamp) { m_TsExpiryTimestamp = newTsExpiryTimestamp; } public java.lang.String getTsPassword() { return m_TsPassword; } public void setTsPassword(java.lang.String newTsPassword) { m_TsPassword = newTsPassword; } public java.lang.Boolean getTsPwChangeRestriction() { return m_TsPwChangeRestriction; } public void setTsPwChangeRestriction(java.lang.Boolean newTsPwChangeRestriction) { m_TsPwChangeRestriction = newTsPwChangeRestriction; } public java.lang.String getTsPwValidity() { return m_TsPwValidity; } public void setTsPwValidity(java.lang.String newTsPwValidity) { m_TsPwValidity = newTsPwValidity; } public com.tokuii.system.ITsUser getTsUserId() { return m_TsUserId; } public void setTsUserId(com.tokuii.system.ITsUser newTsUserId) { m_TsUserId = newTsUserId; } public java.util.Set getTsPasswordIdTsUser() { synchronized (this) { if (m_TsPasswordIdTsUser == null) { m_TsPasswordIdTsUser = new java.util.HashSet(); } } return m_TsPasswordIdTsUser; } public void setTsPasswordIdTsUser(java.util.Set newTsPasswordIdTsUser) { m_TsPasswordIdTsUser = newTsPasswordIdTsUser; } public boolean equals(Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } final TsPassword that = (TsPassword) o; if (m_TsPassword != null ? !m_TsPassword.equals(that.m_TsPassword) : that.m_TsPassword != null) { return false; } Object thisId = m_TsUserId != null ? m_TsUserId.getId() : null; Object thatId = that.m_TsUserId != null ? that.m_TsUserId.getId() : null; if (thisId != null ? !thisId.equals(thatId) : thatId != null) { return false; } return true; } public int hashCode() { int result = 0; result = 29 * result + (m_TsPassword != null ? m_TsPassword.hashCode() : 0); result = 29 * result + (m_TsUserId != null && m_TsUserId.getId() != null ? m_TsUserId.getId().hashCode() : 0); return result; } } The interface: public interface ITsPassword extends java.io.Serializable { java.lang.Long getId(); void setId( java.lang.Long aLong ); int getTsVersion(); void setTsVersion( int index ); java.lang.Object getNonDBField( java.lang.String elementLinkName ); void setNonDBField( java.lang.String elementLinkName, java.lang.Object object ); com.tokuii.system.ITsUser getTsCreateUser(); void setTsCreateUser( com.tokuii.system.ITsUser iTsUser ); java.util.Date getTsCreateTimestamp(); void setTsCreateTimestamp( java.util.Date date ); com.tokuii.system.ITsUser getTsModifyUser(); void setTsModifyUser( com.tokuii.system.ITsUser iTsUser ); java.util.Date getTsModifyTimestamp(); void setTsModifyTimestamp( java.util.Date date ); java.lang.String getTsRecStat(); void setTsRecStat( java.lang.String elementLinkName ); java.lang.String getTsSysRowState(); void setTsSysRowState( java.lang.String elementLinkName ); java.util.Date getTsExpiryTimestamp(); void setTsExpiryTimestamp( java.util.Date date ); java.lang.String getTsPassword(); void setTsPassword( java.lang.String elementLinkName ); java.lang.Boolean getTsPwChangeRestriction(); void setTsPwChangeRestriction( java.lang.Boolean aBoolean ); java.lang.String getTsPwValidity(); void setTsPwValidity( java.lang.String elementLinkName ); com.tokuii.system.ITsUser getTsUserId(); void setTsUserId( com.tokuii.system.ITsUser iTsUser ); java.util.Set getTsPasswordIdTsUser(); void setTsPasswordIdTsUser( java.util.Set set ); } -- This message is automatically generated by JIRA. - If you think it was sent incorrectly contact one of the administrators: http://opensource.atlassian.com/projects/hibernate/secure/Administrators.jspa - For more information on JIRA, see: http://www.atlassian.com/software/jira |