itfsw/mybatis-generator-plugin

可否为batch_insert增加 insert if not exists 逻辑?

id4alex opened this issue · 4 comments

因为很多时候有 insert if not exists 批量插入的需求, 是一个很实用功能.

本来这个repo[https://github.com/beihaifeiwu/dolphin] 已经完成了这个功能,但是觉得他的其他功能写的没你的好, 所以恳请您的repo里面添加这项功能.

itfsw commented

你好,我Github邮箱好像出问题了,一直没有收到这个issue,我看了下https://github.com/beihaifeiwu/dolphin上最新的代码逻辑,其实他已经没有再采用insert if not exists 这种逻辑,因为这要求数据库链接配置需开启allowmultiqueries=true批量执行sql,而且代码逻辑上其实是先执行了一个带条件update然后是带条件插入,这个效率不是很高。
所以我还是考虑按最新的实现上使用mysql “on duplicate key update” 语法来增加这种存在即更新的逻辑,当然如果需要继续采用类似upsertByExample这种和MongoDB类似逻辑,我也会添加支持,但默认不开启,需要的话在插件property配置中增加<property name="allowMultiQueries" value="true"/>来开启支持,但不建议使用。

itfsw commented

新版本已出,考虑下你提的需求,可能并不是真的需要类似MongoDB类似upsertByExample这种情况。大多数情况下应该还是根据主键来进行存在即更新操作,所以UpsertPlugin依然只采用MySQL的on duplicate key update 进行实现。
至于upsertByExample实现延后有好的方法时继续跟进。

感谢你的更新. 抱歉我没有说太清楚.

通常会有一些爬虫的功能,一次性获取几百条记录回来,有的记录通常总量在几千万条量级. 通常的逻辑都是每条记录在java中做查询存在就更新,不存在就插入 这样的操作(通常需要2* list.size() 的 jdbc操作数). 我就想着把这部分的功能往下移到mybatis里面通过一次jdbc操作,完成批量操作,效率会有所提升.

生成的批量sql应该下面这样的一个批量sql去一次执行.
update xxx where if not exists(select xxx where id=id1);
insert xxx where if not exists(select xxx where id=id1);
update xxx where if not exists(select xxx where id=id2);
insert xxx where if not exists(select xxx where id=id2);
update xxx where if not exists(select xxx where id=id3);
insert xxx where if not exists(select xxx where id=id3);

但是通常表结构设计longid 自增作为物理主键, xxxx_hashid(例如user_hashid)作为逻辑主键, 一般我会根据hashid去做判断这条记录存在与否,而不是自增ID(longid) .在这样的情况下我们可能就需要多传递一个field_name(xxxx_hashid) 作为 参数进来.

update xxx where if not exists(select xxx where xxx_hashid=id1);
insert xxx where if not exists(select xxx where xxx_hashid=id1);
update xxx where if not exists(select xxx where xxx_hashid=id2);
insert xxx where if not exists(select xxx where xxx_hashid=id2);
update xxx where if not exists(select xxx where xxx_hashid=id3);
insert xxx where if not exists(select xxx where xxx_hashid=id3);

以上是我的一些想法, 不知道我有没有表述清楚, 先提前谢了!

itfsw commented

新快照版本已出,增加插件属性设置为<property name="allowMultiQueries" value="true"/>情况下支持upsertByExample,upsertByExampleSelective操作,但强力建议不要使用(需保证团队没有使用statement提交sql,否则会存在sql注入风险)。