前两天一人问我,在使用spring mvc (基于注解) 的时候,事务失效(也是基于注解)。问我咋搞。好吧,我承认其实我一直只是在走马观花的看了一下spring的事务处理,因为我现在做的项目基本上只用到了查询,完全没有考虑事务回滚不回滚的问题。不过既然问到了,我就打算看一下。结果问题一大堆。所以,现在记下来,算是总结,也算是备忘。
编程式事务就不搞了。主要是搞声明式和注解式的事务。
由于我对spring事务是个新手。所以我做了几个小例子,一步一步的深入。
第一种:在非mvc中使用声明式事务。
package cn.lyy.model;
public class Teacher {
private int id;
private String name;
private String email;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
package cn.lyy.service;
import org.springframework.transaction.annotation.Transactional;
import cn.lyy.dao.TeacherDao;
import cn.lyy.model.Teacher;
public class TeacherService {
private TeacherDao teacherDao;
public void addTeacher(Teacher teacher) {
teacherDao.insert(teacher);
throw new RuntimeException("运行异常"); //用来测试回滚
}
public TeacherDao getTeacherDao() {
return teacherDao;
}
public void setTeacherDao(TeacherDao teacherDao) {
this.teacherDao = teacherDao;
}
}
package cn.lyy.dao;
import org.springframework.jdbc.core.JdbcTemplate;
import cn.lyy.model.Teacher;
public class TeacherDao {
private JdbcTemplate jdbcTemplate;
public void insert(Teacher teacher) {
final String sql = "insert into teacher values(" + teacher.getId()
+ ",'" + teacher.getName() + "','" + teacher.getEmail() + "')";
jdbcTemplate.execute(sql);
}
public JdbcTemplate getJdbcTemplate() {
return jdbcTemplate;
}
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
}
位于classpath下。
<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<context:property-placeholder location="classpath:jdbc.properties" />
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close" p:driverClassName="${jdbc.driverClassName}"
p:url="${jdbc.url}" p:username="${jdbc.username}" p:password="${jdbc.password}" />
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"
p:dataSource-ref="dataSource" />
<bean id="teacherDao" class="cn.lyy.dao.TeacherDao"
p:jdbcTemplate-ref="jdbcTemplate" />
</beans>
位于classpath下。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
<import resource="classpath:applicationContext-dao.xml" />
<bean id="teacherService" class="cn.lyy.service.TeacherService"
p:teacherDao-ref="teacherDao" />
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager"
p:dataSource-ref="dataSource" />
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="get*" read-only="true" />
<tx:method name="add*" propagation="REQUIRED" isolation="READ_COMMITTED"
rollback-for="java.lang.RuntimeException" />
<tx:method name="update*" />
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="serviceMethod" expression="execution(* cn.lyy.service.*.*(..))" />
<aop:advisor advice-ref="txAdvice" pointcut-ref="serviceMethod" />
</aop:config>
</beans>
位于classpath下。
#Mysql jdbc.driverClassName=com.mysql.jdbc.Driver jdbc.url=jdbc\:mysql\://localhost\:3306/test jdbc.username=root jdbc.password=root ##oracle #jdbc.driverClassName=oracle.jdbc.driver.OracleDriver #jdbc.url=jdbc:oracle:thin:@localhost:1521:ora9i #jdbc.username=lyy #jdbc.password=lyy ##sqlite #jdbc.driverClassName=org.sqlite.JDBC #jdbc.url=jdbc:sqlite:mydb.db #jdbc.username=sa #jdbc.password= #postgre jdbc.driverClassName=org.postgresql.Driver jdbc.url=jdbc:postgresql:test jdbc.username=lyy jdbc.password=lyy测试:package cn.lyy.test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import cn.lyy.model.Teacher;
import cn.lyy.service.TeacherService;
public class TeacherTest {
public static void main(String[] args) {
String configLoaction = "classpath:applicationContext-tx.xml";
ApplicationContext ctx = new ClassPathXmlApplicationContext(
configLoaction);
TeacherService teacherService = ctx.getBean(TeacherService.class);
Teacher teacher = new Teacher();
teacher.setId(2);
teacher.setName("lyy2");
teacher.setEmail("lyy@163.com");
teacherService.addTeacher(teacher);
}
}
这是第一个,也是搭建最累的一个。主要是我选择的数据库是mysql。结果就是从控制台上看,事务确实回滚了。但是,再检查数据库,发现数据仍然插入,开始以为是事务的配置没有写好(对事务不熟),结果查了两天资料才无意中发现mysqlinnodb才支持事务。而且root权限下自动提交。于是换了sqlite数据库试了一下,发现可以成功回滚,最终确定用postgre数据库来做下面的实验。
第二种:注解式事务:因为只是实验。只要改以下两个地方,一是service类上加@Transactional.。然后在配置文件中。注释掉<tx:advice>的一大堆东西,改成
<tx:annotation-driven transaction-manager="transactionManager"/>
就行了。
第二大类:非注解spring mvc + 声明式事务和 非注解springmvc+ 注解式事务
第三种:非注解spring mvc +声明式事务
这个和第一种差不多。不同之处是spring-servlet.xml中:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<bean id="handlerMapping"
class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping">
</bean>
<bean name="/addteacher.do" class="cn.lyy.controller.TeacherController">
<property name="teacherService" ref="teacherService">
</property>
</bean>
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver"
p:prefix="/WEB-INF/view/" p:suffix=".jsp" />
</beans>
第四种:非注解spring mvc + 注解事务
这个和第二种差不多。不同之处也是和上面一样。
下面的这个,也是spring使用得最多的一类
spring mvc(注解)+声明式事务。和spring mvc(注解)+注解式事务
本文通过四个实验探讨了Spring框架中事务管理的不同方式,包括声明式事务和注解式事务,并对比了在非MVC及MVC环境下的应用效果。
733

被折叠的 条评论
为什么被折叠?



