本文记录一个实例:
1、用户邀请码表,里面存邀请码和关联的用户编号,每次有用户注册,就领取(关联)一个邀请码。邀请码都是系统提前生成空挡在表里待分配的(不要问为什么,目前业务就是这样设计的)。
2、系统初始化的时候,或者空闲的邀请码快不够用的时候,会需要追加生成一批邀请码入库。一般系统上线的时候直接入库几十万或者几百万妥妥了。

代码实现步骤:
1、在 Controller 请求,调用Service。
2、Service 中,使用Java程序生成不重复的值,然后按1000一批的方式,分割Controller提交的总数,多次执行。
3、MyBatis XML文件中,3个方法(将每一批邀请码存入创建的临时表》将临时表数据排除掉已经存在的数据转移到正式邀请码表中》显示删除临时表)

主要代码如下:

	/**
	 * 生成一批邀请码(说预期是因为程序生成后,可能数据库已经存在一部分,这里不做严格数量处理,实际入库多少就是多少)
	 * 
	 * @return
	 */
	@PostMapping("/generate")
	public ResultVO batchGenerate() {
		if (request.getRequestURL().toString().contains("localhost")
				|| request.getRequestURL().toString().contains("127.0.0.1")) {
			long _start = System.currentTimeMillis();
			int n = userInviteCodeService.batchGenerateInviteCode(20000);
			String msg = "成功增加" + n + "个邀请码。耗时:" + (System.currentTimeMillis() - _start) + "ms";
			logger.info(msg);
			return new ResultVO(msg);
		} else {
			logger.warn("请在本机使用localhost或127.0.0.1方式请求接口");
			return ResultVO.FORBIDDEN;
		}
	}

	/**
	 * 生成一批推荐码
	 * 
	 * @param count 预生成数量,这里不做严格处理,假设预生成1万个,因为数据库已经存在100个,那么实际生成则是9900个,没有关系。
	 */
	public int batchGenerateInviteCode(int count) {
		// 批量生成验证码
		Map<String, String> inviteCodeMap = new HashMap<>();
		List<UserInviteCode> codeList = new ArrayList<>();
		int i = 0, j = 0;
		UserInviteCode record;
		int successCount = 0;
		while (i < count) {
			String inviteCode = RandomStringUtils.randomAlphanumeric(6).toUpperCase();
			if (inviteCodeMap.put(inviteCode, "1") == null) {
				record = new UserInviteCode();
				record.setInviteCode(inviteCode);
				record.setCreateTime(new Date());
				record.setDelFlag(1);
				record.setVersion(1);
				codeList.add(record);
				i++;
			}
			if (i % 1000 == 0) {
				successCount += saveGenerateInviteCode(codeList);
				codeList = new ArrayList<>();
			}
			j++;
		}
		// 1000倍数后的余数
		successCount += saveGenerateInviteCode(codeList);
		
		logger.info("预生成{}个推荐码,程序产生{}个验证码,程序碰撞重复{}个,{}个邀请码实际入库{}个,与库中重复碰撞{}个", count, j, j - i, count, successCount,
				count - successCount);
		return successCount;
	}

	/**
	 * 持久化code到数据库,list集合大小限制不超过1000
	 * 
	 * @param codeList
	 * @return
	 */
	private int saveGenerateInviteCode(List<UserInviteCode> codeList) {
		int n = 0;
		// 限制单次操作数据的数量为1000,这是经过实测出来的结果请勿随意改动此值!!!
		if (codeList.size() > 0 && codeList.size() <= 1000) {
			try {
				userInviteCodeMapper.saveNewCodeToTempTable(codeList);
				n = userInviteCodeMapper.insertByTempTable();
			} finally {
				// 显式调用,实际上数据库会自动回收
				userInviteCodeMapper.dropTempTable();
			}
		}
		return n;
	}

/**
 * 用户邀请码
 * 
 * @author 单红宇
 * @date   2019年6月28日
 *
 */
public interface UserInviteCodeMapper extends Mapper<UserInviteCode> {

	int saveNewCodeToTempTable(List<UserInviteCode> inviteCodeList);
	
	int insertByTempTable();
	
	void dropTempTable();
}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.shanhy.example.module.user.mapper.UserInviteCodeMapper">
	
	<!-- 1.创建临时表并插入数据(注意:该方法其实就拼接一个很长的SQL,因为数据库对SQL长度有限制,所以调用该方法传入的集合要注意大小限制)为了节约长度,减少换行和变量名的长度等等 -->
	<!-- 对于本例SQL,传入的是6个字符长度的随机值,实测List大小在1300左右可以正常入库,1500就超长了。所以本例实际业务中,限制传入的List大小为1000 -->
	<update id="saveNewCodeToTempTable">
        CREATE TEMPORARY TABLE IF NOT EXISTS user_invite_code_temp1
        <foreach collection="list" item="item" separator="UNION">SELECT #{item.inviteCode} code</foreach>
    </update>
    
    <!-- 2.将临时表数据插入到标准表 -->
    <update id="insertByTempTable">
    	insert into user_invite_code(invite_code, create_time, version, del_flag)
    	select code,now(),1,1 from user_invite_code_temp1 t1
    	where not exists(select * from user_invite_code t2 where t2.invite_code = t1.code)
    </update>
    
    <!-- 3.删除临时表 -->
    <update id="dropTempTable">  
        DROP TEMPORARY TABLE IF EXISTS user_invite_code_temp1
    </update>
    
</mapper>

(结束)