通用mapper 使用自定义id生成数据库主键
一、普通添加方法
①创建一个主键生成策略的类,实现tk.mybatis.mapper.genid.GenId接口:
import tk.mybatis.mapper.genid.GenId; public class IdWorker implements GenId<Long> { @Override public Long genId(String table, String column) {
// 这里自己采用分布式id生成算法实现就好了。 return LeafIDGen.getInstance().nextID(); } }
②直接在id属性上添加注解,使用第①步的主键生成策略即可,如下:
@Id @KeySql(genId = IdWorker.class) private Long id;
③需要将mysql的id改为非自增设置;
二、批量添加方法
第一种方法
添加之前,循环遍历每个要添加的对象,手动设置分布式id,然后进行批量添加
①需要将mysql的id改为非自增设置;
②实体类id属性上不能添加这两个注解:
@Id
@KeySql(genId = IdWorker.class)
③dao接口继承tk.mybatis.mapper.common.MySqlMapper
public interface UserSystemMessageDao extends Mapper<UserSystemMessagePo>, MySqlMapper<UserSystemMessagePo> {
tk.mybatis.mapper.common.MySqlMapper实际上继承了tk.mybatis.mapper.common.special.InsertListMapper,来实现批量插入的。
④手动设置分布式id,例子如下:
List<UserSystemMessagePo> addList = new ArrayList<>(); for (Long accountId : accountIds) { UserSystemMessagePo po = new UserSystemMessagePo();
// 这里手动设置分布式id,使用自己的分布式id生成算法 po.setId(LeafIDGen.getInstance().nextID()); po.setAccountId(accountId); po.setApplicationId(payload.getApplicationId()); po.setPlatformId(payload.getPlatformId()); po.setSystemMessageId(payload.getSystemMessageId()); po.setStatus(LogicStatusEnum.FALSE.getCode()); addList.add(po); } // 批量添加用户系统消息 userSystemMessageDao.insertList(addList);
这里的userSystemMessageDao声明如下:
public interface UserSystemMessageDao extends Mapper<UserSystemMessagePo>, MySqlMapper<UserSystemMessagePo>
该dao继承MySqlMapper后就可以进行批量添加操作了;
注意:通用mapper的很多根据主键的接口方法,都是按照@id来的,所以需要在主键属性上添加该注解,但是使用这个方法进行批量添加时,po类又不能添加@id注解,所以这种方法不可行,会导致:
①通过手动生成id,批量添加没有问题;
②通过需要按主键来查询、更新的接口方法都会有问题,因为没有@id,数据库又没有设置自增id,通用mapper不知道哪个属性是主键,就会把所有属性都当做主键进行查询、更新;
第二种方法
①需要将mysql的id改为非自增设置;
②实体po类id属性只添加@id,告诉通用mapper把这个属性当成主键,如下:
@Id private Long id;
③dao接口继承tk.mybatis.mapper.additional.insert.InsertListMapper
public interface UserSystemMessageDao extends Mapper<UserSystemMessagePo>, InsertListMapper<UserSystemMessagePo> {
④跟第一种方法一样,手动设置id,批量插入
第三种方法
通过查看 tk.mybatis.mapper.additional.insert.InsertListMapper的源码如下:
/* * The MIT License (MIT) * * Copyright (c) 2014-2017 abel533@gmail.com * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package tk.mybatis.mapper.additional.insert; import org.apache.ibatis.annotations.InsertProvider; import tk.mybatis.mapper.annotation.RegisterMapper; import java.util.List; /** * 通用Mapper接口,特殊方法,批量插入,支持批量插入的数据库都可以使用,例如mysql,h2等 * * @param <T> 不能为空 * @author liuzh * @since 3.5.0 */ @RegisterMapper public interface InsertListMapper<T> { /** * 批量插入,支持批量插入的数据库可以使用,例如MySQL,H2等 * <p> * 不支持主键策略,插入前需要设置好主键的值 * <p> * 特别注意:2018-04-22 后,该方法支持 @KeySql 注解的 genId 方式 * * @param recordList * @return */ @InsertProvider(type = InsertListProvider.class, method = "dynamicSQL") int insertList(List<? extends T> recordList); }
其中红色标注的文字,高版本之后,支持@KeySql 生成id的方式,也就是跟普通方法一样了,用法如下:
前面三步跟第二种方法一模一样,只是第④步不再需要手动设置id了,只需要在属性上添加注解即可:
@Id @KeySql(genId = IdWorker.class) private Long id;
IdWorker参考最前面普通方法的定义
注意:批量插入需要采用第二种或者第三种方法,不会导致通用mapper其他接口方法出问题,因为po类添加了@id,通用mapper就知道id属性就是主键。
tk.mybatis.mapper.common.special.InsertListMapper和tk.mybatis.mapper.additional.insert.InsertListMapper的区别参考这里:
https://blog.csdn.net/ABestRookie/article/details/123120445