我们调整一下代码:
Java代码
- package org.ourpioneer.course.dao;
- import java.util.List;
- import org.hibernate.Query;
- import org.hibernate.SessionFactory;
- import org.ourpioneer.course.bean.Course;
- import org.springframework.transaction.annotation.Transactional;
- public class CourseDAOImplHibernate implements CourseDAO {
- private SessionFactory sessionFactory;
- public void setSessionFactory(SessionFactory sessionFactory) {
- this.sessionFactory = sessionFactory;
- }
- @Transactional
- public void delete(Course course) {
- sessionFactory.getCurrentSession().delete(course);
- }
- @Transactional(readOnly = true)
- public List<Course> findAll() {
- Query query = sessionFactory.getCurrentSession().createQuery(
- "from Course");
- return query.list();
- }
- @Transactional(readOnly = true)
- public Course findById(Long courseId) {
- return (Course) sessionFactory.getCurrentSession().get(Course.class,
- courseId);
- }
- @Transactional
- public void save(Course course) {
- sessionFactory.getCurrentSession().saveOrUpdate(course);
- }
- @Transactional
- public void update(Course course) {
- sessionFactory.getCurrentSession().update(course);
- }
- }
这里要注意的是所有DAO的方法必须是支持事务的,这可以通过添加Transactional注解来完成,就很简单了,之前也有过介绍。这样就能保证DAO中所有方法都可以在同一个Session,同一个事务内来执行,达到使用事务的效果。
将代码修改完成后,就要来修改配置文件了:
Xml代码
- <tx:annotation-driven />
- <bean id="transactionManager"
- class="org.springframework.orm.hibernate3.HibernateTransactionManager">
- <property name="sessionFactory" ref="sessionFactory" />
- </bean>
- <bean id="courseDaoHibernate" class="org.ourpioneer.course.dao.CourseDAOImplHibernate">
- <property name="sessionFactory" ref="sessionFactory" />
- </bean>
这样,基于上下文Session的持久化对象就配置完毕了,在示例程序中来执行,就会看到效果。修改测试程序如下:
Java代码
- package org.ourpioneer.course;
- import java.util.GregorianCalendar;
- import java.util.List;
- import org.ourpioneer.course.bean.Course;
- import org.ourpioneer.course.dao.CourseDAO;
- import org.springframework.context.ApplicationContext;
- import org.springframework.context.support.ClassPathXmlApplicationContext;
- public class Demo {
- public static void main(String[] args) {
- ApplicationContext ctx = new ClassPathXmlApplicationContext(
- "classpath:applicationContext.xml");
- CourseDAO courseDAO = (CourseDAO) ctx.getBean("courseDaoHibernate");
- Course course = new Course();
- course.setTitle("Spring ORM");
- course.setStartDate(new GregorianCalendar(2011, 2, 1).getTime());
- course.setEndDate(new GregorianCalendar(2011, 3, 1).getTime());
- course.setFee(100);
- courseDAO.save(course);
- List<Course> courses = courseDAO.findAll();
- Long courseId = courses.get(0).getId();
- course = courseDAO.findById(courseId);
- System.out.println(course);
- course.setFee(200);
- courseDAO.update(course);
- System.out.println(course);
- courseDAO.delete(course);
- }
- }
在控制台,我们可以看到如下输出:

这种方式和使用HibernateTemplate有的不同是它们对异常的处理。HibernateTemplate会将异常统一翻译成Spring的数据访问异常体系中的某个异常,而我们使用上下文的Session时,抛出的就不是Spring的异常,而是HibernateException,如果我们还想看到Spring的异常体系,就需要做点设置,当然这也很简单。
在DAO实现类上加@Respository注解,并且注册一个PersistenceExceptionTranslationPostProcessor实例即可。在Spring的配置文件中,我们加入如下内容:
Xml代码
- <bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"></bean>
这是使用Hibernate的情况,那么使用JPA的情况和这个类似,我们来修改JPA的DAO实现类:
Java代码
- package org.ourpioneer.course.dao;
- import java.util.List;
- import javax.persistence.EntityManager;
- import javax.persistence.PersistenceContext;
- import javax.persistence.Query;
- import org.ourpioneer.course.bean.Course;
- import org.springframework.transaction.annotation.Transactional;
- public class CourseDAOImplJPA implements CourseDAO {
- @PersistenceContext
- private EntityManager entityManager;
- @Transactional
- public void delete(Course course) {
- entityManager.remove(entityManager.merge(course));
- }
- @Transactional(readOnly = true)
- public List<Course> findAll() {
- Query query = entityManager.createQuery("from Course");
- return query.getResultList();
- }
- @Transactional(readOnly = true)
- public Course findById(Long courseId) {
- return entityManager.find(Course.class, courseId);
- }
- @Transactional
- public void save(Course course) {
- entityManager.merge(course);
- }
- @Transactional
- public void update(Course course) {
- entityManager.merge(course);
- }
- }
这里我们使用注解来声明了EntityManager,那么需要在配置文件中在声明一个PersistenceAnnotationBeanPostProcessor实例就好了。配置文件修改为:
Xml代码
- <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
- <property name="entityManagerFactory" ref="entityManagerFactory" />
- </bean>
- <bean id="courseDaoJPA" class="org.ourpioneer.course.dao.CourseDAOImplJPA" />
- <bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"></bean>
之后,将测试程序中的getBean()换成courseDaoJPA即可。
和HibernateTemplate一样,JpaTemplate也会将异常翻译为Spring的数据访问异常,而如果改成entityManagerFactory之后,异常就会变成Java SE的异常,比如非法参数,非法状态等异常。若要继续使用Spring的异常体系,那么要为JPA的DAO实现类加上@Repository注解,然后注册PersistenceExceptionTranslationPostProcessor实例。
至此,我们的Spring的ORM部分已经全部介绍完了,源代码随附件发布。后续将介绍Spring对iBatis的支持。