MyBatis主键生成器KeyGenerator(一)
Mybatis提供了主键生成器接口KeyGenerator,insert语句默认是不返回记录的主键值,而是返回插入的记录条数;如果业务层需要得到记录的主键时,可以通过配置的方式来完成这个功能 。
由于不同的数据库对主键的生成不一样:
(1)针对Sequence主键而言,在执行insert sql前必须指定一个主键值给要插入的记录,如Oracle、DB2,KeyGenerator提供了processBefore()方法。
(2)针对自增主键的表,在插入时不需要主键,而是在插入过程自动获取一个自增的主键,比如MySQL,Postgresql,KeyGenerator提供了processAfter()方法。
KeyGenerator源码如下:
/**
* @author Clinton Begin
*/
public interface KeyGenerator {
//在执行insert之前,设置属性order="BEFORE"
void processBefore(Executor executor, MappedStatement ms, Statement stmt, Object parameter);
//在执行insert之后,设置属性order="AFTER"
void processAfter(Executor executor, MappedStatement ms, Statement stmt, Object parameter);
}
KeyGenerator分别实现了Jdbc3KeyGenerator、SelectKeyGenerator和NoKeyGenerator,其中NoKeyGenerator并没有具体的操作,不需要去关心。
KeyGenerator的实现类如下:
主键生成器的配置方式有两种
(一)当数据库可以自增主键时,如mysql,可以采用如下配置:
<insert id="save" useGeneratedKeys="true" keyColumn="i_id" keyProperty="id">
<span style="white-space:pre"> </span>insert into tbl_log (log_type,log_info) values (#{logType},#{logInfo})
</insert>
这样就是在返回值中带有生成数据的主键,在insert语句调用之后执行,应该是调用的是processAfter方法,并且默认使用的实现类是Jdbc3KeyGenerator,它也只是实现了processAfter方法
(二)当数据库需要执行Sequence主键时,需要另外一种配置,MySQL也可以使用Sequence主键,配置如下:
<insert id="save">
<selectKey resultType="int" keyProperty="id" order="AFTER">
SELECT LAST_INSERT_ID() AS id
</selectKey>
insert into tbl_log (log_type,log_info) values
(#{logType},#{logInfo})
</insert>
通过配置我们可以看到,order=AFTER,这样是在执行完insert语句之后再获得最大id,在Oracle下需要配置成oder=BEFORE了,我们可以猜到这时候使用的是SelectKeyGenerator,接下来我们会对这个两个实现类进行具体的分析。
在SimpleStatementHandler执行具体的update函数时,会进行选择执行Jdbc3KeyGenerator或者SelectKeyGenerator,或者不执行任何KeyGenerator,代码如下:
@Override
public int update(Statement statement) throws SQLException {
String sql = boundSql.getSql();
Object parameterObject = boundSql.getParameterObject();
KeyGenerator keyGenerator = mappedStatement.getKeyGenerator();
int rows;
if (keyGenerator instanceof Jdbc3KeyGenerator) {
statement.execute(sql, Statement.RETURN_GENERATED_KEYS);
rows = statement.getUpdateCount();
keyGenerator.processAfter(executor, mappedStatement, statement, parameterObject);
} else if (keyGenerator instanceof SelectKeyGenerator) {
statement.execute(sql);
rows = statement.getUpdateCount();
keyGenerator.processAfter(executor, mappedStatement, statement, parameterObject);
} else {
statement.execute(sql);
rows = statement.getUpdateCount();
}
return rows;
}
在PreparedStatementHandler中执行update函数时,则使用如下方法:
@Override
public int update(Statement statement) throws SQLException {
PreparedStatement ps = (PreparedStatement) statement;
ps.execute();
int rows = ps.getUpdateCount();
Object parameterObject = boundSql.getParameterObject();
KeyGenerator keyGenerator = mappedStatement.getKeyGenerator();
keyGenerator.processAfter(executor, mappedStatement, ps, parameterObject);
return rows;
}
所以其实可以看到执行的都是processAfter方法,其实具体的调用顺序并不是的根据KeyGenerator的processBefore和processAfter来实现的。
MyBatis主键生成器KeyGenerator(一)的更多相关文章
- MyBatis主键生成器SelectKeyGenerator(三)
前面两篇博客我们介绍了MyBatis主键生成器KeyGenerator(一)和MyBatis主键生成器Jdbc3KeyGenerator(二),接下来我们介绍SelectKeyGenerator, 如 ...
- MyBatis主键生成器Jdbc3KeyGenerator(二)
上一篇博客MyBatis主键生成器KeyGenerator(一)中我们大体介绍了主键生成器的接口及配置等,接下来我们介绍一下KeyGenerator的实现类Jdbc3KeyGenerator Jdbc ...
- 轻量级封装DbUtils&Mybatis之四MyBatis主键
MyBatis主键 不支持对象列表存储时对自增id字段的赋值(至少包括3.2.6和3.3.0版本),如果id不是采用底层DB自增主键赋值,不必考虑此问题 温馨提示:分布式DB环境下,DB主键一般会采用 ...
- Hibernate各种主键生成器策略与配置详解(转载)
http://www.cnblogs.com/kakafra/archive/2012/09/16/2687569.html 1.assigned 主键由外部程序负责生成,在 save() 之前必须指 ...
- Hibernate主键生成器
主键生成器负责生成数据表记录的主键:increment:为long,short或者int类型主键生成唯一标识.只有在没有其他进程往同一张表中插入数据时才能使用.在集群下不能使用! identity:在 ...
- 主键生成器效率提升方案|基于雪花算法和Redis控制进程隔离
背景 主键生成效率用数据库自增效率也是比较高的,为什么要用主键生成器呢?是因为需要insert主表和明细表时,明细表有个字段是主表的主键作为关联.所以就需要先生成主键填好主表明细表的信息后再一次过在一 ...
- MyBatis主键返回
在使用MyBatis做持久层时,insert语句默认是不返回记录的主键值,而是返回插入的记录条数:如果业务层需要得到记录的主键时,可以通过配置的方式来完成这个功能. 比如在表的关联关系中,将数据插入主 ...
- mybatis 主键UUID生成策略
<insert id="insert" parameterType="com.lsfwpt.lawmis.po.SysUser"> <sele ...
- Hibernate中的主键生成器generator
本文讲述Hibernate的generator属性的意义.Generator属性有7种class,本文简略描述了这7种class的意义和用法. [xhtml] view plaincopy <c ...
随机推荐
- Nginx+Tomca+Redis实现负载均衡、资源分离、session共享
目标实现:Nginx作为负载均衡后端多Tomcat实例,通过Redis实现Session共享. 操作系统环境:CentOS 6.8 SSH:SecureCRT 其中 Nginx服务:80端口 Tomc ...
- SpringMVC mock测试详解
@RunWith(SpringRunner.class) @SpringBootTest(classes = WebmanagerApplication.class) //配置事务的回滚,对数据库的增 ...
- sea.js及三种加载方式的异同
一.前言 浏览器本身并不提供模块管理的机制,过去网页开发中,为了使用各种模块,不得不在加入一大堆script标签.这样就使得网页体积臃肿,难以维护,还产生大量的HTTP请求,拖慢显示速度, ...
- mysql常见的优化需要注意的点
1.explain分析explian引用索引基数show indexes from table_name;主键索引具有最好的基数 测试时 不走缓存SELECT SQL_NO_CACHE id from ...
- 剑指架构师系列-ftp服务器
1.安装FTP 我们在开发项目时,肯定需要专门的一台ftp服务器来存在上传的静态资源,今天我们就在CentOS下搭建一个ftp服务器. 1.安装vsftpd组件,安装完后,有/etc/vsftpd/v ...
- CF | Alyona and Mex
Someone gave Alyona an array containing n positive integers a1, a2, ..., an. In one operation, Alyon ...
- Node.js Domain 模块
Node.js Domain(域) 简化异步代码的异常处理,可以捕捉处理try catch无法捕捉的异常.引入 Domain 模块 语法格式如下: var domain = require(" ...
- Bootstrap3 概述
注意:HTML5 文档类型 Bootstrap 使用到的某些 HTML 元素和 CSS 属性需要将页面设置为 HTML5 文档类型.在你项目中的每个页面都要参照下面的格式进行设置. <!DOCT ...
- JBOSS EAP实战(1)
JBOSS的诞生 1998年,在硅谷SUN公司的SAP实验室,一个年轻人正坐在电脑前面思考,然后写着什么东西.不,他没有在写程序,他在写辞呈.他正在做出人生的一个重大决定:他要辞掉在SUN的这份工作, ...
- [extjs5学习笔记]第三十八节 sencha CMD 6.0.0.220版本安装
本文地址:http://blog.csdn.net/sushengmiyan/article/details/46740381 简介 sencha cmd 6安装过程不需要UAC控制了对于widnow ...