事務:是一組原子操作的工作單元,要麼全部成功,要麼全部失敗
Spring管理事務方式:
可以清楚的控制事務的邊界,事務控制粒度化細(編程的方式)
事務相關API不用介入程序之中,將事務管理與實際業務代碼解耦合(配置XML的方式)
Spring提供兩種方式實現編程式的事務管理:

大致步驟:
package com.pb.transaction.demo;
import javax.sql.DataSource;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;
/**
* 使用TransactionManager事務管理
* 缺點:侵入代碼
* 優點:控制度細粒度
*/
public class TransactionManagerDemo {
public static void main(String[] args) {
ClassPathXmlApplicationContext cpx=new ClassPathXmlApplicationContext("applicationContext.xml");
//獲取platform對象
PlatformTransactionManager ptm=(PlatformTransactionManager) cpx.getBean("transactionManager");
//事務定義器
DefaultTransactionDefinition dtd=new DefaultTransactionDefinition();
//設置事務定義器的行為
dtd.setPropagationBehavior(DefaultTransactionDefinition.PROPAGATION_REQUIRED);
//事務狀態通過事務管理器創建
TransactionStatus ts=ptm.getTransaction(dtd);
//進行事務
try {
//獲取數據源
DataSource ds=(DataSource) cpx.getBean("dataSource");
//創建JDBCTemplacte
JdbcTemplate jt=new JdbcTemplate(ds);
//執行更新或者插入等操作
jt.update("insert into person values(11,'TTM',23)");
jt.update("update person set name='張王八' where id=7");
ptm.commit(ts);
System.out.println("===========");
} catch (Exception e) {
ptm.rollback(ts);
System.out.println("撤消=======");
e.printStackTrace();
}
}
}

大致步驟:
package com.pb.transaction.demo;
import javax.sql.DataSource;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import org.springframework.transaction.support.TransactionCallback;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;
/**
* 使用TransactionTemplate事務管理 缺點:侵入代碼 優點:控制度細粒度
*/
public class TransactionTeplateDemo {
public static void main(String[] args) {
ClassPathXmlApplicationContext cpx = new ClassPathXmlApplicationContext(
"applicationContext.xml");
// 獲取platform對象
PlatformTransactionManager ptm = (PlatformTransactionManager) cpx
.getBean("transactionManager");
// 事務模版
TransactionTemplate tt = new TransactionTemplate(ptm);
// 獲取數據源
DataSource ds = (DataSource) cpx.getBean("dataSource");
// 創建JDBCTemplacte
final JdbcTemplate jt = new JdbcTemplate(ds);
// 進行事務回調函數
tt.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus arg0) {
// 執行更新或者插入等操作
jt.update("insert into person values(17,'TOM',23)");
jt.update("update person set name='李四3' where id=4");
}
});
}
}
<?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.1.xsd">
<!-- 聲明數據源 org.springframework.jdbc.datasource.DriverManagerDataSource/com.mchange.v2.c3p0.ComboPooledDataSource-->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<!--驅動 -->
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/>
<!--url -->
<property name="url" value="jdbc:oracle:thin:@localhost:1521:orcl"/>
<!--用戶名 -->
<property name="username" value="accp"/>
<!--密碼 -->
<property name="password" value="accp"/>
</bean>
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
</beans>
主要通過AOP功能實現
不需要修改原有的類
使用TransationProxyFactoryBean指定要介入的事務以及方法
實體類:數據庫中有與之相對應的表
package com.pb.entity;
public class Person {
private Long id;
private String name;
private Integer age;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
dao和實現類
package com.pb.dao;
import java.util.List;
import com.pb.entity.Person;
public interface PersonDao {
public int insert(Person p);
public int batchInsert(List<Person> persons);
}
//實現類
package com.pb.dao.impl;
import java.util.List;
import javax.sql.DataSource;
import org.springframework.jdbc.core.JdbcTemplate;
import com.pb.dao.PersonDao;
import com.pb.entity.Person;
public class PersonDaoImpl implements PersonDao {
private JdbcTemplate jdbcTemplate;
public void setDataSource(DataSource ds){
jdbcTemplate=new JdbcTemplate(ds);
}
@Override
public int insert(Person p) {
String sql="insert into person values(?,?,?)";
Object [] params={p.getId(),p.getName(),p.getAge()};
return jdbcTemplate.update(sql,params);
}
@Override
public int batchInsert(List<Person> persons) {
int count=0;
for (Person person : persons) {
insert(person);
count++;
}
return count;
}
}
測試類
package com.pb.transation.aop.demo;
import java.util.ArrayList;
import java.util.List;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.pb.dao.PersonDao;
import com.pb.entity.Person;
public class FirstAOPTransationDemo {
public static void main(String[] args) {
ClassPathXmlApplicationContext cpx=new ClassPathXmlApplicationContext("applicationContext.xml");
//這裡調用代理的類
PersonDao personDao=(PersonDao) cpx.getBean("personDaoProxy");
Person p1=new Person();
p1.setId(new Long(28));
p1.setName("朱雀");
p1.setAge(199);
Person p2=new Person();
p2.setId(new Long(29));
p2.setName("玄武");
p2.setAge(150);
List<Person> persons=new ArrayList<Person>();
persons.add(p1);
persons.add(p2);
int count=personDao.batchInsert(persons);
System.out.println("更新了,"+count+"條記錄");
}
}
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.1.xsd">
<!-- 聲明數據源 org.springframework.jdbc.datasource.DriverManagerDataSource/com.mchange.v2.c3p0.ComboPooledDataSource-->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<!--驅動 -->
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/>
<!--url -->
<property name="url" value="jdbc:oracle:thin:@localhost:1521:orcl"/>
<!--用戶名 -->
<property name="username" value="accp"/>
<!--密碼 -->
<property name="password" value="accp"/>
</bean>
<!--接口實現類 -->
<bean id="personDao" class="com.pb.dao.impl.PersonDaoImpl">
<property name="dataSource" ref="dataSource"></property>
</bean>
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<bean id="personDaoProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<!--指定接口 -->
<property name="proxyInterfaces" >
<list>
<value>com.pb.dao.PersonDao</value>
</list>
</property>
<!-- 管理的目標 -->
<property name="target" ref="personDao"/>
<!--注入事務管理 -->
<property name="transactionManager" ref="transactionManager"></property>
<!--事務管理的方法 和方式 -->
<property name="transactionAttributes">
<props>
<prop key="batch*">PROPAGATION_REQUIRED</prop>
</props>
</property>
</bean>
</beans>
聲明式事務以方法為邊界,簡單的講,一個方法被看成一個事務
Spring中事務的屬性:



步驟:
<?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:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.1.xsd">
<!-- 聲明數據源 org.springframework.jdbc.datasource.DriverManagerDataSource/com.mchange.v2.c3p0.ComboPooledDataSource-->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<!--驅動 -->
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/>
<!--url -->
<property name="url" value="jdbc:oracle:thin:@localhost:1521:orcl"/>
<!--用戶名 -->
<property name="username" value="accp"/>
<!--密碼 -->
<property name="password" value="accp"/>
</bean>
<!--接口實現類 -->
<bean id="personDao" class="com.pb.dao.impl.PersonDaoImpl">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!--事務管理的類 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!--指明事務管理 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<!--指定方法和方式 -->
<tx:attributes>
<tx:method name="batch*" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
<aop:config>
<!--切入點 -->
<aop:pointcut expression="execution(* com.pb.dao.PersonDao.*(..) )" id="mypoint"/>
<!--關切入點和切入對象事務 -->
<aop:advisor advice-ref="txAdvice" pointcut-ref="mypoint"/>
</aop:config>
</beans>

package com.pb.dao.impl;
import java.util.List;
import javax.sql.DataSource;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import com.pb.dao.PersonDao;
import com.pb.entity.Person;
//在要管理的類下加上@transactional
@Transactional
public class PersonDaoImpl implements PersonDao {
private JdbcTemplate jdbcTemplate;
public void setDataSource(DataSource ds){
jdbcTemplate=new JdbcTemplate(ds);
}
@Override
public int insert(Person p) {
String sql="insert into person values(?,?,?)";
Object [] params={p.getId(),p.getName(),p.getAge()};
return jdbcTemplate.update(sql,params);
}
//在要管理的方法下加上屬性propagation=Propagation.REQUIRED
@Transactional(propagation=Propagation.REQUIRED)
public int batchInsert(List<Person> persons) {
int count=0;
for (Person person : persons) {
insert(person);
count++;
}
return count;
}
}
配置文件中加入一條
<?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:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.1.xsd">
<!-- 聲明數據源 org.springframework.jdbc.datasource.DriverManagerDataSource/com.mchange.v2.c3p0.ComboPooledDataSource-->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<!--驅動 -->
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/>
<!--url -->
<property name="url" value="jdbc:oracle:thin:@localhost:1521:orcl"/>
<!--用戶名 -->
<property name="username" value="accp"/>
<!--密碼 -->
<property name="password" value="accp"/>
</bean>
<!--接口實現類 -->
<bean id="personDao" class="com.pb.dao.impl.PersonDaoImpl">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!--事務管理的類 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!--指明注解方式的事務管理器 -->
<tx:annotation-driven transaction-manager="transactionManager"/>
</beans>