spring結(jié)合hibernate示例詳解
單純Hibernate程序
1、首先是導(dǎo)入hibernate的jar包。
2、 建立用戶和用戶操作記錄實(shí)體,Log.Java和User.java。代碼如下所示。
Log.java
import java.util.Date;
public class Log {
private int id;
//日志的類別.日志一般起到一個(gè)不可否認(rèn)性.
//操作日志 安全日志 事件日志.
private String type;
private String detail;
private Date time;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getDetail() {
return detail;
}
public void setDetail(String detail) {
this.detail = detail;
}
public Date getTime() {
return time;
}
public void setTime(Date time) {
this.time = time;
}
}
User.java
public class User {
private int id;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
3、 并建立與之對(duì)應(yīng)的實(shí)體配置文件,Log.hbm.xml和Use.hbm.xml。代碼如下所示。
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.bjpowernode.usermgr.domain.User" table="t_user">
<id name="id" >
<generator class="native"/>
</id>
<property name="name" />
</class>
</hibernate-mapping>
Log.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.bjpowernode.usermgr.domain.Log" table="t_log">
<id name="id" >
<generator class="native"/>
</id>
<property name="type" />
<property name="detail" />
<property name="time" />
</class>
</hibernate-mapping>
4、Manager層代碼如下所示。
LogManager.java接口
public interface LogManager {
//添加日志.方法
public void addLog(Log log);
}
LogManagerImpl實(shí)現(xiàn)
public class LogManagerImpl implements LogManager {
@Override
public void addLog(Log log) {
HibernateUtils.getSessionFactory().getCurrentSession().save(log);
}
}
UserManager接口
public interface UserManager {
public void addUser(User user);
}
UserManagerImpl.java實(shí)現(xiàn)
public class UserManagerImpl implements UserManager {
@Override
public void addUser(User user) {
Session session = null;
try {
//這個(gè)session中是放到threadlocal.
session = HibernateUtils.getSessionFactory().getCurrentSession();
session.beginTransaction();
// 網(wǎng)用戶表中添加一條同時(shí)網(wǎng)日志中添加一條.
session.save(user);
Log log = new Log();
log.setType("操作日志");
log.setTime(new Date());
log.setDetail("xxx");
LogManager logManager = new LogManagerImpl();
//添加日志.
logManager.addLog(log);
session.getTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally{
HibernateUtils.closeSession(session);
}
}
}
5、是通過(guò)sessionFactory來(lái)創(chuàng)建session,通過(guò)session來(lái)開(kāi)啟提交和關(guān)閉回滾事務(wù),我們把session的開(kāi)啟關(guān)閉封裝到一個(gè)工具類中。HibernateUtils.java代碼如下所示。
public class HibernateUtils {
private static SessionFactory factory;
static {
try {
//讀取hibernate.cfg.xml文件
Configuration cfg = new Configuration().configure();
//建立SessionFactory
factory = cfg.buildSessionFactory();
}catch(Exception e) {
e.printStackTrace();
}
}
public static Session getSession() {
return factory.openSession();
}
public static void closeSession(Session session) {
if (session != null) {
if (session.isOpen()) {
session.close();
}
}
}
public static SessionFactory getSessionFactory() {
return factory;
}
}
6、配置hibernate.cfg.xml文件,包括數(shù)據(jù)庫(kù)名稱,數(shù)據(jù)庫(kù)關(guān)聯(lián)的表,以及用戶名密碼等。代碼如下所示。
<hibernate-configuration>
<session-factory>
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/spring_hibernate_1</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password">root</property>
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="hibernate.show_sql">true</property>
<property name="hibernate.hbm2ddl.auto">update</property>
<property name="hibernate.current_session_context_class">thread</property>
<!--
<property name="hibernate.current_session_context_class">jta</property>
-->
<mapping resource="com/bjpowernode/usermgr/domain/User.hbm.xml"/>
<mapping resource="com/bjpowernode/usermgr/domain/Log.hbm.xml"/>
</session-factory>
</hibernate-configuration>
7、 使用junit進(jìn)行單元測(cè)試,代碼如下所示。
import junit.framework.TestCase;
public class UserManagerImplTest extends TestCase {
public void testAddUser() {
UserManager userManager = new UserManagerImpl();
User user = new User();
user.setName("張三");
userManager.addUser(user);
}
}
在上述操作用,對(duì)事物的控制邊界在業(yè)務(wù)邏輯層,因?yàn)樵赨serManagerImpl中我們調(diào)用addUser()這一方法的同時(shí)要把這一操作寫(xiě)入到日志中,也就是調(diào)用了addLog()方法,而對(duì)于類的方法,一方法一session,一session一事務(wù),那么如果控制事務(wù)的呢?我們要執(zhí)行開(kāi)啟addUser()事務(wù)同時(shí)再開(kāi)啟addLog()事務(wù)嗎?在這里我們沒(méi)有再用以前的openSession方法,選擇用的HibernateUtils.getSessionFactory().getCurrentSession();同時(shí)在hibernate.cfg.xml中對(duì)getCurrentSession()進(jìn)行配置如下, <propertyname="hibernate.current_session_context_class">thread</property>表示在當(dāng)前線程中,與當(dāng)前線程綁定這樣執(zhí)行addUser()方法和addLog()方法使用的是同一個(gè)事務(wù)。
那OpenSession和getCurrentSession的區(qū)別呢?
1、 openSession必須關(guān)閉,currentSession在事務(wù)結(jié)束后自動(dòng)關(guān)閉。
2、 openSession沒(méi)有和當(dāng)前線程綁定,currentSession和當(dāng)前線程綁定。并且使用currentSession需要在我們的hibernate.cfg.xml文件中進(jìn)行事務(wù)的配置,是使用Jdbc事務(wù)還是JTA事務(wù)。
hibernate和spring結(jié)合使用
我們從上述例子中發(fā)現(xiàn),hibernate的事務(wù)是獨(dú)立于hibernate對(duì)數(shù)據(jù)庫(kù)的增刪改查的,并且事務(wù)控制在我們的業(yè)務(wù)邏輯層,對(duì)于獨(dú)立的東西,像是橫切性問(wèn)題,自然想到了AOP,實(shí)際上SpringAOP封裝了對(duì)事務(wù)的管理,使用SpringAOP我們不再負(fù)責(zé)去開(kāi)啟和關(guān)閉事務(wù)。
下面用SpringAOP來(lái)和hibernate結(jié)合。
當(dāng)然也要導(dǎo)入Spring相關(guān)jar。
對(duì)于事務(wù)管理就是一個(gè)橫切性問(wèn)題,把事務(wù)管理模塊化就是我們的aspect,然后再配置文件中進(jìn)行配置,我們可以把事務(wù)單獨(dú)放到一個(gè)配置文件中。
1、代碼如下,applicationContext-common.xml文件。
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd">
<!-- 配置SessionFactoyr -->
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="configLocation">
<value>classpath:hibernate.cfg.xml</value>
</property>
</bean>
<!-- 配置事務(wù)管理器 -->
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory">
<ref bean="sessionFactory"/>
</property>
</bean>
<!-- 哪些類哪些方法使用事務(wù). -->
<aop:config>
<aop:pointcut id="allManagerMethod" expression="execution(* com.bjpowernode.usermgr.manager.*.*(..))"/>
<aop:advisor pointcut-ref="allManagerMethod" advice-ref="txAdvice"/>
</aop:config>
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="add*" propagation="REQUIRED"/>
<tx:method name="del*" propagation="REQUIRED"/>
<tx:method name="modify*" propagation="REQUIRED"/>
<tx:method name="*" propagation="REQUIRED" read-only="true"/>
</tx:attributes>
</tx:advice>
</beans>
首先是配置的是sessionFactory,讓spring拿到hibernate的sessionFactory,以便對(duì)hibernate事務(wù)控制,通過(guò)sessionFactory產(chǎn)生session再訪問(wèn)。這樣就把把hibernate的sessionFactory注入到Spring中了。通過(guò)<property>標(biāo)簽,告訴SpringHibernate的配置文件在哪里,以便spring可以讀取hibernate的配置文件。
其次是配置事務(wù)管理器,把我們的sessionFactory注入給事務(wù)管理器,讓事務(wù)管理器管理事務(wù)。
其次,到底是哪些類哪些方法,開(kāi)始執(zhí)行的時(shí)候執(zhí)行事務(wù),<aop:pointcutid="allManagerMethod"
其次,配置AOP,expression="execution(*com.bjpowernode.usermgr.manager.*.*(..))",到底是哪些類交給spring完成事務(wù)管理?我們應(yīng)用在所有的manager包中的所有方法上,manager所有類所有方法全部參與事務(wù)的運(yùn)行。那在什么地方觸發(fā)開(kāi)啟事務(wù)?
再次,定義一個(gè)Advice,配置事務(wù)的傳播特性,例如addUser()中調(diào)用addLog()方法,是在同一個(gè)事務(wù)還是不在同一個(gè)事務(wù)。以add開(kāi)頭,del開(kāi)頭,modify開(kāi)頭以及其他,我們配置的事務(wù)傳播特性為propagation="REQUIRED",這樣在一個(gè)方法中調(diào)用另一個(gè)方法他們公共一個(gè)線程。
2、讓UserManagerImpl繼承spring提供的對(duì)hibernateDao支持類。
HibernateDaoSupport,這樣繼承之后我們就能拿到session,其實(shí)也就是hibernate中的session,只不過(guò)spring為我們封裝了。我們可以這樣拿到sesion:This.getSession().save(user);或者使用spring封裝好的對(duì)象:
This.getHibernateTemplate().save(user);這樣都封裝到里面了,我們不管理事務(wù)的開(kāi)啟和關(guān)閉。
之前在我們的UserManagerImpl中使用了LogManagerImpl實(shí)例,這次我們可以使用Spring的IOC容器,把他們之間的依賴關(guān)系注入到Spring中,這樣就看不到實(shí)例,面對(duì)接口編程,進(jìn)行了解耦。
接口不變,UserManagerImpl.java代碼如下所示。
public class UserManagerImpl extends HibernateDaoSupport implements UserManager {
private LogManager logManager;
public void setLogManager(LogManager logManager)
{
this.logManager = logManager;
}
@Override
public void addUser(User user)throws Exception {
//this.getSession().save(user);
//或者用.
this.getHibernateTemplate().save(user);
Log log = new Log();
log.setType("操作日志");
log.setTime(new Date());
log.setDetail("xxx");
//LogManager logManager = new LogManagerImpl();
//添加日志.
logManager.addLog(log);
//運(yùn)行期的異常,會(huì)回滾. 并且是他的子類也會(huì)回滾.
//throw new RuntimeException();
//throw new Exception();
}
}
LogManagerImpl.java 代碼如下所示。
public class LogManagerImpl extends HibernateDaoSupport implements LogManager {
@Override
public void addLog(Log log) {
//getSession().save(log);
this.getHibernateTemplate().save(log);
}
}
刪除我們自己建立的HibernateUtils.java類,刪除hibernate.cfg.xml文件中對(duì)getCurrentSession()的事務(wù)配置。
3、在配置文件中配置依賴關(guān)系。
applicationContext-beans.xml代碼如下所示。
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd">
<bean id="userManager" class="com.bjpowernode.usermgr.manager.UserManagerImpl">
<property name="sessionFactory" ref="sessionFactory"/>
<property name="logManager" ref="logManager"/>
</bean>
<bean id="logManager" class="com.bjpowernode.usermgr.manager.LogManagerImpl">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
</beans>
在Junit中測(cè)試程序代碼如下所示。
public class UserManagerImplTest extends TestCase {
public void testAddUser() {
BeanFactory factory = new ClassPathXmlApplicationContext("applicationContext-*.xml");
UserManager userManager = (UserManager) factory.getBean("userManager");
User user = new User();
user.setName("張三");
try {
userManager.addUser(user);
} catch (Exception e) {
e.printStackTrace();
}
}
}
顯示結(jié)果如下圖所示。

這樣就完成了spring和hibernate的結(jié)合,主要是利用SpringAOP對(duì)hibernate的事務(wù)進(jìn)行控制和在Manager層之間的調(diào)用用Spring IOC進(jìn)行控制。
總結(jié)
以上所述是小編給大家介紹的spring結(jié)合hibernate示例詳解,希望對(duì)大家有所幫助,如果大家有任何疑問(wèn)請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!
相關(guān)文章
idea將maven項(xiàng)目改成Spring boot項(xiàng)目的方法步驟
這篇文章主要介紹了idea將maven項(xiàng)目改成Spring boot項(xiàng)目的方法步驟,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-09-09
SpringCloud Feign Jackson自定義配置方式
這篇文章主要介紹了SpringCloud Feign Jackson自定義配置方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-03-03
詳解lombok @Getter @Setter 使用注意事項(xiàng)
這篇文章主要介紹了詳解lombok @Getter @Setter 使用注意事項(xiàng),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-11-11
IDEA中Mybatis的MGB使用逆向工程配置的詳細(xì)教程
這篇文章主要介紹了IDEA中Mybatis的MGB使用逆向工程配置,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-09-09
SpringBoot接收LocalDateTime參數(shù)的方式
這篇文章主要介紹了SpringBoot接收LocalDateTime參數(shù)的方式,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),感興趣的朋友跟隨小編一起看看吧2024-08-08
詳解Spring Cloud Zuul 服務(wù)網(wǎng)關(guān)
本篇文章主要介紹了詳解Spring Cloud Zuul 服務(wù)網(wǎng)關(guān),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-12-12
SpringMVC + jquery.uploadify實(shí)現(xiàn)上傳文件功能
文件上傳是很多項(xiàng)目都會(huì)使用到的功能,SpringMVC當(dāng)然也提供了這個(gè)功能。不過(guò)小編不建議在項(xiàng)目中通過(guò)form表單來(lái)提交文件上傳,這樣做的局限性很大。下面這篇文章主要介紹了利用SpringMVC + jquery.uploadify實(shí)現(xiàn)上傳文件功能的相關(guān)資料,需要的朋友可以參考下。2017-06-06
完美解決request請(qǐng)求流只能讀取一次的問(wèn)題
這篇文章主要介紹了完美解決request請(qǐng)求流只能讀取一次的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-08-08

