Spring 事务管理
事务管理
一个数据库事务是一个被视为单一的工作单元的操作序列。这些操作应该要么完整地执行,要么完全不执行。事务管理是一个重要组成部分,RDBMS 面向企业应用程序,以确保数据完整性和一致性。事务的概念可以描述为具有以下四个关键属性说成是 ACID:
属性 | 描述 |
---|---|
原子性 | 事务应该当作一个单独单元的操作,这意味着整个序列操作要么是成功,要么是失败的。 |
一致性 | 这表示数据库的引用完整性的一致性,表中唯一的主键等。 |
隔离性 | 可能同时处理很多有相同的数据集的事务,每个事务应该与其他事务隔离,以防止数据损坏。 |
持久性 | 一个事务一旦完成全部操作后,这个事务的结果必须是永久性的,不能因系统故障而从数据库中删除。 |
使用 begin transaction 命令开始事务。使用 SQL 查询语句执行各种删除、更新或插入操作。如果所有的操作都成功,则执行提交操作,否则回滚所有操作。
Spring 编程式事务管理
创建student表
CREATE TABLE Student(
ID INT NOT NULL AUTO_INCREMENT,
NAME VARCHAR(20) NOT NULL,
AGE INT NOT NULL,
PRIMARY KEY (ID)
);
创建marks表
CREATE TABLE Marks(
SID INT NOT NULL,
MARKS INT NOT NULL,
YEAR INT NOT NULL
);
studengDao.java
package ds;
import org.springframework.transaction.PlatformTransactionManager;
import javax.sql.DataSource;
import java.util.List;
public interface studentDao {
public void setDataSource(DataSource dataSource);
public void setTransactionManager(PlatformTransactionManager transactionManager);
public void create(String name, Integer age, Integer marks, Integer year);
public List<student> students();
}
student.java
package ds;
public class student {
private Integer age;
private String name;
private Integer id;
private Integer marks;
private Integer year;
private Integer sid;
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public Integer getMarks() {
return marks;
}
public void setMarks(Integer marks) {
this.marks = marks;
}
public Integer getYear() {
return year;
}
public void setYear(Integer year) {
this.year = year;
}
public Integer getSid() {
return sid;
}
public void setSid(Integer sid) {
this.sid = sid;
}
}
studentjdbcTemplate.java
package ds;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
import org.springframework.jdbc.core.namedparam.SqlParameterSource;
import org.springframework.jdbc.core.simple.SimpleJdbcCall;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import javax.sql.DataSource;
import java.util.List;
import java.util.Map;
public class studentJdbcTemplate implements studentDao {
private JdbcTemplate jdbcTemplate;
private PlatformTransactionManager transactionManager;
@Override
public void setDataSource(DataSource dataSource) {
this.jdbcTemplate = new JdbcTemplate(dataSource);
}
@Override
public void setTransactionManager(PlatformTransactionManager transactionManager) {
this.transactionManager = transactionManager;
}
@Override
public void create(String name, Integer age, Integer marks, Integer year) {
TransactionDefinition def = new DefaultTransactionDefinition();
TransactionStatus status = this.transactionManager.getTransaction(def);
try {
String SQL1 = "insert into Student (name, age) values (?, ?)";
jdbcTemplate.update( SQL1, name, age);
// Get the latest student id to be used in Marks table
String SQL2 = "select max(id) from Student";
int sid = jdbcTemplate.queryForObject(SQL2,new Object[]{},Integer.class);
String SQL3 = "insert into Marks(sid, marks, year) " + "values (?, ?, ?)";
jdbcTemplate.update( SQL3, sid, marks, year);
System.out.println("Created Name = " + name + ", Age = " + age);
transactionManager.commit(status);
} catch (DataAccessException e) {
System.out.println("Error in creating record, rolling back");
transactionManager.rollback(status);
throw e;
}
return;
}
@Override
public List<student> students() {
String SQL = "select * from Student, Marks where Student.id=Marks.sid";
List <student> studentMarks = jdbcTemplate.query(SQL,new studentMapper());
return studentMarks;
}
}
studentmapper.java
package ds;
import org.springframework.jdbc.core.RowMapper;
import java.sql.ResultSet;
import java.sql.SQLException;
public class studentMapper implements RowMapper<student> {
@Override
public student mapRow(ResultSet rs, int rowNum) throws SQLException {
student studentMarks = new student();
studentMarks.setId(rs.getInt("id"));
studentMarks.setName(rs.getString("name"));
studentMarks.setAge(rs.getInt("age"));
studentMarks.setSid(rs.getInt("sid"));
studentMarks.setMarks(rs.getInt("marks"));
studentMarks.setYear(rs.getInt("year"));
return studentMarks;
}
}
springconfig.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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd ">
<bean id="studentJdbcTemplate" class="ds.studentJdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
<property name="transactionManager" ref="transactionManager"></property>
</bean>
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/TEST?useSSL=false"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</bean>
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
</beans>
main.java
import ds.student;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import ds.*;
import java.util.List;
public class Main {
public static void main(String[] args) {
ApplicationContext context =
new ClassPathXmlApplicationContext("spring-config.xml");
studentJdbcTemplate studentJDBCTemplate =
(studentJdbcTemplate)context.getBean("studentJdbcTemplate");
System.out.println("------Records creation--------" );
studentJDBCTemplate.create("Zara", 11, 99, 2010);
studentJDBCTemplate.create("Nuha", 20, 97, 2010);
studentJDBCTemplate.create("Ayan", 25, 100, 2011);
System.out.println("------Listing all the records--------" );
List<student> studentMarks = studentJDBCTemplate.students();
for (student record : studentMarks) {
System.out.print("ID : " + record.getId() );
System.out.print(", Name : " + record.getName() );
System.out.print(", Marks : " + record.getMarks());
System.out.print(", Year : " + record.getYear());
System.out.println(", Age : " + record.getAge());
}
}
}
测试
Spring 声明式事务管理
工程目录结构
studentJdbcTemplate.java
package ds;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
import org.springframework.jdbc.core.namedparam.SqlParameterSource;
import org.springframework.jdbc.core.simple.SimpleJdbcCall;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import javax.sql.DataSource;
import java.util.List;
import java.util.Map;
public class studentJdbcTemplate implements studentDao {
private JdbcTemplate jdbcTemplate;
@Override
public void setDataSource(DataSource dataSource) {
System.out.println("setDataSource");
this.jdbcTemplate = new JdbcTemplate(dataSource);
}
@Override
public void create(String name, Integer age, Integer marks, Integer year) {
try {
String SQL1 = "insert into Student (name, age) values (?, ?)";
jdbcTemplate.update( SQL1, name, age);
// Get the latest student id to be used in Marks table
String SQL2 = "select max(id) from Student";
int sid = jdbcTemplate.queryForObject(SQL2,new Object[]{},Integer.class);
String SQL3 = "insert into Marks(sid, marks, year) " + "values (?, ?, ?)";
jdbcTemplate.update( SQL3, sid, marks, year);
System.out.println("Created Name = " + name + ", Age = " + age);
throw new RuntimeException("simulate Error condition");
} catch (DataAccessException e) {
System.out.println("Error in creating record, rolling back");
throw e;
}
}
@Override
public List<student> students() {
String SQL = "select * from Student, Marks where Student.id=Marks.sid";
List <student> studentMarks = jdbcTemplate.query(SQL,new studentMapper());
return studentMarks;
}
}
springconfig.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:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
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">
<!-- Initialization for data source -->
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/TEST?useSSL=false"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</bean>
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="*"/>
</tx:attributes>
</tx:advice>
<aop:config proxy-target-class="true">
<aop:pointcut id="createOperation" expression="execution(* ds.studentJdbcTemplate.create(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="createOperation"/>
</aop:config>
<bean id="studentJDBCTemplate" class="ds.studentJdbcTemplate">
<property name="dataSource" ref="dataSource" />
</bean>
</beans>
main.java
import ds.student;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import ds.*;
import java.util.List;
public class Main {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
studentJdbcTemplate stuJdbcTemplate = (studentJdbcTemplate)context.getBean("studentJDBCTemplate");
System.out.println("------Records creation--------" );
stuJdbcTemplate.create("Zara", 11, 99, 2010);
stuJdbcTemplate.create("Nuha", 20, 97, 2010);
stuJdbcTemplate.create("Ayan", 25, 100, 2011);
System.out.println("------Listing all the records--------" );
List<student> studentMarks = stuJdbcTemplate.students();
for (student record : studentMarks) {
System.out.print("ID : " + record.getId() );
System.out.print(", Name : " + record.getName() );
System.out.print(", Marks : " + record.getMarks());
System.out.print(", Year : " + record.getYear());
System.out.println(", Age : " + record.getAge());
}
}
}
测试结果