首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 软件管理 > 软件架构设计 >

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

2012-06-30 
【第八章】 对ORM的支持 之 8.2 集成Hibernate3 ——跟我学spring3?8.2? 集成Hibernate3?????? Hibernate是全

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

?

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包:

package cn.javass.spring.chapter7;public class UserModel { private int id; private String myName; //省略getter和setter}

?

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

?

<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"><hibernate-mapping> <class name="cn.javass.spring.chapter7.UserModel" table="test"> <id name="id" column="id"><generator column="name"/> </class></hibernate-mapping>

?

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

?

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

?

<bean id="sessionFactory" ref="dataSource"/> <!-- 指定数据源 --> <property name="mappingResources"> <!-- 指定映射定义 --> <list> <value>chapter8/hbm/user.hbm.xml</value> </list> </property> <property name="hibernateProperties"> <!--指定Hibernate属性 --> <props> <prop key="hibernate.dialect"> org.hibernate.dialect.HSQLDialect </prop> </props> </property></bean>

?

6、???获取SessionFactory

?

package cn.javass.spring.chapter8;//省略importpublic class HibernateTest { private static SessionFactory sessionFactory; @BeforeClass public static void beforeClass() { String[] configLocations = new String[] { "classpath:chapter7/applicationContext-resources.xml", "classpath:chapter8/applicationContext-hibernate.xml"}; ApplicationContext ctx = new ClassPathXmlApplicationContext(configLocations); sessionFactory = ctx.getBean("sessionFactory", SessionFactory.class);}}

?

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

?

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

?

@Beforepublic void setUp() { //id自增主键从0开始 final String createTableSql = "create memory table test" + "(id int GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, " + "name varchar(100))"; sessionFactory.openSession(). createSQLQuery(createTableSql).executeUpdate();}@Afterpublic void tearDown() { final String dropTableSql = "drop table test"; sessionFactory.openSession(). createSQLQuery(dropTableSql).executeUpdate();}

?

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

?

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

?

@Testpublic void testFirst() { Session session = sessionFactory.openSession(); Transaction transaction = null; try { transaction = beginTransaction(session); UserModel model = new UserModel(); model.setMyName("myName"); session.save(model); } catch (RuntimeException e) { rollbackTransaction(transaction); throw e; } finally { commitTransaction(session); }}

?

?

private Transaction beginTransaction(Session session) { Transaction transaction = session.beginTransaction(); transaction.begin(); return transaction;}private void rollbackTransaction(Transaction transaction) { if(transaction != null) { transaction.rollback(); }}private void commitTransaction(Session session) { session.close();}

?

?

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

?8.2.2?使用HibernateTemplate

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

?

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

?

@Testpublic void testHibernateTemplate() {HibernateTemplate hibernateTemplate =new HibernateTemplate(sessionFactory); final UserModel model = new UserModel(); model.setMyName("myName"); hibernateTemplate.save(model); //通过回调允许更复杂操作 hibernateTemplate.execute(new HibernateCallback<Void>() { @Override public Void doInHibernate(Session session) throws HibernateException, SQLException { session.save(model); return null; }});}

?

通过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实现:

?

package cn.javass.spring.chapter8.dao.hibernate;import org.springframework.orm.hibernate3.support.HibernateDaoSupport;import cn.javass.spring.chapter7.UserModel;import cn.javass.spring.chapter7.dao.IUserDao;public class UserHibernateDaoImpl extends HibernateDaoSupport implements IUserDao { private static final String COUNT_ALL_HQL = "select count(*) from UserModel"; @Override public void save(UserModel model) { getHibernateTemplate().save(model); } @Override public int countAll() { Number count = (Number) getHibernateTemplate().find(COUNT_ALL_HQL).get(0); return count.intValue(); }}

?

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

?

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

?

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

?

?

<bean id="abstractDao" abstract="true"> <property name="sessionFactory" ref="sessionFactory"/></bean> <bean id="userDao" parent="abstractDao"/>

?

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

?

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

?

@Testpublic void testBestPractice() { String[] configLocations = new String[] { "classpath:chapter7/applicationContext-resources.xml", "classpath:chapter8/applicationContext-hibernate.xml"}; ApplicationContext ctx = new ClassPathXmlApplicationContext(configLocations); IUserDao userDao = ctx.getBean(IUserDao.class); UserModel model = new UserModel(); model.setMyName("test"); userDao.save(model); Assert.assertEquals(1, userDao.countAll());}

?

?

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

?8.2.4? Spring+Hibernate的CRUD

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

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

使用JPA注解@Table指定表名映射;使用注解@Id指定主键映射;使用注解@ Column指定数据库列映射;

?

package cn.javass.spring.chapter8;import javax.persistence.Column;import javax.persistence.Entity;import javax.persistence.GeneratedValue;import javax.persistence.GenerationType;import javax.persistence.Id;import javax.persistence.Table;@Entity@Table(name = "test")public class UserModel2 { @Id @GeneratedValue(strategy = GenerationType.AUTO) private int id; @Column(name = "name") private String myName; //省略getter和setter}

?

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

?

2.1、????????定义SessionFactory

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

?

<bean id="sessionFactory" ref="dataSource"/> <!-- 1、指定数据源 --> <property name="annotatedClasses"> <!-- 2、指定注解类 --> <list><value>cn.javass.spring.chapter8.UserModel2</value></list></property> <property name="hibernateProperties"><!-- 3、指定Hibernate属性 --> <props> <prop key="hibernate.dialect"> org.hibernate.dialect.HSQLDialect </prop> </props> </property></bean>

?

2.2、定义HibernateTemplate?

?

<bean id="hibernateTemplate" ref="sessionFactory"/></bean>

?

3、最后进行CURD测试吧:

?

@Testpublic void testCURD() { String[] configLocations = new String[] { "classpath:chapter7/applicationContext-resources.xml", "classpath:chapter8/applicationContext-hibernate2.xml"}; ApplicationContext ctx = new ClassPathXmlApplicationContext(configLocations); HibernateTemplate hibernateTemplate = ctx.getBean(HibernateTemplate.class); UserModel2 model = new UserModel2(); model.setMyName("test"); insert(hibernateTemplate, model); select(hibernateTemplate, model); update(hibernateTemplate, model); delete(hibernateTemplate, model);}private void insert(HibernateTemplate hibernateTemplate, UserModel2 model) { hibernateTemplate.save(model);}private void select(HibernateTemplate hibernateTemplate, UserModel2 model) { UserModel2 model2 = hibernateTemplate.get(UserModel2.class, 0); Assert.assertEquals(model2.getMyName(), model.getMyName()); List<UserModel2> list = hibernateTemplate.find("from UserModel2"); Assert.assertEquals(list.get(0).getMyName(), model.getMyName());}private void update(HibernateTemplate hibernateTemplate, UserModel2 model) { model.setMyName("test2"); hibernateTemplate.update(model);}private void delete(HibernateTemplate hibernateTemplate, UserModel2 model) { hibernateTemplate.delete(model);}

?

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

?

?

私塾在线原创内容 转载请注明出处【http://sishuok.com/forum/blogPost/list/0/2497.html】

?



哈哈 那就再发个
9 楼 lihu 2012-05-29   按照上面的配置,ApplicationContext ctx = new ClassPathXmlApplicationContext(configLocations); 执行报错 org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionFactory' defined in class path resource [applicationContext-hibernate.xml]: Invocation of init method failed; nested exception is java.lang.NullPointerException 请问是什么原因?

热点排行