通过注解实现Spring 声明式事务管理

小Alan就上亦然篇Spring事务管理入门与进阶做片填补,如果对Spring事务管理还免了解之可以望上同样首文章。

 

实例

以我们初步之前,至少有零星只数据库表是重中之重的,在业务之帮扶下,我们得以兑现各种
CRUD 操作。以 Student 表为条例,该表是应用下述 DDL 在 MySQL TEST
数据库中创造的。

1 CREATE TABLE Student(
2    ID   INT NOT NULL AUTO_INCREMENT,
3    NAME VARCHAR(20) NOT NULL,
4    AGE  INT NOT NULL,
5    PRIMARY KEY (ID)
6 );

亚个说明是 Marks,我们为此来储存基于年份的学员标记。在此,SID 是 Student
表的外键。

1 CREATE TABLE Marks(
2    SID INT NOT NULL,
3    MARKS  INT NOT NULL,
4    YEAR   INT NOT NULL
5 );

现深受咱们编辑 Spring JDBC 应用程序来以 Student 和 Marks
表中实现简单的操作。让咱正好的施用 Eclipse
IDE,并随如下所出示之手续来创造一个 Spring 应用程序:

手续一样:创建一个叫做也 SpringExample 的种,并以创建的种面临的 src 文件夹下创办包 com.tutorialspoint

步骤二:使用 Add JARs 选项添加必需的 Spring 库。

手续三:在品种中补充加其它必需的库 mysql-connector-java.jar,org.springframework.jdbc.jar 和 org.springframework.transaction.jar。如果您还不曾这些库,你得下载它们。

步骤四:创建 DAO
接口 StudentDAO 并列出所有需要之方。尽管她不是少不了的以你可直接编写 StudentJDBCTemplate 类,但是作为一个吓的实行,我们要做吧。

步骤五:在 com.tutorialspoint 包下开创其他必要的 Java
类 StudentMarksStudentMarksMapperStudentJDBCTemplate 和 MainApp。如果需要的话,你得创建其他的
POJO 类。

步骤六:确保您都以 TEST
数据库被开创了 Student 和 Marks 表。还要确保您的 MySQL
服务器运行正常化并且你用被闹的用户称以及密码可读/写访问数据库。

手续七:在 src 文件夹下开创 Beans 配置文件 Beans.xml 。

最终一步:最后一步是创办有 Java 文件及 Bean
配置文件之始末并随如下所显示之方法运行应用程序。

下面是数看对象接口文件 StudentDAO.java 的情:

 1 package com.tutorialspoint;
 2 import java.util.List;
 3 import javax.sql.DataSource;
 4 public interface StudentDAO {
 5    /** 
 6     * This is the method to be used to initialize
 7     * database resources ie. connection.
 8     */
 9    public void setDataSource(DataSource ds);
10    /** 
11     * This is the method to be used to create
12     * a record in the Student and Marks tables.
13     */
14    public void create(String name, Integer age, Integer marks, Integer year);
15    /** 
16     * This is the method to be used to list down
17     * all the records from the Student and Marks tables.
18     */
19    public List<StudentMarks> listStudents();
20 }

以下是 StudentMarks.java 文件的内容:

 1 package com.tutorialspoint;
 2 public class StudentMarks {
 3    private Integer age;
 4    private String name;
 5    private Integer id;
 6    private Integer marks;
 7    private Integer year;
 8    private Integer sid;
 9    public void setAge(Integer age) {
10       this.age = age;
11    }
12    public Integer getAge() {
13       return age;
14    }
15    public void setName(String name) {
16       this.name = name;
17    }
18    public String getName() {
19       return name;
20    }
21    public void setId(Integer id) {
22       this.id = id;
23    }
24    public Integer getId() {
25       return id;
26    }
27    public void setMarks(Integer marks) {
28       this.marks = marks;
29    }
30    public Integer getMarks() {
31       return marks;
32    }
33    public void setYear(Integer year) {
34       this.year = year;
35    }
36    public Integer getYear() {
37       return year;
38    }
39    public void setSid(Integer sid) {
40       this.sid = sid;
41    }
42    public Integer getSid() {
43       return sid;
44    }
45 }

脚是 StudentMarksMapper.java 文件之情节:

 1 package com.tutorialspoint;
 2 import java.sql.ResultSet;
 3 import java.sql.SQLException;
 4 import org.springframework.jdbc.core.RowMapper;
 5 public class StudentMarksMapper implements RowMapper<StudentMarks> {
 6    public StudentMarks mapRow(ResultSet rs, int rowNum) throws SQLException {
 7       StudentMarks studentMarks = new StudentMarks();
 8       studentMarks.setId(rs.getInt("id"));
 9       studentMarks.setName(rs.getString("name"));
10       studentMarks.setAge(rs.getInt("age"));
11       studentMarks.setSid(rs.getInt("sid"));
12       studentMarks.setMarks(rs.getInt("marks"));
13       studentMarks.setYear(rs.getInt("year"));
14       return studentMarks;
15    }
16 }

下是概念之 DAO 接口 StudentDAO 实现类似公事 StudentJDBCTemplate.java:

 1 package com.tutorialspoint;
 2 import java.util.List;
 3 import javax.sql.DataSource;
 4 import org.springframework.dao.DataAccessException;
 5 import org.springframework.jdbc.core.JdbcTemplate;
 6 public class StudentJDBCTemplate implements StudentDAO{
 7    private JdbcTemplate jdbcTemplateObject;
 8    public void setDataSource(DataSource dataSource) {
 9       this.jdbcTemplateObject = new JdbcTemplate(dataSource);
10    }
11    public void create(String name, Integer age, Integer marks, Integer year){
12       try {
13          String SQL1 = "insert into Student (name, age) values (?, ?)";
14          jdbcTemplateObject.update( SQL1, name, age);
15          // Get the latest student id to be used in Marks table
16          String SQL2 = "select max(id) from Student";
17          int sid = jdbcTemplateObject.queryForInt( SQL2 );
18          String SQL3 = "insert into Marks(sid, marks, year) " + 
19                        "values (?, ?, ?)";
20          jdbcTemplateObject.update( SQL3, sid, marks, year);
21          System.out.println("Created Name = " + name + ", Age = " + age);
22          // to simulate the exception.
23          throw new RuntimeException("simulate Error condition") ;
24       } catch (DataAccessException e) {
25          System.out.println("Error in creating record, rolling back");
26          throw e;
27       }
28    }
29    public List<StudentMarks> listStudents() {
30       String SQL = "select * from Student, Marks where Student.id=Marks.sid";
31       List <StudentMarks> studentMarks=jdbcTemplateObject.query(SQL, 
32       new StudentMarksMapper());
33       return studentMarks;
34    }
35 }

而今让我们改变主应用程序文件 MainApp.java,如下所示:

 1 package com.tutorialspoint;
 2 import java.util.List;
 3 import org.springframework.context.ApplicationContext;
 4 import org.springframework.context.support.ClassPathXmlApplicationContext;
 5 public class MainApp {
 6    public static void main(String[] args) {
 7       ApplicationContext context = 
 8              new ClassPathXmlApplicationContext("Beans.xml");
 9       StudentDAO studentJDBCTemplate = 
10       (StudentDAO)context.getBean("studentJDBCTemplate");     
11       System.out.println("------Records creation--------" );
12       studentJDBCTemplate.create("Zara", 11, 99, 2010);
13       studentJDBCTemplate.create("Nuha", 20, 97, 2010);
14       studentJDBCTemplate.create("Ayan", 25, 100, 2011);
15       System.out.println("------Listing all the records--------" );
16       List<StudentMarks> studentMarks = studentJDBCTemplate.listStudents();
17       for (StudentMarks record : studentMarks) {
18          System.out.print("ID : " + record.getId() );
19          System.out.print(", Name : " + record.getName() );
20          System.out.print(", Marks : " + record.getMarks());
21          System.out.print(", Year : " + record.getYear());
22          System.out.println(", Age : " + record.getAge());
23       }
24    }
25 }

以下是部署文件 Beans.xml 的始末:

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <beans xmlns="http://www.springframework.org/schema/beans"
 3     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
 4     xmlns:context="http://www.springframework.org/schema/context"
 5     xmlns:tx="http://www.springframework.org/schema/tx"
 6     xmlns:aop="http://www.springframework.org/schema/aop"
 7     xsi:schemaLocation="http://www.springframework.org/schema/beans
 8    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 
 9    http://www.springframework.org/schema/context
10    http://www.springframework.org/schema/context/spring-context-3.0.xsd
11    http://www.springframework.org/schema/tx
12    http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
13    http://www.springframework.org/schema/aop
14    http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
15 
16     <!-- 开启注解 -->
17     <context:annotation-config />
18 
19     <!-- 注解扫描包路径 -->
20     <context:component-scan base-package="com.tutorialspoint.*" />
21 
22     <!-- 通过spring读取配置文件 -->
23     <bean
24         class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
25         <property name="fileEncoding" value="UTF-8"></property>
26         <property name="locations">
27             <list>
28                 <value>classpath:conf_db.properties</value>
29             </list>
30         </property>
31     </bean>
32 
33     <!-- Initialization for data source -->
34     <bean id="dataSource"
35         class="org.springframework.jdbc.datasource.DriverManagerDataSource">
36         <property name="driverClassName" value="${jdbc.url.driver}" />
37         <property name="url" value="${jdbc.url.master}" />
38         <property name="username" value="${jdbc.username.master}" />
39         <property name="password" value="${jdbc.password.master}" />
40     </bean>
41 
42     <!-- Initialization for TransactionManager -->
43     <bean id="transactionManager"
44         class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
45         <property name="dataSource" ref="dataSource" />
46     </bean>
47     
48     <!-- 支持事务注解 -->
49     <tx:annotation-driven transaction-manager="transactionManager"/>
50 
51     <!-- Definition for studentJDBCTemplate bean -->
52     <bean id="studentJDBCTemplate" class="com.tutorialspoint.StudentJDBCTemplate">
53         <property name="dataSource" ref="dataSource" />
54     </bean>
55 
56 </beans>

以下是数据库配置文件conf_db.properties的内容:

jdbc.url.driver=com.mysql.jdbc.Driver
jdbc.url.master=jdbc:mysql://localhost:3306/TEST
jdbc.username.master=root
jdbc.password.master=123456

说到底给咱们以StudentJDBCTemplate类上面长工作注解,此处不建议于Dao层使用工作注解,在平常干活屡遭一般会下在Service层,小Alan为演示效果节约时间尚无敲Service层代码,请留心,如图:

图片 1

当您做到了创建源和 bean
配置文件后,让我们运行应用程序。如果您的应用程序运行顺畅的言辞,那么会输出如下所出示之可怜。在这种状态下,事务会回滚并且于数据库表中无会见创任何记录。

------Records creation--------
Created Name = Zara, Age = 11
Exception in thread "main" java.lang.RuntimeException: simulate Error condition

当剔除StudentJDBCTemplate类中create方法抛来十分的代码后,你可以尝试上述示范,在这种状况下,会交业务并且你可在数据库被看见记录。

 

专注:项目jar包如图所示,其中为富含了Spring其它地方的一部分jar包,小Alan偷一下疲劳就无失去去了,这同样块大家好品尝只留必要的jar包,以便熟悉Spring所蕴藏的每个jar包在路面临所能够打及之用意,记得将jar包引入项目受到才能够运转上述的以身作则。

图片 2

 

@Transactional注解

@Transactional
可以作用为接口、接口方法、类和近似方式及。当作用为类及时,该类的装有
public
方法将都有所该品种的工作属性,同时,我们啊得于措施级别下该标注来覆盖类级别的定义。

虽 @Transactional 注解可以作用为接口、接口方法、类和近似措施齐,但是
Spring
建议不要以接口或者接口方法上运该注解,因为当时只有当动基于接口的代办时它才会生效。另外,
@Transactional 注解应该单纯给使用至 public 方法及,这是出于 Spring AOP
的本质决定的。如果你于 protected、private 或者默认可见性的不二法门及利用
@Transactional 注解,这将给忽略,也未会见弃来另异常。

默认情况下,只有来自外部的主意调用才见面被AOP代理捕获,也即是,类中方法调用本类内部的其余艺术并无会见滋生事务行为,即使给调用方法应用@Transactional注解进行修饰。

@Transactional参数

参数名称

功能描述

readOnly

该属性用于设置当前事务是否为只读事务,设置为true表示只读,false则表示可读写,默认值为false。例如:@Transactional(readOnly=true)

rollbackFor

该属性用于设置需要进行回滚的异常类数组,当方法中抛出指定异常数组中的异常时,则进行事务回滚。例如:

指定单一异常类:@Transactional(rollbackFor=RuntimeException.class)

指定多个异常类:@Transactional(rollbackFor={RuntimeException.class, Exception.class})

rollbackForClassName

该属性用于设置需要进行回滚的异常类名称数组,当方法中抛出指定异常名称数组中的异常时,则进行事务回滚。例如:

指定单一异常类名称:@Transactional(rollbackForClassName="RuntimeException")

指定多个异常类名称:@Transactional(rollbackForClassName={"RuntimeException","Exception"})

noRollbackFor

该属性用于设置不需要进行回滚的异常类数组,当方法中抛出指定异常数组中的异常时,不进行事务回滚。例如:

指定单一异常类:@Transactional(noRollbackFor=RuntimeException.class)

指定多个异常类:@Transactional(noRollbackFor={RuntimeException.class, Exception.class})

noRollbackForClassName

该属性用于设置不需要进行回滚的异常类名称数组,当方法中抛出指定异常名称数组中的异常时,不进行事务回滚。例如:

指定单一异常类名称:@Transactional(noRollbackForClassName="RuntimeException")

指定多个异常类名称:

@Transactional(noRollbackForClassName={"RuntimeException","Exception"})

propagation

该属性用于设置事务的传播行为。

例如:@Transactional(propagation=Propagation.NOT_SUPPORTED,readOnly=true)

isolation

该属性用于设置底层数据库的事务隔离级别,事务隔离级别用于处理多事务并发的情况,通常使用数据库的默认隔离级别即可,基本不需要进行设置

timeout

该属性用于设置事务的超时秒数,默认值为-1表示永不超时

结束语:无论在经历什么,都要不要轻言放弃,因为从不曾一样栽坚持会让辜负。谁的人生不是荆棘前行,生活无会迎刃而解,也不见面永远安稳,只要努力,就能召开独一无二平凡可贵的温馨。

 

然爱博主:AlanLee

博客地址:http://www.cnblogs.com/AlanLee

本文来源博客园,欢迎大家加入博客园。

 

网站地图xml地图