MyBatis主键生成器SelectKeyGenerator(三)
前面两篇博客我们介绍了MyBatis主键生成器KeyGenerator(一)和MyBatis主键生成器Jdbc3KeyGenerator(二),接下来我们介绍SelectKeyGenerator,
如在Oraclee中并不提供自增组件,提供了Sequence主键,我们就需要执行它的Sequence主键,如在mysql中如下配置:
<insert id="save">
<selectKey resultType="int" keyProperty="id" order="BEFORE">
SELECT LAST_INSERT_ID() AS id
</selectKey>
insert into tbl_log (log_type,log_info) values
(#{logType},#{logInfo})
</insert>
其实现原理就是执行selectKey中的sql语句来获得结果,在SelectKeyGenerator的源码实现中就是执行 select last_insert_id() as id这条sql语句,获得结果,并赋值给id,源码实现如下:
/**
* @author Clinton Begin
* @author Jeff Butler
*/
public class SelectKeyGenerator implements KeyGenerator {
public static final String SELECT_KEY_SUFFIX = "!selectKey";
private boolean executeBefore;
private MappedStatement keyStatement;
public SelectKeyGenerator(MappedStatement keyStatement, boolean executeBefore) {
this.executeBefore = executeBefore;
this.keyStatement = keyStatement;
}
@Override
public void processBefore(Executor executor, MappedStatement ms, Statement stmt, Object parameter) {
if (executeBefore) {
processGeneratedKeys(executor, ms, parameter);
}
}
@Override
public void processAfter(Executor executor, MappedStatement ms, Statement stmt, Object parameter) {
if (!executeBefore) {
processGeneratedKeys(executor, ms, parameter);
}
}
//执行来获得结果值
private void processGeneratedKeys(Executor executor, MappedStatement ms, Object parameter) {
try {
if (parameter != null && keyStatement != null && keyStatement.getKeyProperties() != null) {
String[] keyProperties = keyStatement.getKeyProperties();
final Configuration configuration = ms.getConfiguration();
final MetaObject metaParam = configuration.newMetaObject(parameter);
if (keyProperties != null) {
// Do not close keyExecutor.
// The transaction will be closed by parent executor.
Executor keyExecutor = configuration.newExecutor(executor.getTransaction(), ExecutorType.SIMPLE);
//执行获得主键的sql语句
List<Object> values = keyExecutor.query(keyStatement, parameter, RowBounds.DEFAULT, Executor.NO_RESULT_HANDLER);
if (values.size() == 0) {
throw new ExecutorException("SelectKey returned no data.");
} else if (values.size() > 1) {
throw new ExecutorException("SelectKey returned more than one value.");
} else {
//执行结果
MetaObject metaResult = configuration.newMetaObject(values.get(0));
//返回参数如果是一个
if (keyProperties.length == 1) {
//判断返回参数使用有get方法
if (metaResult.hasGetter(keyProperties[0])) {
setValue(metaParam, keyProperties[0], metaResult.getValue(keyProperties[0]));
} else {
// no getter for the property - maybe just a single value object
// so try that
setValue(metaParam, keyProperties[0], values.get(0));
}
} else {
//如果有多个返回参数则需要循环赋值
handleMultipleProperties(keyProperties, metaParam, metaResult);
}
}
}
}
} catch (ExecutorException e) {
throw e;
} catch (Exception e) {
throw new ExecutorException("Error selecting key or setting result to parameter object. Cause: " + e, e);
}
}
//如果有多个返回参数则需要循环赋值
private void handleMultipleProperties(String[] keyProperties,
MetaObject metaParam, MetaObject metaResult) {
String[] keyColumns = keyStatement.getKeyColumns();
//如果没设置返回参数的值,则使用结果属性的值
if (keyColumns == null || keyColumns.length == 0) {
// no key columns specified, just use the property names
for (int i = 0; i < keyProperties.length; i++) {
setValue(metaParam, keyProperties[i], metaResult.getValue(keyProperties[i]));
}
} else {
if (keyColumns.length != keyProperties.length) {
throw new ExecutorException("If SelectKey has key columns, the number must match the number of key properties.");
}
for (int i = 0; i < keyProperties.length; i++) {
setValue(metaParam, keyProperties[i], metaResult.getValue(keyColumns[i]));
}
}
}
//设置返回参数对应的值
private void setValue(MetaObject metaParam, String property, Object value) {
if (metaParam.hasSetter(property)) {
metaParam.setValue(property, value);
} else {
throw new ExecutorException("No setter found for the keyProperty '" + property + "' in " + metaParam.getOriginalObject().getClass().getName() + ".");
}
}
}
MyBatis主键生成器SelectKeyGenerator(三)的更多相关文章
- MyBatis主键生成器Jdbc3KeyGenerator(二)
上一篇博客MyBatis主键生成器KeyGenerator(一)中我们大体介绍了主键生成器的接口及配置等,接下来我们介绍一下KeyGenerator的实现类Jdbc3KeyGenerator Jdbc ...
- MyBatis主键生成器KeyGenerator(一)
Mybatis提供了主键生成器接口KeyGenerator,insert语句默认是不返回记录的主键值,而是返回插入的记录条数:如果业务层需要得到记录的主键时,可以通过配置的方式来完成这个功能 . 由于 ...
- 轻量级封装DbUtils&Mybatis之四MyBatis主键
MyBatis主键 不支持对象列表存储时对自增id字段的赋值(至少包括3.2.6和3.3.0版本),如果id不是采用底层DB自增主键赋值,不必考虑此问题 温馨提示:分布式DB环境下,DB主键一般会采用 ...
- 主键生成器效率提升方案|基于雪花算法和Redis控制进程隔离
背景 主键生成效率用数据库自增效率也是比较高的,为什么要用主键生成器呢?是因为需要insert主表和明细表时,明细表有个字段是主表的主键作为关联.所以就需要先生成主键填好主表明细表的信息后再一次过在一 ...
- Hibernate各种主键生成器策略与配置详解(转载)
http://www.cnblogs.com/kakafra/archive/2012/09/16/2687569.html 1.assigned 主键由外部程序负责生成,在 save() 之前必须指 ...
- Hibernate主键生成器
主键生成器负责生成数据表记录的主键:increment:为long,short或者int类型主键生成唯一标识.只有在没有其他进程往同一张表中插入数据时才能使用.在集群下不能使用! identity:在 ...
- 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 ...
随机推荐
- Linux学习之CentOS(二十)------vi/vim 按键说明
vi/vim 按键说明 除了上面简易范例的 i, Esc, :wq 之外,其实 vim 还有非常多的按键可以使用. 第一部份:一般模式可用的光标移动.复制粘贴.搜索替换等 移动光标的方法 h 或 向左 ...
- audioplayer.js插件的使用及小bug
之前在项目里用audioplayer.js做的一个页面,改了布局样式,还有插件自身有个bug就是audio添加autoplay属性后有两个音频播放,其中一个无法控制,会一直播放,我查看了官网的demo ...
- SVN错误:SVN Working copy XXX is too old
出错原因: 这是因为使用了低版本的svn生成了.svn内文件内容,但是,使用高版本svn同步时便出现该问题. 解决方法: 找到报错对应的文件夹,里面有个名为.svn的文件夹,删除这个文件夹(这是svn ...
- SAS中常见的数组函数
SAS中常见的数组函数有: dim dimk hbound hboundk lbound lboundk 数组函数计萁数组的维数.上下界,有利于写出可移植的程序,数组函数包括:dim(x) 求数组x第 ...
- OpenSuSE Linux下安装Oracle10g的步骤
OpenSuSE Linux下安装Oracle10g的步骤: --root用户 --1.vi etc/profile 添加脚本: if [ \$USER = "oracle" ]; ...
- FJUT寒假作业第二周G题解快速幂
题目来源:http://210.34.193.66:8080/vj/Contest.jsp?cid=161#P6 题意:求n个数字的乘积对c取摸.主要就是有快速幂扩展到广义幂的过程. 首先题目 ...
- Eleven
A. Eleven time limit per test : 1 second memory limit per test: 256 megabytes input: standard inpu ...
- jQuery CSS 类
通过 jQuery,可以很容易地对 CSS 元素进行操作. jQuery 操作 CSS jQuery 拥有若干进行 CSS 操作的方法.我们将学习下面这些: addClass() - 向被选元素添加一 ...
- xshell连接centos与ubuntu
操作系统:Windows 7 应用软件:Ware Workstation &Xshell 5 Linux:CentOS 7 Minimal &Ubuntu Server 16 ==== ...
- Docker标准化开发测试和生产环境
对于大部分企业来说,搭建 PaaS 既没有那个精力,也没那个必要,用 Docker 做个人的 sandbox 用处又小了点. 可以用 Docker 来标准化开发.测试.生产环境. Docker 占用资 ...