最近,在做springMVC框架练习时,体验了几种事务管理的方式,其中在用@Transactional注解实现事务管理时,遇到了一些问题,最终得到了解决,现跟大家分享下。
先介绍下我做练习用的例子:在数据库中建了个学生信息表(t_student),通过程序插入一条数据,期间通过@Transactional注解实现事务的管理。下面是service层的主要代码块:
@Service
@Transactional
public class StudentService {
@Resource(name = "template")
JdbcTemplate jdbcTemplate;
public void createStudent(Student student) {
String sqlStr = "insert into t_student (id, name, score) values (?, ?, ?)";
jdbcTemplate.update(sqlStr, student.getId(), student.getName(), student.getScore());
}
}
student对象:
public class Student {
private String id;
private String name;
private Integer score;
//此处省略get、set方法
}
正常情况下,插入数据没有问题,现在主要是测试一下在出现异常的情况下,能否回滚,所以在代码中增加了一行抛出异常的代码,如下:
@Service
@Transactional
public class StudentService {
@Resource(name = "template")
JdbcTemplate jdbcTemplate;
public void createStudent(Student student) {
String sqlStr = "insert into t_student (id, name, score) values (?, ?, ?)";
jdbcTemplate.update(sqlStr, student.getId(), student.getName(), student.getScore());
throw new RuntimeException();
}
}
执行插入操作后,控制台确实抛出了异常,如图:
但是发现数据库中依然插入了数据,也就是说事务没有得到控制,没达到预期效果。经过多方查找,发现问题是xml配置文件里未开启对注解的解析,需要增加<tx:annotation-driven transaction-manager="transactionManager"/>,如下图:
开启注解解析后,愉快的启动程序准备测试,结果启动时报错了,如下:
Caused by: java.lang.NoSuchMethodError: org.springframework.core.annotation.AnnotationUtils.isInJavaLangAnnotationPackage(Ljava/lang/annotation/Annotation;)Z
at org.springframework.core.annotation.AnnotatedElementUtils.doProcess(AnnotatedElementUtils.java:209)
at org.springframework.core.annotation.AnnotatedElementUtils.process(AnnotatedElementUtils.java:162)
... 60 more
一月 14, 2019 8:49:59 下午 org.apache.catalina.core.StandardContext loadOnStartup
严重: Servlet /firstweb threw load() exception
java.lang.NoSuchMethodError: org.springframework.core.annotation.AnnotationUtils.isInJavaLangAnnotationPackage(Ljava/lang/annotation/Annotation;)Z
at org.springframework.core.annotation.AnnotatedElementUtils.doProcess(AnnotatedElementUtils.java:209)
at org.springframework.core.annotation.AnnotatedElementUtils.process(AnnotatedElementUtils.java:162)
at org.springframework.core.annotation.AnnotatedElementUtils.getAnnotationAttributes(AnnotatedElementUtils.java:91)
at org.springframework.core.annotation.AnnotatedElementUtils.getAnnotationAttributes(AnnotatedElementUtils.java:85)
报错原因及解决方法参见:
https://mp.csdn.net/postedit/86483891
解决完上述错误后,重新启动,结果又报了另一个错:
Caused by: java.lang.IncompatibleClassChangeError: class org.springframework.core.type.classreading.ClassMetadataReadingVisitor has interface org.springframework.asm.ClassVisitor as super class
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:763)
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
at org.apache.catalina.loader.WebappClassLoader.findClassInternal(WebappClassLoader.java:2854)
at org.apache.catalina.loader.WebappClassLoader.findClass(WebappClassLoader.java:1159)
at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1647)
at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1526)
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:763)
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
at org.apache.catalina.loader.WebappClassLoader.findClassInternal(WebappClassLoader.java:2854)
at org.apache.catalina.loader.WebappClassLoader.findClass(WebappClassLoader.java:1159)
at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1647)
at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1526)
at org.springframework.core.type.classreading.SimpleMetadataReader.<init>(SimpleMetadataReader.java:63)
at org.springframework.core.type.classreading.SimpleMetadataReaderFactory.getMetadataReader(SimpleMetadataReaderFactory.java:98)
at org.springframework.core.type.classreading.CachingMetadataReaderFactory.getMetadataReader(CachingMetadataReaderFactory.java:102)
at org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider.findCandidateComponents(ClassPathScanningCandidateComponentProvider.java:237)
... 53 more
报错原因及解决方法参见:
https://mp.csdn.net/postedit/86484124
最后,启动终于不报错了,执行插入操作后,抛出异常,检查数据库后发现没有插入,也就是说事务得到了有效控制。