1.6 mybatis获取自增主键

1.6 mybatis获取自增主键

mybatis提供了两种方式获取数据库自增主键:

1、通过useGeneratedKeys、keyProperty、keyColumn

2、通过 标签。

在获取数据库自增主键时,我们一般会把数据库主键设置为自动增长的,如有一张数据库表user定义如下:

CREATE TABLE `user` (
    `id` int(11) NOT NULL AUTO_INCREMENT, #自增
    `name` varchar(255) NOT NULL,
    `age` int(11) DEFAULT NULL,
    PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8

对应的User类:

public class User {
    private Integer id;
    private String name;
    private Integer age;
    //...setters and getters
    //...to string...
}

1、useGeneratedKeys、keyProperty、keyColumn

useGeneratedKeyskeyPropertykeyColumn属性,仅能在<insert>或者<update>元素中使用。作用分别如下所示:

useGeneratedKeys :

​这会令 MyBatis 使用 JDBC 的ResultSet.getGeneratedKeys 方法来取出由数据库内部生成的主键(比如:像 MySQL 和 SQL Server 这样的关系数据库管理系统的自动递增字段),默认值:false。

keyProperty:

唯一标记一个属性,MyBatis 会通过 ResultSet.getGeneratedKeys 的返回值,默认:unset。如果希望得到多个生成的列,也可以是逗号分隔的属性名称列表。

keyColumn :

通过生成的键值设置表中的列名,这个设置仅在某些数据库(像 PostgreSQL)是必须的,当主键列不是表中的第一列的时候需要设置。如果希望得到多个生成的列,也可以是逗号分隔的属性名称列表。

如果你的数据库支持自动生成主键的字段(比如 MySQL 和 SQL Server),那么你可以设置 useGeneratedKeys=”true”,然后再把 keyProperty 设置到目标属性上就OK了。如果你的数据库还支持多行插入, 你也可以传入一个数组或集合,并返回自动生成的主键。下面分别进行演示:

获取插入的单条记录的自增id:

<insert id="insert" parameterType="User" useGeneratedKeys="true" keyProperty="id">
    INSERT INTO user (name, age) VALUES (#{name}, #{age})
</insert>

测试代码如下:

@Test    
public void testInsert() {
    User user = new User();
    user.setName("tianshouzhi");
    user.setAge(27);
    System.out.println("插入前 id:" + user.getId());
    sqlSession.insert("com.tianshouzhi.mybatis.batch.mappers.UserMapper.insert", user);
    System.out.println("插入后:" + user.getId());
}

运行程序后控制台输出:

插入前:User{id=null, name='tianshouzhi', age=27}
23:16:10.935 [main] DEBUG com.tianshouzhi.mybatis.batch.mappers.UserMapper.insert - ==> Preparing: INSERT INTO user ( name, age) VALUES ( ?, ?)
23:16:10.998 [main] DEBUG com.tianshouzhi.mybatis.batch.mappers.UserMapper.insert - ==> Parameters: tianshouzhi(String), 27(Integer)
23:16:11.107 [main] DEBUG com.tianshouzhi.mybatis.batch.mappers.UserMapper.insert - <== Updates: 1
插入后:User{id=1, name='tianshouzhi', age=27}

获取批量插入的记录自增id

需要注意的是:获取批量插入的数据自增id之前存在bug,直接mybatis3.4.0之后才修复,读者需要保证mybatis版本>=3.4.0

<insert id="batchInsert" parameterType="java.util.List" useGeneratedKeys="true" keyProperty="id">
    INSERT INTO user (id, name, age) VALUES
    <foreach collection="list" item="user" index="index" separator="," >
        (#{user.id}, #{user.name}, #{user.age})
    </foreach>
</insert>

测试代码如下:

@Test
public void testBatchInsert() {
    User user1 = new User();
    user1.setName("tianshouzhi");
    user1.setAge(27);
    User user2 = new User(); 
    user2.setName("wangxiaoxiao");
    user2.setAge(26);
    List<User> userList = new ArrayList<User>();
    userList.add(user1);
    userList.add(user2);
    System.out.println("插入前:" + userList);
    sqlSession.insert("com.tianshouzhi.mybatis.batch.mappers.UserMapper.batchInsert", userList);
    System.out.println("插入后:" + userList);
}

运行程序后输出:

插入前:[User{id=null, name='tianshouzhi', age=27}, User{id=null, name='wangxiaoxiao', age=26}]
23:16:42.894 [main] DEBUG com.tianshouzhi.mybatis.batch.mappers.UserMapper.batchInsert - ==> Preparing: INSERT INTO user (id, name, age) VALUES (?, ?, ?) , (?, ?, ?)
23:16:42.956 [main] DEBUG com.tianshouzhi.mybatis.batch.mappers.UserMapper.batchInsert - ==> Parameters: null, tianshouzhi(String), 27(Integer), null, wangxiaoxiao(String), 26(Integer)
23:16:43.112 [main] DEBUG com.tianshouzhi.mybatis.batch.mappers.UserMapper.batchInsert - <== Updates: 2
插入后:[User{id=2, name='tianshouzhi', age=27}, User{id=3, name='wangxiaoxiao', age=26}]

2、通过

对于不支持自动生成类型的数据库或可能不支持自动生成主键 JDBC 驱动来说,MyBatis 有另外一种方法来生成主键。通过<selectKey>。如下:

<insert id="insertSelectKey" parameterType="User">
    <selectKey keyProperty="id" resultType="int" order="AFTER">
        SELECT last_insert_id();
    </selectKey>
    INSERT INTO user ( name, age) VALUES ( #{name}, #{age})
</insert>

这里的的作用,在INSERT语句执行完成之后(order=“AFTER”),执行sql: SELECT last_insert_id();语句,获得自增id。这是mysql提供的获取上一次插入记录的自增id的语法,其他数据库中可能不同。

测试代码如下:

@Test
public void insertSelectKey() {
    User user = new User();
    user.setName("tianshouzhi");
    user.setAge(27); 
    System.out.println("插入前:" + user);
    sqlSession.insert("com.tianshouzhi.mybatis.batch.mappers.UserMapper.insertSelectKey", user);
    System.out.println("插入后:" + user);
}

运行程序后,控制台输出:

插入前:User{id=null, name='tianshouzhi', age=27}
23:30:14.961 [main] DEBUG com.tianshouzhi.mybatis.batch.mappers.UserMapper.insertSelectKey - ==> Preparing: INSERT INTO user ( name, age) VALUES ( ?, ?)
23:30:15.008 [main] DEBUG com.tianshouzhi.mybatis.batch.mappers.UserMapper.insertSelectKey - ==> Parameters: tianshouzhi(String), 27(Integer)
23:30:15.102 [main] DEBUG com.tianshouzhi.mybatis.batch.mappers.UserMapper.insertSelectKey - <== Updates: 1
23:30:15.102 [main] DEBUG com.tianshouzhi.mybatis.batch.mappers.UserMapper.insertSelectKey!selectKey - ==> Preparing: SELECT last_insert_id();
23:30:15.102 [main] DEBUG com.tianshouzhi.mybatis.batch.mappers.UserMapper.insertSelectKey!selectKey - ==> Parameters:
23:30:15.102 [main] DEBUG com.tianshouzhi.mybatis.batch.mappers.UserMapper.insertSelectKey!selectKey - <== Total: 1
插入后:User{id=4, name='tianshouzhi', age=27}

可以看到这里同样获取到了数据库自增id。

3 总结:

  • 细心读者会发现,使用需要执行2条sql,而之前使用useGeneratedKeys、keyProperty的方式,只需要执行一个sql就可以了,因此效率更低。
  • 是不支持获取批量插入的记录id的(读者可以自行尝试),而使用useGeneratedKeys、keyProperty的方式是支持的。

因此,笔者建议在绝大部分情况下,都应该使用useGeneratedKeys、keyProperty的方式来获取自增id。只有在数据库不支持自增id的情况下 ,你才应该使用,并将order属性值设置为BEFORE,也就是在INSERT语句执行生成之前,生成这条记录的唯一id。例如使用oracle时,你可以在中先使用序列生成一个唯一id。

selectKey 元素描述如下:

<selectKey keyProperty="id" resultType="int" order="BEFORE" statementType="PREPARED">

属性描述

keyProperty

selectKey 语句结果应该被设置的目标属性。如果希望得到多个生成的列,也可以是逗号分隔的属性名称列表。

keyColumn

匹配属性的返回结果集中的列名称。如果希望得到多个生成的列,也可以是逗号分隔的属性名称列表。

resultType

结果的类型。MyBatis 通常可以推算出来,但是为了更加确定写上也不会有什么问题。MyBatis 允许任何简单类型用作主键的类型,包括字符串。如果希望作用于多个生成的列,则可以使用一个包含期望属性的 Object 或一个 Map。

order

这可以被设置为 BEFOREAFTER。如果设置为 BEFORE,那么它会首先选择主键,设置 keyProperty 然后执行插入语句。如果设置为 AFTER,那么先执行插入语句,然后是 selectKey 元素 - 这和像 Oracle 的数据库相似,在插入语句内部可能有嵌入索引调用。

statementType

与前面相同,MyBatis 支持 STATEMENT,PREPARED 和 CALLABLE 语句的映射类型,分别代表 PreparedStatement 和 CallableStatement 类型。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值