I use HibernateTemplate to do hibernate data access. However, I met a problem on
session lost or session close.Basically, what I did:
Database relationship: 1 student -gt; n courses
public class Student { String studentId; Collection courses; ... public Collection getCourses(){ return courses; }
}
public class StudentDAO { public Student getStudent(String studentId) { return getHibernateTemplate().get(Student.class, studentId); }
}
I can get Student object through StudentDAO.
Student student = (Student) studentDao.getStudent();
However, when I try to call:
student.getCourses();
I got session close or lost exception. I guess that is because Student
domain object cannot find its original session. How can I keep that session to make it work?
Should I use studentDao inside Student domain object's getCourses method?
First thing where in the code are you calling student.getCourses(); and getting a problem? Can we see the code and the applicationContext?
Have you configured transactions?
docs/...ansaction.html
Having quot;no session or session was closedquot; error for this piece of code:Code:
public class StockHibernateDAOTest extends TestCase {
protected ApplicationContext ctx = null;
public void testGetStocks() {
String[] paths = {quot;applicationContext.xmlquot; };
ctx = new ClassPathXmlApplicationContext(paths);
StockDAO stockDao = (StockDAO) ctx.getBean(quot;stockDAOquot;);
List retval = stockDao.getStock();
Iterator iter = retval.iterator();
while( iter.hasNext() ) {
Stock stock = (Stock) iter.next();
stock.getOptions().size();
}
}
}
_________________________________________
applicationContext.xml:
Code:
lt;?xml version=quot;1.0quot; encoding=quot;UTF-8quot;?gt;
lt;!DOCTYPE beans PUBLIC quot;-//SPRING//DTD BEAN//ENquot; quot;dtd/spring-beans.dtdquot;gt;
lt;beansgt;
lt;bean id=quot;dataSourcequot;
class=quot;org..jdbc.datasource.DriverManagerDataSourcequot;gt;
lt;property name=quot;driverClassNamequot;gt;
lt;valuegt;com.mysql.jdbc.Driverlt;/valuegt;
lt;/propertygt;
lt;property name=quot;uclquot;gt;
lt;valuegt;jdbc:mysql--/aaalt;/valuegt;
lt;/propertygt;
lt;property name=quot;usernamequot;gt;
lt;valuegt;aaalt;/valuegt;
lt;/propertygt;
lt;property name=quot;passwordquot;gt;
lt;valuegt;aaa1234lt;/valuegt;
lt;/propertygt;
lt;/beangt;
lt;!-- Hibernate SessionFactory --gt;
lt;bean id=quot;sessionFactoryquot;
class=quot;org..orm.hibernate3.LocalSessionFactoryBeanquot;gt;
lt;property name=quot;dataSourcequot;gt;
lt;ref local=quot;dataSourcequot; /gt;
lt;/propertygt;
lt;property name=quot;mappingResourcesquot;gt;
lt;listgt;lt;valuegt;com/aaa/domain/Stock.hbm.xmllt;/valuegt;
lt;/listgt;
lt;/propertygt;
lt;property name=quot;hibernatePropertiesquot;gt;
lt;propsgt;
lt;prop key=quot;hibernate.dialectquot;gt;
org.hibernate.dialect.MySQLDialect
lt;/propgt;
lt;prop key=quot;hibernate.show_sqlquot;gt;
false
lt;/propgt;
lt;/propsgt;
lt;/propertygt;
lt;/beangt;
lt;!-- Transaction manager for a single Hibernate SessionFactory (alternative to JTA) --gt;
lt;bean id=quot;transactionManagerquot;
class=quot;org..orm.hibernate3.HibernateTransactionManagerquot;gt;
lt;property name=quot;sessionFactoryquot;gt;
lt;ref local=quot;sessionFactoryquot; /gt;
lt;/propertygt;
lt;/beangt;
lt;bean id=quot;stockDAOquot;
class=quot;com.aaa.dao.hibernate.StockHibernateDAOquot;gt;
lt;property name=quot;sessionFactoryquot;gt;
lt;ref local=quot;sessionFactoryquot; /gt;
lt;/propertygt;
lt;/beangt;
lt;/beansgt;
_________________________________________
Stock.hbm.xml:
Code:
lt;?xml version=quot;1.0quot; encoding=quot;UTF-8quot;?gt;
lt;!DOCTYPE hibernate-mapping PUBLIC
quot;-//Hibernate/Hibernate Mapping DTD 3.0//ENquot;
quot;hibernate-mapping-3.0.dtdquot;gt;
lt;hibernate-mapping package=quot;com.aaa.domainquot;gt;
lt;class name=quot;Stockquot; table=quot;STOCKquot; mutable=quot;truequot;gt;
lt;id name=quot;symbolquot; type=quot;java.lang.Stringquot; column=quot;SYMBOLquot; /gt;
lt;set name=quot;optionsquot; lazy=quot;truequot; inverse=quot;truequot; cascade=quot;allquot;gt;
lt;key column=quot;SYMBOLquot; /gt;
lt;one-to-many class=quot;com.aaa.domain.Stockquot;/gt;
lt;/setgt;
lt;/classgt;
lt;/hibernate-mappinggt;
________________________________
Stock.java:
Code:
public class Stock implements Serializable {
private static final long serialVersionUID = 1L;
private String symbol;
private Collection options;
public String getSymbol() {
return symbol;
}
public void setSymbol(String symbol) {
this.symbol = symbol;
}
public Collection getOptions() {
return options;
}
public void setOptions(Collection options) {
this.options = options;
}
}
_______________________________
StockHibernateDAO:
Code:
public class StockHibernateDAO extends HibernateDaoSupport implements
StockDAO {
public List getStock() {
// TODO Auto-generated method stub HibernateCallback callback = new HibernateCallback() {public Object doInHibernate(Session session) throws HibernateException{return session.createQuery(quot;from Stockquot;).list();}
};
return (List) getHibernateTemplate().execute(callback);
}
}First thing, if you put your code in [ code] [ /code] tags its sooo much easier to read .
Second have a look at this.
sho...ion+unit+tests
so you think it won't be problem if I run it within application server?
Thanks alot for your quick response!
The hibernate session has to be open when it tries to load the collection. In hibernate 3.0 lazy initialization is the default.
hib_docs/v3...-fetching-lazy
To solve the problem of the session being closed, you could.
#1. Eagerly load everything in the dao
#2. Extend the session into the view (Open Session in View)
#3. Copy all data to DTOs
Regardless of how you do it though, you should define a transaction boundary in the application/service layer. This allows this layer to work with the lazy loaded properties. Some people like to lazy load from daos and initialise here.
docs/...ansaction.html
There are lots of resources on the forums to help with these issues. I would also have a look at the samples that ship with spring and the hibernate reference manual. |