Mybatis 是一个流行的 orm 框架。它可以用XML维护SQL语句,非常灵活。这是很多开发者选择它作为orm框架的关键。
-
mvnrepository:https ://mvnrepository.com/artifact/org.mybatis/mybatis
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.9</version>
</dependency>
在 Spring Boot 应用程序中使用 mybatis 很容易。只需几个步骤。
本文重点介绍“如何在spring boot中集成mybatis”。不解释mybatis的详细用法。有问题可以参考mybatis官方文档。
创建一个 Maven 项目
成立
基本依赖项是:mysql driver
, database connection pool
, mybatis-spring-boot-starter
.
使用官方提供的mybatis-spring-boot-starter更加方便。
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>io.springcloud</groupId>
<artifactId>springboot-mybatis</artifactId>
<version>0.0.1-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.6.4</version>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<encoding>UTF-8</encoding>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-undertow</artifactId>
</dependency>
<!-- MYSQL driver is required -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- Using the high-performance HikariCP database connection pool -->
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
</dependency>
<!-- MyBatis starter -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.2.2</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<executable>true</executable>
</configuration>
</plugin>
</plugins>
</build>
</project>
映射器接口定义
创建一个 Mapper 接口,其实现将在应用程序运行时动态生成。只是作为一个演示,所以它不是太复杂。只提供了一个简单的查询方法now
。获取数据库服务器上的时间。
package io.springcloud.mybatis.mapper;
import java.time.LocalDateTime;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface FooMapper {
LocalDateTime now();
}
映射器 xml 文件
我将xml文件放在src/main/resources/mapper
目录中。
<!-- foo-mapper.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="io.springcloud.mybatis.mapper.FooMapper">
<select id="now" resultType="java.time.LocalDateTime">
SELECT NOW();
</select>
</mapper>
应用程序.yaml
server:
port: 80
logging:
# Set the log level of the package where the mapper interface is located to DEBUG, so that you can see more detailed SQL execution logs.
level:
"io.springcloud.mybatis.mapper": "DEBUG"
spring:
# MYSQL data source configuration. No need to explain too much.
datasource:
type: com.zaxxer.hikari.HikariDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/demo?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&allowMultiQueries=true
username: root
password: root
mybatis:
# Set the xml configuration file address for mybatis.
# config-location: "classpath:mybatis/mybatis-config.xml"
# Loads all files in the 'mapper' directory (regardless of directory hierarchy) with names ending in '-mapper.xml'.
mapper-locations:
- "classpath:mapper/**/*-mapper.xml"
mybatis.config-location
用于设置mybatis的xml配置文件的路径。配置文件可以让你配置mybatis的插件、缓存等,对于demo项目,这个配置不是必须的。如果想了解更多,可以参考官方文档。
mybatis.mapper-locations
是关键配置。它指定了为映射器接口加载文件的路径xml
(可以使用通配符)。如果配置不正确,没有正确加载xml文件,那么运行时会出现异常:org.apache.ibatis.binding.BindingException: Invalid bound statement (not found)...
如果
xml
文件不在当前项目中,例如在另一个 jar 包中。然后你需要使用classpath*:
作为路径前缀。
Mybatis这里的配置项比较多,可以通过配置类org.mybatis.spring.boot.autoconfigure.MybatisProperties
或者官方文档查看。
注释驱动程序
通过注解设置mapper
接口所在的包(可以有多个) 。@MapperScan
注释类也可以通过annotationClass
属性设置。例如annotationClass = Mapper.class
. @Mapper
然后只加载带有注释的接口。
package io.springcloud.mybatis;
import org.apache.ibatis.annotations.Mapper;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@MapperScan(basePackages = { "io.springcloud.mybatis.mapper" }, annotationClass = Mapper.class)
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
测试
一切准备就绪后就可以出发了。通过运行测试来验证一切是否正常。
package io.springcloud.test;
import java.time.format.DateTimeFormatter;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import io.springcloud.mybatis.Application;
import io.springcloud.mybatis.mapper.FooMapper;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.test.annotation.Rollback;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@SpringBootTest(classes = Application.class, webEnvironment = WebEnvironment.RANDOM_PORT)
public class ApplicationTest {
static final Logger LOGGER = LoggerFactory.getLogger(ApplicationTest.class);
@Autowired
FooMapper fooMapper;
@Test
@Transactional(readOnly = true)
@Rollback(false)
public void test () {
LOGGER.info("result={}", this.fooMapper.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
}
}
控制台输出的关键日志如下:
2022-03-10 18:55:59.606 INFO 10860 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Starting...
2022-03-10 18:56:00.300 INFO 10860 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Start completed.
2022-03-10 18:56:00.311 INFO 10860 --- [ main] o.s.t.c.transaction.TransactionContext : Began transaction (1) for test context [DefaultTestContext@457c9034 testClass = ApplicationTest, testInstance = io.springcloud.test.ApplicationTest@c7ba306, testMethod = test@ApplicationTest, testException = [null], mergedContextConfiguration = [WebMergedContextConfiguration@345f69f3 testClass = ApplicationTest, locations = '{}', classes = '{class io.springcloud.mybatis.Application}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{org.springframework.boot.test.context.SpringBootTestContextBootstrapper=true, server.port=0}', contextCustomizers = set[org.springframework.boot.test.context.filter.ExcludeFilterContextCustomizer@c730b35, org.springframework.boot.test.json.DuplicateJsonObjectContextCustomizerFactory$DuplicateJsonObjectContextCustomizer@22555ebf, org.springframework.boot.test.mock.mockito.MockitoContextCustomizer@0, org.springframework.boot.test.web.client.TestRestTemplateContextCustomizer@10683d9d, org.springframework.boot.test.autoconfigure.actuate.metrics.MetricsExportContextCustomizerFactory$DisableMetricExportContextCustomizer@662ac478, org.springframework.boot.test.autoconfigure.properties.PropertyMappingContextCustomizer@0, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverContextCustomizerFactory$Customizer@3d285d7e, org.springframework.boot.test.context.SpringBootTestArgs@1, org.springframework.boot.test.context.SpringBootTestWebEnvironment@3c407114], resourceBasePath = 'src/main/webapp', contextLoader = 'org.springframework.boot.test.context.SpringBootContextLoader', parent = [null]], attributes = map['org.springframework.test.context.web.ServletTestExecutionListener.activateListener' -> false, 'org.springframework.test.context.event.ApplicationEventsTestExecutionListener.recordApplicationEvents' -> false]]; transaction manager [org.springframework.jdbc.support.JdbcTransactionManager@118fbaf0]; rollback [false]
2022-03-10 18:56:01.061 DEBUG 10860 --- [ main] i.s.mybatis.mapper.FooMapper.now : ==> Preparing: SELECT NOW();
2022-03-10 18:56:01.100 DEBUG 10860 --- [ main] i.s.mybatis.mapper.FooMapper.now : ==> Parameters:
2022-03-10 18:56:01.141 DEBUG 10860 --- [ main] i.s.mybatis.mapper.FooMapper.now : <== Total: 1
2022-03-10 18:56:01.146 INFO 10860 --- [ main] io.springcloud.test.ApplicationTest : result=2022-03-10 18:56:01
2022-03-10 18:56:01.161 INFO 10860 --- [ main] o.s.t.c.transaction.TransactionContext : Committed transaction for test: [DefaultTestContext@457c9034 testClass = ApplicationTest, testInstance = io.springcloud.test.ApplicationTest@c7ba306, testMethod = test@ApplicationTest, testException = [null], mergedContextConfiguration = [WebMergedContextConfiguration@345f69f3 testClass = ApplicationTest, locations = '{}', classes = '{class io.springcloud.mybatis.Application}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{org.springframework.boot.test.context.SpringBootTestContextBootstrapper=true, server.port=0}', contextCustomizers = set[org.springframework.boot.test.context.filter.ExcludeFilterContextCustomizer@c730b35, org.springframework.boot.test.json.DuplicateJsonObjectContextCustomizerFactory$DuplicateJsonObjectContextCustomizer@22555ebf, org.springframework.boot.test.mock.mockito.MockitoContextCustomizer@0, org.springframework.boot.test.web.client.TestRestTemplateContextCustomizer@10683d9d, org.springframework.boot.test.autoconfigure.actuate.metrics.MetricsExportContextCustomizerFactory$DisableMetricExportContextCustomizer@662ac478, org.springframework.boot.test.autoconfigure.properties.PropertyMappingContextCustomizer@0, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverContextCustomizerFactory$Customizer@3d285d7e, org.springframework.boot.test.context.SpringBootTestArgs@1, org.springframework.boot.test.context.SpringBootTestWebEnvironment@3c407114], resourceBasePath = 'src/main/webapp', contextLoader = 'org.springframework.boot.test.context.SpringBootContextLoader', parent = [null]], attributes = map['org.springframework.test.context.web.ServletTestExecutionListener.activateListener' -> false, 'org.springframework.test.context.event.ApplicationEventsTestExecutionListener.recordApplicationEvents' -> false]]
一切都好。
概括
如您所见,这很简单。让我们总结一下关键步骤。
- 添加所需的依赖项(数据库驱动程序、数据源、mybats 启动器)。
- 在配置文件中设置
mybatis.mapper-locations
属性。application
这用于设置映射器接口的xml文件的加载路径。 - 通过注解设置mapper接口的包路径
@MapperScan
。