Spring Boot 整合MyBatis

整合MyBatis

MyBatis是一款优秀的持 久层框架,原名叫作iBaits, 2010 年由ApacheSoftwareFoundation迁移到Google Code并改名为MyBatis,2013年,又迁移到GitHub.上。MyBatis 支持定制化SQL、存储过程以及高级映射。MyBatis几乎避免了所有的JDBC代码手动设置参数以及获取结果集。在传统的SSM框架整合中,使用MyBatis需要大量的XML配置,而在Spring Boot 中,MyBatis 官方提供了一套自动化配置方案,可以做到MyBatis开箱即用。具体使用步骤如下。

1. 创建项目

创建Spring Boot项目,添加MyBatis依赖、数据库驱动依赖以及数据库连接池依赖,代码如下:

<dependency>
    <groupId>org.springframework.bootgroupId>
    <artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
    <groupId>org.mybatis.spring.bootgroupId>
    <artifactId>mybatis-spring-boot-starterartifactId>
    <version>2.2.2version>
dependency>
<dependency>
    <groupId>mysqlgroupId>
    <artifactId>mysql-connector-javaartifactId>
    <scope>runtimescope>
dependency>
<dependency>
    <groupId>com.alibabagroupId>
    <artifactId>druidartifactId>
    <version>1.2.8version>
dependency>
<dependency>
    <groupId>org.projectlombokgroupId>
    <artifactId>lombokartifactId>
    <optional>trueoptional>
dependency>

2. 创建表

在数据库中创建表,代码如下:

DROP TABLE IF EXISTS `book`;
CREATE TABLE `book`  (
  `id` int NOT NULL AUTO_INCREMENT,
  `name` varchar(128) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `author` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

INSERT INTO `book` VALUES (1, '三国演义', '罗贯中');
INSERT INTO `book` VALUES (2, '水浒传', '施耐庵');

创建数据库,在库中创建book表,同时添加两条测试语句。

3. 数据库配置

在application.yml中配置数据库基本连接信息:

spring:
  datasource:
    username: admin
    password: 123456
    #?serverTimezone=UTC解决时区的报错
    url: jdbc:mysql://120.55.61.170:3306/suohechuan?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8
    driver-class-name: com.mysql.cj.jdbc.Driver
    type: com.alibaba.druid.pool.DruidDataSource
    
    #Spring Boot 默认是不注入这些属性值的,需要自己绑定
    #druid 数据源专有配置
    initialSize: 5
    minIdle: 5
    maxActive: 20
    maxWait: 60000
    timeBetweenEvictionRunsMillis: 60000
    minEvictableIdleTimeMillis: 300000
    validationQuery: SELECT 1 FROM DUAL
    testWhileIdle: true
    testOnBorrow: false
    testOnReturn: false
    poolPreparedStatements: true

4. 创建实体类

创建Book实体类,代码如下:

@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class Book {
    private Integer id;
    private String name;
    private String author;
}

5. 创建数据库访问层

创建BookMapper,代码如下:

@Mapper
public interface BookMapper {
    int addBook (Book book) ;
    int deleteBookById (Integer id) ;
    int updateBookById(Book book) ;
    Book getBookById() ;
    List<Book> getAllBooks() ;
}

代码解释:

  • 在项目的根包下 面创建-一个子 包Mapper,在Mapper中创建BookMapper.
  • 有两种方式指明该类是一个 Mapper: 第-种如前面的代码所示,在BookMapper. 上 添加@Mapper注解,表明该接口是一个MyBatis中的Mapper,这种方式需要在每一个Mapper上都添加注解;还有一种简单的方式是在配置类(比如@SpringBootApplication上面)上添加@MapperScan(“org.sang.mappr”)注解,表示扫描org.sang.mapper 包下的所有接口作为Mapper, 这样就不需要在每个接口上配置@Mapper注解了。

6. 创建BookMapper.xml

在与BookMapper相同的位置创建BookMapper.xml文件,代码如下:


DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace= "com.example.testspringboot.BookMapper">
<insert id="addBook" parameterType= "com.example.testspringboot.Book">
    INSERT INTO book (name, author) VALUES (# {name}, # {author})
insert>
<delete id="deleteBookById" parameterType="int">
    DELETE FROM book WHERE id=#{id}
delete>
<update id="updateBookById" parameterType="com.example.testspringboot.Book">
    UPDATE book set name=# { name }, author=# {author} WHERE id=#{id}
update>
<select id="getBookById" parameterType="int" resultType="com.example.testspringboot.Book">
    SELECT * FROM book WHERE id=#{id}
select>
<select id="getAllBooks" resultType="com.example.testspringboot.Book">
    SELECT * FROM book
select>
mapper>

代码解释:

  • 针对 BookMapper接口中的每一个方法都在BookMapper.xml中列出了实现。
  • #{}用来代替接口中的参数,实体类中的属性可以直接通过#{实体类属性名}获取。

7. 创建Service和Controller

创建BookService与BookController,代码如下:

@Service
public class BookService {
    @Autowired
    BookMapper bookMapper;

    public int addBook(Book book) {
        return bookMapper.addBook(book);
    }

    public int updateBook(Book book) {
        return bookMapper.updateBookById(book);
    }

    public int deleteBookById(Integer id) {
        return bookMapper.deleteBookById(id);
    }

    public Book getBookById(Integer id) {
        return bookMapper.getBookById(id);
    }

    public List<Book> getAllBooks() {
        return bookMapper.getAllBooks();

    }
}
@RestController
public class BookController {
    @Autowired
    BookService bookService;

    @GetMapping("/bookOps")
    public void bookOps() {
        Book b1 = new Book();
        b1.setName("西厢记");
        b1.setAuthor("王实甫");
        int i = bookService.addBook(b1);
        System.out.println("addBook>>>" + i);
        Book b2 = new Book();
        b2.setId(1);
        b2.setName("朝花夕拾");
        b2.setAuthor("鲁迅");
        int updateBook = bookService.updateBook(b2);
        System.out.println("updateBook>>" + updateBook);
        Book b3 = bookService.getBookById(1);
        System.out.println("getBookById>>>" + b3);
        int delete = bookService.deleteBookById(2);
        System.out.println("deleteBookById>>" + delete);
        List<Book> allBooks = bookService.getAllBooks();
        System.out.println("getAllBooks>>>" + allBooks);
    }
}

8. 配置pom.xml文件

在Maven工程中,XML配置文件建议写在resources目录下,但是上文的Mapper.xml文件写在包下,Maven在运行时会忽略包下的XML文件,因此需要在pom.xml文件中重新指明资源文件位置,配置如下:

<build>
    <resources>
        <resource>
            <directory>src/main/javadirectory>
            <includes>
                <include>**/*.xmlinclude>
            includes>
        resource>
        <resource>
            <directory>src/main/resourcesdirectory>
        resource>
        	<includes>
                <include>**/*include>
            includes>
    resources>
build>

为了让dao可以找到xml文件,还需要在application.properties中加入

mybatis.type-aliases-package=com.example.testspringboot
mybatis.mapper-locations=com/example/testspringboot/mapper1/*.xml,com/example/testspringboot/mapper2/*.xml
mybatis.mapper-locations=classpath:mapper/*.xml
#SpringBoot 开启 Mybatis 日志
logging.level.org.sysu.rain.Mapper=debug
#注意:其中org.sysu.rain是Mapper包位置 ,等号后面是日志等级。

接下来在浏览器中输入“http://localhost:8080/bookOps" ,即可看到数据库中数据的变化,控制台也打印出相应的日志。

addBook>>>1
updateBook>>1
getBookById>>>Book(id=1, name=朝花夕拾, author=鲁迅)
deleteBookById>>1
getAllBooks>>>[Book(id=1, name=朝花夕拾, author=鲁迅), Book(id=7, name=西厢记, author=王实甫)]

通过上面的例子可以看到,MyBatis 基本上实现了开箱即用的特性。自动化配置将开发者从繁杂的配置文件中解脱出来,以专注于业务逻辑的开发。

MyBatis多数据源

JdbcTemplate可以配置多数据源,MyBatis 也可以配置,但是步骤要稍微复杂一些。

1. 创建数据库

创建两个数据库。两个库中都创建book表,再各预设1条数据,创建脚本如下:

第一个数据库中

DROP TABLE IF EXISTS `book`;
CREATE TABLE `book`  (
  `id` int NOT NULL AUTO_INCREMENT,
  `name` varchar(128) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `author` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

INSERT INTO `book` VALUES (1, '三国演义', '罗贯中');

第二个数据库中

DROP TABLE IF EXISTS `book`;
CREATE TABLE `book`  (
  `id` int NOT NULL AUTO_INCREMENT,
  `name` varchar(128) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `author` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

INSERT INTO `book` VALUES (1, '水浒传', '施耐庵');

2. 创建项目

创建Spring Boot Web项目,添加如下依赖:

<dependency>
    <groupId>org.springframework.bootgroupId>
    <artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
    <groupId>mysqlgroupId>
    <artifactId>mysql-connector-javaartifactId>
    <scope>runtimescope>
dependency>
<dependency>
    <groupId>org.mybatis.spring.bootgroupId>
    <artifactId>mybatis-spring-boot-starterartifactId>
    <version>2.2.2version>
dependency>
<dependency>
    <groupId>com.alibabagroupId>
    <artifactId>druid-spring-boot-starterartifactId>
    <version>1.2.8version>
dependency>
<dependency>
    <groupId>org.projectlombokgroupId>
    <artifactId>lombokartifactId>
    <optional>trueoptional>
dependency>

注意这里添加的数据库连接池依赖是druid-spring-boot-starter。 druid-spring-boot-starter 可以帮助开发者在SpringBoot项目中轻松集成Druid数据库连接池和监控。

3. 配置数据库连接

在application.properties中配置数据库连接信息,代码如下:

spring:
  datasource:
  	#数据源1
    one:
      username: admin
      password: 123456
      #?serverTimezone=UTC解决时区的报错
      url: jdbc:mysql://120.55.61.170:3306/suohechuan?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8
      driver-class-name: com.mysql.cj.jdbc.Driver
      type: com.alibaba.druid.pool.DruidDataSource
    #数据源2
    two:
      username: fristweb
      password: dTNFJW4B5MrwT4KS
      #?serverTimezone=UTC解决时区的报错
      url: jdbc:mysql://120.55.61.170:3306/fristweb?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8
      driver-class-name: com.mysql.cj.jdbc.Driver
      type: com.alibaba.druid.pool.DruidDataSource
    
    #Spring Boot 默认是不注入这些属性值的,需要自己绑定
    #druid 数据源专有配置
    initialSize: 5
    minIdle: 5
    maxActive: 20
    maxWait: 60000
    timeBetweenEvictionRunsMillis: 60000
    minEvictableIdleTimeMillis: 300000
    validationQuery: SELECT 1 FROM DUAL
    testWhileIdle: true
    testOnBorrow: false
    testOnReturn: false
    poolPreparedStatements: true

配置两个数据源,区别主要是数据库不同,其他都是一样的。

4. 配置数据源

创建DataSourceConfig配置数据源,根据application.properties中的配置生成两个数据源:

@Configuration
public class DataSourceConfig {
    @Bean
    @ConfigurationProperties("spring.datasource.one")
    DataSource dsOne(){
        return DruidDataSourceBuilder.create().build();
    }
    @Bean
    @ConfigurationProperties("spring.datasource.two")
    DataSource dsTwo(){
        return DruidDataSourceBuilder.create().build();
    }
}

代码解释:

  • DataSourceConfig中提供了两个数据源: dsOne 和dsTwo,默认方法名即实例名。
  • @ConfigurationProperties 注解表示使用不同前缀的配置文件来创建不同的DataSource实例。

5.创建MyBatis配置

配置MyBatis,主要提供SqlSessionFactory实例和SqlSessionTemplate实例,代码如下:

@Configuration
@MapperScan(value = "com.example.testspringboot.mapper1",sqlSessionFactoryRef ="sqlSessionFactoryBean1")
public class MyBatisConfigOne {
    @Autowired
    @Qualifier("dsOne")
    DataSource dsOne;
    @Bean
    SqlSessionFactory sqlSessionFactoryBean1() throws Exception {
        SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
        factoryBean.setDataSource(dsOne);
        return factoryBean.getObject();
    }

    @Bean
    SqlSessionTemplate sqlSessionTemplate1() throws Exception {
        return new SqlSessionTemplate(sqlSessionFactoryBean1());
    }
}

代码解释:

  • 在@MapperScan 注解中指定Mapper接口所在的位置,同时指定SqlSessionFactory的实例名,则该位置下的Mapper将使用SqlSessionFactory 实例。
  • 提供SqlSessionFactory 的实例,直接创建出来,同时将DataSource 的实例设置给SqlSessionFactory,这里创建的SqlSessionFactory 实例也就是@MapperScan注解中sqlSessionFactoryRef参数指定的实例。
  • 提供一个SqlSessionTemplate 实例。这是一个线程安全类,主要用来管理MyBatis 中的SqlSession操作。

当MyBatisConfigOne创建成功后,参考MyBatisConfigOne 创建MyBatisConfigTwo,代码如下:

@Configuration
@MapperScan(value = "com.example.testspringboot.mapper2",sqlSessionFactoryRef ="sqlSessionFactoryBean2")
public class MyBatisConfigTwo {
    @Autowired
    @Qualifier("dsTwo")
    DataSource dsTwo;
    @Bean
    SqlSessionFactory sqlSessionFactoryBean2() throws Exception {
        SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
        factoryBean.setDataSource(dsTwo);
        return factoryBean.getObject();
    }

    @Bean("sqlSessionFactoryBean2")
    SqlSessionTemplate sqlSessionTemplate2() throws Exception {
        return new SqlSessionTemplate(sqlSessionFactoryBean2());
    }
}

6. 创建Mapper

分别在org.sang.mapper1和org.sang.mapper2包下创建两个不同的Mapper以及相应的Mapper映射文件,代码如下。

org.sang.mapper中:

public interface BookMapper {
    List<Book> getAllBooks() ;
}

DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace= "com.example.testspringboot.mapper1.BookMapper">
    <select id="getAllBooks" resultType="com.example.testspringboot.Book">
        select * from book;
    select>
mapper>

org. sang.mapper2中:

public interface BookMapper2 {
    List<Book> getAllBooks () ;
}

DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace= "com.example.testspringboot.mapper2.BookMapper2">
    <select id="getAllBooks" resultType="com.example.testspringboot.Book">
        select * from book;
    select>
mapper>

这两个不同的Mapper将操作不同的数据源。

7. 创建Controller

简便起见,这里直接将Mapper注入Controller中,代码如下:

@RestController
public class BookController {
    @Autowired
    BookMapper bookMapper;
    @Autowired
    BookMapper2 bookMapper2;

    @GetMapping("/test1")
    public void test1() {
        List<Book> books1 = bookMapper.getAllBooks();
        List<Book> books2 = bookMapper2.getAllBooks();
        System.out.println("books1:" + books1);
        System.out.println("books2 :" + books2);
    }
}

在Controller中注入两个不同的Mapper,然后调用两个Mapper中的查询方法。

8. 配置pom.xml文件

在Maven工程中,XML配置文件建议写在resources目录下,但是上文的Mapper.xml文件写在包下,Maven在运行时会忽略包下的XML文件,因此需要在pom.xml文件中重新指明资源文件位置,配置如下:

<build>
    <resources>
        <resource>
            <directory>src/main/javadirectory>
            <includes>
                <include>**/*.xmlinclude>
            includes>
        resource>
        <resource>
            <directory>src/main/resourcesdirectory>
        resource>
        	<includes>
                <include>**/*.xmlinclude>
            includes>
    resources>
build>

为了让dao可以找到xml文件,还需要在application.properties中加入

mybatis.type-aliases-package=com.example.testspringboot
mybatis.mapper-locations=com/example/testspringboot/mapper1/*.xml,com/example/testspringboot/mapper2/*.xml
mybatis.mapper-locations=classpath:mapper/*.xml

7. 测试

最后,在浏览器地址栏输入“http://localhost:8080/test1",控制台打印日志。JdbcTemplate多数据源配置成功。

books1:[Book(id=1, name=三国演义, author=罗贯中)]
books2: [Book(id=2, name=水浒传, author=施耐庵)]

你可能感兴趣的:(Spring,Boot,java)