[学习笔记] Spring之MyBatis与Spring的整合

# 学习 # · 2021-02-11

Spring整合MyBatis的准备工作

1、导入相关的jar包。

<!--导入相关的依赖包-->
<dependencies>
    <!--junit-->
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
    </dependency>
    <!--mysql-->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.30</version>
    </dependency>
    <!--mybatis-->
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>3.5.6</version>
    </dependency>
    <!--Spring-->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>5.2.0.RELEASE</version>
    </dependency>
    <!--Spring JDBC-->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-jdbc</artifactId>
        <version>5.2.0.RELEASE</version>
    </dependency>
    <!--Asceptj-->
    <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>
</dependencies>

2、创建User实体类。

public class User {

  private long id;
  private String name;
  private String pwd;

  //省略getter/setter方法

}

3、编写数据访问层Dao接口。

public interface UserMapper {
    public List<User> selectUser();
}

4、编写SQK映射文件UserMapper.xml。

<mapper namespace="com.demo.dao.UserMapper">
    <!--select查询-->
    <select id="selectUser" resultType="User">
        select * from user;
    </select>
</mapper>

5、编写MyBatis配置文件。

<configuration>
    <!--设置POJO包下的类的别名-->
    <typeAliases>
        <package name="com.demo.pojo"/>
    </typeAliases>

    <!--此处数据库连接配置由Spring处理-->
    <!--此处绑定Mapper文件由Spring处理-->
</configuration>

实现Spring与MyBatis整合

1、步骤一:编写Spring配置文件,配置数据源。

<?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-3.2.xsd">

    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
        <property name="url" value="jdbc:mysql://localhost:3306/mybatisdb"></property>
        <property name="username" value="root"></property>
        <property name="password" value="123456"></property>
    </bean>

</beans>

(1)dataSource使用Spring的数据源替换MyBatis的配置,这里使用Spring的JDBC。

(2)目前流行的数据源有:dbcp、c3p0、Proxool等,它们都实现了连接池的功能。

(3)若url属性包含特殊符号,则需要使用<![CDATA[]]>进行标记,或将其替换为实体引用&amp;

2、步骤二:配置SqlSessionFactoryBean。

<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
    <!--引用数据源组件-->
    <property name="dataSource" ref="dataSource"></property>
    <!--绑定MyBatis配置文件-->
    <property name="configLocation" value="classpath:mybatis-config.xml"></property>
    <!--配置SQL映射文件-->
    <property name="mapperLocations" value="classpath:com/demo/dao/*.xml"></property>
</bean>

(1)配置SQL映射文件信息的另一种写法。

<property name="mapperLocations">
    <list>
        <value>classpath:com/demo/dao/*.xml</value>
    </list>
</property>

3、步骤三:使用SqlSessionTemplate实现数据库的操作。

//创建UserMapper实现类,并实现UserMapper接口
public class UserMapperImpl implements UserMapper{

    private SqlSessionTemplate sqlSession;
    public void setSqlSession(SqlSessionTemplate sqlSession) { this.sqlSession = sqlSession; }

    public List<User> selectUser() {
        return sqlSession.getMapper(UserMapper.class).selectUser();
    }
}
<!--配置SqlSessionTemplate-->
<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
    <constructor-arg index="0" ref="sqlSessionFactory"></constructor-arg>
</bean>
<!--配置Dao组件并注入SqlSessionTemplate实例-->
<bean id="UserMapper" class="com.demo.dao.UserMapperImpl">
    <property name="sqlSession" ref="sqlSession"></property>
</bean>

(1)SqlSessionTemplate类实现了MyBatis的SqlSession接口,可以替换MyBatis中原有的SqlSession实现类提供数据库访问操作。

(2)使用SqlSessionTemplate可以更好地简化工作,可以保证和当前Spring事务相关联,自动管理会话的生命周期,包括必要的关闭、提交和回滚操作。

4、步骤四:创建测试类。

@Test
public void run() {
    ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
    List<User> userList = context.getBean(UserMapper.class).selectUser();
    for(User u : userList) {
        System.out.println(u);
    }
}

5、使用SqlSessionDaoSupport 简化SqlSessionTemplate的配置和获取:

(1)修改实现类。

public class UserMapperImpl extends SqlSessionDaoSupport implements UserMapper{

    public List<User> selectUser() {
        SqlSession sqlSession = getSqlSession();
        return sqlSession.getMapper(UserMapper.class).selectUser();
    }

}

(2)修改Spring配置文件。

<!--省略数据源配置-->

<!--配置SqlSessionFactoryBean-->

<!--配置Dao,注册Bean-->
<bean id="UserMapper" class="com.demo.dao.UserMapperImpl">
    <property name="sqlSessionFactory" ref="sqlSessionFactory"></property>
</bean>

注入映射器实现

1、手动编写映射器实现存在的问题:

(1)SqlSession.selectList() 等方式需要采用字符串来指定映射项。

(2)SqlSession.getMapper() 等方式需要每次调用时都实现一次映射器接口,才能调用相应的方法,即每次的执行到getMapper(UserMapper.class)时,都会实现一次此接口,占用资源和时间。

sqlSession.getMapper(UserMapper.class).selectUser();

2、注入映射器实现的方法一:使用MapperFactoryBean注入映射器。修改Spring配置文件:

<!--省略数据源配置-->

<!--配置SqlSessionFactoryBean-->

<!-- 注入映射器,MapperFactoryBean -->
<bean id="UserMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
    <!--mapperInterface属性指定映射器(只能是接口类型,不能是某个实现类)-->
    <property name="mapperInterface" value="com.demo.dao.UserMapper"></property>
    <property name="sqlSessionFactory" ref="sqlSessionFactory"></property>
</bean>

3、方法二:使用MapperScannerConfigurer注入映射器。修改Spring配置文件:

<!--省略数据源配置-->

<!--配置SqlSessionFactoryBean-->

<!--配置Dao,注册Bean-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
    <property name="basePackage" value="com.demo.dao"></property>
</bean>

(1)basePackage属性指定扫描的基准包,多个基准包以逗号隔开。

(2)MapperScannerConfigurer将递归扫描基准包,如果它们在SQL映射文件中定义过,则将他们动态注册为MapperFactoryBean。

4、更普遍的做法:在使用MapperScannerConfigurer自动完成映射器注册后,使用注解实现对业务组件的依赖注入。

public class UserServiceImpl implements UserService {

    @Autowired
    private UserMapper userMapper;
    public List<User> selectUser() {
        return userMapper.selectUser();
    }

}

声明式事务

1、声明式事务:基于AOP实现,无需编写任何事务管理代码,所有的工作全在配置文件中完成。

2、配置并实现声明式事务:

(1)编写SQL映射文件。

<insert id="insertUser" parameterType="User">
    insert into user(id, name, pwd) values(#{id}, #{name}, #{pwd})
</insert>

<!--编写一条错误的SQL语句-->
<delete id="deleteUser" parameterType="int">
    deletes from user where id=#{id}
</delete>

(2)修改UserMapper接口及其实现类:在SQL语句异常情况下,需要使用事务管理。

public class UserMapperImpl extends SqlSessionDaoSupport implements UserMapper{
    public List<User> selectUser() {
        SqlSession sqlSession = getSqlSession();

        //实例化一个新的User实体
        User user = new User();
        user.setId(17);
        user.setName("小王");
        user.setPwd("123456");

        //添加新用户
        sqlSession.getMapper(UserMapper.class).insertUser(user);
        //删除旧用户
        sqlSession.getMapper(UserMapper.class).deleteUser(16);

        return sqlSession.getMapper(UserMapper.class).selectUser();
    }
}

(3)定义事务管理器Bean,并为其注入数据源dataSource。

<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <constructor-arg ref="dataSource" />
</bean>

(4)配置事务增强。

<tx:advice id="txAdvice" transaction-manager="transactionManager">
    <!-- 定义属性,声明事务规则 -->
    <tx:attributes>
        <tx:method name="insert*"></tx:method>
        <tx:method name="delete*"></tx:method>
        <tx:method name="update*"></tx:method>
        <tx:method name="*"></tx:method>
    </tx:attributes>
</tx:advice>

(5)定义切入点,配置事务切入。

<aop:config>
    <aop:pointcut id="txPointcut" expression="execution(* com.demo.dao.UserMapperImpl.*(..))"/>
    <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcut"></aop:advisor>
</aop:config>

3、<tx:method>属性说明:

(1)propagation:事务传播机制。

  ①REQUIRED:支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。

  ②SUPPORTS:支持当前事务,如果当前没有事务,就以非事务方式执行。

  ③MANDATORY:支持当前事务,如果当前没有事务,就抛出异常。

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

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

  ⑥NEVER:以非事务方式执行,如果当前存在事务,则抛出异常。

  ⑦NESTED:支持当前事务,如果当前事务存在,则执行一个嵌套事务,如果当前没有事务,就新建一个事务。

(2)isolation:事务隔离等级,即当前事务和其他事务的隔离成都,在并发事务处理的情况下需要考虑其设置。

  ①DEFAULT:使用后端数据库默认的隔离级别。

  ②READ_UNCOMMITTED:允许读取尚未提交的更改。可能导致脏读、幻影读或不可重复读。

  ③READ_COMMITTED:允许从已经提交的并发事务读取。可防止脏读,但幻影读和不可重复读仍可能会发生。

  ④REPEATABLE_READ:对相同字段的多次读取的结果是一致的,除非数据被当前事务本身改变。可防止脏读和不可重复读,但幻影读仍可能发生。

  ⑤SERIALIZABLE:完全服从ACID的隔离级别,确保不发生脏读、不可重复读和幻影读。这在所有隔离级别中也是最慢的,因为它通常是通过完全锁定当前事务所涉及的数据表来完成的。

(3)timeout:事务超时时间,即允许事务运行的最长时间。

(4)read-only:事务是否为只读,默认为false。

(5)rollback-for:设定能够出发回滚的异常类型。Spring默认只在抛出Runtime Exceotion时才标识事务回滚。

(6)no-rollback-for:设定不触发回滚的异常类型。Spring默认checked Exception不会触发事务回滚。


使用注解实现声明式事务处理

1、Spring支持使用注解配置声明式事务,所使用的注解是@Transactional

2、实现步骤:

(1)在Spring配置文件中配置事务管理类,并添加对注解配置的事务支持。

<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <constructor-arg ref="dataSource" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven>

(2)使用注解来配置事务。

@Transactional
public class UserMapperImpl extends SqlSessionDaoSupport implements UserMapper{
    public List<User> selectUser() {
        //省略实现代码
    }
}

3、@Transactional注解的属性:

如无特殊说明,本博所有文章均为博主原创。

如若转载,请注明出处:一木林多 - https://www.l5v.cn/archives/218/

评论