Spring中集成Hibernate和JPA

在Spring中集成Hibernate

声明Hibernate的Seccion工厂

SessionFactory主要负责Hibernate Seccion的打开、关闭以及管理。
在Spring中,我们要通过Spring的某一个Hibernate Seccion工厂bean来获取Hibernate SessionFactory。从3.1版本开始,Spring提供了三个Seccion工厂bean供我们选择:

  • org.springframework.orm.hibernate4.LocalSessionFactoryBean;
  • org.springframework.orm.hibernate3.LocalSessionFactoryBean;
  • org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean;

这些Seccion工厂bean都是Spring FactoryBean接口的实现,它们会产生一个Hibernate SessionFactory,它能够装配进任何SessionFactory类型的属性中。这样的话。就能在应用的Spring上下文中,与其他的bean一起配置Hibernate Seccion工厂。
至于选择使用哪一个Seccion工厂,这取决于使用哪个版本的Hibernate以及你使用XML还是使用注解来定义对象-数据库之间的映射关系。这里我使用的是Hibernate4.1.4版本,所以我使用org.springframework.orm.hibernate4.LocalSessionFactoryBean。配置如下:

@Bean
    public LocalSessionFactoryBean sessionFactory(DataSource dataSource)
    {
        LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
        sessionFactory.setDataSource(dataSource);
        sessionFactory.setPackagesToScan(new String[] {"entity"});
        Properties properties = new Properties();
        properties.setProperty("dialect", "org.hibernate.dialect.H2Dialect");
        sessionFactory.setHibernateProperties(properties);
        return sessionFactory;

    }

其它版本的配置等用到再补上。

构建不依赖于Spring的Hibernate代码

@Autowired
    private SessionFactory sessionFactory;  

    public SessionFactory getSessionFactory() {  
        return sessionFactory;  
    } 
    private Session getSession() {
        return sessionFactory.getCurrentSession();
        //return sessionFactory.openSession();
    }

openSession()与getCurrentSession()的区别:
openSession: 当调用SessionFactory的openSession方法时,它总是创建一个新的session给你。不会绑定到当前的线程中去,并且需要手动区关闭。
getCurrentSession: 采用getCurrentSession()创建的Session会绑定到当前的线程中去(返回的都是同一个Session),在commit或rollback后会自动关闭。
这里我们使用getCurrentSession(),但是getCurrentSession()方法必须配置事务管理,配置如下:
RootConfig.java

@Bean
    public HibernateTransactionManager transactionManager(SessionFactory sessionFactory)
    {
        HibernateTransactionManager transactionManager = new HibernateTransactionManager();     
        transactionManager.setSessionFactory(sessionFactory);       
        return transactionManager;
    }
            //价于XML配置如下
            // <bean id="transactionManager"          class="org.springframework.orm.hibernate4.HibernateTransactionManager">  
            //<property name="sessionFactory" ref="sessionFactory"></property>  
            //  </bean>  

WebConfig.java

@EnableTransactionManagement    //开启事务支持
//作用等价于<tx:annotation-driven />

并且在server层使用事务

@Transactional

在Spring中集成JPA

在Spring中使用JPA的第一步是要在Spring应用上下文中配置实体管理器工厂。

配置实体管理器工厂

基于JPA的应用程序需要使用EntityManagerFactory的实现类来获取EntityManager实例。JPA定义了两种类型的实体管理器:

  • 应用程序管理类型:当应用程序向实体管理器工厂直接请求实体管理器时,工厂会创建一个实体管理器。在这种模式下,程序要负责打开或关闭实体管理器并在事务中对其进行控制。这种方式的实体管理器适合于不运行在Java EE容器中的独立应用程序。
  • 容器管理类型:实体管理器由Java EE创建和管理。应用程序根本不与实体管理器打交道。相反,实体管理器直接通过注入或JNDI来获取。容器负责配置实体管理器工厂。这种类型的实体管理器最适用于Java EE容器,在这种情况下会希望在persistence.xml指定的JPA配置之外保持一些自己对JPA的控制。

以上两种实体管理器实现了同一个EntityManager接口。关键区别在于EntityManager的创建和管理方式。 应用程序管理类型的EntityManager是由EntityManagerFactory创建的,而后者时通过PersistenceProvider的createEntityManagerFactory()方法得到的。
不管你希望使用哪种EntityManagerFactory,Spring都会负责管理EntityManager。
这两种实体管理器工厂分别由对应的Spring工厂Bean创建:

  • LocalEntityManagerFactoryBean:生成应用程序管理类型的EntityManagerFactory;
  • LocalContainerEntityManagerFactoryBean:生成容器管理类型的EntityManagerFactory;

这里我只配置容器管理类型的EntityManagerFactory。

使用容器管理类型的JPA

@Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactoryBean(DataSource dataSource,JpaVendorAdapter adapter)
    {
        LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = 
                new LocalContainerEntityManagerFactoryBean();
        entityManagerFactoryBean.setDataSource(dataSource);
        entityManagerFactoryBean.setJpaVendorAdapter(adapter);
        entityManagerFactoryBean.setPackagesToScan("entity");//扫描实体类包
        return entityManagerFactoryBean;
    }

JpaVendorAdapter属性用于指明所使用的是哪一个厂商的JPA实现。Spring提供了多个JPA厂商适配器:

  • EclipseLinkJpaVendorAdapter
  • HIbernateJpaVendorAdapter
  • OpenJpaVendorAdapter
  • TopLinkJpaVendorAdapter(在Spring3.1中,已经被废弃了)

我们使用Hibernate作为JPA实现。

@Bean
    public JpaVendorAdapter jpaVendorAdapter()
    {
        HibernateJpaVendorAdapter adapter = new HibernateJpaVendorAdapter();
        adapter.setGenerateDdl(false);//一些其他属性自行设置
        return adapter; 
    }

声明JPA事务管理

@Bean
    public JpaTransactionManager transactionManager(EntityManagerFactory entityManagerFactoryBean)
    {
        JpaTransactionManager transactionManager = new JpaTransactionManager();
        transactionManager.setEntityManagerFactory(entityManagerFactoryBean);
        return transactionManager;
    }

编写基于JPA的Repository

testDao .java

package test.dao;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import org.springframework.stereotype.Repository;
import entity.Admin;
@Repository
public class testDao {  
    @PersistenceUnit
    private EntityManagerFactory factory;//@PersistenceUnit会将EntityManagerFactory 注入到testDao中
    public Admin find(int id) {
        Admin admin = factory.createEntityManager().find(Admin.class, id);
        return admin;
    }
    ...
}

但是每个方法都会调用createEntityManager()。而且每次调用Repository方法时,都会创建一个新的EntityManager。
如下展示了借助@PersistenceContext注解注入EntityManager:

package test.dao;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import org.springframework.stereotype.Repository;
import entity.Admin;
@Repository
public class testDao {  
    @PersistenceContext
    private EntityManager em;
    public Admin getAdmin(int id) {
        Admin admin = em.find(Admin.class, id);
        return admin;
    }
    ...
}

在这个Repository中,直接设置了EntityManager,就没有必要再通过EntityManagerFactory创建EntityManager了。但是你可能会担心EntityManager会有线程安全性的问题,因为EntityManager并不是线程安全的。
@PersistenceContext并不会真正注入EntityManager。它没有将真正的EntityManager设置给Repository,而是给了它一个EntityManager的代理。真正的EntityManager是与当前事务相关联的那一个,如果不存在这样的EntityManager话,就会创建一个新的。这样的话,我们就能始终以线程安全的方式使用实体管理器。
另外,@PersistenceUnit与@PersistenceContext并不是Spring的注解,它们是由JPA规范提供的。为了让Spring理解这些注解,并注入EntityManagerFactory或EntityManager,我们必须要配置Spring的PersistenceAnnotationBeanPostProcessor。如果你已经使用了< context:annotation-config >或< context:component-scan > 那么就不用担心了,因为这些配置元素会自动注册PersistenceAnnotationBeanPostProcessor bean。否则,我们需要显示地注册这个Bean。

    @Bean
    public PersistenceAnnotationBeanPostProcessor processor()
    {
        return new PersistenceAnnotationBeanPostProcessor();
    }

以上只是学习Spring实战所写的笔记,如有错误,请指正。谢谢

猜你喜欢

转载自blog.csdn.net/z1790424577/article/details/80766490