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 ...
随机推荐
- Splay讲解
Splay讲解 Splay是平衡树的一种,是一种二叉搜索树,我们先讲解一下它的核心部分. Splay的核心部分就是splay,可能有些人会说什么鬼?这样讲解是不是太不认真了?两个字回答:不是.第一个S ...
- Linux 基本bash命令
1.查看文件大小.内存大小.cpu信息.硬盘空间 显示当前目录所有文件大小的命令:ls -lht 内存空间.CPU信息.硬盘空间:htop.top(htop详解参考:http://blog.csdn. ...
- Unity3D各平台Application.xxxPath的路径
前几天我们游戏在一个同事的Android手机上启动时无法正常进入,经查发现Application.temporaryCachePath和Application.persistentDataPath返回 ...
- Leetcode难度表及解题汇总
Leetcode难度表及解题汇总 参考网上一份题目难度表,以及本人的解题. Id Question Difficulty Frequency Data Structures Algorithms Bl ...
- Android简易实战教程--第三十八话《自定义通知NotifiCation》
上一篇小案例,完成了一个普通的通知,点击通知启动了一个活动.但是那里的通知没有加入些"靓点",这一篇就给它加入自定义的布局,完成自定义的通知. 应用:比如QQ音乐为例,当点击音乐播 ...
- Texlive 更新命令
设置repository tlmgr repository set http://mirror.hust.edu.cn/CTAN/systems/texlive/tlnet 上面的例子使用的是华中科技 ...
- Android艺术开发探索——第二章:IPC机制(下)
Android艺术开发探索--第二章:IPC机制(下) 我们继续来讲IPC机制,在本篇中你将会学习到 ContentProvider Socket Binder连接池 一.使用ContentProvi ...
- 一起聊聊什么是P问题、NP问题、NPC问题
概念 P问题:如果一个问题可以找到一个能在多项式的时间里解决它的算法,那么这个问题就属于P问题.通常NOI和NOIP不属于P类问题,我们常见到的一些信息奥赛的题目都是P问题. NP问题:可以在多项式的 ...
- Python实现数据库一键导出为Excel表格
依赖 Python2711 xlwt MySQLdb 数据库相关 连接 获取字段信息 获取数据 Excel基础 workbook sheet 案例 封装 封装之后 测试结果 总结 数据库数据导出为ex ...
- premake设置静态运行库
premake设置静态运行库(金庆的专栏)链接protobuf库时,碰到RuntimeLibrary不匹配:1>libprotobufd.lib(int128.obj) : error LNK2 ...