知识点

相关文章

更多

最近更新

更多

【第八章】 对ORM的支持 之 8.2 集成Hibernate3 ——跟我学spring3

2019-03-01 14:27|来源: 开涛

8.2  集成Hibernate3

      Hibernate是全自动的ORM框架,能自动为对象生成相应SQL并透明的持久化对象到数据库。

Spring2.5+版本支持Hibernate 3.1+版本,不支持低版本,Spring3.0.5版本提供对Hibernate 3.6.0 Final版本支持。

8.2.1  如何集成

      Spring通过使用如下Bean进行集成Hibernate:

  • LocalSessionFactoryBean :用于支持XML映射定义读取:

        configLocation和configLocations:用于定义Hibernate配置文件位置,一般使用如classpath:hibernate.cfg.xml形式指定;

        mappingLocations :用于指定Hibenate映射文件位置,如chapter8/hbm/user.hbm.xml;

        hibernateProperties:用于定义Hibernate属性,即Hibernate配置文件中的属性;

        dataSource:定义数据源;

hibernateProperties、dataSource用于消除Hibernate配置文件,因此如果使用configLocations指定配置文件,就不要设置这两个属性了,否则会产生重复配置。推荐使用dataSource来指定数据源,而使用hibernateProperties指定Hibernate属性。

  • AnnotationSessionFactoryBean:用于支持注解风格映射定义读取,该类继承LocalSessionFactoryBean并额外提供自动查找注解风格配置模型的能力:

        annotatedClasses:设置注解了模型类,通过注解指定映射元数据。

        packagesToScan:通过扫描指定的包获取注解模型类,而不是手工指定,如“cn.javass.**.model”将扫描cn.javass包及子包下的model包下的所有注解模型类。

接下来学习一下Spring如何集成Hibernate吧:

1、准备jar包:

首先准备Spring对ORM框架支持的jar包:

org.springframework.orm-3.0.5.RELEASE.jar  //提供对ORM框架集成


下载hibernate-distribution-3.6.0.Final包,获取如下Hibernate需要的jar包:

hibernate3.jar                       //核心包

lib\required\antlr-2.7.6.jar              //HQL解析时使用的包

lib\required\javassist-3.9.0.GA.jar       //字节码类库,类似于cglib

lib\required\commons-collections-3.1.jar  //对集合类型支持包,前边测试时已经提供过了,无需再拷贝该包了

lib\required\dom4j-1.6.1.jar            //xml解析包,用于解析配置使用

lib\required\jta-1.1.jar                 //JTA事务支持包

lib\jpa\hibernate-jpa-2.0-api-1.0.0.Final.jar //用于支持JPA

       

下载slf4j-1.6.1.zip(http://www.slf4j.org/download.html),slf4j是日志系统门面(Simple Logging Facade for Java),用于对各种日志框架提供给一致的日志访问接口,从而能随时替换日志框架(如log4j、java.util.logging):

slf4j-api-1.6.1.jar              //核心API

slf4j-log4j12-1.6.1.jar          //log4j实现

将这些jar包添加到类路径中。

2、对象模型定义,此处使用第七章中的UserModel

  1. package cn.javass.spring.chapter7;  

  2. public class UserModel {  

  3.    private int id;  

  4.    private String myName;  

  5.    //省略getter和setter  

  6. }  

3、Hibernate映射定义(chapter8/hbm/user.hbm.xml),定义对象和数据库之间的映射:

  1. <?xml version="1.0" encoding="UTF-8"?>  

  2. <!DOCTYPE hibernate-mapping PUBLIC  

  3.        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"  

  4.        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">  

  5. <hibernate-mapping>  

  6.    <class name="cn.javass.spring.chapter7.UserModel" table="test">  

  7.        <id name="id" column="id"><generator class="native"/></id>  

  8.        <property name="myName" column="name"/>  

  9.    </class>  

  10. </hibernate-mapping>  

4、   数据源定义,此处使用第7章的配置文件,即“chapter7/ applicationContext-resources.xml”文件。

5、   SessionFactory配置定义(chapter8/applicationContext-hibernate.xml):

  1. <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">  

  2.    <property name="dataSource" ref="dataSource"/> <!-- 指定数据源 -->  

  3.      <property name="mappingResources">     <!-- 指定映射定义 -->  

  4.        <list>  

  5.          <value>chapter8/hbm/user.hbm.xml</value>  

  6.        </list>  

  7.      </property>  

  8.      <property name="hibernateProperties">   <!--指定Hibernate属性 -->  

  9.        <props>  

  10.          <prop key="hibernate.dialect">  

  11.              org.hibernate.dialect.HSQLDialect  

  12.          </prop>  

  13.        </props>  

  14.      </property>  

  15. </bean>  

6、   获取SessionFactory

  1. package cn.javass.spring.chapter8;  

  2. //省略import  

  3. public class HibernateTest {  

  4.    private static SessionFactory sessionFactory;  

  5.    @BeforeClass  

  6.    public static void beforeClass() {  

  7.        String[] configLocations = new String[] {  

  8.                "classpath:chapter7/applicationContext-resources.xml",  

  9.                "classpath:chapter8/applicationContext-hibernate.xml"};  

  10.        ApplicationContext ctx = new ClassPathXmlApplicationContext(configLocations);  

  11.        sessionFactory = ctx.getBean("sessionFactory", SessionFactory.class);  

  12. }  

  13. }  

此处我们使用了chapter7/applicationContext-resources.xml定义的“dataSource”数据源,通过ctx.getBean("sessionFactory", SessionFactory.class)获取SessionFactory。

7、通过SessionFactory获取Session对象进行创建和删除表:

  1. @Before  

  2. public void setUp() {  

  3.  //id自增主键从0开始  

  4.  final String createTableSql = "create memory table test" + "(id int GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, " + "name varchar(100))";  

  5.  sessionFactory.openSession().  

  6.  createSQLQuery(createTableSql).executeUpdate();  

  7. }  

  8. @After  

  9. public void tearDown() {  

  10.    final String dropTableSql = "drop table test";  

  11.    sessionFactory.openSession().  

  12.    createSQLQuery(dropTableSql).executeUpdate();  

  13. }  

使用SessionFactory创建Session,然后通过Session对象的createSQLQuery创建本地SQL执行创建和删除表。

8、使用SessionFactory获取Session对象进行持久化数据:

  1. @Test  

  2. public void testFirst() {  

  3.    Session session = sessionFactory.openSession();  

  4.    Transaction transaction = null;  

  5.    try {  

  6.        transaction = beginTransaction(session);  

  7.        UserModel model = new UserModel();  

  8.        model.setMyName("myName");  

  9.        session.save(model);  

  10.    } catch (RuntimeException e) {  

  11.        rollbackTransaction(transaction);  

  12.        throw e;  

  13.    } finally {  

  14.        commitTransaction(session);  

  15.    }  

  16. }  

  1. private Transaction beginTransaction(Session session) {  

  2.    Transaction transaction = session.beginTransaction();  

  3.    transaction.begin();  

  4.    return transaction;  

  5. }  

  6. private void rollbackTransaction(Transaction transaction) {  

  7.   if(transaction != null) {  

  8.        transaction.rollback();  

  9.    }  

  10. }  

  11. private void commitTransaction(Session session) {  

  12.    session.close();  

  13. }  

  14.  

使用SessionFactory获取Session进行操作,必须自己控制事务,而且还要保证各个步骤不会出错,有没有更好的解决方案把我们从编程事务中解脱出来?Spring提供了HibernateTemplate模板类用来简化事务处理和常见操作。

8.2.2 使用HibernateTemplate

HibernateTimplate模板类用于简化事务管理及常见操作,类似于JdbcTemplate模板类,对于复杂操作通过提供HibernateCallback回调接口来允许更复杂的操作。

接下来示例一下HibernateTemplate的使用:

  1. @Test  

  2. public void testHibernateTemplate() {  

  3. HibernateTemplate hibernateTemplate =  

  4. new HibernateTemplate(sessionFactory);  

  5.    final UserModel model = new UserModel();  

  6.    model.setMyName("myName");  

  7.    hibernateTemplate.save(model);  

  8.    //通过回调允许更复杂操作  

  9.    hibernateTemplate.execute(new HibernateCallback<Void>() {  

  10.        @Override  

  11.        public Void doInHibernate(Session session)  

  12.            throws HibernateException, SQLException {  

  13.            session.save(model);  

  14.            return null;  

  15.        }});  

  16. }  

  17.  

通过new HibernateTemplate(sessionFactory) 创建HibernateTemplate模板类对象,通过调用模板类的save方法持久化对象,并且自动享受到Spring管理事务的好处。

而且HibernateTemplate 提供使用HibernateCallback回调接口的方法execute用来支持复杂操作,当然也自动享受到Spring管理事务的好处。

8.2.3  集成Hibernate及最佳实践

      类似于JdbcDaoSupport类,Spring对Hibernate也提供了HibernateDaoSupport类来支持一致的数据库访问。HibernateDaoSupport也是DaoSupport实现:

      接下来示例一下Spring集成Hibernate的最佳实践:

1、 定义Dao接口,此处使用cn.javass.spring.chapter7.dao. IUserDao

2、 定义Dao接口实现,此处是Hibernate实现:

  1.      

  2. package cn.javass.spring.chapter8.dao.hibernate;  

  3. import org.springframework.orm.hibernate3.support.HibernateDaoSupport;  

  4. import cn.javass.spring.chapter7.UserModel;  

  5. import cn.javass.spring.chapter7.dao.IUserDao;  

  6. public class UserHibernateDaoImpl extends HibernateDaoSupport implements IUserDao {  

  7.    private static final String COUNT_ALL_HQL = "select count(*) from UserModel";  

  8.    @Override  

  9.    public void save(UserModel model) {  

  10.        getHibernateTemplate().save(model);  

  11.    }  

  12.    @Override  

  13.    public int countAll() {  

  14.        Number count = (Number) getHibernateTemplate().find(COUNT_ALL_HQL).get(0);  

  15.        return count.intValue();  

  16.    }  

  17. }  

此处注意首先Hibernate实现放在dao.hibernate包里,其次实现类命名如UserHibernateDaoImpl,即×××HibernateDaoImpl,当然如果自己有更好的命名规范可以遵循自己的,此处只是提个建议。

3、进行资源配置,使用resources/chapter7/applicationContext-resources.xml

4、dao定义配置,在chapter8/applicationContext-hibernate.xml中添加如下配置:

  1. <bean id="abstractDao" abstract="true">  

  2.    <property name="sessionFactory" ref="sessionFactory"/>  

  3. </bean>    

  4. <bean id="userDao"  class="cn.javass.spring.chapter8.dao.hibernate.UserHibernateDaoImpl" parent="abstractDao"/>    

首先定义抽象的abstractDao,其有一个sessionFactory属性,从而可以让继承的子类自动继承sessionFactory属性注入;然后定义userDao,且继承abstractDao,从而继承sessionFactory注入;我们在此给配置文件命名为applicationContext-hibernate.xml表示Hibernate实现。

5、 最后测试一下吧(cn.javass.spring.chapter8. HibernateTest):

  1. @Test  

  2. public void testBestPractice() {  

  3.    String[] configLocations = new String[] {  

  4.            "classpath:chapter7/applicationContext-resources.xml",  

  5.            "classpath:chapter8/applicationContext-hibernate.xml"};  

  6.    ApplicationContext ctx = new ClassPathXmlApplicationContext(configLocations);  

  7.    IUserDao userDao = ctx.getBean(IUserDao.class);  

  8.    UserModel model = new UserModel();  

  9.    model.setMyName("test");  

  10.    userDao.save(model);  

  11.    Assert.assertEquals(1, userDao.countAll());  

  12. }  

和Spring JDBC框架的最佳实践完全一样,除了使用applicationContext-hibernate.xml代替了applicationContext-jdbc.xml,其他完全一样。也就是说,DAO层的实现替换可以透明化。

8.2.4  Spring+Hibernate的CRUD

      Spring+Hibernate CRUD(增删改查)我们使用注解类来示例,让我们看具体示例吧:

1、首先定义带注解的模型对象UserModel2

  • 使用JPA注解@Table指定表名映射;

  • 使用注解@Id指定主键映射;

  • 使用注解@ Column指定数据库列映射;

  1. package cn.javass.spring.chapter8;  

  2. import javax.persistence.Column;  

  3. import javax.persistence.Entity;  

  4. import javax.persistence.GeneratedValue;  

  5. import javax.persistence.GenerationType;  

  6. import javax.persistence.Id;  

  7. import javax.persistence.Table;  

  8. @Entity  

  9. @Table(name = "test")  

  10. public class UserModel2 {  

  11.    @Id @GeneratedValue(strategy = GenerationType.AUTO)  

  12.    private int id;  

  13.    @Column(name = "name")  

  14.    private String myName;  

  15.    //省略getter和setter  

  16. }  

2、 定义配置文件(chapter8/applicationContext-hibernate2.xml):

2.1、        定义SessionFactory

此处使用AnnotationSessionFactoryBean通过annotatedClasses属性指定注解模型来定义映射元数据;

  1. <bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">  

  2. <property name="dataSource" ref="dataSource"/>  <!-- 1、指定数据源 -->  

  3.  <property name="annotatedClasses">           <!-- 2、指定注解类 -->  

  4.     <list><value>cn.javass.spring.chapter8.UserModel2</value></list>  

  5. </property>  

  6.  <property name="hibernateProperties"><!-- 3、指定Hibernate属性 -->  

  7.    <props>  

  8.     <prop key="hibernate.dialect">  

  9.        org.hibernate.dialect.HSQLDialect  

  10.     </prop>  

  11.    </props>  

  12.  </property>  

  13. </bean>  

2.2、定义HibernateTemplate

  1. <bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate">  

  2.    <property name="sessionFactory" ref="sessionFactory"/>  

  3. </bean>  

3、最后进行CURD测试吧:

  1. @Test  

  2. public void testCURD() {  

  3.    String[] configLocations = new String[] {  

  4.            "classpath:chapter7/applicationContext-resources.xml",  

  5.            "classpath:chapter8/applicationContext-hibernate2.xml"};  

  6.    ApplicationContext ctx =  new ClassPathXmlApplicationContext(configLocations);  

  7.    HibernateTemplate hibernateTemplate =  ctx.getBean(HibernateTemplate.class);  

  8.    UserModel2 model = new UserModel2();  

  9.    model.setMyName("test");  

  10.    insert(hibernateTemplate, model);  

  11.    select(hibernateTemplate, model);  

  12.    update(hibernateTemplate, model);  

  13.    delete(hibernateTemplate, model);  

  14. }  

  15.  

  16. private void insert(HibernateTemplate hibernateTemplate, UserModel2 model) {  

  17.    hibernateTemplate.save(model);  

  18. }  

  19. private void select(HibernateTemplate hibernateTemplate, UserModel2 model) {  

  20.    UserModel2 model2 = hibernateTemplate.get(UserModel2.class, 0);  

  21.    Assert.assertEquals(model2.getMyName(), model.getMyName());  

  22.    List<UserModel2> list = hibernateTemplate.find("from UserModel2");  

  23.    Assert.assertEquals(list.get(0).getMyName(), model.getMyName());  

  24. }  

  25. private void update(HibernateTemplate hibernateTemplate, UserModel2 model) {  

  26.    model.setMyName("test2");  

  27.    hibernateTemplate.update(model);  

  28. }  

  29. private void delete(HibernateTemplate hibernateTemplate, UserModel2 model) {  

  30.    hibernateTemplate.delete(model);  

  31. }  

      Spring集成Hibernate进行增删改查是不是比Spring JDBC方式简单许多,而且支持注解方式配置映射元数据,从而减少映射定义配置文件数量。

本文链接:领悟书生教程网,转自http://sishuok.com/forum/blogPost/list/0/2497.html

相关问答

更多