使用Spring的声明式事务----Annotation注解方式
程序员文章站
2022-05-21 09:28:47
...
这里列一个小的demo工程,直接利用Spring的jdbcTemplate访问Mysql数据库。
工程结构:
数据库中的tbl_student表结构如下:
数据实体类Student.java代码如下:
package com.mysrc.entity; import java.sql.Date; public class Student { private int id; private String name; private Date birth; private float score; public Student() { } 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 Date getBirth() { return birth; } public void setBirth(Date birth) { this.birth = birth; } public float getScore() { return score; } public void setScore(float score) { this.score = score; } @Override public String toString() { return "Student [id=" + id + ", name=" + name + ", birth=" + birth + ", score=" + score + "]"; } }
数据访问类StudentDao.java代码如下:
package com.mysrc.dao; import java.util.List; import org.springframework.jdbc.core.JdbcTemplate; import com.mysrc.entity.Student; import com.mysrc.entity.StudentRowMapper; public class StudentDao { private JdbcTemplate jdbcTemplate; public void setJdbcTemplate(JdbcTemplate jdbcTemplate) { this.jdbcTemplate = jdbcTemplate; } public Student getStudentById(int id) { return jdbcTemplate.queryForObject( "select * from tbl_student where id = ?", new Object[] { id }, new StudentRowMapper()); } public List<Student> getAllStudent() { return jdbcTemplate.query("select * from tbl_student", new StudentRowMapper()); } public int insertStudent(Student student) { return jdbcTemplate.update( "insert into tbl_student(name,birth,score) values(?,?,?)", new Object[] { student.getName(), student.getBirth(), student.getScore() }); } public int deleteStudent(int id) { return jdbcTemplate.update("delete from tbl_student where id = ? ", new Object[] { id }); } public int updateStudent(Student student) { return jdbcTemplate.update( " update tbl_student set name=?,birth=?,score=? where id=? ", new Object[] { student.getName(), student.getBirth(), student.getScore(), student.getId() }); } }
服务类StudentService.java代码如下:
package com.mysrc.service; import java.sql.Date; import java.util.List; import org.springframework.transaction.annotation.Isolation; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; import com.mysrc.dao.StudentDao; import com.mysrc.entity.Student; public class StudentService { private StudentDao dao; public void setDao(StudentDao dao) { this.dao = dao; } @Transactional(propagation = Propagation.NESTED, timeout = 1000, isolation = Isolation.READ_COMMITTED, rollbackFor = Exception.class, noRollbackFor = CustomRuntimeException.class) public void doComplexLogic() { // select List<Student> list = dao.getAllStudent(); for (Student student : list) { System.out.println(student); } // update Student student = list.get(0); student.setName("zhejiang"); dao.updateStudent(student); System.out.println("did update temporarily..."); // int a = 9 / 0; // 遇到异常,整个事务回滚 // 如果try catch捕获这个异常,那整个事务会顺利执行,不会回滚 int b = 2; if (b > 1) { throw new CustomRuntimeException(); // 事务不会回滚,也就是上面的update操作会提交 } // insert student = new Student(); student.setName("hello"); student.setBirth(new Date(354778)); student.setScore(78.9f); dao.insertStudent(student); System.out.println("did insert..."); // delete dao.deleteStudent(3); System.out.println("did delete..."); } class CustomRuntimeException extends RuntimeException { public CustomRuntimeException() { super(); } public CustomRuntimeException(String msg) { super(msg); } } }
doComplexLogic()方法模拟一个复杂的数据库操作过程,方法上加上了@Transactional,其中的各个注解的属性后面再详细研究。网上有人说@Transactional 只能被应用到public方法上, 对于其它非public的方法,如果标记了@Transactional也不会报错,但方法没有事务功能,这个未验证。
Spring的上下文配置文件applicationContext.xml内容如下:
<?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" 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.xsd" xmlns:tx="http://www.springframework.org/schema/tx"> <bean id="basicDataSource" class="org.apache.commons.dbcp.BasicDataSource"> <property name="url" value="jdbc:mysql://127.0.0.1:3306/mytestdb?characterEncoding=utf8" /> <property name="driverClassName" value="com.mysql.jdbc.Driver" /> <property name="username" value="root" /> <property name="password" value="123456" /> <property name="maxActive" value="100" /> <property name="maxIdle" value="30" /> <property name="maxWait" value="1000" /> <property name="validationQuery" value="select 1" /> </bean> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <constructor-arg name="dataSource" ref="basicDataSource"> </constructor-arg> </bean> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager "> <property name="dataSource"> <ref bean="basicDataSource" /> </property> </bean> <bean id="studentDao" class="com.mysrc.dao.StudentDao"> <property name="jdbcTemplate"> <ref bean="jdbcTemplate" /> </property> </bean> <bean id="studentService" class="com.mysrc.service.StudentService"> <property name="dao"> <ref bean="studentDao" /> </property> </bean> <tx:annotation-driven transaction-manager="transactionManager" /> <!--这句话的作用是注册事务注解处理器 --> </beans>
测试类MyTester.java代码如下:
package com.mysrc.test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.mysrc.service.StudentService; public class MyTester { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext( "applicationContext.xml"); StudentService studentService = (StudentService) context .getBean("studentService"); studentService.doComplexLogic(); } }
@Transactional 的所有可选属性如下
属性 | 类型 | 默认值 | 说明 |
propagation | Propagation枚举 | REQUIRED | 事务传播属性 |
isolation | isolation枚举 | DEFAULT | 事务隔离级别 |
readOnly | boolean | false | 是否只读 |
timeout | int | -1 | 超时(秒) |
rollbackFor | Class[] | {} | 需要回滚的异常类 |
rollbackForClassName | String[] | {} | 需要回滚的异常类名 |
noRollbackFor | Class[] | {} | 不需要回滚的异常类 |
noRollbackForClassName | String[] | {} | 不需要回滚的异常类名 |
整个eclipse工程代码文件在附件中。。
推荐阅读
-
Spring声明式事务和@Aspect的拦截顺序问题的解决
-
Spring实战之使用XML方式管理声明式事务操作示例
-
Spring实战之使用TransactionProxyFactoryBean实现声明式事务操作示例
-
Spring实现声明式事务的方法详解
-
使用spring声明式事务失效之第二弹
-
使用spring声明式事务失效之第二弹
-
使用spring+springMVC 组合开发,声明式事务失效
-
使用spring+springMVC 组合开发,声明式事务失效
-
Spring MVC @Transactional注解方式事务失效的解决办法
-
Spring整合Hibernate事务注解使用的坑-配置事务管理器