MyBatis是一款优秀的持 久层框架,原名叫作iBaits, 2010 年由ApacheSoftwareFoundation迁移到Google Code并改名为MyBatis,2013年,又迁移到GitHub.上。MyBatis 支持定制化SQL、存储过程以及高级映射。MyBatis几乎避免了所有的JDBC代码手动设置参数以及获取结果集。在传统的SSM框架整合中,使用MyBatis需要大量的XML配置,而在Spring Boot 中,MyBatis 官方提供了一套自动化配置方案,可以做到MyBatis开箱即用。具体使用步骤如下。
创建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>
在数据库中创建表,代码如下:
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表,同时添加两条测试语句。
在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
创建Book实体类,代码如下:
@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class Book {
private Integer id;
private String name;
private String author;
}
创建BookMapper,代码如下:
@Mapper
public interface BookMapper {
int addBook (Book book) ;
int deleteBookById (Integer id) ;
int updateBookById(Book book) ;
Book getBookById() ;
List<Book> getAllBooks() ;
}
代码解释:
在与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>
代码解释:
创建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);
}
}
在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 基本上实现了开箱即用的特性。自动化配置将开发者从繁杂的配置文件中解脱出来,以专注于业务逻辑的开发。
JdbcTemplate可以配置多数据源,MyBatis 也可以配置,但是步骤要稍微复杂一些。
创建两个数据库。两个库中都创建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, '水浒传', '施耐庵');
创建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数据库连接池和监控。
在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
配置两个数据源,区别主要是数据库不同,其他都是一样的。
创建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();
}
}
代码解释:
配置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());
}
}
代码解释:
当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());
}
}
分别在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将操作不同的数据源。
简便起见,这里直接将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中的查询方法。
在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
最后,在浏览器地址栏输入“http://localhost:8080/test1",控制台打印日志。JdbcTemplate多数据源配置成功。
books1:[Book(id=1, name=三国演义, author=罗贯中)]
books2: [Book(id=2, name=水浒传, author=施耐庵)]