一个 JPA 事物的问题,请大家一定要戳进来帮我看下,谢谢了!

Palm 发布于 2014年06月10日 | 更新于 2014年06月26日
无人欣赏。

是这样的: 首先由两张表 A . B A表中有一个字段 主键id 在B表中是外键 且 这两个表被两个以上系统同时使用.

然后 流程中需要将生成四个 6位字符,挑选一个 A表不存在的字符添加到A表中。然后使用该字符关联数据到B表中.

大概方法结构是这样的:

@Transactional(rollbackFor=Exception.class,value="transactionManager")
xxx F ()throws Exception{
     String enbleId=getxxx();//这里是循环将四个字符插入到A表 如果成功没有异常则使用该ID
     updatexxx(enbleId); //在这里经过得到的有效id 更新到B表
}

getxxx()方法结果是这样的:

getxxx(){
       //准备好四个6位的字符串数组 ids []; 
   for(String srcid : ids){
        try{ 
            //这里使用srcid insert 到A表如果异常 进入catch 进行下一次循环
            //如果没有问题 break; 结束循环 返回这个 有效字符串到上面方法 F ()
            return enbleid;
         } catch(Exception e){
           continue;
         }
    }
}

上面这种结果 ,会出现这样几个问题:

  1. 当 在getxxx 方法中 只要有主键唯一约束异常存在则在F() 处被事物管控回滚 ,即使 我使用catch 处理 然后得到有效字符串 。也会回滚并且抛出异常。 2.在方法F ()中调用的getxxx 方法中一次生成的四个id 字符串 为了有效使用 依次插入 设想 异常 必定为主键惟一约束所以进入catch 进入下一轮循环,然后得到有效id insert 到A表 然后返回再更新到B表。 但是 并不是设想的那般, 当在getxxx 方法中存在依次主键约束异常,得到有效id后 回到F()方法都会被JPA事物拦截 回滚事物 然后导致B表不能更新抛出异常

请问这是为什么 ? 如果我在F()方法中捕获异常 ,还可以接受 ,我在内部捕获异常且处理了 为什么还会回滚事物呢?

之前想先查询 再插入,害怕中间的时间差导致 主键约束 所以采用这种方法,但是现在确实很多问题 只要重复就会失败 请问这种问题应该如何解决???

---------------update------------------------------------------

忘记备注了,该问题已经有解决方案了,在试运行,监控中。 将两个事务分开就可以了。

共5条回复
tinyfool 回复于 2014年06月11日

完全不懂什么是JPA

Palm 回复于 2014年06月11日

@tinyfool JPA 是EJB开发的 一个为POJO提供持久化标准规范 一般JPA是作为hibernate的接口使用的,用于规范hibernate orm 实现 它是一个标准 我知道的 也就这么多

hashmap 回复于 2014年06月11日

当我的客户把JPA和iBatis放在我面前让我选择的时候,我毫不犹豫的选择了后者。

Palm 回复于 2014年06月11日

3楼 @hashmap 我觉得 JPA 对持久化 还是挺好的 主要是兼容其它框架 的时候 整合 不好 就很难弄了 各种问题不断 使用好了 也挺方便的 但是我也只是用 底层原理的 问题i我也解决不了

windydays 回复于 2014年06月26日

"害怕中间的时间差导致 主键约束 " 这个不合理吧,如果是Select和Update在一个事务里,应该可以保证一致性的。

登录 或者 注册