javascript
跟我学Spring3(8.2):对ORM的支持之集成Hibernate3
8.2? 集成Hibernate3
Hibernate是全自動(dòng)的ORM框架,能自動(dòng)為對(duì)象生成相應(yīng)SQL并透明的持久化對(duì)象到數(shù)據(jù)庫(kù)。
Spring2.5+版本支持Hibernate 3.1+版本,不支持低版本,Spring3.0.5版本提供對(duì)Hibernate 3.6.0 Final版本支持。
8.2.1? 如何集成
Spring通過使用如下Bean進(jìn)行集成Hibernate:
- LocalSessionFactoryBean :用于支持XML映射定義讀取:
configLocation和configLocations:用于定義Hibernate配置文件位置,一般使用如classpath:hibernate.cfg.xml形式指定;
mappingLocations :用于指定Hibenate映射文件位置,如chapter8/hbm/user.hbm.xml;
hibernateProperties:用于定義Hibernate屬性,即Hibernate配置文件中的屬性;
dataSource:定義數(shù)據(jù)源;
hibernateProperties、dataSource用于消除Hibernate配置文件,因此如果使用configLocations指定配置文件,就不要設(shè)置這兩個(gè)屬性了,否則會(huì)產(chǎn)生重復(fù)配置。推薦使用dataSource來指定數(shù)據(jù)源,而使用hibernateProperties指定Hibernate屬性。
- AnnotationSessionFactoryBean:用于支持注解風(fēng)格映射定義讀取,該類繼承LocalSessionFactoryBean并額外提供自動(dòng)查找注解風(fēng)格配置模型的能力:
annotatedClasses:設(shè)置注解了模型類,通過注解指定映射元數(shù)據(jù)。
packagesToScan:通過掃描指定的包獲取注解模型類,而不是手工指定,如“cn.javass.**.model”將掃描cn.javass包及子包下的model包下的所有注解模型類。
接下來學(xué)習(xí)一下Spring如何集成Hibernate吧:
1、準(zhǔn)備jar包:
首先準(zhǔn)備Spring對(duì)ORM框架支持的jar包:
| org.springframework.orm-3.0.5.RELEASE.jar? //提供對(duì)ORM框架集成 |
下載hibernate-distribution-3.6.0.Final包,獲取如下Hibernate需要的jar包:
|
下載slf4j-1.6.1.zip(http://www.slf4j.org/download.html),slf4j是日志系統(tǒng)門面(Simple Logging Facade for Java),用于對(duì)各種日志框架提供給一致的日志訪問接口,從而能隨時(shí)替換日志框架(如log4j、java.util.logging):
| slf4j-api-1.6.1.jar???????? ?????//核心API slf4j-log4j12-1.6.1.jar????????? //log4j實(shí)現(xiàn) |
將這些jar包添加到類路徑中。
2、對(duì)象模型定義,此處使用第七章中的UserModel:
java代碼:| 1 2 3 4 5 6 | package cn.javass.spring.chapter7; public class UserModel { ????private int id; ????private String myName; ????//省略getter和setter } |
3、Hibernate映射定義(chapter8/hbm/user.hbm.xml),定義對(duì)象和數(shù)據(jù)庫(kù)之間的映射:
java代碼:| 1 2 3 4 5 6 7 8 9 10 | <?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 class="native"/></id> ????????<property name="myName" column="name"/> ????</class> </hibernate-mapping> |
?
4、???數(shù)據(jù)源定義,此處使用第7章的配置文件,即“chapter7/applicationContext-resources.xml”文件。
5、???SessionFactory配置定義(chapter8/applicationContext-hibernate.xml):
java代碼:| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> ????<property name="dataSource" ref="dataSource"/> <!-- 指定數(shù)據(jù)源 --> ??????<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:
java代碼:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 | package cn.javass.spring.chapter8; //省略import public 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”數(shù)據(jù)源,通過ctx.getBean(“sessionFactory”, SessionFactory.class)獲取SessionFactory。
7、通過SessionFactory獲取Session對(duì)象進(jìn)行創(chuàng)建和刪除表:
java代碼:| 1 2 3 4 5 6 7 8 9 10 11 12 13 | @Before public 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(); } @After public void tearDown() { ????final String dropTableSql = "drop table test"; ????sessionFactory.openSession(). ????createSQLQuery(dropTableSql).executeUpdate(); } |
使用SessionFactory創(chuàng)建Session,然后通過Session對(duì)象的createSQLQuery創(chuàng)建本地SQL執(zhí)行創(chuàng)建和刪除表。
8、使用SessionFactory獲取Session對(duì)象進(jìn)行持久化數(shù)據(jù):
java代碼:| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | @Test public 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); ????} } |
| 1 2 3 4 5 6 7 8 9 10 11 12 13 | 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進(jìn)行操作,必須自己控制事務(wù),而且還要保證各個(gè)步驟不會(huì)出錯(cuò),有沒有更好的解決方案把我們從編程事務(wù)中解脫出來?Spring提供了HibernateTemplate模板類用來簡(jiǎn)化事務(wù)處理和常見操作。
8.2.2?使用HibernateTemplate
HibernateTimplate模板類用于簡(jiǎn)化事務(wù)管理及常見操作,類似于JdbcTemplate模板類,對(duì)于復(fù)雜操作通過提供HibernateCallback回調(diào)接口來允許更復(fù)雜的操作。
接下來示例一下HibernateTemplate的使用:
java代碼:| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | @Test public void testHibernateTemplate() { HibernateTemplate hibernateTemplate = new HibernateTemplate(sessionFactory); ????final UserModel model = new UserModel(); ????model.setMyName("myName"); ????hibernateTemplate.save(model); ????//通過回調(diào)允許更復(fù)雜操作 ????hibernateTemplate.execute(new HibernateCallback<Void>() { ????????@Override ????????public Void doInHibernate(Session session) ????????????throws HibernateException, SQLException { ????????????session.save(model); ????????????return null; ????????}}); } |
通過new HibernateTemplate(sessionFactory) 創(chuàng)建HibernateTemplate模板類對(duì)象,通過調(diào)用模板類的save方法持久化對(duì)象,并且自動(dòng)享受到Spring管理事務(wù)的好處。
而且HibernateTemplate 提供使用HibernateCallback回調(diào)接口的方法execute用來支持復(fù)雜操作,當(dāng)然也自動(dòng)享受到Spring管理事務(wù)的好處。
8.2.3? 集成Hibernate及最佳實(shí)踐
類似于JdbcDaoSupport類,Spring對(duì)Hibernate也提供了HibernateDaoSupport類來支持一致的數(shù)據(jù)庫(kù)訪問。HibernateDaoSupport也是DaoSupport實(shí)現(xiàn):
接下來示例一下Spring集成Hibernate的最佳實(shí)踐:
1、?定義Dao接口,此處使用cn.javass.spring.chapter7.dao. IUserDao:
2、?定義Dao接口實(shí)現(xiàn),此處是Hibernate實(shí)現(xiàn):
java代碼:| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | 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實(shí)現(xiàn)放在dao.hibernate包里,其次實(shí)現(xiàn)類命名如UserHibernateDaoImpl,即×××HibernateDaoImpl,當(dāng)然如果自己有更好的命名規(guī)范可以遵循自己的,此處只是提個(gè)建議。
3、進(jìn)行資源配置,使用resources/chapter7/applicationContext-resources.xml:
4、dao定義配置,在chapter8/applicationContext-hibernate.xml中添加如下配置:
java代碼:| 1 2 3 4 | <bean id="abstractDao" abstract="true"> ????<property name="sessionFactory" ref="sessionFactory"/> </bean>?? <bean id="userDao"? class="cn.javass.spring.chapter8.dao.hibernate.UserHibernateDaoImpl" parent="abstractDao"/> |
首先定義抽象的abstractDao,其有一個(gè)sessionFactory屬性,從而可以讓繼承的子類自動(dòng)繼承sessionFactory屬性注入;然后定義userDao,且繼承abstractDao,從而繼承sessionFactory注入;我們?cè)诖私o配置文件命名為applicationContext-hibernate.xml表示Hibernate實(shí)現(xiàn)。
5、?最后測(cè)試一下吧(cn.javass.spring.chapter8. HibernateTest):
java代碼:| 1 2 3 4 5 6 7 8 9 10 11 12 | @Test public 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框架的最佳實(shí)踐完全一樣,除了使用applicationContext-hibernate.xml代替了applicationContext-jdbc.xml,其他完全一樣。也就是說,DAO層的實(shí)現(xiàn)替換可以透明化。
8.2.4? Spring+Hibernate的CRUD
Spring+Hibernate CRUD(增刪改查)我們使用注解類來示例,讓我們看具體示例吧:
1、首先定義帶注解的模型對(duì)象UserModel2:
- 使用JPA注解@Table指定表名映射;
- 使用注解@Id指定主鍵映射;
- 使用注解@ Column指定數(shù)據(jù)庫(kù)列映射;
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | 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屬性指定注解模型來定義映射元數(shù)據(jù);
java代碼:| 1 2 3 4 5 6 7 8 9 10 11 12 13 | <bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"> <property name="dataSource" ref="dataSource"/>? <!-- 1、指定數(shù)據(jù)源 --> ??<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?:
java代碼:| 1 2 3 | <bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate"> ????<property name="sessionFactory" ref="sessionFactory"/> </bean> |
3、最后進(jìn)行CURD測(cè)試吧:
java代碼:| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | @Test public 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進(jìn)行增刪改查是不是比Spring JDBC方式簡(jiǎn)單許多,而且支持注解方式配置映射元數(shù)據(jù),從而減少映射定義配置文件數(shù)量。
《新程序員》:云原生和全面數(shù)字化實(shí)踐50位技術(shù)專家共同創(chuàng)作,文字、視頻、音頻交互閱讀總結(jié)
以上是生活随笔為你收集整理的跟我学Spring3(8.2):对ORM的支持之集成Hibernate3的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: hibernate实现增删改查的各种方法
- 下一篇: Hibernate标识符属性(主键)生成