I am building a small medical record application using Hibernate. I have
Patient:
patient_id Long natively generated identifier firstname String lastname String birthdate Date gender String
LabTest
labtest_id Long natively generated identifier name String highValue float lowValue float
Patient_Labtest:
patient_labtest_id Long natively generated identifier patient Patient pt_id Long labtest LabTest labtest_id Long value Long date Date
Patient_Labtest is a link table with labvalue and labdate as additional properties. I need to access the Patient_Labtest values from Patient. Lots of information on doing link tables as long as they have no additional properties, but when the table needs to contain other properties, it gets very confusing very fast. I've implemented the link as a one-to-many from Patient to Patient_Labtest and as many-to-one from Patient_Labtest to Labtest.
I can load data into the Patient and Labtest easily enough, but the Patient_Labtest is challenging. This seems to bring up the current problem, the LazyInitializationException. The session seems to be open until asked to add a Patient_Labtest, then it acts closed and throws the exception. See below.
Hibernate version: 3.1 in Eclipse 3.1
Mapping documents:
<hibernate-mapping>
<class name="medrecmodel.Patient" table="patient">
<id name="id" column="patient_id">
<generator class="native"/>
</id>
<property name="lastName" column="lastname" />
<property name="firstName" column="firstname" />
<property name="birthdate" column="birthdate" type="java.sql.Date"/>
<property name="gender" column="gender" />
<set name="patient_labtest">
<key column="pt_id"/>
<one-to-many class="medrecmodel.Patient_Labtest"/>
</set>
</class>
</hibernate-mapping>
<hibernate-mapping>
<class
name="medrecmodel.LabTest"
table="labtest">
<id name="labtest_id" column="labtest_id">
<generator class="native"/>
</id>
<property name="name" column="name"/>
<property name="highValue" column = "highvalue"/>
<property name="lowValue" column = "lowvalue"/>
</class>
</hibernate-mapping>
<hibernate-mapping>
<class
name="medrecmodel.Patient_Labtest"
table="patient_labtest">
<id name="patient_labtest_id">
<generator class="native"/>
</id>
<property
name="value"
column="value"/>
<property
name="sqlDate"
column="date"
type="java.sql.Date"/>
<many-to-one name="labtest"
column="labtest_id"
not-null="true"
class="medrecmodel.LabTest"/>
</class>
</hibernate-mapping>
Code between sessionFactory.openSession() and session.close():
public void addLab(LabTest labtest, float labvalue, Date labdate) {
Session session2 = HibernateUtil.getSessionFactory().getCurrentSession();
session2.beginTransaction();
Patient_Labtest ptlab = new Patient_Labtest(this,labtest,labvalue,labdate);
System.out.println("Patient.addLab> ptlab= "+ptlab.toString());
System.out.println("Patient.addLab>sessionOpen ="+session2.isOpen());
getPatient_labtest().add(ptlab);
session2.getTransaction().commit();
}
Full stack trace of any exception that occurs:
Patient.getLabs called
GetSessionFactory called
11:25:50,125 DEBUG SQL:346 - select patient_la0_.patient_labtest_id as patient1_2_, patient_la0_.value as value2_, patient_la0_.date as date2_, patient_la0_.labtest_id as labtest4_2_ from patient_labtest patient_la0_
Hibernate: select patient_la0_.patient_labtest_id as patient1_2_, patient_la0_.value as value2_, patient_la0_.date as date2_, patient_la0_.labtest_id as labtest4_2_ from patient_labtest patient_la0_
Patient.getLabs. List= []
GetSessionFactory called
Patient.addLab> ptlab= 3, 2, 100.0, 2006-04-01
Patient.addLab>sessionOpen =true
11:25:50,156 ERROR LazyInitializationException:19 - failed to lazily initialize a collection of role: medrecmodel.Patient.patient_labtest, no session or session was closed
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: medrecmodel.Patient.patient_labtest, no session or session was closed
at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:358)
at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationExceptionIfNotConnected(AbstractPersistentCollection.java:350)
at org.hibernate.collection.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:343)
at org.hibernate.collection.AbstractPersistentCollection.write(AbstractPersistentCollection.java:183)
at org.hibernate.collection.PersistentSet.add(PersistentSet.java:165)
at medrecmodel.Patient.addLab(Patient.java:94)
at medrectest.LabTestTest.testListEvents(LabTestTest.java:70)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at junit.framework.TestCase.runTest(TestCase.java:154)
at junit.framework.TestCase.runBare(TestCase.java:127)
at junit.framework.TestResult$1.protect(TestResult.java:106)
at junit.framework.TestResult.runProtected(TestResult.java:124)
at junit.framework.TestResult.run(TestResult.java:109)
at junit.framework.TestCase.run(TestCase.java:118)
at junit.framework.TestSuite.runTest(TestSuite.java:208)
at junit.framework.TestSuite.run(TestSuite.java:203)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:478)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:344)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:196)
Name and version of the database you are using: MySQL Server 5.0
The generated SQL (show_sql=true):
LabTestTest>Calling setup
HibernateUtil called
11:25:48,203 INFO SchemaExport:155 - Running hbm2ddl schema export
11:25:48,218 DEBUG SchemaExport:173 - import file not found: /import.sql
11:25:48,218 INFO SchemaExport:182 - exporting generated schema to database
11:25:48,218 DEBUG SchemaExport:296 - alter table patient_labtest drop foreign key FK8DE11465C0A10992
11:25:48,359 DEBUG SchemaExport:296 - alter table patient_labtest drop foreign key FK8DE1146591F476D1
11:25:48,453 DEBUG SchemaExport:296 - drop table if exists labtest
11:25:48,468 DEBUG SchemaExport:296 - drop table if exists patient
11:25:48,484 DEBUG SchemaExport:296 - drop table if exists patient_labtest
11:25:48,500 DEBUG SchemaExport:296 - create table labtest (labtest_id bigint not null auto_increment, name varchar(255), highvalue float, lowvalue float, primary key (labtest_id))
11:25:48,578 DEBUG SchemaExport:296 - create table patient (patient_id bigint not null auto_increment, lastname varchar(255), firstname varchar(255), birthdate date, gender varchar(255), primary key (patient_id))
11:25:48,640 DEBUG SchemaExport:296 - create table patient_labtest (patient_labtest_id bigint not null auto_increment, value float, date date, labtest_id bigint not null, pt_id bigint, primary key (patient_labtest_id))
11:25:48,687 DEBUG SchemaExport:296 - alter table patient_labtest add index FK8DE11465C0A10992 (pt_id), add constraint FK8DE11465C0A10992 foreign key (pt_id) references patient (patient_id)
11:25:48,781 DEBUG SchemaExport:296 - alter table patient_labtest add index FK8DE1146591F476D1 (labtest_id), add constraint FK8DE1146591F476D1 foreign key (labtest_id) references labtest (labtest_id)
11:25:48,890 INFO SchemaExport:202 - schema export complete
Debug level Hibernate log excerpt:
Patient.getLabs called
GetSessionFactory called
11:37:28,937 DEBUG SessionImpl:273 - opened session at timestamp: 11439130489
11:37:28,937 DEBUG ThreadLocalSessionContext:290 - allowing method [beginTransaction] in non-transacted context
11:37:28,937 DEBUG ThreadLocalSessionContext:300 - allowing proxied method [beginTransaction] to proceed to real session
11:37:28,937 DEBUG JDBCTransaction:54 - begin
11:37:28,937 DEBUG ConnectionManager:358 - opening JDBC connection
11:37:28,953 DEBUG DriverManagerConnectionProvider:93 - total checked-out connections: 0
11:37:28,953 DEBUG DriverManagerConnectionProvider:99 - using pooled JDBC connection, pool size: 0
11:37:28,953 DEBUG JDBCTransaction:59 - current autocommit status: false
11:37:28,953 DEBUG JDBCContext:190 - after transaction begin
11:37:28,953 DEBUG ThreadLocalSessionContext:300 - allowing proxied method [createQuery] to proceed to real session
11:37:28,953 DEBUG QueryPlanCache:69 - unable to locate HQL query plan in cache; generating (from Patient_Labtest)
11:37:28,953 DEBUG QueryTranslatorImpl:236 - parse() - HQL: from medrecmodel.Patient_Labtest
11:37:28,968 DEBUG AST:252 - --- HQL AST ---
\-[QUERY] 'query'
\-[SELECT_FROM] 'SELECT_FROM'
\-[FROM] 'from'
\-[RANGE] 'RANGE'
\-[DOT] '.'
+-[IDENT] 'medrecmodel'
\-[IDENT] 'Patient_Labtest'
11:37:28,968 DEBUG ErrorCounter:68 - throwQueryException() : no errors
11:37:28,968 DEBUG HqlSqlBaseWalker:111 - select << begin [level=1, statement=select]
11:37:28,984 DEBUG FromElement:104 - FromClause{level=1} : medrecmodel.Patient_Labtest (no alias) -> patient_la0_
11:37:28,984 DEBUG HqlSqlBaseWalker:117 - select : finishing up [level=1, statement=select]
11:37:28,984 DEBUG HqlSqlWalker:446 - processQuery() : ( SELECT ( FromClause{level=1} patient_labtest patient_la0_ ) )
11:37:28,984 DEBUG HqlSqlWalker:648 - Derived SELECT clause created.
11:37:28,984 DEBUG JoinProcessor:128 - Using FROM fragment [patient_labtest patient_la0_]
11:37:28,984 DEBUG HqlSqlBaseWalker:123 - select >> end [level=1, statement=select]
11:37:28,984 DEBUG AST:222 - --- SQL AST ---
\-[SELECT] QueryNode: 'SELECT' querySpaces (patient_labtest)
+-[SELECT_CLAUSE] SelectClause: '{derived select clause}'
| +-[SELECT_EXPR] SelectExpressionImpl: 'patient_la0_.patient_labtest_id as patient1_2_' {FromElement{explicit,not a collection join,not a fetch join,fetch non-lazy properties,classAlias=null,role=null,tableName=patient_labtest,tableAlias=patient_la0_,origin=null,colums={,className=medrecmodel.Patient_Labtest}}}
| \-[SQL_TOKEN] SqlFragment: 'patient_la0_.value as value2_, patient_la0_.date as date2_, patient_la0_.labtest_id as labtest4_2_'
\-[FROM] FromClause: 'from' FromClause{level=1, fromElementCounter=1, fromElements=1, fromElementByClassAlias=[], fromElementByTableAlias=[patient_la0_], fromElementsByPath=[], collectionJoinFromElementsByPath=[], impliedElements=[]}
\-[FROM_FRAGMENT] FromElement: 'patient_labtest patient_la0_' FromElement{explicit,not a collection join,not a fetch join,fetch non-lazy properties,classAlias=null,role=null,tableName=patient_labtest,tableAlias=patient_la0_,origin=null,colums={,className=medrecmodel.Patient_Labtest}}
11:37:28,984 DEBUG ErrorCounter:68 - throwQueryException() : no errors
11:37:28,984 DEBUG QueryTranslatorImpl:206 - HQL: from medrecmodel.Patient_Labtest
11:37:28,984 DEBUG QueryTranslatorImpl:207 - SQL: select patient_la0_.patient_labtest_id as patient1_2_, patient_la0_.value as value2_, patient_la0_.date as date2_, patient_la0_.labtest_id as labtest4_2_ from patient_labtest patient_la0_
11:37:28,984 DEBUG ErrorCounter:68 - throwQueryException() : no errors
11:37:29,000 DEBUG HQLQueryPlan:219 - HQL param location recognition took 0 mills (from Patient_Labtest)
11:37:29,000 DEBUG QueryPlanCache:75 - located HQL query plan in cache (from Patient_Labtest)
11:37:29,000 DEBUG HQLQueryPlan:148 - find: from Patient_Labtest
11:37:29,000 DEBUG QueryParameters:262 - named parameters: {}
11:37:29,000 DEBUG AbstractBatcher:311 - about to open PreparedStatement (open PreparedStatements: 0, globally: 0)
Hibernate: select patient_la0_.patient_labtest_id as patient1_2_, patient_la0_.value as value2_, patient_la0_.date as date2_, patient_la0_.labtest_id as labtest4_2_ from patient_labtest patient_la0_
11:37:29,000 DEBUG AbstractBatcher:424 - preparing statement
11:37:29,000 DEBUG AbstractBatcher:327 - about to open ResultSet (open ResultSets: 0, globally: 0)
11:37:29,000 DEBUG Loader:682 - processing result set
11:37:29,000 DEBUG Loader:709 - done processing result set (0 rows)
11:37:29,000 DEBUG AbstractBatcher:334 - about to close ResultSet (open ResultSets: 1, globally: 1)
11:37:29,015 DEBUG AbstractBatcher:319 - about to close PreparedStatement (open PreparedStatements: 1, globally: 1)
11:37:29,015 DEBUG AbstractBatcher:470 - closing statement
11:37:29,031 DEBUG Loader:839 - total objects hydrated: 0
11:37:29,031 DEBUG StatefulPersistenceContext:821 - initializing non-lazy collections
11:37:29,031 DEBUG ThreadLocalSessionContext:300 - allowing proxied method [getTransaction] to proceed to real session
11:37:29,031 DEBUG JDBCTransaction:103 - commit
11:37:29,031 DEBUG SessionImpl:355 - automatically flushing session
11:37:29,031 DEBUG JDBCContext:181 - before transaction completion
11:37:29,031 DEBUG SessionImpl:411 - before transaction completion
11:37:29,031 DEBUG JDBCTransaction:116 - committed JDBC Connection
11:37:29,031 DEBUG JDBCContext:195 - after transaction completion
11:37:29,031 DEBUG ConnectionManager:341 - aggressively releasing JDBC connection
11:37:29,031 DEBUG ConnectionManager:378 - releasing JDBC connection [ (open PreparedStatements: 0, globally: 0) (open ResultSets: 0, globally: 0)]
11:37:29,046 DEBUG DriverManagerConnectionProvider:129 - returning connection to pool, pool size: 1
11:37:29,046 DEBUG SessionImpl:442 - after transaction completion
11:37:29,046 DEBUG SessionImpl:371 - automatically closing session
11:37:29,046 DEBUG SessionImpl:291 - closing session
11:37:29,046 DEBUG ConnectionManager:312 - connection already null in cleanup : no action
Patient.getLabs. List= []
GetSessionFactory called
11:37:29,046 DEBUG SessionImpl:273 - opened session at timestamp: 11439130490
11:37:29,046 DEBUG ThreadLocalSessionContext:290 - allowing method [beginTransaction] in non-transacted context
11:37:29,046 DEBUG ThreadLocalSessionContext:300 - allowing proxied method [beginTransaction] to proceed to real session
11:37:29,046 DEBUG JDBCTransaction:54 - begin
11:37:29,046 DEBUG ConnectionManager:358 - opening JDBC connection
11:37:29,046 DEBUG DriverManagerConnectionProvider:93 - total checked-out connections: 0
11:37:29,046 DEBUG DriverManagerConnectionProvider:99 - using pooled JDBC connection, pool size: 0
11:37:29,046 DEBUG JDBCTransaction:59 - current autocommit status: false
11:37:29,046 DEBUG JDBCContext:190 - after transaction begin
Patient.addLab> ptlab= 3, 2, 100.0, 2006-04-01
11:37:29,062 DEBUG ThreadLocalSessionContext:300 - allowing proxied method [isOpen] to proceed to real session
Patient.addLab>sessionOpen =true
11:37:29,062 ERROR LazyInitializationException:19 - failed to lazily initialize a collection of role: medrecmodel.Patient.patient_labtest, no session or session was closed
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: medrecmodel.Patient.patient_labtest, no session or session was closed
at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:358)
at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationExceptionIfNotConnected(AbstractPersistentCollection.java:350)
at org.hibernate.collection.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:343)
at org.hibernate.collection.AbstractPersistentCollection.write(AbstractPersistentCollection.java:183)
at org.hibernate.collection.PersistentSet.add(PersistentSet.java:165)
at medrecmodel.Patient.addLab(Patient.java:93)
at medrectest.LabTestTest.testListEvents(LabTestTest.java:70)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at junit.framework.TestCase.runTest(TestCase.java:154)
at junit.framework.TestCase.runBare(TestCase.java:127)
at junit.framework.TestResult$1.protect(TestResult.java:106)
at junit.framework.TestResult.runProtected(TestResult.java:124)
at junit.framework.TestResult.run(TestResult.java:109)
at junit.framework.TestCase.run(TestCase.java:118)
at junit.framework.TestSuite.runTest(TestSuite.java:208)
at junit.framework.TestSuite.run(TestSuite.java:203)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:478)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:344)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:196)
Any advice would be greatly appreciated!
Roy D
Iowa
|