7税产、spring與hibernate的集成(spring筆記)

一、spring和Hibernate的集成(編程式事務(wù))(工程spring_hibernate_1

1.1 openSession

就是session = HibernateUtils.getSession();獲得的session偷崩。如果有多個類使用該方法獲得session辟拷,那么將會有多個session。

1.2 currentSession

就是session = HibernateUtils.getSessionFactory().getCurrentSession();獲得當(dāng)前線程的session阐斜。這樣如果有多個類衫冻,就可以使用此方法獲得session達(dá)到同步的效果。

1.3 openSession和currentSession的區(qū)別

  • openSession必須關(guān)閉谒出,而currentSession在事務(wù)結(jié)束后自動關(guān)閉
  • openSession沒有和當(dāng)前線程綁定隅俘,currentSession和當(dāng)前線程綁定

1.4 如果使用currentSession需要在hibernate.cfg.xml文件中進(jìn)行配置

  • 如果是本地事務(wù)(jdbc事務(wù))
    <property name="hibernate.current_session_context_class">thread</property>

  • 如果是全局事務(wù)(jta事務(wù))
    <property name="hibernate.current_session_context_class">jta</property>

1.5 示例

實(shí)體類:
User.java

private int id;
private String name;

Log.java

private int id; 
//操作日志、安全日志到推、事件日志
private String type;
private String detail;
private Date time;

配置文件:
User.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 package="com.bjsxt.usermgr.model">
    <class name="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 package="com.bjsxt.usermgr.model">
    <class name="Log" table="t_log">
        <id name="id">
            <generator class="native"/>
        </id>
        <property name="type"/>
        <property name="detail"/>
        <property name="time"/>
    </class>
</hibernate-mapping>

UserManagerImpl.java

package com.bjsxt.usermgr.manager;
import java.util.Date;
import org.hibernate.Session;
import com.bjsxt.usermgr.model.Log;
import com.bjsxt.usermgr.model.User;
import com.bjsxt.usermgr.util.HibernateUtils;

public class UserManagerImpl implements UserManager {

    public void addUser(User user) {
        Session session = null;
        try {
            session = HibernateUtils.getSession();
            //session = HibernateUtils.getSessionFactory().getCurrentSession();
            session.beginTransaction();
            
            session.save(user);

            Integer.parseInt("asdfsdfsfsd");
            Log log = new Log();
            log.setType("安全日志");
            log.setDetail("xxx進(jìn)入系統(tǒng)");
            log.setTime(new Date());

            LogManager logManager = new LogManagerImpl();
            logManager.addLog(log);

            session.getTransaction().commit();
        }catch(Exception e) {
            e.printStackTrace();
            session.getTransaction().rollback();
        }finally {
            HibernateUtils.closeSession(session);
        }
    }
}

說明:

  • 1.上面我們使用的是傳統(tǒng)方式考赛,當(dāng)我們存入用戶之后再想要存入日志的時候,使用addLog(log);方法進(jìn)行保存日志莉测,但是在保存日志的時候我們需要一個session颜骤,同時我們注意到這兩個保存操作必須使用同一個session,當(dāng)然我們可以將session傳遞到日志記錄的業(yè)務(wù)類中捣卤,但是這樣hibernate就侵入到程序中了忍抽,在JavaEE中我們是使用的ThreadLocal類來保證這兩個操作使用的是同一個session,那么在hibernate中我們可以使用currentSession董朝,這個類就可以達(dá)到同步的效果鸠项。

  • 2.在程序中我們這樣得到currentSession:

session = HibernateUtils.getSessionFactory().getCurrentSession();

同時我們此時就不需要顯示關(guān)閉session了,同時在日志記錄業(yè)務(wù)類中我們也可以使用同樣的方法獲得當(dāng)前線程中的session子姜,實(shí)現(xiàn)同步祟绊。
LogManagerImpl.java

package com.bjsxt.usermgr.manager;
import com.bjsxt.usermgr.model.Log;
import com.bjsxt.usermgr.util.HibernateUtils;
public class LogManagerImpl implements LogManager {

    public void addLog(Log log) {
        HibernateUtils.getSessionFactory().getCurrentSession().save(log);
    }
}
  • 3.使用currentSession我們需要在hibernate的配置文件中進(jìn)行配置:
<!DOCTYPE hibernate-configuration PUBLIC
    "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
    "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">

<hibernate-configuration>
    <session-factory>
        <property name="hibernate.connection.url">jdbc:mysql://localhost/spring_hibernate_1</property>
        <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
        <property name="hibernate.connection.username">root</property>
        <property name="hibernate.connection.password">walp1314</property>
        <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
        <property name="hibernate.show_sql">true</property>
        
        <property name="hibernate.current_session_context_class">thread</property>
        <!-- 
        <property name="hibernate.current_session_context_class">jta</property>
         -->        
        <mapping resource="com/bjsxt/usermgr/model/User.hbm.xml"/>
        <mapping resource="com/bjsxt/usermgr/model/Log.hbm.xml"/>
    </session-factory>
</hibernate-configuration>

可以看到我們需要根據(jù)事務(wù)的類型配置currentSession,所謂本地事務(wù)哥捕,就是基于JDBC的事務(wù)牧抽,可以理解為ThreadLocal,或者叫針對一個數(shù)據(jù)庫的事務(wù)遥赚;而全局事務(wù)可以理解為針對多個數(shù)據(jù)庫的事務(wù)扬舒。

注意:本例子是模擬我們進(jìn)行某種操作時,日志系統(tǒng)進(jìn)行相應(yīng)的記錄工作凫佛,這兩個工作必須是同步的讲坎。

二孕惜、spring和Hibernate的集成(采用聲明式事務(wù))(工程spring_hibernate_2

2.1 spring事務(wù)的傳播特性

  • <1>PROPAGATION_REQUIRED 如果存在一個事務(wù),則支持當(dāng)前事務(wù)晨炕。如果沒有事務(wù)則開啟衫画,一般使用此傳播特性。

  • <2>PROPAGATION_SUPPORTS 如果存在一個事務(wù)府瞄,支持當(dāng)前事務(wù)碧磅。如果沒有事務(wù),則非事務(wù)的執(zhí)行遵馆,即不用事務(wù)。

  • <3>PROPAGATION_MANDATORY 如果已經(jīng)存在一個事務(wù)丰榴,支持當(dāng)前事務(wù)货邓。如果沒有一個活動的事務(wù),則拋出異常四濒。

  • <4>PROPAGATION_REQUIRES_NEW 總是開啟一個新的事務(wù)换况。如果一個事務(wù)已經(jīng)存在,則將這個存在的事務(wù)掛起盗蟆。

  • <5>PROPAGATION_NOT_SUPPORTED 總是非事務(wù)地執(zhí)行戈二,并掛起任何存在的事務(wù)。

  • <6>PROPAGATION_NEVER 總是非事務(wù)地執(zhí)行喳资,如果存在一個活動事務(wù)觉吭,則拋出異常。

  • <7>PROPAGATION_NESTED 如果一個活動的事務(wù)存在仆邓,則運(yùn)行在一個嵌套的事務(wù)中. 如果沒有活動事務(wù), 則按TransactionDefinition.PROPAGATION_REQUIRED屬性執(zhí)行(spring特有的

2.2 spring的隔離級別

  • <1>ISOLATION_DEFAULT 這是一個PlatfromTransactionManager默認(rèn)的隔離級別鲜滩,使用數(shù)據(jù)庫默認(rèn)的事務(wù)隔離級別。另外四個與JDBC的隔離級別相對應(yīng)节值。

  • <2>ISOLATION_READ_UNCOMMITTED 這是事務(wù)最低的隔離級別徙硅,它充許令外一個事務(wù)可以看到這個事務(wù)未提交的數(shù)據(jù)。這種隔離級別會產(chǎn)生臟讀搞疗,不可重復(fù)讀和幻像讀嗓蘑。

  • <3>ISOLATION_READ_COMMITTED 保證一個事務(wù)修改的數(shù)據(jù)提交后才能被另外一個事務(wù)讀取。另外一個事務(wù)不能讀取該事務(wù)未提交的數(shù)據(jù)匿乃。

  • <4>ISOLATION_REPEATABLE_READ 這種事務(wù)隔離級別可以防止臟讀桩皿,不可重復(fù)讀。但是可能出現(xiàn)幻像讀扳埂。它除了保證一個事務(wù)不能讀取另一個事務(wù)未提交的數(shù)據(jù)外业簿,還保證了避免下面的情況產(chǎn)生(不可重復(fù)讀)。

  • <5>ISOLATION_SERIALIZABLE 這是花費(fèi)最高代價但是最可靠的事務(wù)隔離級別阳懂。事務(wù)被處理為順序執(zhí)行梅尤。除了防止臟讀柜思,不可重復(fù)讀外,還避免了幻像讀巷燥。

2.3 示例

這里對于上面的示例我們不實(shí)用編程式事務(wù)了赡盘,而是交給spring進(jìn)行管理。首先需要配置sessionFactory缰揪、事務(wù)管理器陨享、事務(wù)的傳播特性和哪些類的哪些方法參與事務(wù),而這些配置我們一般放在一個公共的配置文件中:
applicationContext-common.xml

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

<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">
    <!-- 配置sessionFactory --><!-- 將相關(guān)配置注入到spring中 -->
    <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
        <property name="configLocation">
            <value>classpath:hibernate.cfg.xml</value>
        </property> 
    </bean>           
    
    <!-- 配置事務(wù)管理器 --><!-- 將sessionFactory注入到spring的事務(wù)管理器中 -->
    <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
        <property name="sessionFactory">
            <ref bean="sessionFactory"/>
        </property> 
    </bean>
    
    <!-- 配置事務(wù)的傳播特性 --><!-- 首先我們需要注入事務(wù)管理器 -->
    <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="*" read-only="true"/><!-- 其他方法設(shè)置為只讀钝腺,可以提高效率 -->
        </tx:attributes>
    </tx:advice>
    
    <!-- 哪些類的哪些方法參與事務(wù) -->
    <aop:config>
        <aop:pointcut id="allManagerMethod" expression="execution(* com.bjsxt.usermgr.manager.*.*(..))"/>
        <aop:advisor pointcut-ref="allManagerMethod" advice-ref="txAdvice"/>
    </aop:config>
</beans>

說明:對于將hibernate的配置文件注入到spring中時的classpath是spring實(shí)現(xiàn)的一個協(xié)議抛姑,讓spring可以找到hibernate的配置文件,于是我們hibernate的配置文件也可以不用默認(rèn)的名字艳狐。

對于需要注入sessionFactory的業(yè)務(wù)類我們可以單獨(dú)在一個配置文件中進(jìn)行配置:
applicationContext-beans.xml

<?xml version="1.0" encoding="UTF-8"?>
<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.bjsxt.usermgr.manager.UserManagerImpl">
        <property name="sessionFactory" ref="sessionFactory"/>
        <property name="logManager" ref="logManager"/>
    </bean>
    
    <bean id="logManager" class="com.bjsxt.usermgr.manager.LogManagerImpl">
        <property name="sessionFactory" ref="sessionFactory"/>
    </bean>
</beans>

hibernate.cfg.xml

<!DOCTYPE hibernate-configuration PUBLIC
    "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
    "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">

<hibernate-configuration>
<session-factory>
    <property name="hibernate.connection.url">jdbc:mysql://localhost/spring_hibernate_2</property>
    <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
    <property name="hibernate.connection.username">root</property>
    <property name="hibernate.connection.password">walp1314</property>
    <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
    <property name="hibernate.show_sql">true</property>
    <property name="hibernate.current_session_context_class">thread</property>
    <!-- 
        <property name="hibernate.current_session_context_class">jta</property>
    -->
    <property name="dialect"></property>
    <mapping resource="com/bjsxt/usermgr/model/User.hbm.xml" />
    <mapping resource="com/bjsxt/usermgr/model/Log.hbm.xml" />
</session-factory>
</hibernate-configuration>

此時我們在業(yè)務(wù)類中使用的時候就需要繼承spring的HibernateDaoSupport類:
UserManagerImpl.java

package com.bjsxt.usermgr.manager;
import java.util.Date;
import org.hibernate.Session;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import com.bjsxt.usermgr.model.Log;
import com.bjsxt.usermgr.model.User;
import com.bjsxt.usermgr.util.HibernateUtils;

public class UserManagerImpl extends HibernateDaoSupport implements UserManager {
    
    private LogManager logManager;
    
    public void addUser(User user) throws Exception {
        this.getHibernateTemplate().save(user);
        Log log = new Log();
        log.setType("安全日志");
        log.setDetail("xxx進(jìn)入系統(tǒng)");
        log.setTime(new Date());
        logManager.addLog(log);
        throw new Exception();
    }
    
    public void setLogManager(LogManager logManager) {
        this.logManager = logManager;
    }
}

LogManagerImpl.java

package com.bjsxt.usermgr.manager;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import com.bjsxt.usermgr.model.Log;
import com.bjsxt.usermgr.util.HibernateUtils;

public class LogManagerImpl extends HibernateDaoSupport implements LogManager {

    public void addLog(Log log) {
        this.getHibernateTemplate().save(log);
    }
}

測試:Client.java

package com.bjsxt.usermgr.client;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.bjsxt.usermgr.manager.UserManager;
import com.bjsxt.usermgr.manager.UserManagerImpl;
import com.bjsxt.usermgr.model.User;

public class Client {

    public static void main(String[] args) {
        User user = new User();
        user.setName("張三");
        
        BeanFactory factory = new ClassPathXmlApplicationContext("applicationContext-*.xml");
        UserManager userManager = (UserManager)factory.getBean("userManager");
        try {
            userManager.addUser(user);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

說明:在實(shí)際開發(fā)中我們一般使用注解的方式定硝,這在筆記(spring+struts2+Hibernate+maven+EasyUI開發(fā)環(huán)境搭建)中已經(jīng)說明了,這里不細(xì)說了毫目。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末蔬啡,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子镀虐,更是在濱河造成了極大的恐慌箱蟆,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,194評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件刮便,死亡現(xiàn)場離奇詭異空猜,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)诺核,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,058評論 2 385
  • 文/潘曉璐 我一進(jìn)店門抄肖,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人窖杀,你說我怎么就攤上這事漓摩。” “怎么了入客?”我有些...
    開封第一講書人閱讀 156,780評論 0 346
  • 文/不壞的土叔 我叫張陵管毙,是天一觀的道長。 經(jīng)常有香客問我桌硫,道長夭咬,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,388評論 1 283
  • 正文 為了忘掉前任铆隘,我火速辦了婚禮卓舵,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘膀钠。我一直安慰自己掏湾,他們只是感情好裹虫,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,430評論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著融击,像睡著了一般筑公。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上尊浪,一...
    開封第一講書人閱讀 49,764評論 1 290
  • 那天匣屡,我揣著相機(jī)與錄音,去河邊找鬼拇涤。 笑死捣作,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的工育。 我是一名探鬼主播虾宇,決...
    沈念sama閱讀 38,907評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼如绸!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起旭贬,我...
    開封第一講書人閱讀 37,679評論 0 266
  • 序言:老撾萬榮一對情侶失蹤怔接,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后稀轨,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體扼脐,經(jīng)...
    沈念sama閱讀 44,122評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,459評論 2 325
  • 正文 我和宋清朗相戀三年奋刽,在試婚紗的時候發(fā)現(xiàn)自己被綠了瓦侮。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,605評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡佣谐,死狀恐怖肚吏,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情狭魂,我是刑警寧澤罚攀,帶...
    沈念sama閱讀 34,270評論 4 329
  • 正文 年R本政府宣布,位于F島的核電站雌澄,受9級特大地震影響斋泄,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜镐牺,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,867評論 3 312
  • 文/蒙蒙 一炫掐、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧睬涧,春花似錦募胃、人聲如沸旗唁。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,734評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽逆皮。三九已至,卻和暖如春参袱,著一層夾襖步出監(jiān)牢的瞬間电谣,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,961評論 1 265
  • 我被黑心中介騙來泰國打工抹蚀, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留剿牺,地道東北人。 一個月前我還...
    沈念sama閱讀 46,297評論 2 360
  • 正文 我出身青樓环壤,卻偏偏與公主長得像晒来,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子郑现,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,472評論 2 348

推薦閱讀更多精彩內(nèi)容