Spring整合Mybatis方案一與AOP事務(wù)

方案一:使用絕對(duì)定位SQL的方式
手動(dòng)編寫(xiě)DAO接口和實(shí)現(xiàn)類
namespace+id定位動(dòng)態(tài)SQL

第一步:創(chuàng)建項(xiàng)目,導(dǎo)入依賴 mysql,mybatis,log4j,Spring
<meta charset="utf-8">


image.png

dbcp連接池依賴:


image.png

Mybatis的插件,資源拷貝,指定編譯版本。

第二步:插件生成表對(duì)應(yīng)的實(shí)體類和mapper映射文件
注意:mybatis的核心配置文件,可以整合到?jīng)]有


image.png

注意:
不生成DAO接口(非Mapper代理方式)
不生成Example
需要手動(dòng)編寫(xiě)DAO接口和實(shí)現(xiàn)類。

generatorConfig.xml 代碼如下 :

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE generatorConfiguration PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN" "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd" >
<generatorConfiguration >
<classPathEntry location="D:\Program Files\repository\mysql\mysql-connector-java\5.1.34\mysql-connector-java-5.1.34.jar" ></classPathEntry>
<context id="context1" >
<commentGenerator>

<property name="suppressAllComments" value="true" />
</commentGenerator>

<jdbcConnection driverClass="com.mysql.jdbc.Driver" connectionURL="jdbc:mysql://localhost:3306/testmybatis01?characterEncoding=utf-8" userId="root" password="zyh" />

<javaModelGenerator targetPackage="com.zyh.pojo" targetProject="src/main/java" />

<sqlMapGenerator targetPackage="com.zyh.mapper" targetProject="src/main/java" />



<table tableName="t_user_info" domainObjectName="UserInfo"
enableCountByExample="false"
enableUpdateByExample="false"
enableSelectByExample="false"
enableDeleteByExample="false">
</table>

</context>
</generatorConfiguration>

生成:只能點(diǎn)擊一次。 使用mybatis 自動(dòng)生成插件
注意:需要注意的地方如上配置文件所示: 取到了自動(dòng)生成 dao 以及 不自動(dòng)生成模板 example 。

image.png

第三步:開(kāi)發(fā)DAO接口和實(shí)現(xiàn)類

需要繼承整合類:extends org.mybatis.spring.support.SqlSessionDaoSupport
它可以幫助我們直接得到SqlSession
得到 SqlSession的方式,調(diào)用父類的方法getSqlSession()
this.getSqlSession()【需要注入: sqlSessionFactory】
不需要手動(dòng)關(guān)閉,容器管理

注意:事務(wù)不要用SqlSession直接提交。

Dao 如下所示 :
public interface UserInfoDao {
void addUserInfo(UserInfo userInfo);
void deleteUserinfo(Long aLong);
void updateUserInfo(UserInfo userInfo);
UserInfo queryUserInfoById(Long aLong);
List<UserInfo> queryUserInfoAll();
}

DaoImpl如下所示:
public class UserInfoDaoImpl extends SqlSessionDaoSupport implements UserInfoDao {
@Override
public void addUserInfo(UserInfo userInfo) {
getSqlSession().insert("com.zyh.mapper.UserInfoMapper.insert",userInfo);
}

@Override
public void deleteUserinfo(Long aLong) {
    getSqlSession().delete("com.zyh.mapper.UserInfoMapper.deleteByPrimaryKey",aLong);
}

@Override
public void updateUserInfo(UserInfo userInfo) {
    getSqlSession().update("com.zyh.mapper.UserInfoMapper.updateByPrimaryKeySelective",userInfo);
}

@Override
public UserInfo queryUserInfoById(Long aLong) {
    return getSqlSession().selectOne("com.zyh.mapper.UserInfoMapper.selectByPrimaryKey",aLong);
}

@Override
public List<UserInfo> queryUserInfoAll() {
    return  getSqlSession().selectList("com.zyh.mapper.UserInfoMapper.selectUserInfoAll");
}

}

通過(guò)源碼分析:可以只需要注入 SqlSessionFactory ,就可以得到SqlSession

第四步:配置整合持久層

使用Spring的核心配置文件替換Mybatis的核心配置文件。
同時(shí)由Spring來(lái)提供SqlSessionFactory

部分配置文件如下所示:

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="org.gjt.mm.mysql.Driver"></property>
<property name="url" value="jdbc:mysql:///testmybatis01?characterEncoding=utf-8"></property>
<property name="username" value="root"></property>
<property name="password" value="zyh"></property>
</bean>

<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">

<property name="dataSource" ref="dataSource"></property>

<property name="mapperLocations" value="classpath:com/zyh/mapper/*Mapper.xml"></property>
</bean>

<bean id="userInfoDao" class="com.zyh.dao.UserInfoDaoImpl">
<property name="sqlSessionFactory" ref="sqlSessionFactory"></property>
</bean>

配置整合:
1)連接池
org.gjt.mm.mysql.Driver
jdbc:mysql:///testmybatis01?characterEncoding=utf-8

image.png
  1. 創(chuàng)建SqlSessionFactory(由Spring提供)
    工廠org.mybatis.spring.SqlSessionFactoryBean


    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">

    <property name="dataSource" ref="dataSource"></property>

    <property name="mapperLocations" value="classpath:com/zyh/mapper/*Mapper.xml"></property>
    </bean>

含有注冊(cè)實(shí)體
源碼確認(rèn):這個(gè)工廠 Bean返回的對(duì)象是:SqlSessionFactory


image.png
  1. 把工廠注入給DAO(讓DAO具備得到SqlSession的能力)

    <bean id="userInfoDao" class="com.zyh.dao.UserInfoDaoImpl">
    <property name="sqlSessionFactory" ref="sqlSessionFactory"></property>
    </bean>


    image.png

第五步 : 測(cè)試 :
增刪改查如下所示: 都是成功的 輸出結(jié)果就不給大家截圖了。
public class testUserInfoDao {
@Test
public void testUserInfoDaoAdd(){
ClassPathXmlApplicationContext classPathXmlApplicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");
UserInfoDao userInfoDao = (UserInfoDao) classPathXmlApplicationContext.getBean("userInfoDao");
UserInfo userInfo=new UserInfo();
userInfo.setuName("張穎豪8/16");
userInfo.setuPass("魏雪8/16");
userInfoDao.addUserInfo(userInfo);
}
@Test
public void testUserInfoDaoUpdate(){
ClassPathXmlApplicationContext classPathXmlApplicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");
UserInfoDao userInfoDao = (UserInfoDao) classPathXmlApplicationContext.getBean("userInfoDao");
UserInfo userInfo=new UserInfo();
userInfo.setuId(138l);
userInfo.setuName("張穎豪xxx8/16");
userInfo.setuPass("魏雪xxx8/16");
userInfoDao.updateUserInfo(userInfo);
}
@Test
public void testFindUserInfoDao(){
ClassPathXmlApplicationContext classPathXmlApplicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");
UserInfoDao userInfoDao = (UserInfoDao) classPathXmlApplicationContext.getBean("userInfoDao");
UserInfo userInfo = userInfoDao.queryUserInfoById(138l);
Log.info(userInfo);
}
@Test
public void testUserInfoDaoDelete(){
ClassPathXmlApplicationContext classPathXmlApplicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");
UserInfoDao userInfoDao = (UserInfoDao) classPathXmlApplicationContext.getBean("userInfoDao");
userInfoDao.deleteUserinfo(138l);
}
@Test
public void testQueryAll(){
ClassPathXmlApplicationContext classPathXmlApplicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");
UserInfoDao userInfoDao = (UserInfoDao) classPathXmlApplicationContext.getBean("userInfoDao");
List<UserInfo> userInfos = userInfoDao.queryUserInfoAll();
Log.info(userInfos);
}
}

AOP事務(wù)(由Spring提供)

不用自己編寫(xiě)事務(wù)通知類

一般是在服務(wù)層加AOP事務(wù)。不是在持久層加。


image.png

優(yōu)化:


image.png

添加服務(wù)層,在服務(wù)層加AOP事務(wù)。

事務(wù)傳遞到持久層
使用Spring事務(wù)通知類整合

聲明式事務(wù)
事務(wù)管理
傳統(tǒng)方式:手動(dòng)編碼在業(yè)務(wù)邏輯層控制事務(wù)
采取AOP的方式實(shí)現(xiàn)聲明式事務(wù)
頂級(jí)接口:(事務(wù)通知類)
org.springframework.transaction.PlatformTransactionManager
Mybatis操作數(shù)據(jù)庫(kù)事務(wù),使用Spring 的JDBC事務(wù)控制類。
實(shí)現(xiàn)類:
org.springframework.jdbc.datasource.DataSourceTransactionManager

第六步:開(kāi)發(fā)服務(wù)層接口和實(shí)現(xiàn)類
public interface UserService {
void addUserInfo(UserInfo userInfo);
void deleteUserinfo(Long aLong);
void updateUserInfo(UserInfo userInfo);
UserInfo queryUserInfoById(Long aLong);
List<UserInfo> queryUserInfoAll();
void updateAll(UserInfo addUserInfo,UserInfo updateInfo);
}

實(shí)現(xiàn)類如下所示:

public class UserServiceImpl implements UserService {

private UserInfoDaoImpl userInfoDao;

public void setUserInfoDao(UserInfoDaoImpl userInfoDao) {
    this.userInfoDao = userInfoDao;
}

@Override
public void addUserInfo(UserInfo userInfo) {
    userInfoDao.addUserInfo(userInfo);
}

@Override
public void deleteUserinfo(Long aLong) {
    userInfoDao.deleteUserinfo(aLong);
}

@Override
public void updateUserInfo(UserInfo userInfo) {
    userInfoDao.updateUserInfo(userInfo);
}

@Override
public UserInfo queryUserInfoById(Long aLong) {

    return userInfoDao.queryUserInfoById(aLong);
}

@Override
public List<UserInfo> queryUserInfoAll() {
    return userInfoDao.queryUserInfoAll();
}
@Override
public void  updateAll(UserInfo addUserInfo,UserInfo updateInfo){

    userInfoDao.addUserInfo(addUserInfo);
    userInfoDao.updateUserInfo(updateInfo);
}

}

第七步:配置整合AOP事務(wù)
思路:事務(wù)管理器->事務(wù)通知切面->通知者
事務(wù)頂級(jí)接口:

image.png

總的配置文件如下所示:

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="org.gjt.mm.mysql.Driver"></property>
<property name="url" value="jdbc:mysql:///testmybatis01?characterEncoding=utf-8"></property>
<property name="username" value="root"></property>
<property name="password" value="zyh"></property>
</bean>

<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">

<property name="dataSource" ref="dataSource"></property>

<property name="mapperLocations" value="classpath:com/zyh/mapper/*Mapper.xml"></property>
</bean>

<bean id="userInfoDao" class="com.zyh.dao.UserInfoDaoImpl">
<property name="sqlSessionFactory" ref="sqlSessionFactory"></property>
</bean>

<!-- 4,創(chuàng)建服務(wù)層對(duì)象,注入DAO 目標(biāo)類對(duì)象-->
<bean id="userInfoService" class="com.zyh.service.UserServiceImpl">
    <property name="userInfoDao" ref="userInfoDao"></property>
</bean>
<!-- 5,創(chuàng)建事務(wù)管理通知類對(duì)象-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <!-- 注入數(shù)據(jù)源-->
    <property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 6,定義事務(wù)通知切面,讓事務(wù)應(yīng)用到具體的方法 -->
<tx:advice id="myAdvice" transaction-manager="transactionManager">
    <tx:attributes>
        <tx:method name="add*" propagation="REQUIRED"/>
        <tx:method name="delete*" propagation="REQUIRED"/>
        <tx:method name="update*" propagation="REQUIRED"/>
        <tx:method name="query*" read-only="true"/>
    </tx:attributes>
</tx:advice>
<!-- 7,AOP編程:讓切入點(diǎn)和通知關(guān)聯(lián)形成切面 -->
<aop:config>
    <aop:pointcut id="myPoint" expression="execution(* com.zyh.service.*.*(..))"></aop:pointcut>
    <aop:advisor advice-ref="myAdvice"  pointcut-ref="myPoint"></aop:advisor>
</aop:config>

aop全自動(dòng)編程:tx:method指向服務(wù)層的方法。
Mybatis有的版本底層可以自動(dòng)提交事務(wù),從服務(wù)層的角度,必須加上AOP事務(wù)配置。【我們這個(gè)版本沒(méi)有這個(gè)問(wèn)題】

第八步:測(cè)試

測(cè)試方法如下所示:
public class testUserInfoTransaction {
@Test
public void testtransaction(){
ClassPathXmlApplicationContext classPathXmlApplicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");
UserService userInfoService = (UserService) classPathXmlApplicationContext.getBean("userInfoService");
UserInfo addUserInfo=new UserInfo();
addUserInfo.setuName("我是新添加的用戶名");
addUserInfo.setuPass("我是新添加的密碼");
UserInfo updateUserInfo=new UserInfo();
updateUserInfo.setuId(12l);
updateUserInfo.setuName("事物增加");
updateUserInfo.setuPass("事物增加");
userInfoService.updateAll(addUserInfo,updateUserInfo);
}
}

在實(shí)現(xiàn)類中的方法如下所示: 可以看到 第一條和第二條語(yǔ)句中間有個(gè)異常產(chǎn)生
當(dāng)我們沒(méi)有做事物處理的前后 得出的結(jié)果是完全不一致的。

@Override
public void  updateAll(UserInfo addUserInfo,UserInfo updateInfo){

    userInfoDao.addUserInfo(addUserInfo);
    int i=1/0;
    userInfoDao.updateUserInfo(updateInfo);
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,156評(píng)論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,401評(píng)論 3 415
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事。” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 176,069評(píng)論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 62,873評(píng)論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,635評(píng)論 6 408
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 55,128評(píng)論 1 323
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,203評(píng)論 3 441
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 42,365評(píng)論 0 288
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,881評(píng)論 1 334
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,733評(píng)論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,935評(píng)論 1 369
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,475評(píng)論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,172評(píng)論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 34,582評(píng)論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 35,821評(píng)論 1 282
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,595評(píng)論 3 390
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,908評(píng)論 2 372

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