In the previous post we saw the working of the HibernateTemplate. As discussed Spring doesn't need us to work with it. We can now directly work with the SessionFactory.
The output indicates the code worked !!
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> <property name="dataSource" ref="c3pDataSource" /> <property name="mappingResources"> <list> <value>com/data/model/Person.hbm.xml </value> </list> </property> <property name="hibernateProperties"> <props> <prop key="dialect">org.hibernate.dialect.MySQLDialect</prop> <prop key="show_sql">true</prop> <prop key="hibernate.hbm2ddl.auto">create</prop> </props> </property> </bean> <bean id="personDAO" class="com.data.dao.PersonDAO" > <property name="sessionFactory" ref="sessionFactory" /> </bean>The sessionFactory bean is same as the previous post.What has changed is the PersonDAO class. I wired it with the SessionFactory bean.
public class PersonDAO implements IPersonDAO { private SessionFactory sessionFactory; public SessionFactory getSessionFactory() { return sessionFactory; } public void setSessionFactory(SessionFactory sessionFactory) { this.sessionFactory = sessionFactory; } //other methods }I tried to access the session using the sessionFactory's getCurrentSession() method. This led to the below failure:
Exception in thread "main" org.hibernate.HibernateException: No Hibernate Session bound to thread,
and configuration does not allow creation of non-transactional one here
at org.springframework.orm.hibernate3.SpringSessionContext.currentSession(SpringSessionContext.java:63)
at org.hibernate.impl.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:622)
at com.data.dao.PersonDAO.getCrntSession(PersonDAO.java:34)
at com.data.dao.PersonDAO.save(PersonDAO.java:93)
at com.test.Client.testPersonLifeCycle(Client.java:56)
at com.test.Client.main(Client.java:48)
The sessionFactory implementation does not work in the absence of a transactional context unlike the HibernateTemplate. I tries to use the context class setting <prop key="current_session_context_class">thread</prop>but that did not help either. So I decided to go with my own session management. The DAO class is as below:
@Repository public class PersonDAO implements IPersonDAO { private SessionFactory sessionFactory; private Session session; public Session getCrntSession() { return session; } public Transaction initialize() { if (null != session) { throw new RuntimeException("session is still open"); } else { session = sessionFactory.openSession(); } Transaction transaction = session.beginTransaction(); return transaction; } public void closeAfterOperation() { session.flush(); session.close(); session = null; } private static final Logger logger = Logger.getLogger(PersonDAO.class); @SuppressWarnings("unchecked") @Override public List<Person> getAllPersons() { logger.debug("getAllPersons from system"); Session session = this.getCrntSession(); List<Person> persons = new ArrayList<Person>(0); Query query = session.createQuery("from Person"); persons = query.list(); logger.debug("Total Retrieved items : " + persons.size()); return persons; } @Override public int findTotalPersons() { logger.debug("findTotalPersons: fetching record count "); final Session session = this.getCrntSession(); int total = session.createQuery("from PERSON").list().size(); return total; } @Override public Person getPersonById(final long personId) { logger.debug("fetching record with id : " + personId); Person person = null; final Session session = this.getCrntSession(); person = (Person) session.get(Person.class, personId); return person; } @Override public void updatePerson(final Person person) { final Session session = this.getCrntSession(); session.update(person); } @Override public void save(Person person) { final Session session = this.getCrntSession(); session.save(person); } @Override public void delete(Person person) { final Session session = this.getCrntSession(); session.delete(person); } public SessionFactory getSessionFactory() { return sessionFactory; } public void setSessionFactory(SessionFactory sessionFactory) { this.sessionFactory = sessionFactory; } }I tested it using the below code:
public static void main(String[] args) { final ApplicationContext beanFactory = new ClassPathXmlApplicationContext("spring-hib-template.xml"); PersonDAO personDAOImpl = (PersonDAO) beanFactory.getBean("personDAO"); System.out.println(personDAOImpl); Transaction transaction = personDAOImpl.initialize(); testPersonLifeCycle(personDAOImpl); transaction.commit(); personDAOImpl.closeAfterOperation(); } public static void testPersonLifeCycle(final IPersonDAO personDAO) { Person person = new Person(); person.setName("Vinod"); person.setAge(26); personDAO.save(person); final Long personId = person.getId(); System.out.println("Person was saved with id " + personId); person = personDAO.getPersonById(personId); person.setName("Raja"); personDAO.updatePerson(person); System.out.println("Person with id " +personId + " was updated"); person = personDAO.getPersonById(personId); System.out.println("Person with id " + personId + " is " + person.getName() + " and age is " + person.getAge()); personDAO.delete(person); System.out.println("person with id " + personId + " has been deleted successfully"); }As can be seen, I executed my code by starting and managing my own transactions.
The output indicates the code worked !!
com.data.dao.PersonDAO@17b40fe Person was saved with id 2 78 [main] DEBUG com.data.dao.PersonDAO - fetching record with id : 2 Person with id 2 was updated 78 [main] DEBUG com.data.dao.PersonDAO - fetching record with id : 2 Person with id 2 is Raja and age is 26 person with id 2 has been deleted successfullyIf Hibernate annotations is used then we would need to work with a different sessionFactory
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"> <property name="dataSource" ref="dataSource" /> <property name="annotatedClasses"> <list> <value>com.data.model.Person</value> </list> </property> <property name="hibernateProperties"> <props> <prop key="dialect">org.hibernate.dialect.MySQLDialect</prop> <prop key="show_sql">true</prop> </props> </property> </bean>This class extends the LocalSessionFactoryBean that we saw earlier. An alternative to annotatedClasses property is
<property name="packagesToScan"> <list> <value>com.data.model.Person</value> </list> </property>
No comments:
Post a Comment