Spring与MyBatis的集成

Spring与MyBatis的集成

要在Spring中使用MyBatis,需要在Spring的配置文件中定义一些类
  • SqlSessionFactoryBean:为整合应用提供SqlSession对象资源。
  • SqlSessionTemplate:负责管理MyBatis的SqlSession,调用SQL映射语句,实现对数据库的访问。
  • MapperFactoryBean:根据指定Mapper接口生成Bean实例。
  • MapperScannerConfigurer:根据指定包批量扫描Mapper接口并生成实例。
Spring和MyBatis的大致整合步骤

在这里插入图片描述

  1. 首先在Spring的配置文件中配置数据库连接(此处用druid的数据库连接池)
<!--1.配置数据库连接池 dataSource就是druid数据库连接池;也可以引入外部数据源文件-->
    <!-- 如果是引入外部连接数据库的配置文件需要注意修改property 标签的value属性
    	<context:property-placeholder location="database.properties"/>
		<property name="password" value="${password}"></property> -->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
        <property name="url" value="jdbc:mysql://localhost:3306/smbms?relaxAutoCommit=true&amp;zeroDateTimeBehavior=convertToNull"></property>
        <property name="username" value="root"></property>
        <property name="password" value="root"></property>
    </bean>
  1. 配置SqlSessionFactoryBean对象,这里需要注意的是:在Spring的配置文件中可以引入MyBatis的配置文件,也可以在Spring的配置文件中配置MyBatis配置文件所能配置。但是两者不建议同时使用,要么引入外部配置文件,要么在Spring配置文件中配置一些规则。
 <!--2.配置SqlSessionFactoryBean对象-->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource"></property>
        <!--指定MyBatis的总配置文件的位置;不能和configuration属性一起使用,要么引入外部配置文件,要么在spring的配置文件中配置-->
        <!--<property name="configLocation" value="classpath:mybatis-config.xml"></property>-->
        <!--注册Mapper.xml文件(和在MyBatis的总配置文件中做注册效果一样)-->
        <property name="mapperLocations">
            <list>
                <value>classpath:com/bd/dao/*.xml</value>
            </list>
        </property>
        <!--类型别名-->
        <property name="typeAliasesPackage" value="com.bd.pojo"/>
        <!--总配置文件-->
        <property name="configuration">
            <bean class="org.apache.ibatis.session.Configuration">
                <!--开启驼峰命名规则-->
                <property name="mapUnderscoreToCamelCase" value="true"/>
                <!--开启最高权限自动映射-->
                <property name="autoMappingBehavior" value="FULL"/>
            </bean>
        </property>
    </bean>
  1. 为DAO层的接口映射相应的Mapper.xml文件(其中value值根据自己的情况决定是否加*号 ")
<!--递归扫描基准包下所有接口,若它们在SQL映射文件中定义过,则动态注册为MapperFactoryBean,如此即可批量产生映射器实现类,即和mapper.xml文件进行映射-->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="com.bd.dao" />
    </bean>
  1. 另外需要开启注解扫描
	<!--spring扫描项目中的注解,指定需要扫描的基类包,多个包可用逗号隔开-->
    <context:component-scan base-package="com.bd"/>
  1. DAO层的接口和配置文件正常编写
public interface UserMapper {

    /**
     * 查询全部用户
     * @return 返回用户集合
     */
    public List<User> selectAll();
}
  • 对应的Mapper.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.bd.dao.UserMapper">
    <!--查询全部用户-->
    <select id="selectAll" resultType="user">
        select * from user
    </select>
</mapper>
  1. 编写service层的接口和实现类(通过注解的方式)
@Component
@Service
public class UserServiceImpl implements UserService {
    @Autowired
    private UserMapper userMapper;
    
    @Override
    public List<User> selectAll() {
        return  userMapper.selectAll();
    }
}
  1. 测试(有两种测试方法)
  • 测试一:正常的通过getBean创建对象,调用方法
public void test01(){
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserService us = context.getBean("userServiceImpl", UserService.class);
        us.selectAll().forEach(System.out::println);
        userService.selectAll().forEach(System.out::println);
}
  • 测试二:通过注解的方式创建对象和指定配置文件的路径,类上边的两个注解联合使用。@RunWith标注当前类是一个运行类,不是测试类(需要注意junit4的包版本不能太低)
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:applicationContext.xml")
public class TestSpring {
    @Autowired
    private UserService userService;

    @Test
    public void test01(){
        userService.selectAll().forEach(System.out::println);
    }
}
小结:MapperScannerConfigurer 与@Autowired注解或@Resource注解配合使用,自动创建映射器实现并注入给业务组件,能够最大限度地减少DAO组件与业务组件的编码和配置工作。

Spring提供了声明式事务支持

  • 事务配置步骤
    • 导入tx和aop命名空间
    • 定义事务管理器Bean,并为其注入数据源Bean
    • 通过<tx:advice>配置事务增强,绑定事务管理器并针对不同方法定义事务规则
    • 配置切面,将事务增强与方法切入点组合
事务的属性
  • propagation:事务传播机制

    • REQUIRED(默认值):指定当前方法必须放在一个事务中,如果当前没有可运行的事务环境,则新建一个事务。
    • REQUIRES_NEW 、MANDATORY、NESTED:指定当前方法会创建一个新的事务,如果当前运行环境有事务,则挂起该事务,直到新的事务提交,则继续执行被挂起的事务。
    • SUPPORTS:如果当前运行环境有可用事务,则将当前方法加入到正在运行的事务中,如果没有可运行的事务,则当前方法以非事务(不要事务)的方式运行。
    • NOT_SUPPORTED、NEVER:声明方法不需要事务。如果方法没有关联到一个事务,容器不会为他开启事务,如果方法在一个事务中被调用,该事务会被挂起,调用结束后,原先的事务会恢复执行。
  • ACID数据库的四个隔离级别

    • A:原子性:一个事务中的一组SQL语句,要么全部执行成功,要么全部执行失败。
    • C:一致性:事务在完成前和完成后,所有的数据保持一致的状态。
    • I:隔离性:一个事务的执行不能被其他事务所影响。
    • D:持久性:一个事务一旦提交,事物的操作便永久性的保存在数据库中。
  • 关于事务隔离级别的三个名词(这是由于事务并发而引起的问题)

    • 脏读:一个事务还没有提交,另外一个事务读取到了他修改后的数据。
    • 幻读:先进行了一个查询,另外一个事务向表中又添加了新的数据,所以再次查询,查询结果和之前不一致。
    • 不可重复读:在同一个事务中,执行两条同样的SQL语句,但是查询的结果不同。
  • isolation:事务隔离等级

    • DEFAULT(默认值):使用数据库默认的事务隔离级别。
    • READ_COMMITTED:提交读,较为安全,造成不可重复读。
    • READ_UNCOMMITTED:未提交读,造成脏读。
    • REPEATABLE_READ:可重复读,使用for udpate加查询锁,造成幻读。
    • SERIALIZABLE:串行读,可以解决脏读、不可重复读、幻读,效率非常低。
事务属性 2
  • timeout:事务超时时间,允许事务运行的最长时间,以秒为单位。默认值为-1,表示不超时。
  • read-only:事务是否为只读,默认值为false。
  • rollback-for:设定能够触发回滚的异常类型。
    • Spring默认只在抛出runtime exception时才标识事务回滚。
    • 可以通过全限定类名指定需要回滚事务的异常,多个类名用逗号隔开。
  • no-rollback-for:设定不触发回滚的异常类型。
    • Spring默认checked Exception不会触发事务回滚。
    • 可以通过全限定类名指定不需回滚事务的异常,多个类名用英文逗号隔开。

配置声明式事务的步骤

  1. 在Spring的配置文件中添加事务管理
	<!--事务管理;其中ref属性值是数据库连接池的唯一标识id-->
    <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"></property>
    </bean>
  1. 配置事务增强,给不同前缀的方法添加不同的事务类型
	<!--事务增强/可通过注解实现更简单方便-->
    <tx:advice id="txAdvice" transaction-manager="txManager">
        <tx:attributes>
            <tx:method name="select*" read-only="true"/>
            <tx:method name="get*" read-only="true"/>
            <tx:method name="insert*" rollback-for="RuntimeException"/>
        </tx:attributes>
    </tx:advice>
  1. 配置切面
	<aop:config>
        <aop:pointcut id="myPoint" expression="execution(* com.bd.service..*.*(..))"/>
        <aop:advisor advice-ref="txAdvice" pointcut-ref="myPoint" />
    </aop:config>

以上是通过配置文件添加事务,使用起来配置繁琐,不够灵活!

通过注解的方式声明事务

  1. 在Spring的配置文件中添加事务管理并添加对注解配置的事务的支持(可以省略二、三步骤)。
	<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"></property>
    </bean>
    <tx:annotation-driven transaction-manager="txManager"/>
  1. 然后再需要添加事务的方法上添加@Transactional注解。
	@Transactional(rollbackFor = {RuntimeException.class})
    @Override
    public void insertUser(User user) {
        userMapper.insertUser(user);
    }
  1. @Transactional使用的位置

    1. 接口实现类或接口实现方法上,而不是接口类中。
    2. 此方法必须是public修饰的,否则不会生效。
  2. @Transactional注解的属性

属性类型说明
propagation枚举型:Propagation可选的传播性设置。使用举例:@Transactional(propagation=Propagation.REQUIRES_NEW)
isolation枚举型:Isolation可选的隔离性级别。使用举例:@Transactional(isolation=Isolation.READ_COMMITTED)
readOnly布尔型是否为只读型事务。使用举例:@Transactional(readOnly=true)
readOnlytimeoutint型(以秒为单位)事务超时。使用举例:Transactional(timeout=10)
rollbackFor一组 Class 类的实例,必须是Throwable的子类一组异常类,遇到时 必须 回滚。使用举例:@Transactional(rollbackFor={SQLException.class}),多个异常用逗号隔开
rollbackForClassName一组 Class 类的名字,必须是Throwable的子类一组异常类名,遇到时 必须 回滚。使用举例:@Transactional(rollbackForClassName={“SQLException”}),多个异常用逗号隔开
noRollbackFor一组 Class 类的实例,必须是Throwable的子类一组异常类,遇到时 必须不 回滚
noRollbackForClassName一组 Class 类的名字,必须是Throwable的子类一组异常类名,遇到时 必须不 回滚
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值