Spring整合Mybatis

时间:2021-07-21
本文章向大家介绍Spring整合Mybatis,主要包括Spring整合Mybatis使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

spring 整合 Mybatis

1、为什么要整合?【整合的是什么东西?】

  • Spring整合Mybatis
  1. 让Spring来接管SqlSessionFactory的创建。【FactoryBean】
  2. 让Mybatis事务由Dao层变到Service层来控制【声明式事务】

2、让Spring来接管SqlSessionFactory的创建

  1. 导入依赖

数据库驱动、数据源、Junit、SpringIOC相关的依赖、spring-jdbc.jar、Mybatis相关依赖、Spring跟Mybatis整合的依赖

<dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>5.1.6.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-jdbc</artifactId>
        <version>5.1.6.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
    </dependency>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.6</version>
    </dependency>
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid</artifactId>
        <version>1.1.10</version>
    </dependency>
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>3.5.2</version>
    </dependency>
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis-spring</artifactId>
        <version>1.3.2</version>
    </dependency>
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-log4j12</artifactId>
        <version>1.7.7</version>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.18.16</version>
    </dependency>
</dependencies>

  1. 准备工作

JavaBean、持久层

  • JavaBean
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Employee {

    private Integer id;
    private String empName;
    private Double salary;
    private Integer deptId;

}


  • 持久层
public interface EmployeeDao {

    List<Employee> findAll();

}

  1. Spring配置文件
  1. 数据源
  2. SqlSessionFacotryBean
  3. 让Spring来创建和管理XxxMapper代理
<?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:context="http://www.springframework.org/schema/context"
       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/context
       http://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/aop
       http://www.springframework.org/schema/aop/spring-aop.xsd">

    <!-- 加载外部配置文件 -->
    <context:property-placeholder location="classpath*:*.properties"/>

    <!-- 1.配置数据源 -->
    <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="maxActive" value="30000"/>
    </bean>

    <!-- 2.配置SqlSessionFactoryBean,由它来生产SqlSessionFactory对象 -->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource"/>
        <!-- 别名包 -->
        <property name="typeAliasesPackage" value="com.java2007.pojo"/>
    </bean>

    <!-- 3.由Spring来接管XxxMapper代理对象
        Spring创建XxxMapper代理对象,并放入到容器中,默认的ID就是类名首字母小写
    -->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="com.java2007.dao"/>
        <!-- 可选配置,一般都不配 -->
        <!--<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>-->
    </bean>

</beans>

  1. 测试
public class SpringTest {

    /**
     *
     * @throws Exception
     */
    @Test
    public void test01() throws Exception {
        ApplicationContext ioc = new ClassPathXmlApplicationContext("applicationContext.xml");
        //UserDao userDao = (UserDao) ioc.getBean("userDao");
        //userDao.save();
        //UserService userService = ioc.getBean(UserService.class);
        //userService.save();

        EmployeeDao employeeDao = (EmployeeDao) ioc.getBean("employeeDao");
        System.out.println(employeeDao);
        List<Employee> employees = employeeDao.findAll();
        for (Employee employee : employees) {
            System.out.println(employee);
        }

    }
}


  • SqlSessionFactoryBean常用属性的配置
<!-- 2.配置SqlSessionFactoryBean,由它来生产SqlSessionFactory对象 -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
    <property name="dataSource" ref="dataSource"/>
    <!-- 别名包 -->
    <property name="typeAliasesPackage" value="com.java2007.pojo"/>
    <!--<property name="configuration" ref="abc"/>-->
    <!-- 配置mapper.xml文件所在的路径 -->
    <property name="mapperLocations" value="classpath*:mapper/*.xml" />
    <!-- 指定mybatis全局配置文件,classpath不要加* -->
    <!--<property name="configLocation" value="classpath:mybatis/mybatis-config.xml"/>-->
    <!-- 配置插件:如分页插件 -->
    <property name="plugins">
        <array>
            <bean class="com.github.pagehelper.PageInterceptor">
                <property name="properties">
                    <value>
                        helperDialect=mysql
                        reasonable=true
                    </value>
                </property>
            </bean>
        </array>
    </property>
</bean>

3、让Mybatis事务由Dao层变到Service层来控制

----- 【声明式事务】

  1. 引入依赖
<!-- 事务相关的依赖 -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-tx</artifactId>
    <version>5.1.6.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-aspects</artifactId>
    <version>5.1.6.RELEASE</version>
</dependency>

  1. 准备转账案例
  • AccountDao
public interface AccountDao {

    /**
     * 更新账户
     * @param account
     */
    void update(Account account);

    /**
     * 根据名称查询账户
     * @param accountName
     * @return
     */
    Account findByName(String accountName);

}

  • AccountDao.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.java2007.dao.AccountDao">

    <resultMap id="BaseResultMap" type="Account">
        <id column="id" property="id"/>
        <result column="account_name" property="accountName"/>
        <result column="balance" property="balance"/>
    </resultMap>

    <!-- void update(Account account); -->
    <update id="update" parameterType="Account">
        UPDATE t_account SET balance = #{balance} WHERE account_name = #{accountName}
    </update>

    <!-- Account findByName(String accountName); -->
    <select id="findByName" parameterType="string" resultMap="BaseResultMap">
        SELECT * FROM t_account WHERE account_name = #{accountName}
    </select>

</mapper>

  • accountService
public interface AccountService {

    /**
     * 转账
     * @param fromAccount
     * @param toAccount
     * @param money
     * @return
     */
    boolean transfer(String fromAccount, String toAccount, Double money);

}

  • accountServiceImpl
public class AccountServiceImpl implements AccountService {

    private AccountDao accountDao;

    public void setAccountDao(AccountDao accountDao) {
        this.accountDao = accountDao;
    }

    /**
     * 转账
     *
     * @param fromAccount
     * @param toAccount
     * @param money
     * @return
     */
    @Override
    public boolean transfer(String fromAccount, String toAccount, Double money) {

        Account from = accountDao.findByName(fromAccount);

        if(from.getBalance() < money) {
            throw new RuntimeException("钱不够");
        }

        from.setBalance(from.getBalance() - money);
        accountDao.update(from);
		//手动制造异常
        int i=1/0;

        Account to = accountDao.findByName(toAccount);
        to.setBalance(to.getBalance() + money);
        accountDao.update(to);

        return true;
    }
}

  1. Spring配置文件
<bean id="accountService" class="com.java2007.service.impl.AccountServiceImpl">
    <property name="accountDao" ref="accountDao"/>
</bean>

<!-- 配置声明式事务 : 由Spring来控制整个业务层的事务 -->
<!-- 1.配置事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <!-- 数据源 -->
    <property name="dataSource" ref="dataSource"/>
</bean>

<!-- 2.配置事务通知 -->
<tx:advice transaction-manager="transactionManager" id="ta">
    <!-- 配置事务属性 -->
    <tx:attributes>
        <tx:method name="transfer"/>
    </tx:attributes>
</tx:advice>

<!-- 3.配置aop -->
<aop:config>
    <aop:pointcut id="pt" expression="execution(* com.java2007.service.impl.*.*(..))"/>
    <!-- 配置切面 -->
    <aop:advisor advice-ref="ta" pointcut-ref="pt"/>
    <!--<aop:advisor advice-ref="ta" pointcut="execution(* com.java2007.service.impl.*.*(..))"/>-->
</aop:config>


  1. 测试
/**
 * 测试转账
 * @throws Exception
 */
@Test
public void test02() throws Exception {
    ApplicationContext ioc = new ClassPathXmlApplicationContext("applicationContext.xml");
    AccountService accountService = (AccountService) ioc.getBean("accountService");
    System.out.println(accountService.transfer("tom", "lucy", 200D));
}

十三、声明式事务属性配置

<!-- 2.配置事务通知 -->
<tx:advice transaction-manager="transactionManager" id="ta">
    <!-- 配置事务属性 -->
    <tx:attributes>
        <!-- 哪些方法需要使用上怎样的事务 -->
        <!--
            name : 方法名【可以使用通配符】
            timeout : 超时时间,一般不指定,默认值-1【永不超时】
            propagation : 事务的传播行为
                SUPPORTS == 支持  : 一般在查询时使用。
                REQUIRED == 必需 : 一般用于增删改。【默认值】
            read-only : 是否只读
                true == 只读型事务,只有查询用
                false == 读写型事务,增删改用【默认值】
            isolation : 隔离级别
                DEFAULT : 由数据库决定
                READ_UNCOMMITTED : 读未提交
                READ_COMMITTED : 读已提交
                REPEATABLE_READ  : 可重复读
                SERIALIZABLE : 串行化
            no-rollback-for : 如果出现了异常,什么都不回滚
            rollback-for : 如果出现了指定异常类型来回滚事务。默认是运行时异常回滚事务
        -->
        <!--<tx:method name="transfer"
                   timeout="-1"
                   propagation="REQUIRED"
                   read-only="true"
                   isolation="REPEATABLE_READ"
                   no-rollback-for=""
                   rollback-for=""/>-->
        <!-- 如果是查询:由通配方法名的形式规定采用怎样的事务 -->
        <tx:method name="find*" propagation="SUPPORTS" read-only="true" />
        <tx:method name="select*" propagation="SUPPORTS" read-only="true" />
        <tx:method name="get*" propagation="SUPPORTS" read-only="true" />
        <tx:method name="query*" propagation="SUPPORTS" read-only="true" />
        <tx:method name="search*" propagation="SUPPORTS" read-only="true" />
        <!-- 上面的如果都不匹配,则采用最后能够匹配的方法 -->
        <tx:method name="*" rollback-for="Exception"/>
    </tx:attributes>
</tx:advice>

原文地址:https://www.cnblogs.com/qxlzzj/p/15039185.html