为什么Spring不抛出DuplicateKeyException,而是抛出MySQLIntegrityConstraintViolationException?

时间:2018-07-27 10:35:13

标签: spring duplicates

我有一个插入句子,该句子出现了重复键,它应该作为DuplicateKeyException抛出,但是我却有一个MySQLIntegrityConstraintViolationException。 为什么Spring没有将其包装为DuplicateKeyException?

高度赞赏。讨论欢迎。

代码和异常堆栈在下面。

异常堆栈:

com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry '2750633-163072083-袋-0' for key 'uk_unit_name'
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:422)
at com.mysql.jdbc.Util.handleNewInstance(Util.java:404)
at com.mysql.jdbc.Util.getInstance(Util.java:387)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:932)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3878)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3814)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2478)
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2625)
at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2551)
at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:1861)
at com.mysql.jdbc.PreparedStatement.execute(PreparedStatement.java:1192)
at com.dianping.zebra.single.jdbc.SinglePreparedStatement$2.doAction(SinglePreparedStatement.java:83)
at com.dianping.zebra.single.jdbc.SinglePreparedStatement$2.doAction(SinglePreparedStatement.java:80)
at com.dianping.zebra.single.jdbc.SingleStatement.executeWithFilterOrigin(SingleStatement.java:228)
at com.dianping.zebra.single.jdbc.SingleStatement.access$000(SingleStatement.java:37)
at com.dianping.zebra.single.jdbc.SingleStatement$8.executeSingleStatement(SingleStatement.java:215)
at com.dianping.zebra.filter.DefaultJdbcFilter.executeSingleStatement(DefaultJdbcFilter.java:59)
at com.dianping.zebra.single.jdbc.SingleStatement$8.executeSingleStatement(SingleStatement.java:212)
at com.dianping.zebra.filter.DefaultJdbcFilter.executeSingleStatement(DefaultJdbcFilter.java:59)
at com.dianping.zebra.single.jdbc.SingleStatement$8.executeSingleStatement(SingleStatement.java:212)
at com.dianping.zebra.filter.DefaultJdbcFilter.executeSingleStatement(DefaultJdbcFilter.java:59)
at com.dianping.zebra.single.jdbc.SingleStatement$8.executeSingleStatement(SingleStatement.java:212)
at com.dianping.zebra.monitor.filter.CatFilter.executeSingleStatement(CatFilter.java:153)
at com.dianping.zebra.single.jdbc.SingleStatement$8.executeSingleStatement(SingleStatement.java:212)
at com.dianping.zebra.single.jdbc.SingleStatement.executeWithFilter(SingleStatement.java:220)
at com.dianping.zebra.single.jdbc.SinglePreparedStatement.executeUpdate(SinglePreparedStatement.java:80)
at com.dianping.zebra.single.jdbc.SinglePreparedStatement.execute(SinglePreparedStatement.java:62)
at com.dianping.zebra.group.jdbc.GroupPreparedStatement.executeUpdateOnConnection(GroupPreparedStatement.java:172)
at com.dianping.zebra.group.jdbc.GroupPreparedStatement.executeUpdate(GroupPreparedStatement.java:159)
at com.dianping.zebra.group.jdbc.GroupPreparedStatement.execute(GroupPreparedStatement.java:98)
at org.apache.ibatis.executor.statement.PreparedStatementHandler.update(PreparedStatementHandler.java:44)
at org.apache.ibatis.executor.statement.RoutingStatementHandler.update(RoutingStatementHandler.java:69)
at org.apache.ibatis.executor.SimpleExecutor.doUpdate(SimpleExecutor.java:48)
at org.apache.ibatis.executor.BaseExecutor.update(BaseExecutor.java:105)
at org.apache.ibatis.executor.CachingExecutor.update(CachingExecutor.java:71)
at org.apache.ibatis.session.defaults.DefaultSqlSession.update(DefaultSqlSession.java:152)
at org.apache.ibatis.session.defaults.DefaultSqlSession.insert(DefaultSqlSession.java:141)
at sun.reflect.GeneratedMethodAccessor130.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:408)
at com.sun.proxy.$Proxy46.insert(Unknown Source)
at org.mybatis.spring.SqlSessionTemplate.insert(SqlSessionTemplate.java:254)
at org.apache.ibatis.binding.MapperMethod.execute(MapperMethod.java:51)
at org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:52)
at com.sun.proxy.$Proxy58.insertSelective(Unknown Source)
at sun.reflect.GeneratedMethodAccessor314.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at com.dianping.zebra.dao.AsyncMapperProxy.invoke(AsyncMapperProxy.java:67)
at com.sun.proxy.$Proxy58.insertSelective(Unknown Source)
at com.hh6plus.repository.impl.UnitRepositoryImpl.create(UnitRepositoryImpl.java:53)

呼叫者代码:

@Slf4j
@Repository
public class UnitRepositoryImpl implements UnitRepository {

    @Autowired
    private UnitMapper unitMapper;

    @Override
    public void create(Unit unit, boolean checkNameDuplicate) {
        UnitPO po = UnitPoConverter.convertToPo(unit);
        try {
            /***** exception thrown below *****/
            unitMapper.insertSelective(po);

            fillUnitIdWithId(po.getTenantId(), po.getPoiId(), po.getId(), po);

        } catch (DuplicateKeyException e) {
            /***** code expected to be processed, but not happened. *****/
            if (checkNameDuplicate) {
                throw e;
            }

            log.warn("duplicate.unit:{}.", unit, e);
            List<Unit> existsUnits = this.findByName(unit.getTenantId(), unit.getPoiId(), unit.getName());
            if (CollectionUtils.isNotEmpty(existsUnits)) {
                Unit existsUnit = existsUnits.get(0);
                BeanUtils.copyProperties(existsUnit, unit);
            }
        }
    }
}

被叫方代码:

java代码:

public interface UnitMapper {
/**
 * This method was generated by MyBatis Generator.
 * This method corresponds to the database table unit
 *
 * @mbggenerated Thu Jul 19 18:07:32 CST 2018
 */
int insert(UnitPO record);
}

mybatis xml:

  <insert id="insertSelective" parameterType="com.hh6plus.dao.model.UnitPO">
    <!--
      WARNING - @mbggenerated
      This element is automatically generated by MyBatis Generator, do not modify.
      This element was generated on Thu Jul 19 18:07:32 CST 2018.
    -->
    <selectKey keyProperty="id" order="AFTER" resultType="java.lang.Long">
      SELECT LAST_INSERT_ID()
    </selectKey>
    insert into unit
    <trim prefix="(" suffix=")" suffixOverrides=",">
      <if test="tenantId != null">
        tenant_id,
      </if>
      <if test="poiId != null">
        poi_id,
      </if>
      <if test="name != null">
        name,
      </if>
      <if test="rank != null">
        rank,
      </if>
      <if test="operator != null">
        operator,
      </if>
      <if test="deleted != null">
        deleted,
      </if>
      <if test="createdTime != null">
        created_time,
      </if>
      <if test="modifiedTime != null">
        modified_time,
      </if>
      <if test="unitId != null">
        unit_id,
      </if>
    </trim>
    <trim prefix="values (" suffix=")" suffixOverrides=",">
      <if test="tenantId != null">
        #{tenantId,jdbcType=INTEGER},
      </if>
      <if test="poiId != null">
        #{poiId,jdbcType=INTEGER},
      </if>
      <if test="name != null">
        #{name,jdbcType=VARCHAR},
      </if>
      <if test="rank != null">
        #{rank,jdbcType=BIGINT},
      </if>
      <if test="operator != null">
        #{operator,jdbcType=INTEGER},
      </if>
      <if test="deleted != null">
        #{deleted,jdbcType=BIGINT},
      </if>
      <if test="createdTime != null">
        #{createdTime,jdbcType=TIMESTAMP},
      </if>
      <if test="modifiedTime != null">
        #{modifiedTime,jdbcType=TIMESTAMP},
      </if>
      <if test="unitId != null">
        #{unitId,jdbcType=BIGINT},
      </if>
    </trim>
  </insert>

1 个答案:

答案 0 :(得分:0)

问题解决了。 实际上,springframework将SQLException包装到DuplicateKeyException中并被捕获。 我说没有被捕获的原因是,我被公司中的一个日志组件误导了,该组件自动记录SQLException,而与代码中的catchensen无关。 抱歉,我的信息不正确。