欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Spring 整合 Mybatis

程序员文章站 2022-03-11 21:40:55
...

Spring整合MyBatis

前提

maven 3.6.0

IDEA 2017.02

Druid 数据源

MySQL 5.7

导入依赖

Spring 核心依赖
Spring -jdbc 依赖
Mybatis 依赖
Spring和 MyBtis 的整合依赖
数据库驱动
连接池

依赖配置文件

如果 Mybatis 使用的是 3.X版本 整合包 需要使用 1.3.0 以上的版本

<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-context</artifactId>
  <version>4.2.6.RELEASE</version>
</dependency>
<dependency>
  <groupId>org.mybatis</groupId>
  <artifactId>mybatis</artifactId>
  <version>3.5.3</version>
</dependency>
<!-- 如果 Mybatis 使用的是 3.X版本 整合包 需要使用 1.3.0 以上的版本 -->
<dependency>
  <groupId>org.mybatis</groupId>
  <artifactId>mybatis-spring</artifactId>
  <version>1.3.2</version>
</dependency>
<dependency>
  <groupId>mysql</groupId>
  <artifactId>mysql-connector-java</artifactId>
  <version>5.1.47</version>
</dependency>
<dependency>
  <groupId>com.alibaba</groupId>
  <artifactId>druid</artifactId>
  <version>1.0.18</version>
</dependency>
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-jdbc</artifactId>
  <version>4.2.6.RELEASE</version>
</dependency>

新建目录结构

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yD1nTe3a-1574059427678)(04- Spring整合Mybatis.assets/1573717415644.png)]

创建Mapper 接口和映射文件

Mapper 接口

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

在 resources 中新建一个 mapper 目录 专门存储 sql 映射文件

注意保持四个一致

<?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">
<!--namespace 命名空间-->
<mapper namespace="cn.bdqn.mapper.UserMapper">
    <select id="selectAll" resultType="user">
        SELECT * FROM smbms_user
    </select>
</mapper>

maven 中 默认 不会加载 java 目录中的配置文件

在pom.xml 文件中

<!-- 去加载 src/main/java 中的 sql 映射文件 -->
<resources>
  <resource>
    <directory>src/main/resources</directory>
  </resource>
  <resource>
    <directory>src/main/java</directory>
    <excludes>
      <exclude>**/*.xml</exclude>
    </excludes>
    <filtering>true</filtering>
  </resource>
</resources>

创建Spring核心配置文件

创建数据源

<!-- 配置数据源连接池 -->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
    <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
    <property name="url" value="jdbc:mysql://localhost:3306/smbms"/>
    <property name="username" value="root"/>
    <property name="password" value="123456"/>
</bean>

创建sqlsessionFactory

<!-- 配置 Mybatis SQLSession 工厂 -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
    <!-- 工厂依赖于数据源 -->
    <property name="dataSource" ref="dataSource"/>
    <!-- 配置别名 -->
    <property name="typeAliasesPackage" value="cn.bdqn.pojo"/>
    <property name="mapperLocations" value="classpath:mapper/*.xml"/>
</bean>

测试流程

新建UserService 层

public class UserService {
	
    private UserMapper mapper ;
    public void setMapper(UserMapper mapper) {
        this.mapper = mapper;
    }
    public  void selectAll(){
        List<User> users = mapper.selectAll();
        for(User user : users){
            System.out.println(user.getUserName()+ "\t" + user.getUserPassword());
        }
    }
}

测试类

@Test
public void test() {
    ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
    UserService userService = (UserService) app.getBean("userService");
    userService.selectAll();
}

添加所需要的bean

UserService

<bean id="userService" class="cn.bdqn.service.UserService">
    <property name="mapper" ref="userMapper"/>
</bean>

mapper

<!-- 配置mapper 对象
扫描 basePackage 包中的所有的 mapper 接口 
自动生成 以该接口名称(首字母小写的)命名的 bean
-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
    <property name="basePackage" value="cn.bdqn.mapper"/>
</bean>

事务 配置

把拥有多个步骤的事情 看做是一件事情
中间任意一个步骤出现问题, 整件事件失败

事务四大特性

原子性

整体性(一致性)

隔离性

持久性

转账案例

引入aop 的依赖

<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-context</artifactId>
  <version>4.2.6.RELEASE</version>
</dependency>
<dependency>
  <groupId>org.mybatis</groupId>
  <artifactId>mybatis-spring</artifactId>
  <version>1.3.2</version>
</dependency>
<dependency>
  <groupId>mysql</groupId>
  <artifactId>mysql-connector-java</artifactId>
  <version>5.1.47</version>
</dependency>
<dependency>
  <groupId>com.alibaba</groupId>
  <artifactId>druid</artifactId>
  <version>1.0.18</version>
</dependency>
<dependency>
  <groupId>org.mybatis</groupId>
  <artifactId>mybatis</artifactId>
  <version>3.5.3</version>
</dependency>
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-jdbc</artifactId>
  <version>4.2.6.RELEASE</version>
</dependency>
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-aop</artifactId>
  <version>4.2.6.RELEASE</version>
</dependency>
<dependency>
  <groupId>org.aspectj</groupId>
  <artifactId>aspectjweaver</artifactId>
  <version>1.9.4</version>
</dependency>

1- 数据库设计

USE `smbms`;

/*Table structure for table `account` */

DROP TABLE IF EXISTS `account`;

CREATE TABLE `account` (
  `id` int(5) NOT NULL,
  `name` varchar(50) COLLATE utf8_unicode_ci DEFAULT NULL,
  `balance` int(5) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

/*Data for the table `account` */

insert  into `account`(`id`,`name`,`balance`) values 
(10010,'李四',5000),
(10086,'张三',5000);

2- mapper接口

public interface AccountMapper {
    /**
     *  银行转账 转出方
     *  outId 转出方 id
     *  money 转出金额
     */
    boolean out(@Param("id") int outId ,@Param("money") double money);

    /**
     *  银行转账 转入方
     *  inId 转入方 id
     *  money 转入金额
     */
    boolean in(@Param("id") int inId ,@Param("money") double money);
}

3- mapper sql 映射文件

<?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">
<!--namespace 命名空间-->
<mapper namespace="cn.bdqn.mapper.AccountMapper">

    <update id="out" >
        UPDATE account SET balance = balance - #{money} WHERE id = #{id}
    </update>

    <update id="in" >
        UPDATE account SET balance = balance + #{money} WHERE id = #{id}
    </update>
</mapper>

4- AccountService

public class AccountService {

    private AccountMapper mapper;
    public void setMapper(AccountMapper mapper) {
        this.mapper = mapper;
    }

    public boolean transfer(int outid, int inid, double money){
        // 转出
        boolean out = mapper.out(outid, money);
        int i = 1/0;
        // 转入
        boolean in = mapper.in(inid, money);

        return out && in;
    }
}

5- spring核心配置文件

<!-- 声明一个 事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource"/>
</bean>

<!--AOP 理念-->
<!-- 配置增强 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
    <tx:attributes>
        <tx:method name="transfer" propagation="REQUIRED" isolation="DEFAULT" />
    </tx:attributes>
</tx:advice>

<!-- 配置连接点和切入点 -->
<aop:config>
    <aop:pointcut id="pointcutId" expression="execution(* cn..*.*(..))"/>
    <aop:advisor advice-ref="txAdvice" pointcut-ref="pointcutId"/>
</aop:config>

6- 测试

public class AccountTest {

    @Test
    public void transferTest(){
        ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
        AccountService accountService = (AccountService) app.getBean("accountService");
        accountService.transfer(10086, 10010, 1000);
    }
}

使用注解

配置文件开启注解支持

<!-- 声明一个 事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource"/>
</bean>
<!-- 开启注解扫描 -->
<context:component-scan base-package="cn.bdqn.service"/>
<!-- 开启 注解式 事务配置 -->
<tx:annotation-driven transaction-manager="transactionManager"/>

在需要使用事务的方法上添加注解

@Service
public class AccountService {

    @Autowired
    private AccountMapper mapper;
    public void setMapper(AccountMapper mapper) {
        this.mapper = mapper;
    }

    @Transactional
    public boolean transfer(int outid, int inid, double money){
        // 转出
        boolean out = mapper.out(outid, money);
        int i = 1/0;
        // 转入
        boolean in = mapper.in(inid, money);
        return out && in;
    }
}

事务的详细配置

传播行为

	事务传播行为(propagation behavior)指的就是当一个事务方法被另一个事务方法调用时,这个事务方法应该如何进行。 
	例如:methodA事务方法调用methodB事务方法时,methodB是继续在调用者methodA的事务中运行呢,还是为自己开启一个新事务运行,这就是由methodB的事务传播行为决定的。
  • REQUIRED

如果存在一个事务,则支持当前事务。如果没有事务则开启一个新的事务。 
  • SUPPORTS

如果存在一个事务,支持当前事务。如果没有事务,则非事务的执行。
一般 查询方式使用该方式

隔离级别

隔离级别 对应值 可能产生的问题
读未提交 read_uncommitted 脏读
读已提交 read_committed 不可重复读
可重复读 repeatable 幻读
串行化 serializable 没有问题
@Transactional(propagation = Propagation.REQUIRED,isolation = Isolation.DEFAULT)

只读

read-only

@Transactional(propagation = Propagation.REQUIRED,isolation = Isolation.DEFAULT,readOnly = true)

事务超时时间设定

timeout

触发回滚的异常类型

rollback-for
no-rollback-for

// 一旦出现 空指针异常 , 回滚操作
@Transactional(rollbackFor = NullPointerException.class)
相关标签: 整合