一、前言


使用MyBatis进行插入操作的时候,如果表的主键是自增的,针对不同的数据库相应的操作也不同。我们在实际开发中无非是两种情况比较多,一种是Oracle sequence,另外一种就是MySQL自增主键。本文主要应用于MySQL数据库,针对返回自增主键和不返回自增主键两种情况通过案例说明。


二、案例

♦新建一张数据库表t_user


CREATE TABLE `t_user` (
  `id` int(50) NOT NULL AUTO_INCREMENT,
  `loginId` varchar(20) DEFAULT NULL,
  `userName` varchar(100) DEFAULT NULL,
  `role` varchar(255) DEFAULT NULL,
  `note` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8;

♦修改UserMapper接口类,增加addUser方法


/**
* 新增用户
* @param user
 * @return
*/
public void addUser(User user);

♦针对不返回自增主键的情况


修改UserMapper.xml文件


<insert id="addUser" parameterType="com.queen.mybatis.bean.User">
	insert into
	t_user(loginId,userName,role,note)
	values(#{loginId},#{userName},#{role},#{note})
</insert>

测试类MyBatisTest,增加testAddNoReturnID方法


@Test
public void testAddNoReturnID() throws IOException {
	SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
	SqlSession openSession = sqlSessionFactory.openSession();
		
	try{
		UserMapper mapper = openSession.getMapper(UserMapper.class);
		User user = new User("queen","奎恩","海贼王副把手","专门负责提鞋的。。。");
		mapper.addUser(user);
		System.out.println("***************"+user.getId()+"***************");
		openSession.commit();
	}finally{
		openSession.close();
	}

}

运行测试,控制台打印


2017-07-31 21:00:13,811 [main] [org.apache.ibatis.transaction.jdbc.JdbcTransaction]-[DEBUG] Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@7cd1be26]
2017-07-31 21:00:13,816 [main] [com.queen.mybatis.mapper.UserMapper.addUser]-[DEBUG] ==>  Preparing: insert into t_user(loginId,userName,role,note) values(?,?,?,?) 
2017-07-31 21:00:13,923 [main] [com.queen.mybatis.mapper.UserMapper.addUser]-[DEBUG] ==> Parameters: queen(String), 奎恩(String), 海贼王副把手(String), 专门负责提鞋的。。。(String)
2017-07-31 21:00:13,925 [main] [com.queen.mybatis.mapper.UserMapper.addUser]-[DEBUG] <==    Updates: 1
***************0***************

控制台返回的ID为0,但是实际上数据库保存的数据ID为1,这种配置方式并不能在完成插入操作后将插入时的主键值存放到保存的对象中。数据库数据:


mysql> select * from t_user;
+----+---------+----------+----------------+-----------------------
+
| id | loginId | userName | role           | note
|
+----+---------+----------+----------------+-----------------------
+
|  1 | queen   | 奎恩     | 海贼王副把手   | 专门负责提鞋的。。。 |
+----+---------+----------+----------------+-----------------------
1 row in set (0.00 sec)

♦针对返回自增主键的情况


上述第一种情况能满足大部分情况,但有时候我们会遇到类似一对多的那种表结构,在插入多端数据时,需要获取刚刚保存了的“一”这一方的主键。那么这个时候,上述的配置就无法满足需要了。为此我们需要使用MyBatis提供的keyProperty 来单独配置针对自增主键的处理。
修改UserMapper.xml文件


<insert id="addUser" parameterType="com.queen.mybatis.bean.User"
	useGeneratedKeys="true" keyProperty="id">
	insert into
	t_user(loginId,userName,role,note)
	values(#{loginId},#{userName},#{role},#{note})
</insert>


请仔细对比这里的配置和上面的配置是不同的,增加了useGeneratedKeys=”true” keyProperty=”id”这两个属性。
mysql支持自增主键,自增主键值的获取,mybatis也是利用statement.getGenreatedKeys();
useGeneratedKeys=”true”;使用自增主键获取主键值策略
keyProperty;指定对应的主键属性,也就是mybatis获取到主键值以后,将这个值封装给javaBean的哪个属性


修改测试类MyBatisTest


/*User user = new User("queen","奎恩","海贼王副把手","专门负责提鞋的。。。");*/
User user = new User("Lucy","路西","剑士","灭了多弗兰明哥");

运行,控制台打印如下:


2017-07-31 21:10:39,744 [main] [com.queen.mybatis.mapper.UserMapper.addUser]-[DEBUG] ==>  Preparing: insert into t_user(loginId,userName,role,note) values(?,?,?,?) 
2017-07-31 21:10:39,837 [main] [com.queen.mybatis.mapper.UserMapper.addUser]-[DEBUG] ==> Parameters: Lucy(String), 路西(String), 剑士(String), 灭了多弗兰明哥(String)
2017-07-31 21:10:39,842 [main] [com.queen.mybatis.mapper.UserMapper.addUser]-[DEBUG] <==    Updates: 1
***************2***************

查询数据库


mysql> select * from t_user;
+----+---------+----------+----------------+-----------------------
+
| id | loginId | userName | role           | note
|
+----+---------+----------+----------------+-----------------------
+
|  1 | queen   | 奎恩     | 海贼王副把手   | 专门负责提鞋的。。。 |
+----+---------+----------+----------------+-----------------------
+    +         +          +                +                      
|  2 | queen   | 路西     | 剑士           | 灭了多弗兰明哥       |
+----+---------+----------+----------------+-----------------------
1 row in set (0.00 sec)

♦上面两种情况都是MySQL自增主键的情况,那么MySQL如果是自己维护主键ID,那么这个时候我们要怎么处理呢?

我们先来假设一下t_user表主键ID 是通过uuid获取的,现在我们如何配置?


新建数据库表t_user_temp


CREATE TABLE `t_user_temp` (
  `id` varchar(50) NOT NULL,
  `loginId` varchar(20) DEFAULT NULL,
  `userName` varchar(100) DEFAULT NULL,
  `role` varchar(255) DEFAULT NULL,
  `note` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

新增UserTemp类


/**
 * @since 2017-07-31
 * @author queen 定义一个Java类
 *
 */
public class UserTemp {
	// ID,唯一性
	private String id;
	// 登录ID
	private String loginId;
	// 用户名
	private String userName;
	// 角色
	private String role;
	// 备注
	private String note;

	public UserTemp(String loginId, String userName, String role,
			String note) {
		this.loginId = loginId;
		this.userName = userName;
		this.role = role;
		this.note = note;
	}

	public UserTemp() {
	}

	public String getId() {
		return id;
	}

	public void setId(String id) {
		this.id = id;
	}

	public String getLoginId() {
		return loginId;
	}

	public void setLoginId(String loginId) {
		this.loginId = loginId;
	}

	public String getUserName() {
		return userName;
	}

	public void setUserName(String userName) {
		this.userName = userName;
	}

	public String getRole() {
		return role;
	}

	public void setRole(String role) {
		this.role = role;
	}

	public String getNote() {
		return note;
	}

	public void setNote(String note) {
		this.note = note;
	}

新增UserTempMapper接口类


/**
 * @since 2017-07-31
 * @author queen 
 * 定义一个UserMapper接口
 *
 */
public interface UserTempMapper {
	
	/**
	 * 新增用户
	 * @param user
	 * @return
	 */
	public void addUserTemp(UserTemp userTemp);
}

新增UserTempMapper.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="com.queen.mybatis.mapper.UserTempMapper">
	<insert id="addUserTemp" parameterType="com.queen.mybatis.bean.UserTemp">
		<selectKey keyProperty="id" order="BEFORE" resultType="java.lang.String">
			SELECT uuid()
		</selectKey>
		insert into
		t_user_temp(id,loginId,userName,role,note)
		values(#{id},#{loginId},#{userName},#{role},#{note})
	</insert>
</mapper>


order=”BEFORE”:当前sql在插入sql之前运行
AFTER:当前sql在插入sql之后运行
resultType:查出的数据的返回值类型

BEFORE运行顺序:
先运行selectKey查询id的sql;查出id值封装给javaBean的id属性
在运行插入的sql;就可以取出id属性对应的值
AFTER运行顺序:
先运行插入的sql(从序列中取出新值作为id);
再运行selectKey查询id的sql;



同时,将UserTempMapper.xml注册到全局配置文件mybatis-config.xml中


<mappers>
	<mapper resource="UserMapper.xml" />
	<mapper resource="UserTempMapper.xml" />
</mappers>

修改测试类MyBatisTest,增加testUserTemp方法


@Test
public void testUserTemp() throws IOException {
	SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
	SqlSession openSession = sqlSessionFactory.openSession();
		
	try{
		UserTempMapper mapper = openSession.getMapper(UserTempMapper.class);
		UserTemp userTemp = new UserTemp("leibeika","蕾贝卡","剑士","公主");
		mapper.addUserTemp(userTemp);
		System.out.println("***************"+userTemp.getId()+"***************");
		openSession.commit();
	}finally{
		openSession.close();
	}

}

运行测试,控制台打印如下:


2017-07-31 21:36:40,905 [main] [com.queen.mybatis.mapper.UserTempMapper.addUserTemp]-[DEBUG] ==>  Preparing: insert into t_user_temp(id,loginId,userName,role,note) values(?,?,?,?,?) 
2017-07-31 21:36:40,910 [main] [com.queen.mybatis.mapper.UserTempMapper.addUserTemp]-[DEBUG] ==> Parameters: 79545e69-75f5-11e7-ab42-68f728526994(String), leibeika(String), 蕾贝卡(String), 剑士(String), 公主(String)
2017-07-31 21:36:40,911 [main] [com.queen.mybatis.mapper.UserTempMapper.addUserTemp]-[DEBUG] <==    Updates: 1
***************79545e69-75f5-11e7-ab42-68f728526994***************


通过如上配置,就能够实现MySQL的ID在非自增情况下,如何获取主键ID的值。

完整工程的结构如下:




mysql添加自增主 mysql如何设置自增主键_主键


至此,我们关于MyBatis基础篇之如何获取自增主键的值介绍完毕,本文主要针对的MySQL数据库如何获取自增ID和非自增ID的案例,下一节我们将介绍一下Oracle是如何实现获得序列的。