I have some problems configuring a one-to-one relationship between two classes.
I've read few topics in the forum and the FAQ, but I can't sort out it.
When I use load to get the class by its id it works as expected (lazy), but if I use Criteria by id or get it goes for the other class (marked as lazy).
How could I solve it? Is this a bug or I'm doing something brong?
Here's the mapping and code...
Hibernate 3.3.0.GA
Code:
<class name="ar.com.test.ClassA" table="TEST_CLASS_A" lazy="true">
<id name="id" column="ID">
<generator class="sequence">
<param name="sequence">SEQ_ID_CLASS_A</param>
</generator>
</id>
<one-to-one name="classC"
outer-join="false"
class="ar.com.test.ClassC"
lazy="proxy"
fetch="select"
constrained="true"
property-ref="classA" />
</class>
<class name="ar.com.test.ClassC" table="TEST_CLASS_C" lazy="true">
<id name="id" column="ID">
<generator class="sequence">
<param name="sequence">SEQ_ID_CLASS_C</param>
</generator>
</id>
<many-to-one name="classA"
class="ar.com.test.ClassA"
column="CLASS_A_ID"
unique="true"
cascade="all"
not-null="true"
lazy="proxy"
fetch="select"
/>
</class>
/** class a **/
public class ClassA {
private Integer id;
private ClassC classC;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public ClassC getClassC() {
return classC;
}
public void setClassC(ClassC classC) {
this.classC = classC;
}
}
/** class c **/
public class ClassC {
private Integer id;
private ClassA classA;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public ClassA getClassA() {
return classA;
}
public void setClassA(ClassA classA) {
this.classA = classA;
}
}
/** DAO **/
public class ClassDao extends HibernateDaoSupport {
public ClassA loadClassA(Integer id) {
return (ClassA) getHibernateTemplate().load(ClassA.class, id);
}
public ClassC loadClassC(Integer id) {
return (ClassC) getHibernateTemplate().load(ClassC.class, id);
}
@SuppressWarnings("unchecked")
public List<ClassA> findClassAByIdsList(final List<Integer> idsList) {
return getHibernateTemplate().executeFind(new HibernateCallback() {
public Object doInHibernate(Session session)
throws HibernateException, SQLException {
Criteria criteria = session
.createCriteria(ClassA.class);
criteria.add(Restrictions.in("id", idsList));
criteria.addOrder(Order.asc("id"));
return criteria.list();
}
});
}
@SuppressWarnings("unchecked")
public List<ClassA> findClassCByIdsList(final List<Integer> idsList) {
return getHibernateTemplate().executeFind(new HibernateCallback() {
public Object doInHibernate(Session session)
throws HibernateException, SQLException {
Criteria criteria = session
.createCriteria(ClassC.class);
criteria.add(Restrictions.in("id", idsList));
criteria.addOrder(Order.asc("id"));
return criteria.list();
}
});
}
/** Test **/
public class ClassDaoTest extends AbstractTransactionalSpringContextTests {
protected ClassDao classDao;
public ClassDaoTest(String name) {
super(name);
setPopulateProtectedVariables(true);
}
public void testLoadA() {
ClassA classA = classDao.loadClassA(Integer.valueOf(4));
assertNotNull(classA);
assertEquals(Integer.valueOf(4), classA.getId());
assertTrue("ClassC initialized",
!Hibernate.isPropertyInitialized(classA, "classC"));
}
public void testLoadC() {
ClassC classC = classDao.loadClassC(Integer.valueOf(3));
assertNotNull(classC);
assertEquals(Integer.valueOf(3), classC.getId());
assertTrue("ClassA initialized",
!Hibernate.isPropertyInitialized(classC, "classA"));
}
public void testFindA() {
List<Integer> idsList = new ArrayList<Integer>();
idsList.add(4);
idsList.add(5);
List<ClassA> listClassA = classDao.findClassAByIdsList(idsList);
assertNotNull(listClassA);
assertEquals(true, listClassA.size() > 0);
for(ClassA classA : listClassA) {
assertTrue("ClassC initialized",
!Hibernate.isPropertyInitialized(classA, "classC"));
}
}
public void testFindC() {
List<Integer> idsList = new ArrayList<Integer>();
idsList.add(3);
idsList.add(4);
List<ClassA> listClassA = classDao.findClassAByIdsList(idsList);
assertNotNull(listClassA);
assertEquals(true, listClassA.size() > 0);
for(ClassA classA : listClassA) {
assertTrue("ClassA initialized",
!Hibernate.isPropertyInitialized(classA, "classC"));
}
}
@Override
protected String[] getConfigLocations() {
return new String[] {
"classpath:test-properties-spring.xml",
"classpath:test-datasource.xml",
"classpath:test-persistence.xml",
"classpath:test-hibernate-class-mappings.xml",
"classpath:test-hibernate-properties.xml",
"classpath:test-transaction-manager.xml",
"classpath:test-class-dao.xml"};
}
}
And the log from the junit test:
Code:
12:27:00,703 INFO [ClassDaoTest] Loading context for locations: classpath:test-properties-spring.xml,classpath:test-datasource.xml,classpath:test-persistence.xml,classpath:test-hibernate-class-mappings.xml,classpath:test-hibernate-properties.xml,classpath:test-transaction-manager.xml,classpath:test-class-dao.xml
SLF4J: This version of SLF4J requires log4j version 1.2.12 or later. See also http://www.slf4j.org/codes.html#log4j_version
12:27:02,656 INFO [Environment] Hibernate 3.3.0.GA
12:27:02,671 INFO [Environment] loaded properties from resource hibernate.properties: {hibernate.cglib.use_reflection_optimizer=true, hibernate.bytecode.use_reflection_optimizer=false}
12:27:02,671 WARN [Environment] Property [hibernate.cglib.use_reflection_optimizer] has been renamed to [hibernate.bytecode.use_reflection_optimizer]; update your properties appropriately
12:27:02,671 INFO [Environment] Bytecode provider name : javassist
12:27:02,687 INFO [Environment] using JDK 1.4 java.sql.Timestamp handling
12:27:03,140 INFO [HbmBinder] Mapping class: ar.com.test.ClassA -> TEST_CLASS_A
12:27:03,234 INFO [HbmBinder] Mapping class: ar.com.test.ClassC -> TEST_CLASS_C
12:27:03,359 WARN [Environment] Property [hibernate.cglib.use_reflection_optimizer] has been renamed to [hibernate.bytecode.use_reflection_optimizer]; update your properties appropriately
12:27:03,375 INFO [ConnectionProviderFactory] Initializing connection provider: org.springframework.orm.hibernate3.LocalDataSourceConnectionProvider
12:27:04,171 INFO [SettingsFactory] RDBMS: DB2/HP64, version: SQL08026
12:27:04,171 INFO [SettingsFactory] JDBC driver: IBM DB2 JDBC Universal Driver Architecture, version: 3.1.57
12:27:04,312 INFO [Dialect] Using dialect: ar.com.osde.wf.utils.OptimizedDB2Dialect
12:27:04,328 INFO [TransactionFactoryFactory] Using default transaction strategy (direct JDBC transactions)
12:27:04,328 INFO [TransactionManagerLookupFactory] No TransactionManagerLookup configured (in JTA environment, use of read-write or transactional second-level cache is not recommended)
12:27:04,328 INFO [SettingsFactory] Automatic flush during beforeCompletion(): disabled
12:27:04,328 INFO [SettingsFactory] Automatic session close at end of transaction: disabled
12:27:04,343 INFO [SettingsFactory] Scrollable result sets: enabled
12:27:04,343 INFO [SettingsFactory] JDBC3 getGeneratedKeys(): enabled
12:27:04,343 INFO [SettingsFactory] JDBC result set fetch size: 100
12:27:04,343 INFO [SettingsFactory] Connection release mode: on_close
12:27:04,343 INFO [SettingsFactory] Default schema: DBWFGEND_1_4
12:27:04,343 INFO [SettingsFactory] Default batch fetch size: 1
12:27:04,343 INFO [SettingsFactory] Generate SQL with comments: enabled
12:27:04,343 INFO [SettingsFactory] Order SQL updates by primary key: disabled
12:27:04,343 INFO [SettingsFactory] Order SQL inserts for batching: disabled
12:27:04,343 INFO [SettingsFactory] Query translator: org.hibernate.hql.ast.ASTQueryTranslatorFactory
12:27:04,343 INFO [ASTQueryTranslatorFactory] Using ASTQueryTranslatorFactory
12:27:04,343 INFO [SettingsFactory] Query language substitutions: {}
12:27:04,343 INFO [SettingsFactory] JPA-QL strict compliance: disabled
12:27:04,343 INFO [SettingsFactory] Second-level cache: enabled
12:27:04,343 INFO [SettingsFactory] Query cache: enabled
12:27:04,359 INFO [SettingsFactory] Cache region factory : org.hibernate.cache.impl.bridge.RegionFactoryCacheProviderBridge
12:27:04,359 INFO [RegionFactoryCacheProviderBridge] Cache provider: ar.com.osde.wf.core.cache.impl.EhCacheProvider
12:27:04,359 INFO [SettingsFactory] Optimize cache for minimal puts: disabled
12:27:04,359 INFO [SettingsFactory] Structured second-level cache entries: disabled
12:27:04,359 INFO [SettingsFactory] Query cache factory: org.hibernate.cache.StandardQueryCacheFactory
12:27:04,375 INFO [SettingsFactory] Statistics: enabled
12:27:04,375 INFO [SettingsFactory] Deleted entity synthetic identifier rollback: disabled
12:27:04,375 INFO [SettingsFactory] Default entity-mode: pojo
12:27:04,375 INFO [SettingsFactory] Named query checking : enabled
12:27:04,468 INFO [SessionFactoryImpl] building session factory
12:27:05,171 INFO [SessionFactoryObjectFactory] Not binding factory to JNDI, no JNDI name configured
12:27:05,171 INFO [UpdateTimestampsCache] starting update timestamps cache at region: org.hibernate.cache.UpdateTimestampsCache
12:27:05,187 INFO [StandardQueryCache] starting query cache at region: org.hibernate.cache.StandardQueryCache
12:27:05,312 WARN [ClassDaoTest] No bean with name 'transactionStatus'
12:27:05,421 INFO [ClassDaoTest] Began transaction (1): transaction manager [org.springframework.orm.hibernate3.HibernateTransactionManager@6835fb]; default rollback = true
12:27:05,468 INFO [ClassDaoTest] Rolled back transaction after test execution
12:27:05,468 WARN [ClassDaoTest] No bean with name 'transactionStatus'
12:27:05,484 INFO [ClassDaoTest] Began transaction (1): transaction manager [org.springframework.orm.hibernate3.HibernateTransactionManager@6835fb]; default rollback = true
12:27:05,484 INFO [ClassDaoTest] Rolled back transaction after test execution
12:27:05,484 WARN [ClassDaoTest] No bean with name 'transactionStatus'
12:27:05,484 INFO [ClassDaoTest] Began transaction (1): transaction manager [org.springframework.orm.hibernate3.HibernateTransactionManager@6835fb]; default rollback = true
12:27:05,609 DEBUG [SQL]
/* criteria query */ select
this_.ID as ID0_0_
from
DBWFGEND_1_4.TEST_CLASS_A this_
where
this_.ID in (
?, ?
)
order by
this_.ID asc
12:27:05,796 DEBUG [IntegerType] binding '4' to parameter: 1
12:27:05,812 DEBUG [IntegerType] binding '5' to parameter: 2
12:27:05,859 DEBUG [IntegerType] returning '4' as column: ID0_0_
12:27:05,859 DEBUG [IntegerType] returning '5' as column: ID0_0_
12:27:05,875 DEBUG [SQL]
/* load ar.com.test.ClassC */ select
classc0_.ID as ID1_0_,
classc0_.CLASS_A_ID as CLASS2_1_0_
from
DBWFGEND_1_4.TEST_CLASS_C classc0_
where
classc0_.CLASS_A_ID=?
12:27:05,875 DEBUG [IntegerType] binding '4' to parameter: 1
12:27:05,875 DEBUG [IntegerType] returning '3' as column: ID1_0_
12:27:05,968 DEBUG [IntegerType] returning '4' as column: CLASS2_1_0_
12:27:05,968 DEBUG [SQL]
/* load ar.com.test.ClassC */ select
classc0_.ID as ID1_0_,
classc0_.CLASS_A_ID as CLASS2_1_0_
from
DBWFGEND_1_4.TEST_CLASS_C classc0_
where
classc0_.CLASS_A_ID=?
12:27:05,968 DEBUG [IntegerType] binding '5' to parameter: 1
12:27:05,968 DEBUG [IntegerType] returning '4' as column: ID1_0_
12:27:05,968 DEBUG [IntegerType] returning '5' as column: CLASS2_1_0_
12:27:05,968 INFO [ClassDaoTest] Rolled back transaction after test execution
12:27:05,984 WARN [ClassDaoTest] No bean with name 'transactionStatus'
12:27:05,984 INFO [ClassDaoTest] Began transaction (1): transaction manager [org.springframework.orm.hibernate3.HibernateTransactionManager@6835fb]; default rollback = true
12:27:05,984 DEBUG [SQL]
/* criteria query */ select
this_.ID as ID0_0_
from
DBWFGEND_1_4.TEST_CLASS_A this_
where
this_.ID in (
?, ?
)
order by
this_.ID asc
12:27:06,015 DEBUG [IntegerType] binding '3' to parameter: 1
12:27:06,015 DEBUG [IntegerType] binding '4' to parameter: 2
12:27:06,015 DEBUG [IntegerType] returning '4' as column: ID0_0_
12:27:06,015 DEBUG [SQL]
/* load ar.com.test.ClassC */ select
classc0_.ID as ID1_0_,
classc0_.CLASS_A_ID as CLASS2_1_0_
from
DBWFGEND_1_4.TEST_CLASS_C classc0_
where
classc0_.CLASS_A_ID=?
12:27:06,015 DEBUG [IntegerType] binding '4' to parameter: 1
12:27:06,031 DEBUG [IntegerType] returning '3' as column: ID1_0_
12:27:06,031 DEBUG [IntegerType] returning '4' as column: CLASS2_1_0_
12:27:06,031 INFO [ClassDaoTest] Rolled back transaction after test execution
12:27:06,031 INFO [SessionFactoryImpl] closing