本文共 3267 字,大约阅读时间需要 10 分钟。
Mysql的 insert常用方法——插入后返回插入成功后的主键
SELECT LAST_INSERT_ID() ]]>
上面的方法利用的是mysql的LAST_INSERT_ID()函数会返回当前连接上次插入记录的自增主键。
public long insert(BudgetPlanBO budgetPlanBO) { LoggerUtil.debug(LOGGER, "insert", budgetPlanBO); return ucdpBudgetPlanDAO.insert(BudgetPlanConvertor.convertBOtoDO(budgetPlanBO)); }
public long insert(BudgetPlanBO budgetPlanBO) { LoggerUtil.debug(LOGGER, "insert", budgetPlanBO); try { return ucdpBudgetPlanDAO.insert(BudgetPlanConvertor.convertBOtoDO(budgetPlanBO)); } catch (DuplicateKeyException e) { return ucdpBudgetPlanDAO.queryByUniqueId(budgetPlanBO.getPlanType().name(), budgetPlanBO.getBizDate(), budgetPlanBO.getBizCode()).getId(); } }
以上的日志打印存在严重问题,不仅在线上环境打不了日志,而且打出来的日志没有具体参数,没有排查的实际帮助意义。
public long insert(BudgetPlanBO budgetPlanBO) { LoggerUtil.info(LOGGER, "[createBudget]插入预算:{0}", budgetPlanBO); try { //same as above. } catch (DuplicateKeyException e) { //same as above. } }
存在两个问题:
以上语句只是一次创建,在实际项目中一个接口要进行200+次的批量创建。开发环境没问题,但在预发环境中批量创建出现了部分成功部分失败的问题。唯一索引的搜索,使得本语句变成了一写多读的情况。就会导致一直返回0,因为写连接跟读连接不是同一个,解决方法是通过开启事务,强制使用同一连接进行读写。除非一定要获取插入id的情况,否则不推荐使用事务来获取插入id。public long insert(BudgetPlanBO budgetPlanBO) { LoggerUtil.info(LOGGER, "[createBudget]插入预算:{0}", budgetPlanBO); return this.ucdpMngTransactionTemplate.execute(new TransactionCallback() { @Override public Long doInTransaction(TransactionStatus transactionStatus) { try { return ucdpBudgetPlanDAO.insert(BudgetPlanConvertor.convertBOtoDO(budgetPlanBO)); } catch (DuplicateKeyException e) { return ucdpBudgetPlanDAO.queryByUniqueId(budgetPlanBO.getPlanType().name(), budgetPlanBO.getBizDate(), budgetPlanBO.getBizCode()).getId(); } catch (Throwable e) { LoggerUtil.error(LOGGER, "[insert]插入预算异常, Exception={0}", JSON.toJSONString(e)); transactionStatus.setRollbackOnly(); throw new UcdpMngException(e.getMessage()); } } }); }
转载地址:http://tbrsi.baihongyu.com/