Loading

Spring整合Mybatis

一. 简单实现Mybatis

  1. 导入相关依赖(pom.xml)

    <dependency>
       <groupId>org.mybatis</groupId>
       <artifactId>mybatis</artifactId>
       <version>3.5.2</version>
    </dependency>
    <dependency>
       <groupId>mysql</groupId>
       <artifactId>mysql-connector-java</artifactId>
       <version>5.1.47</version>
    </dependency>
    
  2. 编写实体类

    package com.wtw.pojo;
    import lombok.Data;
    @Data //lombok注解,实现set和get方法
    public class User {
        private int id;
        private String userName;
        private String password;
    }
    
  3. 编写UserDao接口

    package com.wtw.dao;
    import com.wtw.pojo.User;
    import java.util.List;
    public interface UserMapper {
        public List<User> selectUser();//简单的俩个方法接口,查询所有用户和按id查询
        public User selectUserById();
    }
    
  4. 编写接口对应的Mapper映射文件(UserMapper.xml)

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="com.wtw.dao.UserMapper">
        <select id="selectUser" resultType="User">
        select * from user
       </select>
        <select id="selectUserById" resultType="User">
            select * from user where id=1
        </select>
    
    </mapper>
    

    注意此文件内不能有中文注释,否则运行报错:

    Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sqlSessionFactory' defined in class path resource [spring-dao.xml]: Invocation of init method failed; nested exception is org.springframework.core.NestedIOException: Failed to parse mapping resource: 'file [D:\Desktop\spring-transaction\target\classes\com\wtw\dao\mapper\UserMapper.xml]'; nested exception is org.apache.ibatis.builder.BuilderException: Error creating document instance. Cause: com.sun.org.apache.xerces.internal.impl.io.MalformedByteSequenceException: 1 字节的 UTF-8 序列的字节 1 无效。

    ​ 目前没找到解决方法,有待解决???

  5. 编写mybatis配置文件(mybatis-config.xml),resource目录下,默认为classpath

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE configuration
            PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-config.dtd">
    <configuration>
        <typeAliases>
            <package name="com.wtw.pojo"/>
        </typeAliases>
    <!--后面在beans.xml中做了,这里需要先打开注释->
    <!--配置数据库环境->
    <!-    <environments default="development">-->
    <!--        <environment id="development">-->
    <!--            <transactionManager type="JDBC"/>-->
    <!--            <dataSource type="POOLED">-->
    <!--                <property name="driver" value="com.mysql.jdbc.Driver"/>-->
    <!--                <property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=true&amp;useUnicode=true&amp;characterEncoding=utf8"/>-->
    <!--                <property name="username" value="root"/>-->
    <!--                <property name="password" value="4321"/>-->
    <!--            </dataSource>-->
    <!--        </environment>-->
    <!--    </environments>-->
    <!--配置mapper.xml映射文件的路径->
    <!--    <mappers>-->
    <!--        <package name="com.wtw.dao"/>-->
    <!--    </mappers>-->
    
    </configuration>
    
  6. 编写测试类进行测试

    import com.wtw.dao.UserMapper;
    import com.wtw.pojo.User;
    import org.apache.ibatis.io.Resources;
    import org.apache.ibatis.session.SqlSession;
    import org.apache.ibatis.session.SqlSessionFactory;
    import org.apache.ibatis.session.SqlSessionFactoryBuilder;
    import org.junit.Test;
    import java.io.IOException;
    import java.io.InputStream;
    import java.util.List;
    public class Test1 {
        @Test
        public void selectUser() {
    
            String resource = "mybatis-config.xml";
            InputStream inputStream= null;
            try {
                inputStream = Resources.getResourceAsStream(resource);//注意此处的Resource类要导对包apache下的
            } catch (IOException e) {
                e.printStackTrace();
            }//读取mybatis配置文件
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
            SqlSession sqlSession = sqlSessionFactory.openSession();//通过SqlSessionFactory新建sqlSession
    
            UserMapper mapper = sqlSession.getMapper(UserMapper.class);
    
            List<User> userList = mapper.selectUser();
    
            for (User user:userList) {
                System.out.println(user);
            }
            sqlSession.close();//开启资源都要记得关闭
        }
    }
    
  7. 运行上面的测试类,发现报错,需要配置Maven静态资源过滤问题(pom.xml)

    <build>
       <resources>
           <resource>
               <directory>src/main/java</directory>
               <includes>
                   <include>**/*.properties</include>
                   <include>**/*.xml</include>
               </includes>
               <filtering>true</filtering>
           </resource>
       </resources>
    </build>
    

    数据库名:mybatis

    表名:user 字段:id int,username String ,password String

    二. Spring整合mybatis(MyBatis-Spring)

    1. 导入依赖

      <!--spring相关-->
      <dependency>
         <groupId>org.springframework</groupId>
         <artifactId>spring-webmvc</artifactId>
         <version>5.1.10.RELEASE</version>
      </dependency>
      <dependency>
         <groupId>org.springframework</groupId>
         <artifactId>spring-jdbc</artifactId>
         <version>5.1.10.RELEASE</version>
      </dependency>
      <!--aspectJ AOP 织入器-->
      <dependency>
         <groupId>org.aspectj</groupId>
         <artifactId>aspectjweaver</artifactId>
         <version>1.9.4</version>
      </dependency>
      <!--mybatis-spring整合包-->
      <dependency>
         <groupId>org.mybatis</groupId>
         <artifactId>mybatis-spring</artifactId>
         <version>2.0.2</version>
      </dependency>
      
    2. 编写Spring配置文件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"
            xsi:schemaLocation="http://www.springframework.org/schema/beans
             http://www.springframework.org/schema/beans/spring-beans.xsd">
      </beans>
      
    3. 在beans.xml中配置数据源,取代mybatis-config.xml中的配置

      <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
         <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
         <property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=true&amp;useUnicode=true&amp;characterEncoding=utf8"/>
         <property name="username" value="root"/>
         <property name="password" value="xxxx"/>
      </bean>
      
    4. 在beans.xml中配置SqlSessionFactory,与Mybatis关联

      <!--    配置SqlSessionFactory-->
          <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
              <property name="dataSource" ref="dataSource"/>
      <!--        关联Mybatis配置文件及mapper.xml-->
              <property name="configLocation" value="classpath:mybatis-config.xml"/>
              <property name="mapperLocations" value="classpath:com/wtw/dao/*.xml"/>
          </bean>
      
    5. 在beans.xml中注册sqlSessionTemplate , 关联sqlSessionFactory,sqlSessionTemplate等同于SqlSession,Spring帮忙封装了

      <!--注册sqlSessionTemplate , 关联sqlSessionFactory-->
      <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
         <!--利用构造器注入,这里只能用构造器注入,因为SqlSessionFactoryBean类中只有构造方法,没有定义set方法-->
         <constructor-arg index="0" ref="sqlSessionFactory"/>
      </bean>
      
    6. 编写UserDao接口的实现类,从而使用sqlSessionTemplate

      package com.wtw.dao;
      import com.wtw.pojo.User;
      import org.mybatis.spring.SqlSessionTemplate;
      import java.util.List;
      public class UserDaoImpl implements UserMapper {
          //使用sqlSession时不用我们自己new,IOC交由Spring管理,所以这里必须有set方法。记得去beans.xml中去注册bean
          private SqlSessionTemplate sqlSession;
          public void setSqlSession(SqlSessionTemplate sqlSession) {
              this.sqlSession = sqlSession;
          }
          public List<User> selectUser() {
              UserMapper mapper = sqlSession.getMapper(UserMapper.class);
              return mapper.selectUser();
          }
      }
      
      
      <bean id="userDao" class="com.wtw.dao.UserDaoImpl">
         <property name="sqlSession" ref="sqlSession"/>
      </bean>
      
    7. 编写测试类,测试

      import com.wtw.dao.UserMapper;
      import com.wtw.pojo.User;
      import org.junit.Test;
      import org.springframework.context.ApplicationContext;
      import org.springframework.context.support.ClassPathXmlApplicationContext;
      import java.util.List;
      public class Test2 {
          @Test
          public void test2(){
              ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
              UserMapper mapper = context.getBean("userDao", UserMapper.class);
              List<User> userList = mapper.selectUser();
              for (User user:userList) {
                  System.out.println(user);
              }
          }
      }
      

    三. 实现方式二

    1.2.3.4.步同上

    第五步 不需要再去管理SqlSessionTemplate,即不需要去注册sqlSessionTemplate,实现UserDao接口时,去继承SqlSessionDaoSupport类,

    package com.wtw.dao;
    import com.wtw.pojo.User;
    import org.mybatis.spring.support.SqlSessionDaoSupport;
    import java.util.List;
    //方式二 继承SqlSessionDaoSupport 省去了new sqlSession,直接利用 getSqlSession() 获得 , 然后直接注入SqlSessionFactory
    public class UserDao2Impl extends SqlSessionDaoSupport implements UserMapper {
    
        public List<User> selectUser() {
            return getSqlSession().getMapper(UserMapper.class).selectUser();
        }
    
        public User selectUserById() {
            return getSqlSession().getMapper(UserMapper.class).selectUserById();
        }
    
    }
    

    这里还需要修改beans.xml文件的配置

     <bean id="userDao" class="com.wtw.dao.UserDao2Impl">
            <property name="sqlSessionFactory" ref="sqlSessionFactory"/>
        </bean>
    

    测试:

    import com.wtw.dao.UserMapper;
    import com.wtw.pojo.User;
    import org.junit.Test;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    import java.util.List;
    public class Test3 {
        @Test
        public void test3(){
            ApplicationContext context = new ClassPathXmlApplicationContext("beans2.xml");
            UserMapper mapper= context.getBean("userDao", UserMapper.class);
            List<User> userList = mapper.selectUser();
            for (User user:userList) {
                System.out.println(user);
            }
            System.out.println(mapper.selectUserById());
        }
    }
    

    四. 声明式事务

    事务:用来保证应用数据的一致性和完整性。

    四大原则:ACID

    1. 原子性(atomicity)

    2. 一系列的操作是一个整体,要么全部执行,要么全部不执行。

    3. 一致性(consistency)

    4. 实时提交,只要有操作产生,事务就被提交,数据在资源中永远被更新。

    5. 隔离性(isolation)

    6. 多个事务处理同一数据,相互隔离,不会互相影响。

    7. 持久性(durability)

      事务一旦提交,无论系统出现什么问题,数据都不会被影响,结果被持久化在了数据库这样的存储器上。

    四大原则的作用就是保证一系列的操作要么全部成功,要么全部失败,终极目的就是保证应用数据的一致性和完整性。


    Spring中的事务管理

    支持编程式事务管理和声明式的事务管理

    编程式事务管理

    • 将事务管理代码嵌到业务方法中来控制事务的提交和回滚
    • 缺点:必须在每个事务操作业务逻辑中包含额外的事务管理代码

    声明式事务管理

    • 将事务管理代码从业务方法中分离出来,以声明的方式来实现事务管理。
    • 将事务管理作为横切关注点,通过aop方法模块化。Spring中通过Spring AOP框架支持声明式事务管理。

    实现步骤:

    1.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:tx="http://www.springframework.org/schema/tx"
           xmlns:aop="http://www.springframework.org/schema/aop"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans.xsd
           http://www.springframework.org/schema/tx
           http://www.springframework.org/schema/tx/spring-tx.xsd
           http://www.springframework.org/schema/aop
           http://www.springframework.org/schema/aop/spring-aop.xsd">
    
    

    2.在beans.xml中注册事务管理器

    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
           <property name="dataSource" ref="dataSource" />
    </bean>
    

    3.配置事务的通知

    <!--配置事务通知-->
        <tx:advice id="txAdvice" transaction-manager="transactionManager">
            <tx:attributes>
                <!--配置哪些方法使用事务,*为全部方法,配置事务的传播特性,默认REQUIRED-->
                <tx:method name="*" propagation="REQUIRED"/>
    <!--            <tx:method name="selectUser" propagation="REQUIRED"/>-->
    <!--            <tx:method name="deleteUser" propagation="REQUIRED"/>-->
    <!--            <tx:method name="insertUser" propagation="REQUIRED"/>-->
            </tx:attributes>
        </tx:advice>
    

    4.配置AOP,说明在哪里织入事务

     <!--配置aop织入事务-->
        <aop:config>
            <aop:pointcut id="txPointcut" expression="execution(* com.wtw.dao.impl.*.*(..))"/>
            <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcut"/>
        </aop:config>
    

    事务传播性详解:

    事务传播行为就是多个事务方法相互调用时,事务如何在这些方法间传播。

    spring支持7种事务传播行为:

    • propagation_requierd:如果当前没有事务,就新建一个事务,如果已存在一个事务中,加入到这个事务中,这是最常见的选择,默认。

    • propagation_supports:支持当前事务,如果没有当前事务,就以非事务方法执行。

    • propagation_mandatory:使用当前事务,如果没有当前事务,就抛出异常。

    • propagation_required_new:新建事务,如果当前存在事务,把当前事务挂起。

    • propagation_not_supported:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。

    • propagation_never:以非事务方式执行操作,如果当前事务存在则抛出异常。

    • propagation_nested:如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与propagation_required类似的操作


posted @ 2021-01-11 18:10  恋R  阅读(138)  评论(0编辑  收藏  举报