Spring整合MyBatis

配置數(shù)據(jù)源

1.引入jdbc.properties配置文件

jdbc.properties

jdbc.url=jdbc:mysql://localhost:3306/mybatis?useUnicode=true&characterEncoding=utf-8&useSSL=false
jdbc.username=root
jdbc.password=root
jdbc.driver=com.mysql.jdbc.Driver
jdbc.init=1
jdbc.minIdle=1
jdbc.maxActive=3

2.整合Spring配置文件和properties配置文件

applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:aop="http://www.springframework.org/schema/aop"

       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                           http://www.springframework.org/schema/beans/spring-beans.xsd
                           http://www.springframework.org/schema/context
                           http://www.springframework.org/schema/context.spring-context.xsd">
        <context:property-placeholder location="jdbc.properties"/>
        <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
                <!--基本配置-->
                <property name="driverClassName" value="${jdbc.driver}"/>
                <property name="url" value="${jdbc.url}"/>
                <property name="username" value="${jdbc.username}"/>
                <property name="password" value="${jdbc.password}"/>

                <!--配置初始化大小,最小,最大-->
                <property name="initialSize" value="${jdbc.init}"/>
                <property name="minIdle" value="${jdbc.minIdle}"/>
                <property name="maxActive" value="${jdbc.maxActive}"/>

                <!--配置獲取連接等待超時(shí)的時(shí)間-->
                <property name="maxWait" value="60000"/>

                <!--配置間隔多久才進(jìn)行一次檢測(cè),檢測(cè)需要關(guān)閉的空閑連接,單位是毫秒-->
                <property name="timeBetweenEvictionRunsMillis" value="60000"/>

                <!--配置一個(gè)連接在池中最小生存的時(shí)間,單位是毫秒-->
                <property name="minEvictableIdleTimeMillis" value="300000"/>
        </bean>
</beans>

3.Druid連接池可選參數(shù)

    <!--配置初始化大小,最小,最大-->
                <property name="initialSize" value="${jdbc.init}"/>
                <property name="minIdle" value="${jdbc.minIdle}"/>
                <property name="maxActive" value="${jdbc.maxActive}"/>

                <!--配置獲取連接等待超時(shí)的時(shí)間-->
                <property name="maxWait" value="60000"/>

                <!--配置間隔多久才進(jìn)行一次檢測(cè),檢測(cè)需要關(guān)閉的空閑連接,單位是毫秒-->
                <property name="timeBetweenEvictionRunsMillis" value="60000"/>

                <!--配置一個(gè)連接在池中最小生存的時(shí)間,單位是毫秒-->
                <property name="minEvictableIdleTimeMillis" value="300000"/>

4.Druid監(jiān)控中心

web.xml

  <servlet>
      <servlet-name>DruidStatView</servlet-name>
      <servlet-class>com.alibaba.druid.support.http.StatViewServlet</servlet-class>
  </servlet>
  <servlet-mapping>
      <servlet-name>DruidStatView</servlet-name>
      <url-pattern>/druid/*</url-pattern>
  </servlet-mapping>

5.測(cè)試監(jiān)控中心

配置tomcat,并訪問(wèn)protocol://ip:port/project/druid/index.html

整合MyBatis

1.導(dǎo)入依賴

        <!--Spring整合MyBatis-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>1.3.2</version>
        </dependency>

        <!--MyBatis-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.5</version>
        </dependency>

        <!--mysql驅(qū)動(dòng)-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.47</version>
            <scope>runtime</scope>
        </dependency>

2.配置SqlSessionFactory

<!--生產(chǎn)SqlSessionFactory-->
        <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
               <!--注入連接池-->
                <property name="dataSource" ref="dataSource"/>
                <!--注冊(cè)mapper文件信息,如果映射文件和dao接口 同包且同名,則此配置可以省略-->
                <property name="mapperLocations">
                        <list>
                                <value>classpath:cn/ozl/dao/*.xml</value>
                        </list>
                </property>
                <!--為mapper文件中的實(shí)體定義缺省包路徑-->
                <property name="typeAliasesPackage" value="cn.ozl.entity"></property>
        </bean>

3.配置MapperScannerConfigurer

管理DAO實(shí)現(xiàn)類的創(chuàng)建,并創(chuàng)建DAO對(duì)象,存入工廠管理

  1. 掃描所有DAO接口,去構(gòu)建DAO實(shí)現(xiàn)
  2. 將DAO實(shí)現(xiàn)存入工廠管理
  3. DAO實(shí)現(xiàn)對(duì)象在工廠的id是:“首字母小寫(xiě)的接口類名”,例如UserDao=>userDao
 <bean id="mapperScannerConfigurer9" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
            <property name="basePackage" value="cn.ozl.dao"/>
            <!--只有一個(gè)SqlSessionFactory的bean可以省略-->
            <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
        </bean>

4.配置Service

<bean id="userService" class="cn.ozl.service.UserServiceImpl">
            <property name="userDao" ref="userDao"/>
        </bean>

事務(wù)

applicationContext.xml

  <!--引入一個(gè)事務(wù)管理器,其中依賴DataSource,借以獲得連接,進(jìn)而控制事務(wù)邏輯-->
        <bean id="tx" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
            <property name="dataSource" ref="dataSource"/>
         </bean>

        <!--事務(wù)通知-->
        <tx:advice id="txManager" transaction-manager="tx">
            <!--事務(wù)屬性-->
            <tx:attributes>
                <!--<tx:method name="queryUser" isolation="DEFAULT" propagation="SUPPORTS" read-only="true" timeout="-1" rollback-for="Exception"/>-->
                <tx:method name="queryUser"  propagation="SUPPORTS" />
                <!--<tx:method name="insertUser" isolation="DEFAULT" propagation="REQUIRED" read-only="false" timeout="-1" rollback-for="Exception"/>-->
                <tx:method name="*User"  rollback-for="Exception"/>
                <!--剩余的所有方法-->
                <tx:method name="*"/>
            </tx:attributes>
        </tx:advice>

        <!--編織 聲明式事務(wù)控制-->
        <aop:config>
            <aop:pointcut id="pzl_tx" expression="execution(* cn.ozl.service.UserServiceImpl.*(..))"/>
            <aop:advisor advice-ref="txManager" pointcut-ref="pzl_tx"/>
        </aop:config>

UserServiceImpl

public class UserServiceImpl implements UserService{
    private UserDao userDao;

    public UserDao getUserDao() {
        return userDao;
    }

    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }

    public List<User> queryUsers() {
        return userDao.queryUsers();
    }

    public void insertUser(User user) {
        userDao.insertUser(user);
    }

    public void updateUser(User user) {
        userDao.updateUser(user);
    }

    public Integer deleteUser(Integer id) {
        Integer integer=userDao.deleteUser(id);
        System.out.println(integer);
        if (1==1){
            try {
                throw new SQLException("test 事務(wù)");
            } catch (SQLException e) {
                e.printStackTrace();
                throw new RuntimeException("test 事務(wù)!!");
            }
        }
        return integer;
    }
}

test測(cè)試

  @Test
    public void testtx(){
        ApplicationContext context = new ClassPathXmlApplicationContext("/applicationContext.xml");
        UserService userService = (UserService) context.getBean("userService");
        userService.deleteUser(1002);
    }

1.配置DataSourceTransactionManager

事務(wù)管理器,其中持有DataSoure,可以控制事務(wù)功能(rollback,commit等)

  <!--引入一個(gè)事務(wù)管理器,其中依賴DataSource,借以獲得連接,進(jìn)而控制事務(wù)邏輯-->
        <bean id="tx" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
            <property name="dataSource" ref="dataSource"/>
         </bean>

注意:DataSourceTransactionManagerSqlSessionFactoryBean要注入同一個(gè)DataSourcebean,否則事務(wù)控制會(huì)失敗

2.配置事務(wù)通知

基于事務(wù)管理,進(jìn)一步控制,生成一個(gè)額外的功能:advice
此Advice可以切入任何的需要事務(wù)的方法,通過(guò)事務(wù)管理器為方法控制事務(wù)

 <!--事務(wù)通知-->
        <tx:advice id="txManager" transaction-manager="tx">
            <!--事務(wù)屬性-->
            <tx:attributes>
                <!--<tx:method name="queryUser" isolation="DEFAULT" propagation="SUPPORTS" read-only="true" timeout="-1" rollback-for="Exception"/>-->
                <tx:method name="queryUser"  propagation="SUPPORTS" />
                <!--<tx:method name="insertUser" isolation="DEFAULT" propagation="REQUIRED" read-only="false" timeout="-1" rollback-for="Exception"/>-->
                <tx:method name="*User"  rollback-for="Exception"/>
                <!--剩余的所有方法-->
                <tx:method name="*"/>
            </tx:attributes>
        </tx:advice>

3.事務(wù)屬性

3.1隔離級(jí)別

isolation

  1. default (默認(rèn)值)(采取數(shù)據(jù)庫(kù)的默認(rèn)設(shè)置)(建議)
  2. read-uncommited 讀未提交
  3. read-commited 讀提交
  4. repeatable-read 可重復(fù)讀
  5. serialized-read 序列化讀

隔離級(jí)別由低到高:read-uncommited<read-commited<repeatable-read<serialized-read

安全性:級(jí)別越高,多事務(wù)并發(fā)時(shí),越安全,因?yàn)楣蚕淼臄?shù)據(jù)越來(lái)越少,事務(wù)彼此之間干擾減少
并發(fā)性:級(jí)別越高,多事務(wù)并發(fā)時(shí),并發(fā)越差,因?yàn)楣蚕淼臄?shù)據(jù)越來(lái)越少,事務(wù)間阻塞情況增多

事務(wù)并發(fā)時(shí)的安全問(wèn)題

  1. 臟讀:一個(gè)事務(wù)讀取到另一個(gè)事務(wù)還未提交的數(shù)據(jù)
    大于read-uncommited可防止
  2. 不可重復(fù)讀:一個(gè)事務(wù)內(nèi)多次讀取一行數(shù)據(jù)的相同內(nèi)容,其結(jié)果不一致
    大于read-commited可防止
  3. 幻讀:一個(gè)事務(wù)內(nèi)多次讀取一張表中相同的內(nèi)容,其結(jié)果不一致
    大于repeatale-read可防止
<tx:method name="insertUser" isolation="DEFAULT" propagation="REQUIRED" read-only="false" timeout="-1" rollback-for="Exception"/>

3.2傳播行為

propagation

當(dāng)涉及到事務(wù)的嵌套(Service調(diào)用Service)中,可能存在的問(wèn)題

  1. SUPPORTS=不存在外部事務(wù),則不開(kāi)啟新的事務(wù),存在外部事務(wù),則合并到外部事務(wù)中(適合查詢)
  2. REQUIRED=不存在外部事務(wù),則開(kāi)啟事務(wù),存在外部事務(wù),則合并到外部事務(wù)中(默認(rèn)值)(適合增刪改)
<tx:method name="insertUser" isolation="DEFAULT" propagation="REQUIRED" read-only="false" timeout="-1" rollback-for="Exception"/>

3.3讀寫(xiě)性

readonly

  1. true:只讀,可提交查詢效率(適合查詢)
  2. false:可讀可寫(xiě) (默認(rèn)值)(適合增刪改)
<tx:method name="insertUser" isolation="DEFAULT" propagation="REQUIRED" read-only="false" timeout="-1" rollback-for="Exception"/>

3.4事務(wù)超時(shí)

timeout

當(dāng)事務(wù)所需操作的數(shù)據(jù)被其他事務(wù)占用,則等待

  1. 100:自定義等待時(shí)間100(秒)
  2. -1:由數(shù)據(jù)庫(kù)指定等待時(shí)間,默認(rèn)值(建議)
<tx:method name="insertUser" isolation="DEFAULT" propagation="REQUIRED" read-only="false" timeout="-1" rollback-for="Exception"/>

3.5事務(wù)回滾

rollback-for

  1. 如果事務(wù)中拋出 RuntimeException,則自動(dòng)回滾
  2. 如果事務(wù)中拋出 CheckException(非運(yùn)行時(shí)異常 Exception),不會(huì)自動(dòng)回滾,而是默認(rèn)提交事務(wù)
  3. 處理方案:將CheckException轉(zhuǎn)換成RuntimeException上拋,或設(shè)置rollback-for=“Exception”
<tx:method name="*User"  rollback-for="Exception"/>
   public Integer deleteUser(Integer id) {
        Integer integer=userDao.deleteUser(id);
        System.out.println(integer);
        if (1==1){
            try {
                throw new SQLException("test 事務(wù)");
            } catch (SQLException e) {
                e.printStackTrace();
                throw new RuntimeException("test 事務(wù)!!");
            }
        }
        return integer;
    }

4.編織

將管理的advice切入需要事務(wù)的業(yè)務(wù)中

  <!--編織 聲明式事務(wù)控制-->
        <aop:config>
            <aop:pointcut id="pzl_tx" expression="execution(* cn.ozl.service.UserServiceImpl.*(..))"/>
            <aop:advisor advice-ref="txManager" pointcut-ref="pzl_tx"/>
        </aop:config>
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容