javax.persistence.RollbackException: Transaction marked as rollbackOnly异常出现的原因以及避免方法
2016-10-12 12:24
555 查看
这次的需求是实现导入功能,要求:如果导入的内容以及存在,那就以excel表格的形式反馈给用户,并且告知用户每一行的错误原因;如果该条记录数据库中不存在,那么就添加到数据库中。
一开始,我的思路是在执行save操作时用try-catch包围,如果catch到了异常,那么就将这个对像放到errors中,在最后将errors导出成excel。
但是问题来了,由于我的repository是继承自JPARepository的,并且为了提高插入的效率,在service中加了@Transactional(noRollbackFor = Exception.class)注解。正是因为加了这个注解,所以导致了javax.persistence.RollbackException: Transaction marked as rollbackOnly异常的发生。
下面先来举个小列子
@Transactional(noRollbackFor = Exception.class)
Public void A(){
for(int 1=0;i<10;i++)
try{
add(i);
}catch(Exception e){
输出(i);
}
}
@Transactional
Public void add(int i){
if(i>5)
Throw a exception//假设抛出一个异常
将 i 插入到数据库中
}
在这种情况下就会出现javax.persistence.RollbackException: Transaction marked as rollbackOnly异常。
当在A方法中执行B方法时,虽然A方法加了 noRollbackFor = Exception.class ,但是由于调用的B方法没有加,并且在B中抛出了异常,那么就会报这个错误,也无法达到我的目的,即插入0到5这几个数字,而是会全部回滚。
我的需求跟这个类似,我本来想通过try-catch来捕捉到插入失败的对象,然后分析异常原因,再导出给用户,好让他们修改完之后再上传。但是我调用Jpa的sava方法,它本身的实现中就加了@Transactional,没有加noRollbackFor = Exception.class,因此即便我在service方法中加了@Transactional(noRollbackFor = Exception.class),也会回滚。
下面我的解决方法是进行预处理,在插入之前先进行判重,即将考试表中的考题拿出来,为了提高判重效率,先将String的考题构建Hash值,然后进行比较,这样的比较速度会大大提高。代码如下
@Transactional
public Map<String, Object> save(List<Exam> exams) {
Map<String, Object> error = new HashMap<>();
List<Exam> errors = new ArrayList<>();
List<String> errorMsgs = new ArrayList<>();
List<String> tests = repo.findTests();
List<Integer> testHashcodes = new ArrayList<Integer>();
for (String test : tests) {
testHashcodes.add(test.hashCode());
}
int hashcode = -1;
for (Exam exam : exams) {
hashcode = exam.getTest().hashCode();
if (testHashcodes.contains(hashcode)) {
errors.add(exam);
errorMsgs.add("题目重复");
} else {
repo.save(exam);
testHashcodes.add(hashcode);
}
}
error.put("errors", errors);
error.put("errormsg", errorMsgs);
return error;
}
一开始,我的思路是在执行save操作时用try-catch包围,如果catch到了异常,那么就将这个对像放到errors中,在最后将errors导出成excel。
但是问题来了,由于我的repository是继承自JPARepository的,并且为了提高插入的效率,在service中加了@Transactional(noRollbackFor = Exception.class)注解。正是因为加了这个注解,所以导致了javax.persistence.RollbackException: Transaction marked as rollbackOnly异常的发生。
下面先来举个小列子
@Transactional(noRollbackFor = Exception.class)
Public void A(){
for(int 1=0;i<10;i++)
try{
add(i);
}catch(Exception e){
输出(i);
}
}
@Transactional
Public void add(int i){
if(i>5)
Throw a exception//假设抛出一个异常
将 i 插入到数据库中
}
在这种情况下就会出现javax.persistence.RollbackException: Transaction marked as rollbackOnly异常。
当在A方法中执行B方法时,虽然A方法加了 noRollbackFor = Exception.class ,但是由于调用的B方法没有加,并且在B中抛出了异常,那么就会报这个错误,也无法达到我的目的,即插入0到5这几个数字,而是会全部回滚。
我的需求跟这个类似,我本来想通过try-catch来捕捉到插入失败的对象,然后分析异常原因,再导出给用户,好让他们修改完之后再上传。但是我调用Jpa的sava方法,它本身的实现中就加了@Transactional,没有加noRollbackFor = Exception.class,因此即便我在service方法中加了@Transactional(noRollbackFor = Exception.class),也会回滚。
下面我的解决方法是进行预处理,在插入之前先进行判重,即将考试表中的考题拿出来,为了提高判重效率,先将String的考题构建Hash值,然后进行比较,这样的比较速度会大大提高。代码如下
@Transactional
public Map<String, Object> save(List<Exam> exams) {
Map<String, Object> error = new HashMap<>();
List<Exam> errors = new ArrayList<>();
List<String> errorMsgs = new ArrayList<>();
List<String> tests = repo.findTests();
List<Integer> testHashcodes = new ArrayList<Integer>();
for (String test : tests) {
testHashcodes.add(test.hashCode());
}
int hashcode = -1;
for (Exam exam : exams) {
hashcode = exam.getTest().hashCode();
if (testHashcodes.contains(hashcode)) {
errors.add(exam);
errorMsgs.add("题目重复");
} else {
repo.save(exam);
testHashcodes.add(hashcode);
}
}
error.put("errors", errors);
error.put("errormsg", errorMsgs);
return error;
}
相关文章推荐
- spring事务(Transaction )报 marked as rollback-only异常的原因及解决方法
- JPA出现Transaction marked as rollback only异常 总结
- java:Transaction marked as rollbackOnly异常原因及解决
- 解决Could not commit JPA transaction RollbackException: Transaction marked as rollbackOnly
- Transaction rolled back because it has been marked as rollback-only异常
- 解决Could not commit JPA transaction RollbackException: Transaction marked as rollbackOnly
- Spring捕获异常出错。Transaction marked as rollbackOnly
- UnexpectedRollbackException: Transaction rolled back because it has been marked as rollback-only
- Transaction rolled back because it has been marked as rollback-only分析解决方法
- ConcurrentModificationException异常出现原因以及解决方法
- 调用Set.add(All)出现java.lang.UnsupportedOperationException异常原因以及解决方法
- List ConcurrentModificationException出现原因以及避免方法
- 解决Could not commit JPA transaction RollbackException: Transaction marked as rollbackOnly
- Could not commit JPA transaction; nested exception is javax.persistence.RollbackException 解决方法
- Rational Rose 2003破解版的下载与安装以及出现java.lang.ClassNotFoundException异常的解决方法
- Transaction rolled back because it has been marked as rollback-only”
- Srping Transaction rolled back because it has been marked as rollback-only解决方案
- 使用MySQL和Hibernate时,出现java.lang.UnsupportedOperationException: Update queries only supported through HQL异常的解决方法
- Transaction rolled back because it has been marked as rollback-only”
- “Transaction rolled back because it has been marked as rollback-only”