MyBatis是一个开源 Java 持久层框架,可以作为JDBC和Hibernate的替代品。它可以帮助我们减少代码并简化结果的检索,让我们专注于编写自定义 SQL 查询或存储过程。
在本教程中,我们将学习如何使用 MyBatis 和 Spring Boot 插入数据时返回自动生成的 ID。
依赖设置 在开始之前,让我们在pom.xml中添加mybatis-spring-boot-starter依赖项:
<dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>3.0.3</version> </dependency> |
让我们首先创建一个将在整篇文章中使用的简单示例。
1. 定义实体 首先,让我们创建一个代表汽车的简单实体类:
public class Car { private Long id; private String model; // getters and setters } |
CREATE TABLE IF NOT EXISTS CAR ( ID INTEGER PRIMARY KEY AUTO_INCREMENT, MODEL VARCHAR(100) NOT NULL ); |
2. 定义数据源 接下来,让我们指定数据源。我们将使用 H2 嵌入式数据库:
@Bean public DataSource dataSource() { EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder(); return builder .setType(EmbeddedDatabaseType.H2) .setName("testdb") .addScript("car-schema.sql") .build(); } @Bean public SqlSessionFactory sqlSessionFactory() throws Exception { SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean(); factoryBean.setDataSource(dataSource()); return factoryBean.getObject(); } |
使用注释 让我们定义Mapper,它代表 MyBatis 用于将方法绑定到相应 SQL 语句的接口:
@Mapper public interface CarMapper { // ... } |
@Insert("INSERT INTO CAR(MODEL) values (#{model})") void save(Car car); |
要检索生成的 ID,我们可以使用@Options或@SelectKey注释。
1. @Options注释 我们可以扩展插入语句的一种方法是使用@Options注释:
@Insert("INSERT INTO CAR(MODEL) values (#{model})") @Options(useGeneratedKeys = true, keyColumn = "ID", keyProperty = "id") void saveUsingOptions(Car car); |
- useGeneratedKeys – 表示我们是否要使用生成的密钥功能
- keyColumn – 设置包含键的列的名称
- keyProperty – 表示保存键值的字段名称
在后台,MyBatis 使用反射将 ID 列的值映射到Car对象的id字段中。
接下来,让我们创建一个测试来确认一切是否按预期进行:
@Test void givenCar_whenSaveUsingOptions_thenReturnId() { Car car = new Car(); car.setModel("BMW"); carMapper.saveUsingOptions(car); assertNotNull(car.getId()); } |
2. @SelectKey注释 返回 ID 的另一种方法是使用@SelectKey注释。当我们想要使用序列或身份函数来检索标识符时,此注释非常有用。
此外,如果我们使用@SelectKey注释修饰我们的方法,MyBatis 会忽略诸如@Options之类的注释。
让我们在CarMapper内部创建一个新方法来检索插入后的标识值:
@Insert("INSERT INTO CAR(MODEL) values (#{model})") @SelectKey(statement = "CALL IDENTITY()", before = false, keyColumn = "ID", keyProperty = "id", resultType = Long.class) void saveUsingSelectKey(Car car); |
- statement – 保存将在插入语句之后执行的语句
- before – 表示语句应该在插入之前还是之后执行
- keyColumn – 保存代表键的列的名称
- keyProperty – 指定将保存语句返回的值的字段的名称
- resultType – 表示keyProperty的类型
为了能够在 H2 数据库上执行CALL IDENTITY(),我们需要将模式设置为LEGACY:
"testdb;MODE=LEGACY" |
@Test void givenCar_whenSaveUsingSelectKey_thenReturnId() { Car car = new Car(); car.setModel("BMW"); carMapper.saveUsingSelectKey(car); assertNotNull(car.getId()); } |