设为首页 收藏本站
查看: 1203|回复: 0

[经验分享] 关于mybatis批量插入

[复制链接]

尚未签到

发表于 2016-11-26 07:46:41 | 显示全部楼层 |阅读模式
  引用了http://topmanopensource.iyunv.com/blog/1833001这篇博客上的方法,可是怎么也取不到,说主键为空,无奈自己断点看源代码:

private void processGeneratedKeys(Executor executor, MappedStatement ms, Object parameter) {
try {
//parameter就是要插入的对象
if (parameter != null && keyStatement != null && keyStatement.getKeyProperties() != null) {
//只能一个主键
String keyProperty = keyStatement.getKeyProperties()[0]; // just one key property is supported
final Configuration configuration = ms.getConfiguration();
//这个东西是关键,下面看这个东西有没有主键对应的属性的set方法的,稍后看里面的东西
final MetaObject metaParam = configuration.newMetaObject(parameter);
//有set方法就执行选择key的部分
if (keyProperty != null && metaParam.hasSetter(keyProperty)) {
// Do not close keyExecutor.
// The transaction will be closed by parent executor.
Executor keyExecutor = configuration.newExecutor(executor.getTransaction(), ExecutorType.SIMPLE);
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 {
metaParam.setValue(keyProperty, values.get(0));
}
}
}
} catch (ExecutorException e) {
throw e;
} catch (Exception e) {
throw new ExecutorException("Error selecting key or setting result to parameter object. Cause: " + e, e);
}
  再来看看们如果我们的参数是一个List,批量插入么,当然是List之流,看看构造

MetaObject metaParam

private MetaObject(Object object, ObjectFactory objectFactory, ObjectWrapperFactory objectWrapperFactory) {
this.originalObject = object;
this.objectFactory = objectFactory;
this.objectWrapperFactory = objectWrapperFactory;
if (object instanceof ObjectWrapper) {
this.objectWrapper = (ObjectWrapper) object;
} else if (objectWrapperFactory.hasWrapperFor(object)) {
this.objectWrapper = objectWrapperFactory.getWrapperFor(this, object);
} else if (object instanceof Map) {
this.objectWrapper = new MapWrapper(this, (Map) object);
} else if (object instanceof Collection) {
this.objectWrapper = new CollectionWrapper(this, (Collection) object);
} else {
this.objectWrapper = new BeanWrapper(this, object);
}
}
  很清楚,如果是List,那么objectWapper就是CollectionWrapper的对象,然后这个CollectionWrapper的hasSetter方法直接抛了异常
  public boolean hasSetter(String name) {
    throw new UnsupportedOperationException();
  }
  然后就没有然后了,这个是我看到的内容,不知道前面博客中的是怎么实现的,或者我的理解有误也请了解的大虾帮着解释下,然后说说我自己的实现:
  首先是mapper文件

<insert id="batchInsertOrderItem" >
insert into amg_order_item
<foreach collection="snames" item="item" open="(" separator="," close=")">
${item}
</foreach>
values
<foreach collection="entities" separator="," item="entity">
<foreach collection="snames" item="item" open="(" separator="," close=")">
<if test="item=='order_item_id'">
(SELECT UUID_SHORT())
</if>
<if test="item!='order_item_id'">
#{entity.${s_l_name_update_map[item]}}
</if>
</foreach>
</foreach>
</insert>
  由于mybatis被团队改造过了,所以跟原生的估计有些不一样,我这里是拼装值的时候直接判断如果是id的那个属性的值,就直接加上(SELECT UUID_SHORT())这个了。
  好吧,又看了下,我迷茫了原来如果批量插入参数是List,在某一步会包装成map,DefaultSqlSession [line: 148] - update(String, Object)    在这里,

public int update(String statement, Object parameter) {
try {
dirty = true;
MappedStatement ms = configuration.getMappedStatement(statement);
//包装成map
return executor.update(ms, wrapCollection(parameter));
} catch (Exception e) {
throw ExceptionFactory.wrapException("Error updating database.  Cause: " + e, e);
} finally {
ErrorContext.instance().reset();
}
}


private Object wrapCollection(final Object object) {
if (object instanceof List) {
StrictMap<Object> map = new StrictMap<Object>();
map.put("list", object);
return map;
} else if (object != null && object.getClass().isArray()) {
StrictMap<Object> map = new StrictMap<Object>();
map.put("array", object);
return map;
}
return object;
}
public static class StrictMap<V> extends HashMap<String, V> {
private static final long serialVersionUID = -5741767162221585340L;
@Override
public V get(Object key) {
if (!super.containsKey(key)) {
throw new BindingException("Parameter '" + key + "' not found. Available parameters are " + this.keySet());
}
return super.get(key);
}
}
  
那所以在后面进行判断主键是否有set方法的时候就是用的MapWrapper的实例,直接返回了true;
  public boolean hasSetter(String name) {
    return true;
  }
  那然后就是往这个map中放了一个键值对,即主键与对应的值,可是疑问又来了,这个map中包装的是List啊,是批量插入啊,一个key怎么够用啊,暂时还没搞灵清。由于代码是改过的,所以无法跟踪查看原来的实现了,悲催

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-305620-1-1.html 上篇帖子: mybatis 无效的列类型 下篇帖子: maven+springMVC+mybatis框架搭建
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表