当前位置 : 首页 » 文章分类 :  开发  »  Spring-整合MyBatis

Spring-整合MyBatis

Spring 整合 MyBatis 笔记

mybatis-spring 官方中文文档
http://www.mybatis.org/spring/zh/index.html

MyBatis-Spring-Boot-Starter官方文档
http://www.mybatis.org/spring-boot-starter/mybatis-spring-boot-autoconfigure/index.html


事务内切换数据源失败问题

@Transactional 注解的方法内 切换数据源会失败。

解决方法:
1、在事务外切换数据源,比如想切换到从库查询数据,在事务外切换到从库查到数据后再切换回原来的数据源,然后把查到的数据作为一个参数传入到事务方法中。
2、我们总监说的,在使用的时候,标注上
@Transactional(propagation=NOT_SUPPORTED)
把现有的事务挂起就好了

Invalid bound statement (not found)

一开始以为是没有配 maven 的 <build> <resources> <resource>,导致mapper.xml没有打包进去,从而找不到xml,后来仔细检查发现.xml在包中,但还是提示这个错误。
https://blog.csdn.net/hello_world_qwp/article/details/79030823
https://blog.csdn.net/k469785635/article/details/77532512

后来发现是application.properties中没有配置 mybatis.mapperLocations 属性

mybatis.mapperLocations=classpath:mapper/*.xml

mybatis.mapperLocations 属性

当mybatis的xml文件和mapper接口不在相同包下时,需要用mapperLocations属性指定xml文件的路径。*是个通配符,代表所有的文件,**代表所有目录下

如果Mapper.xml与Mapper.class在同一个包下且同名,spring扫描Mapper.class的同时会自动扫描同名的Mapper.xml并装配到Mapper.class。
如果Mapper.xml与Mapper.class不在同一个包下或者不同名,就必须使用配置mapperLocations指定mapper.xml的位置。
此时spring是通过识别mapper.xml中的 <mapper namespace="com.fan.mapper.UserDao"> namespace的值来确定对应的Mapper.class的。

官方文档:
如果 MyBatis 映射器 XML 文件在和映射器类相同的路径下不存在,那么另外一个需要 配置文件的原因就是它了。使用这个配置,有两种选择。第一是手动在 MyBatis 的 XML 配 置文件中使用<mappers>部分来指定类路径。第二是使用工厂 bean 的 mapperLocations 属 性。
mapperLocations 属性使用一个资源位置的 list。 这个属性可以用来指定 MyBatis 的 XML 映射器文件的位置。 它的值可以包含 Ant 样式来加载一个目录中所有文件, 或者从基路径下 递归搜索所有路径。比如:

<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
  <property name="dataSource" ref="dataSource" />
  <property name="mapperLocations" value="classpath*:sample/config/mappers/**/*.xml" />
</bean>

这会从类路径下加载在 sample.config.mappers 包和它的子包中所有的 MyBatis 映射器 XML 文件。

Springboot mybatis集成 Invalid bound statement (not found)
https://blog.csdn.net/qq_35981283/article/details/78590090

SqlSessionFactoryBean
http://www.mybatis.org/spring/zh/factorybean.html


Spring整合MyBatis实例

mybatis-spring 第二章 入门
http://www.mybatis.org/spring/zh/getting-started.html

添加maven依赖

<dependency>
  <groupId>org.mybatis</groupId>
  <artifactId>mybatis-spring</artifactId>
  <version>x.x.x</version>
</dependency>

配置sqlSessionFactory Bean

要和 Spring 一起使用 MyBatis,你需要在 Spring 应用上下文中定义至少两样东西:一个 SqlSessionFactory 和至少一个数据映射器mapper类。

使用xml配置

在 MyBatis-Spring 中,SqlSessionFactoryBean 是用于创建 SqlSessionFactory 的。要 配置这个工厂 bean,放置下面的代码在 Spring 的 XML 配置文件中:

<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
  <property name="dataSource" ref="dataSource" />
</bean>

要注意 SqlSessionFactory 需要一个 DataSource(数据源,译者注) 。这可以是任意 的 DataSource,配置它就和配置其它 Spring 数据库连接一样。

使用JavaConfig配置

或者使用 JavaConfig 配置

@Configuration
public class MySQLConfig {
@Primary
@Bean(name = "sqlSessionFactory")
public SqlSessionFactory sqlSessionFactoryBean() throws Exception {
    org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration();
    // 全局映射器启用缓存
    configuration.setCacheEnabled(true);
    // 查询时,关闭关联对象即时加载以提高性能
    configuration.setLazyLoadingEnabled(true);
    // 设置关联对象加载的形态,此处为按需加载字段(加载字段由SQL指 定),不会加载关联表的所有字段,以提高性能
    configuration.setAggressiveLazyLoading(false);
    // 对于未知的SQL查询,允许返回不同的结果集以达到通用的效果
    configuration.setMultipleResultSetsEnabled(true);
    // 允许使用列标签代替列名
    configuration.setUseColumnLabel(true);
    // 给予被嵌套的resultMap以字段-属性的映射支持
    configuration.setAutoMappingBehavior(AutoMappingBehavior.FULL);
    // 对于批量更新操作缓存SQL以提高性能
    configuration.setDefaultExecutorType(ExecutorType.SIMPLE);
    // 数据库超过25000秒仍未响应则超时
    configuration.setDefaultStatementTimeout(25000);
    configuration.setMapUnderscoreToCamelCase(true);
    // 允许使用自定义的主键值(比如由程序生成的UUID 32位编码作为键值),数据表的PK生成策略将被覆盖
    //configuration.setUseGeneratedKeys(true);

    Properties properties = new Properties();
    properties.setProperty("dialect", "mysql");

    ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();

    SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
    sqlSessionFactoryBean.setDataSource(dataSource());
    sqlSessionFactoryBean.setConfiguration(configuration);
    sqlSessionFactoryBean.setConfigurationProperties(properties);
    //sqlSessionFactoryBean.setConfigLocation(resolver.getResource("classpath:mybatis-config.xml"));
    sqlSessionFactoryBean.setMapperLocations(resolver.getResources("classpath*:mapper/*.xml"));
    return sqlSessionFactoryBean.getObject();
}
}

定义Mapper接口

假设你定义了一个如下的数据 mapper 接口:

public interface UserMapper {
  @Select("SELECT * FROM users WHERE id = #{userId}")
  User getUser(@Param("userId") String userId);
}

配置Mapper Bean

mybatis-spring 第六章 注入映射器
http://www.mybatis.org/spring/zh/mappers.html

MyBatis-Spring 提供了一个动态代理的实现 MapperFactoryBean。这个类 可以让你直接注入数据映射器接口到你的 service 层 bean 中。当使用映射器时,你仅仅如调 用你的 DAO 一样调用它们就可以了,但是你不需要编写任何 DAO 实现的代码,因为 MyBatis-Spring 将会为你创建代理。

MapperFactoryBean 创建的代理控制开放和关闭 session,翻译任意的异常到 Spring 的 DataAccessException 异常中。此外,如果需要或参与到一个已经存在活动事务中,代理将 会开启一个新的 Spring 事务。

数据映射器接口可以按照如下做法加入到 Spring 中:

<bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
  <property name="mapperInterface" value="org.mybatis.spring.sample.mapper.UserMapper" />
  <property name="sqlSessionFactory" ref="sqlSessionFactory" />
</bean>

要注意,所指定的映射器类必须是一个接口,而不是具体的实现类。在这个示例中,注解被用来指定 SQL 语句,但是 MyBatis 的映射器 XML 文件也可以用。

MapperFactoryBean 创建的代理类实现了 UserMapper 接口,并且注入到应用程序中。 因为代理创建在运行时环境中(Runtime,译者注) ,那么指定的映射器必须是一个接口,而 不是一个具体的实现类。

如果 UserMapper 有一个对应的 MyBatis 的 XML 映射器文件, 如果 XML 文件在类路径的 位置和映射器类相同时, 它会被 MapperFactoryBean 自动解析。 没有必要在 MyBatis 配置文件中去指定映射器 , 除非映射器的 XML 文件在不同的类路径下 。 可以参考 SqlSessionFactoryBean 的 configLocation 属性(第三章)来获取更多信息。

一旦配置好,你可以用注入其它任意 Spring 的 bean 相同的方式直接注入映射器到你的 business/service 对象中。MapperFactoryBean 处理 SqlSession 的创建和关闭它。如果使用 了 Spring 的事务,那么当事务完成时,session 将会提交或回滚。最终,任何异常都会被翻 译成 Spring 的 DataAccessException 异常。

通过Mapper Bean执行SQL

调用 MyBatis 数据方法现在只需一行代码:

public class FooServiceImpl implements FooService {

private UserMapper userMapper;

public void setUserMapper(UserMapper userMapper) {
  this.userMapper = userMapper;
}

public User doSomeBusinessStuff(String userId) {
  return this.userMapper.getUser(userId);
}
}

Spring Boot整合MyBatis实例

在IDEA中创建Spring Initializr项目

添加maven依赖

1、引入整合MyBatis的核心依赖mybatis-spring-boot-starter
2、引入连接mysql的必要依赖mysql-connector-java
3、引入spring-boot-starter-test用来做单元测试验证数据访问

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.winterchen</groupId>
    <artifactId>springboot-mybatis-demo2</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>springboot-mybatis-demo2</name>
    <description>Demo project for Spring Boot</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.8.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>1.3.1</version>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>


</project>

配置数据源

Spring Boot 默认配置文件为application.properties,在其中添加数据源配置:

spring.datasource.url=jdbc:mysql://localhost:3306/test
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.driver-class-name=com.mysql.jdbc.Driver

或者根据个人喜好改用更简洁的yml配置文件application.yml

spring:
  datasource:
     url: jdbc:mysql://127.0.0.1:3306/mytest
     username: root
     password: 123456
     driver-class-name: com.mysql.jdbc.Driver

spring boot自带的DataSourceAutoConfiguration会自动读取application.properties文件的spring.datasource.*属性并自动配置单数据源。
spring boot自动创建的默认数据源是tomcat jdbc connection pool,并将数据源自动注入到sqlSessionFactory中,sqlSessionFactory会自动注入到Mapper中,一切都不用管,直接拿起来使用就行了。


创建mysql数据表

创建数据库mytest,切换到mytest,并创建表t_user
sql语句如下:

CREATE DATABASE mytest;

USE mytest;

CREATE TABLE t_user(
  id BIGINT NOT NULL PRIMARY KEY AUTO_INCREMENT,
  name VARCHAR(255) NOT NULL ,
  password VARCHAR(255) NOT NULL ,
  phone VARCHAR(255) NOT NULL
) ENGINE=INNODB AUTO_INCREMENT=1000 DEFAULT CHARSET=utf8;

创建实体User

/**
 * User实体映射类
 * Created by Administrator on 2017/11/24.
 */

public class User {
    private Integer id;
    private String name;
    private String password;
    private String phone;
    //省略 get 和 set ...
}

创建Mapper接口

import com.xxx.User;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;

/**
 * User映射类
 * Created by Administrator on 2017/11/24.
 */
@Mapper
public interface UserMapper {

    @Select("SELECT * FROM T_USER WHERE PHONE = #{phone}")
    User findUserByPhone(@Param("phone") String phone);

    @Insert("INSERT INTO T_USER(NAME, PASSWORD, PHONE) VALUES(#{name}, #{password}, #{phone})")
    int insert(@Param("name") String name, @Param("password") String password, @Param("phone") String phone);

}

可以在Mapper类上面添加注解@Mapper来使Spring将其自动扫描为bean,但每个Mapper类都要加比较麻烦,或者在启动类中添加@MapperScan实现对所有Mapper类的自动扫描。


SpringBoot启动类

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class SpringbootMybatisDemo2Application {
    public static void main(String[] args) {
        SpringApplication.run(SpringbootMybatisDemo2Application.class, args);
    }
}

单元测试

import com.xxx.User;
import com.xxx.UserMapper;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringbootMybatisDemo2ApplicationTests {
    @Autowired
    private UserMapper userMapper;

    @Test
    public void test(){
        userMapper.insert("winterchen", "123456", "12345678910");
        User u = userMapper.findUserByPhone("12345678910");
        Assert.assertEquals("winterchen", u.getName());
    }
}

Spring boot Mybatis 整合(注解版)
https://blog.csdn.net/Winter_chen001/article/details/78622141

Spring boot Mybatis 整合(完整版)
https://blog.csdn.net/winter_chen001/article/details/77249029

spring boot(六):如何优雅的使用mybatis(更详细)
https://www.cnblogs.com/ityouknow/p/6037431.html

Spring Boot整合MyBatis(《Spring Cloud微服务实战》作者翟永超)
http://blog.didispace.com/springbootmybatis/


上一篇 Spring-@Scheduled定时任务

下一篇 Java-Jar包

阅读
2,625
阅读预计12分钟
创建日期 2018-06-26
修改日期 2018-12-20
类别
百度推荐