Mybatis 框架,如何在insert的同时获取自增的主键?


Mybatis 框架,在insert的同时获取自增的主键

在 MyBatis 中,当你插入一条记录并且想要获取自增主键(通常是数据库自动产生的 ID)时,可以通过使用 <insert> 标签内的 useGeneratedKeyskeyProperty 属性来实现。

下面是一个例子,展示如何在 MyBatis 的映射文件中插入一条记录并返回自增主键:

假设你有一个 User 类,其中包含 id 字段作为主键,你希望在插入新用户后能够获取这个自动生成的 ID。

  1. 首先,在你的实体类中确保主键字段有对应的 getter 和 setter 方法。(也可以使用注解,不用手动写出来)

    @Data
    public class User {
        private Long id;
    
        private String name;
    
        private Integer age;
    
        private String email;
    
        public User() {
        }
    
        public User(Long id, String name, Integer age, String email) {
            this.id = id;
            this.name = name;
            this.age = age;
            this.email = email;
        }
    }
    
  2. 在 MyBatis 的映射文件中使用 useGeneratedKeyskeyProperty 属性

    假设你的映射文件是 UserMapper.xml

    <insert id="save" useGeneratedKeys="true" keyProperty="id">
            insert into User(name, age, email)
            values (#{name}, #{age}, #{email})
    </insert>
    

    这里 useGeneratedKeys="true" 表示启用生成主键的功能,而 keyProperty="id" 指定将生成的主键值设置到 User 对象的 id 属性上。

  3. 在 Java 代码中调用插入方法

    当你调用这个插入方法时,传入的 User 对象的 id 将会被设置为数据库生成的主键值。

    测试类

    @SpringBootTest
    public class UserServiceTest {
        @Resource
        private UserService userService;
    
        @Test
        public void testAddUser() {
            User user = new User();
            user.setName("1号用户");
            user.setAge(18);
            user.setEmail("123465@qq.com");
            int result = userService.saveUser(user);
            System.out.println(result + "--------" + user.getId());
    
        }
    }
    

    service层:

    public interface UserService {
        List<User> getAllUser();
    
        int saveUser(User user);
    }
    

    impl实现类:

    @Service
    public class UserServiceImpl implements UserService {
        @Autowired
        private UserMapper  userMapper;
    
        @Override
        public int saveUser(User user) {
            return userMapper.save(user);
        }
    }
    

    mapper层:

    public interface UserMapper {
        List<User> queryAllUser();
    
        int save(User user);
    }
    

    调用 insertUser 方法后,MyBatis自动填充 入参对象User 对象的 id 属性。

    注意,是自动填充你的入参对象里的字段,不需要你在代码中特意添加返回类型。

    如果mapper层上的入参使用的是 @Param 注解,给参数去了别名 那在sql中也要带上别名

    public interface UserMapper {
        List<User> queryAllUser();
    
        int save(@Param("user")User user);
    }
    
    <insert id="save" useGeneratedKeys="true" keyProperty="user.id">
            insert into User(name, age, email)
            values (#{user.name}, #{user.age}, #{user.email})
    </insert>
    

    至于,keyProperty属性中参数所要 指定对应的JavaBean对象中属性要不要也加上相应的别名,目前测试着加不加都行

    测试环境是:

    • spring boot 2.6.13
    • mybatis-spring-boot-starter:2.2.2
    • mybatis:3.5.9
    • mybatis-spring:2.0.7
    • mybatis-plus-boot-starter:3.5.5

    我个人选择倾向选择不加,万一报错,还能先考虑到是不是没加别名的原因,排除一个错误可能。


    特别注意,返回类型为 int 表示插入操作影响的行数,通常情况下,如果插入成功,这个值会是 1。但如果你不关心影响的行数,也可以将返回类型更改为 void

    另外还有一点需要注意: Integer、Long 、Boolean都可以作为insert, delete, update的返回值。

    在 MyBatis 中,insert 语句本身通常不会返回任何值,因为 SQL 的 INSERT 语句设计上就是用来插入数据并不返回任何结果的。但是,MyBatis 提供了一些机制来处理插入操作后的一些需求,比如获取自动生成的主键。

    如果你想要返回除自增主键外的其他值,可能需要使用存储过程或者在插入之后执行另一个查询来获取所需的值。但是,在标准的 SQL 插入语句中,直接返回非自动生成的值是不常见的。

请注意,这种方法依赖于你的数据库支持自增主键功能,比如 MySQL 的 AUTO_INCREMENT。对于不同的数据库,自增主键的实现可能略有不同,但基本原理是相似的。

另外,如果你使用的是 MyBatis Generator 自动生成的代码,通常这些设置会自动为你处理好。如果你手动编写映射文件,那么遵循上述步骤即可。


加餐: keyColumn keyProperty useGeneratedKeys 这3个属性的用法和使用场景

在 MyBatis 中,当你在执行插入操作并需要获取由数据库自动生成的键值时,keyColumn, keyProperty, 和 useGeneratedKeys 这三个属性就变得非常有用。它们主要用于处理自增主键或者其他类型的自动产生的唯一标识符。下面分别解释这三个属性的含义和使用场景:

1. useGeneratedKeys

这个属性用于指示 MyBatis 是否应该尝试获取由数据库生成的键。当设置为 true 时,MyBatis 将尝试从数据库中检索生成的键值,并将其设置到映射的对象上。

使用场景:

  • 当你使用自增主键(如 MySQL 的 AUTO_INCREMENT)或者序列(如 PostgreSQL 的 SEQUENCE)时,需要在插入数据后获取这个自动生成的键值。

2. keyProperty

这个属性指定一个 JavaBean 属性的名字,MyBatis 会在插入操作后将数据库生成的键值设置到该属性上。通常,这会是你的实体类中的一个字段,例如 id

使用场景:

  • 当你需要将数据库生成的键值保存到你的 Java 对象中,以便于后续使用或返回给调用者。

3. keyColumn

这个属性指定了数据库表中生成键所在的列的名称。这在数据库有多个可能的候选键或自增列的情况下尤为重要,确保 MyBatis 知道应该关注哪一列。

使用场景:

  • 当你的表中有多个候选键或自增列时,需要明确告诉 MyBatis 应该关注哪一列。
  • 在某些数据库中,例如 Oracle,可能会有多个列通过触发器或其他机制生成键值。

综合使用示例

假设你有一个 User 类,其中包含一个 id 字段作为主键,并且你在数据库中使用自增主键。

方式一:XML 映射文件中使用(二选一)

<insert id="insertUser" useGeneratedKeys="true" keyProperty="id" keyColumn="id">
    INSERT INTO user (username, password) VALUES (#{username}, #{password})
</insert>

方式二:注解中使用(二选一)

@Insert("INSERT INTO user (username, password) VALUES (#{username}, #{password})")
@Options(useGeneratedKeys = true, keyProperty = "id", keyColumn = "id")
public int insertUser(User user);

以上配置将确保在插入用户后,User 实体中的 id 字段会被数据库自动生成的键值填充。这样你就可以立即使用这个 ID 进行其他操作,例如立即获取刚插入的用户记录等。

综上所述:

一般情况,只需要有useGeneratedKeys="true" keyProperty="id"2个属性一起搭配使用就行。

二般情况下,数据库的表有多个可能的候选键或自增列,为确保 MyBatis 知道应该关注哪一列,才需要keyColumn属性指定数据库表中生成键所在的列的名称。

SpringBoot
SpringCloud
JAVA-技能点
知识点