Spring_第六章【Spring的事務程式碼實現】
1:spring的7中事務傳播行為
傳播行為 |
含義 |
propagation_required(xml檔案中為required) |
表示當前方法必須在一個具有事務的上下文中執行,如有客戶端有事務在進行,那麼被呼叫端將在該事務中執行,否則的話重新開啟一個事務。(如果被呼叫端發生異常,那麼呼叫端和被呼叫端事務都將回滾) |
propagation_supports(xml檔案中為supports) |
表示當前方法不必需要具有一個事務上下文,但是如果有一個事務的話,它也可以在這個事務中執行 |
propagation_mandatory(xml檔案中為mandatory) |
表示當前方法必須在一個事務中執行,如果沒有事務,將丟擲異常 |
propagation_nested(xml檔案中為nested) |
表示如果當前方法正有一個事務在執行中,則該方法應該執行在一個巢狀事務中,被巢狀的事務可以獨立於被封裝的事務中進行提交或者回滾。如果封裝事務存在,並且外層事務丟擲異常回滾,那麼內層事務必須回滾,反之,內層事務並不影響外層事務。如果封裝事務不存在,則同propagation_required的一樣 |
propagation_never(xml檔案中為never) |
表示當方法務不應該在一個事務中執行,如果存在一個事務,則丟擲異常 |
propagation_requires_new(xml檔案中為requires_new) |
表示當前方法必須執行在它自己的事務中。一個新的事務將啟動,而且如果有一個現有的事務在執行的話,則這個方法將在執行期被掛起,直到新的事務提交或者回滾才恢復執行。 |
propagation_not_supported(xml檔案中為not_supported) |
表示該方法不應該在一個事務中執行。如果有一個事務正在執行,他將在執行期被掛起,直到這個事務提交或者回滾才恢復執行 |
2:Spring對應資料庫中的事務隔離級別
隔離級別 |
含義 |
isolation_default |
使用資料庫預設的事務隔離級別 |
isolation_read_uncommitted |
允許讀取尚未提交的修改,可能導致髒讀、幻讀和不可重複讀 |
isolation_read_committed |
允許從已經提交的事務讀取,可防止髒讀、但幻讀,不可重複讀仍然有可能發生 |
isolation_repeatable_read |
對相同欄位的多次讀取的結果是一致的,除非資料被當前事務自生修改。可防止髒讀和不可重複讀,但幻讀仍有可能發生 |
isolation_serializable |
完全服從acid隔離原則,確保不發生髒讀、不可重複讀、和幻讀,但執行效率最低。 |
3:Spring事務介面簡介
3.1PlatformTransactionManager (平臺事務管理器)
Spring事務管理器的介面是org.springframework.transaction.PlatfromTransactionManager,如上圖所示,Spring並不直接管理事務,
通過這個介面,Spring為各個平臺如JDBC、Hibernate等都提供了對應的事務管理器,也就是將事務管理的職責委託給Hibernate或者JTA等持久化機制所提供的相關平臺框架的事務來實現。
我們進入到 PlatformTransactionManager 介面,檢視原始碼:
①、TransactionStatus getTransaction(TransactionDefinition definition) ,事務管理器 通過TransactionDefinition,獲得“事務狀態”,從而管理事務。
②、void commit(TransactionStatus status) 根據狀態提交
③、void rollback(TransactionStatus status) 根據狀態回滾
也就是說Spring事務管理的為不同的事務API提供一致的程式設計模型,具體的事務管理機制由對應各個平臺去實現。
比如下面我們匯入實現事務管理的兩種平臺:JDBC和Hibernate
然後我們再次檢視PlatformTransactionManager介面,會發現它多了幾個實現類,如下:
3.2TransactionStatus 事務狀態
在上面 PlatformTransactionManager 介面中,有如下方法:
這個方法返回的是 TransactionStatus物件,然後程式根據返回的物件來獲取事務狀態,然後進行相應的操作。
而 TransactionStatus 這個介面的內容如下:
這個介面描述的是一些處理事務提供簡單的控制事務執行和查詢事務狀態的方法,在回滾或提交的時候需要應用對應的事務狀態
3.3TransactionDefinition 事務定義
上面講到的事務管理器介面PlatformTransactionManager通過getTransaction(TransactionDefinition definition)方法來得到事務,這個方法裡面的引數是TransactionDefinition類,這個類就定義了一些基本的事務屬性。
那麼什麼是事務屬性呢?事務屬性可以理解成事務的一些基本配置,描述了事務策略如何應用到方法上。事務屬性包含了5個方面,如圖所示:
TransactionDefinition 介面方法如下:
4:Spring實現事務主要有兩種方式
程式設計式事務處理:所謂程式設計式事務指的是通過編碼方式實現事務,允許使用者在程式碼中精確定義事務的邊界。即類似於JDBC程式設計實現事務管理。管理使用TransactionTemplate或者直接使用底層的PlatformTransactionManager。對於程式設計式事務管理,spring推薦使用TransactionTemplate。
宣告式事務處理:管理建立在AOP之上的。其本質是對方法前後進行攔截,然後在目標方法開始之前建立或者加入一個事務,在執行完目標方法之後根據執行情況提交或者回滾事務。宣告式事務最大的優點就是不需要通過程式設計的方式管理事務,這樣就不需要在業務邏輯程式碼中摻雜事務管理的程式碼,只需在配置檔案中做相關的事務規則宣告(或通過基於@Transactional註解的方式),便可以將事務規則應用到業務邏輯中。
簡單地說,程式設計式事務侵入到了業務程式碼裡面,但是提供了更加詳細的事務管理;而宣告式事務由於基於AOP,所以既能起到事務管理的作用,又可以不影響業務程式碼的具體實現。
5:公共程式碼
實體兩個:分別是訂單和商品
package com.thit.entity;
import java.util.Date;
//訂單表
public class Order {
private String id;//訂單id
private String productsId;//商品id
private int number;//購買數量
private double price;//價格
private Date createTime;//下單時間
private Date sendTime;//發單時間
private Date confirmTime;//確認收貨時間
private String consignee;//收貨人
private String consigneePhone;//收貨人電話
private String consigneeAddress;//收貨人地址
private String status;//狀態
public Order() {
}
public Order(String id, String productsId, int number, double price, String consignee, String consigneePhone, String consigneeAddress) {
this.id = id;
this.productsId = productsId;
this.number = number;
this.price = price;
this.consignee = consignee;
this.consigneePhone = consigneePhone;
this.consigneeAddress = consigneeAddress;
}
public String getProductsId() {
return productsId;
}
public void setProductsId(String productsId) {
this.productsId = productsId;
}
public int getNumber() {
return number;
}
public void setNumber(int number) {
this.number = number;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public Date getCreateTime() {
return createTime;
}
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
public Date getSendTime() {
return sendTime;
}
public void setSendTime(Date sendTime) {
this.sendTime = sendTime;
}
public Date getConfirmTime() {
return confirmTime;
}
public void setConfirmTime(Date confirmTime) {
this.confirmTime = confirmTime;
}
public String getConsignee() {
return consignee;
}
public void setConsignee(String consignee) {
this.consignee = consignee;
}
public String getConsigneePhone() {
return consigneePhone;
}
public void setConsigneePhone(String consigneePhone) {
this.consigneePhone = consigneePhone;
}
public String getConsigneeAddress() {
return consigneeAddress;
}
public void setConsigneeAddress(String consigneeAddress) {
this.consigneeAddress = consigneeAddress;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
}
dao和實現類兩個
package com.thit.dao;
import java.util.List;
import com.thit.entity.Order;
public interface OrderDao {
void insert(Order order);
void update(Order order);
void delete(String id);
Order select(String id);
List<Order> select();
}
----實現類----
package com.thit.daoimpl;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Repository;
import com.thit.dao.OrderDao;
import com.thit.entity.Order;
@Repository
public class OrderDaoImpl implements OrderDao {
@Autowired
private JdbcTemplate jdbcTemplate;
public void insert(Order order) {
// TODO Auto-generated method stub
String sql = "insert into orders values(?,?,?,?,?,?,?,?,?,?,?)";
jdbcTemplate.update(sql, order.getId(), order.getProductsId(), order.getNumber(), order.getPrice(),
order.getCreateTime(), order.getSendTime(), order.getConfirmTime(), order.getConsignee(),
order.getConsigneePhone(), order.getConsigneeAddress(), order.getStatus());
}
public void update(Order order) {
// TODO Auto-generated method stub
String sql = "update orders set create_time=?,send_time=?,confirm_time=?,consignee=?,consignee_phone=?,consignee_address=?,status=? where id=?";
jdbcTemplate.update(sql, order.getProductsId(), order.getNumber(), order.getPrice(), order.getCreateTime(),
order.getSendTime(), order.getConfirmTime(), order.getConsignee(), order.getConsigneePhone(),
order.getConsigneeAddress(), order.getStatus(), order.getId());
}
public void delete(String id) {
// TODO Auto-generated method stub
String sql = "delete from orders where id=?";
jdbcTemplate.update(sql, id);
}
public Order select(String id) {
// TODO Auto-generated method stub
String sql = "select form orders where id=?";
return jdbcTemplate.queryForObject(sql, new OrderRowMapper(), id);
}
public List<Order> select() {
// TODO Auto-generated method stub
String sql = "select * from orders";
return jdbcTemplate.query(sql, new OrderRowMapper());
}
public JdbcTemplate getJdbcTemplate() {
return jdbcTemplate;
}
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
private class OrderRowMapper implements RowMapper<Order> {
public Order mapRow(ResultSet resultSet, int rowNum) throws SQLException {
// TODO Auto-generated method stub
Order order = new Order();
order.setId(resultSet.getString("id"));
order.setProductsId(resultSet.getString("products_id"));
order.setNumber(resultSet.getInt("number"));
order.setPrice(resultSet.getDouble("price"));
order.setCreateTime(resultSet.getTimestamp("create_time"));
order.setSendTime(resultSet.getTimestamp("send_time"));
order.setConfirmTime(resultSet.getTimestamp("confirm_time"));
order.setConsignee(resultSet.getString("consignee"));
order.setConsigneePhone(resultSet.getString("consignee_phone"));
order.setConsigneeAddress(resultSet.getString("consignee_address"));
order.setStatus(resultSet.getString("status"));
return order;
}
}
}
package com.thit.dao;
import java.util.List;
import com.thit.entity.Product;
public interface ProductDao {
void insert(Product product);
void update(Product product);
void delete(String id);
Product select(String id);
List<Product> select();
}
-----實現類----
package com.thit.daoimpl;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Repository;
import com.thit.dao.ProductDao;
import com.thit.entity.Product;
@Repository
public class ProductDaoImpl implements ProductDao {
//通過set方法自動注入
@Autowired
private JdbcTemplate jdbcTemplate;
public void insert(Product product) {
String sql = "insert into products values(?,?,?,?,?)";
jdbcTemplate.update(sql,product.getId(),product.getTitle(),product.getPrice(),product.getStock(),product.getStatus());
}
public void update(Product product) {
String sql = "update products set title=?,price=?,stock=?,status=? where id=?";
jdbcTemplate.update(sql,product.getTitle(),product.getPrice(),product.getStock(),product.getStatus(),product.getId());
}
public void delete(String id) {
// TODO Auto-generated method stub
String sql = "delete form products where id=?";
jdbcTemplate.update(sql);
}
public Product select(String id) {
String sql = "select * from products where id=?";
Product p=jdbcTemplate.queryForObject(sql, new RowMapper<Product>() {
public Product mapRow(ResultSet resultSet, int rowNum) throws SQLException {
// TODO Auto-generated method stub
Product product=new Product();
product.setId(resultSet.getString("id"));
product.setTitle(resultSet.getString("title"));
product.setPrice(resultSet.getDouble("price"));
product.setStock(resultSet.getInt("stock"));
product.setStatus(resultSet.getString("status"));
return product;
}
}, id);
return p;
}
public List<Product> select() {
// TODO Auto-generated method stub
String sql = "select * from products";
List<Product> list= jdbcTemplate.query(sql,new RowMapper<Product>() {
public Product mapRow(ResultSet resultSet, int rowNum) throws SQLException {
Product product=new Product();
product.setId(resultSet.getString("id"));
product.setTitle(resultSet.getString("title"));
product.setPrice(resultSet.getDouble("price"));
product.setStock(resultSet.getInt("stock"));
product.setStatus(resultSet.getString("status"));
return product;
}
});
return list;
}
public JdbcTemplate getJdbcTemplate() {
return jdbcTemplate;
}
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
}
service
package com.thit.service;
import com.thit.entity.Order;
public interface OrderService {
void addOrder(Order order);
}
公共配置檔案:spring_dao.xml
<context:component-scan base-package="com.thit.daoimpl"></context:component-scan>
<bean id="datasource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql://localhost:3306/xxx?serverTimezone=GMT&useUnicode=true&characterEncoding=UTF-8"></property>
<property name="username" value="root"></property>
<property name="password" value="123456"></property>
</bean>
<bean id="Template" class="org.springframework.jdbc.core.JdbcTemplate" >
<property name="dataSource" ref="datasource"></property>
</bean>
根據不同的serviceImp來方案驗證不同的結果
6:程式設計式事務實現
6.1PlatformTransactionManager實現
配置檔案
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
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.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<import resource="spring_dao.xml"/>
<!-- 基於底層API的spring事務管理
private PlatformTransactionManager transactionManager;
TransactionDefinition transactionDefinition;
TransactionStatus status;
-->
<context:component-scan base-package="com.thit"></context:component-scan>
<bean id="tsManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="datasource" />
</bean>
<bean id="tsDefinition" class="org.springframework.transaction.support.DefaultTransactionDefinition">
<property name="propagationBehaviorName" value="PROPAGATION_REQUIRED" />
</bean>
</beans>
程式碼實現類
package com.thit.serviceImpl;
import java.util.Date;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.orm.hibernate3.HibernateTransactionManager;
import org.springframework.stereotype.Service;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import com.thit.dao.OrderDao;
import com.thit.dao.ProductDao;
import com.thit.entity.Order;
import com.thit.entity.Product;
import com.thit.service.OrderService;
@Service(value="orderServiceimpl111")
public class OrderServiceImpl implements OrderService {
@Autowired
private OrderDao orderDao;
@Autowired
private ProductDao productDao;
@Autowired
private PlatformTransactionManager transactionManager;
@Autowired
private TransactionDefinition transactionDefinition;
//private HibernateTransactionManager hibernateTransactionManager;
public void addOrder(Order order) {
// TODO Auto-generated method stub
//訂單表
order.setCreateTime(new Date());
order.setStatus("待付款");
TransactionStatus status=null;
//開啟事務
try {
//插入一條訂單資料並且根據訂單資料的下單數在商品表庫存相對減少
orderDao.insert(order);
Product p=productDao.select(order.getProductsId());
p.setStock(p.getStock()-order.getNumber());
productDao.update(p);
//提交事務
transactionManager.commit(status);
} catch (Exception e) {
// TODO: handle exception
transactionManager.rollback(status);
e.printStackTrace();
}
}
}
6.2TransactionTemplate實現
配置檔案:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
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.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<import resource="spring_dao.xml"/>
<!-- spring 程式設計式事務基於transactionTemplate
-->
<context:component-scan base-package="com.thit"></context:component-scan>
<bean id="tsManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="datasource" />
</bean>
<bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">
<property name="transactionManager" ref="tsManager"/>
</bean>
</beans>
程式碼實現:
package com.thit.serviceImpl;
import java.util.Date;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallback;
import org.springframework.transaction.support.TransactionTemplate;
import com.thit.dao.OrderDao;
import com.thit.dao.ProductDao;
import com.thit.entity.Order;
import com.thit.entity.Product;
import com.thit.service.OrderService;
@Service(value="orderServiceimpl2")
public class OrderServiceImpl2 implements OrderService {
@Autowired
private OrderDao orderDao;
@Autowired
private ProductDao productDao;
@Autowired
private TransactionTemplate template;
public void addOrder(final Order order) {
// TODO Auto-generated method stub
//訂單表
System.out.println("進入");
order.setCreateTime(new Date());
order.setStatus("待付款測試2");
template.execute(new TransactionCallback<Object>() {
public Object doInTransaction(TransactionStatus status) {
// TODO Auto-generated method stub
//開啟事務
try {
orderDao.insert(order);
//商品
Product p=productDao.select(order.getProductsId());
p.setStock(p.getStock()-order.getNumber());
productDao.update(p);
} catch (Exception e) {
// TODO: handle exception
//回滾
status.setRollbackOnly();
e.printStackTrace();
}
return null;
}
});
}
}
6.3基於TransactionProxyFactoryBean (bean工廠代理)--需要顯示的為每一個業務類配置,每多一個業務類就要進行新增
<import resource="spring_dao.xml" />
<!-- spring bean工廠代理 -->
<bean id="tsManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="datasource" />
</bean>
<bean id="OrderServiceImpl3" class="com.thit.serviceImpl.OrderServiceImpl3"></bean>
<bean id="orderService" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="transactionManager" ref="tsManager"/>
<property name="transactionAttributes">
<props>
<prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>
<prop key="find*">PROPAGATION_REQUIRED,readOnly</prop>
<prop key="search*">PROPAGATION_REQUIRED,readOnly</prop>
<prop key="*">PROPAGATION_REQUIRED</prop>
</props>
</property>
<property name="target" ref="OrderServiceImpl3"/>
</bean>
Java程式碼:
package com.thit.serviceImpl;
import java.util.Date;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallback;
import org.springframework.transaction.support.TransactionTemplate;
import com.thit.dao.OrderDao;
import com.thit.dao.ProductDao;
import com.thit.entity.Order;
import com.thit.entity.Product;
import com.thit.service.OrderService;
public class OrderServiceImpl3 implements OrderService {
@Autowired
private OrderDao orderDao;
@Autowired
private ProductDao productDao;
public void addOrder( Order order) {
// TODO Auto-generated method stub
// 訂單表
System.out.println("進入");
order.setCreateTime(new Date());
order.setStatus("待付款測試2");
List<Order> list=orderDao.select();
System.out.println(list.size());
orderDao.insert(order);
// 商品
Product p = productDao.select(order.getProductsId());
p.setStock(p.getStock() - order.getNumber());
productDao.update(p);
}
}
7:宣告式事務實現
7.1基於配置檔案
配置檔案如下
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
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.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<import resource="spring_dao.xml" />
<!-- spring 宣告式事務 -->
<bean id="OrderServiceImpl5" class="com.thit.serviceImpl.OrderServiceImpl3"></bean>
<!-- 1 事務管理器 -->
<bean id="tsManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="datasource" />
</bean>
<!-- 2 事務詳情(事務通知) , 在aop篩選基礎上,比如對ABC三個確定使用什麼樣的事務。例 如:AC讀寫、B只讀 等
<tx:attributes> 用於配置事務詳情(屬性屬性)
<tx:method name=""/> 詳情具體配置
propagation 傳播行為 , REQUIRED:必須;
REQUIRES_NEW:必須是新的
isolation 隔離級別
-->
<tx:advice id="txid" transaction-manager="tsManager">
<tx:attributes>
<tx:method name="insert*" propagation="REQUIRED" isolation="DEFAULT"/>
<tx:method name="delete*" propagation="REQUIRED" isolation="REPEATABLE_READ"/>
<tx:method name="select*" propagation="REQUIRED"/>
<tx:method name="update*" propagation="REQUIRED"/>
<tx:method name="*" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
<!-- 將管理器交予spring
* transaction-manager 配置事務管理器
* proxy-target-class
false:jdk實現動態代理
true : 底層強制使用cglib 代理
-->
<!-- 3 AOP程式設計,利用切入點表示式從目標類方法中 確定增強的聯結器,從而獲得切入點 -->
<aop:config proxy-target-class="false">
<aop:pointcut id="pointcutid" expression="execution(* com.thit.serviceImpl.*.*(..))" />
<!-- 關聯切入點和通知 -->
<aop:advisor advice-ref="txid" pointcut-ref="pointcutid"/>
</aop:config>
</beans>
Java程式碼:
package com.thit.serviceImpl;
import java.util.Date;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallback;
import org.springframework.transaction.support.TransactionTemplate;
import com.thit.dao.OrderDao;
import com.thit.dao.ProductDao;
import com.thit.entity.Order;
import com.thit.entity.Product;
import com.thit.service.OrderService;
public class OrderServiceImpl3 implements OrderService {
@Autowired
private OrderDao orderDao;
@Autowired
private ProductDao productDao;
//宣告式事務程式碼簡潔 第一種當時基於攔截器
public void addOrder( Order order) {
// TODO Auto-generated method stub
// 訂單表
System.out.println("進入");
order.setCreateTime(new Date());
order.setStatus("待付款測試2");
List<Order> list=orderDao.select();
System.out.println(list.size());
orderDao.insert(order);
// 商品
Product p = productDao.select(order.getProductsId());
p.setStock(p.getStock() - order.getNumber());
productDao.update(p);
}
}
7.2基於註解實現宣告式事務
配置檔案如下:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
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.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<import resource="spring_dao.xml" />
<context:component-scan base-package="com.thit.servicImpl"></context:component-scan>
<!-- spring 基於註解的tx -->
<bean id="tsManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="datasource" />
</bean>
<!-- 事務驅動 -->
<tx:annotation-driven transaction-manager="tsManager" proxy-target-class="true"/>
</beans>
程式碼只需要新增
package com.thit.servicImpl;
import java.util.Date;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import com.thit.dao.OrderDao;
import com.thit.dao.ProductDao;
import com.thit.entity.Order;
import com.thit.entity.Product;
import com.thit.service.OrderService;
@Service(value="OrderServiceImpl6")
public class OrderServiceImpl6 implements OrderService {
@Autowired
private OrderDao orderDao;
@Autowired
private ProductDao productDao;
//設定事務傳播性和隔離級別
@Transactional(propagation=Propagation.REQUIRED,readOnly=false,isolation=Isolation.REPEATABLE_READ)
public void addOrder( Order order) {
// TODO Auto-generated method stub
// 訂單表
System.out.println("進入");
order.setCreateTime(new Date());
order.setStatus("待付款測試2");
List<Order> list=orderDao.select();
System.out.println(list.size());
orderDao.insert(order);
// 商品
Product p = productDao.select(order.getProductsId());
p.setStock(p.getStock() - order.getNumber());
productDao.update(p);
}
}
測試程式碼如下:
package com.thit.test;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.thit.entity.Order;
import com.thit.servicImpl.OrderServiceImpl6;
import com.thit.service.OrderService;
import com.thit.serviceImpl.OrderServiceImpl;
import com.thit.serviceImpl.OrderServiceImpl2;
import com.thit.serviceImpl.OrderServiceImpl3;
public class test1 {
public static void main(String[] args) {
test1 t = new test1();
t.testAddOrder6();
}
// 基於底層API
public void testAddOrder() {
System.out.println("開始1132");
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring_service1.xml");
Order order = new Order("100023", "100002", 2, 1799, "", "", "測試1");
OrderServiceImpl orderServiceImpl = (OrderServiceImpl) applicationContext.getBean("orderServiceimpl111");
orderServiceImpl.addOrder(order);
}
// 基於transactiontemplate
public void testAddOrder1() {
System.out.println("開始");
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring_service2.xml");
Order order = new Order("100025", "100002", 2, 1799, "", "", "");
OrderServiceImpl2 orderServiceImpl = (OrderServiceImpl2) applicationContext.getBean("orderServiceimpl2");
orderServiceImpl.addOrder(order);
}
// 申明式事務,基於配置檔案
public void testAddOrder3() {
System.out.println("開始3");
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring_service3.xml");
Order order = new Order("100035", "100002", 2, 1799, "", "", "申請式事務testAddOrder3()");
OrderServiceImpl3 orderServiceImpl = (OrderServiceImpl3) applicationContext.getBean("OrderServiceImpl3");
orderServiceImpl.addOrder(order);
}
// 申明式事務,基於配置檔案
public void testAddOrder4() {
System.out.println("開始4");
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring_service4.xml");
Order order = new Order("100034", "100002", 2, 1799, "", "", "申請式事務testAddOrder4");
OrderServiceImpl3 orderServiceImpl = (OrderServiceImpl3) applicationContext.getBean("OrderServiceImpl3");
orderServiceImpl.addOrder(order);
}
// 申明式事務,基於配置檔案
public void testAddOrder5() {
System.out.println("開始5");
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring_service5.xml");
Order order = new Order("100041", "100002", 2, 1799, "", "", "申請式事務testAddOrder5() ");
OrderServiceImpl3 orderServiceImpl = (OrderServiceImpl3) applicationContext.getBean("OrderServiceImpl5");
orderServiceImpl.addOrder(order);
}
// 申明式事務,基於配置檔案
public void testAddOrder6() {
System.out.println("開始6");
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring_service6.xml");
Order order = new Order("100043", "100002", 2, 1799, "", "", "申請式事務testAddOrder5() ");
OrderService orderServiceImpl = (OrderService) applicationContext.getBean("OrderServiceImpl6");
orderServiceImpl.addOrder(order);
}
}
=========================================================================================================
專案目錄結構
附錄建表sql:
//訂單表
create table orders
(
id char(6) not null COMMENT '編號',
products_id char(6) not null COMMENT '商品編號',
number int COMMENT '數量',
price double COMMENT '價格',
create_time datetime COMMENT '下單時間',
send_time datetime COMMENT '發貨時間',
confirm_time datetime COMMENT '確認收貨時間',
consignee varchar(20) COMMENT '收貨人',
consignee_phone char(11) COMMENT '收貨人電話',
consignee_address varchar(100) COMMENT '收貨人地址',
status varchar(10) COMMENT '狀態',
primary key (id)
);
//商品表
create table products
(
id char(6) not null COMMENT '商品id',
title varchar(20) COMMENT '商品名稱',
price double COMMENT '價格',
stock int COMMENT '庫存數',
status varchar(10) COMMENT '狀態',
primary key (id)
);
insert into products values('100001','蘋果',2,100,'正常');
insert into products values('100002','香蕉',5,100,'正常');
insert into products values('100003','橘子',5,100,'正常');