HibernateにおけるSpring AOPトランザクション管理
データベースにおけるデータの整合性と整合性を保証するには、トランザクション管理が必要です。 SpringのAOP技術は、開発者がトランザクションの宣言を管理できるようにします。
Spring AOPでHibernateトランザクションを管理する方法を示す例です。
__P.S多くのHibernateとSpringの設定ファイルは非表示になっています。重要なファイルがいくつか表示されますが、手作りしたい場合は記事の最後に完全なプロジェクトをダウンロードしてください。
1.テーブルの作成
MySQLテーブルスクリプト、
‘製品
‘テーブル、 ‘
手元にある製品
‘の表を参照してください。
CREATE TABLE `mkyong`.`product` ( `PRODUCT__ID` bigint(20) unsigned NOT NULL AUTO__INCREMENT, `PRODUCT__CODE` varchar(20) NOT NULL, `PRODUCT__DESC` varchar(255) NOT NULL, PRIMARY KEY (`PRODUCT__ID`) USING BTREE ) ENGINE=InnoDB AUTO__INCREMENT=1 DEFAULT CHARSET=utf8; CREATE TABLE `mkyong`.`product__qoh` ( `QOH__ID` bigint(20) unsigned NOT NULL AUTO__INCREMENT, `PRODUCT__ID` bigint(20) unsigned NOT NULL, `QTY` int(10) unsigned NOT NULL, PRIMARY KEY (`QOH__ID`), KEY `FK__product__qoh__product__id` (`PRODUCT__ID`), CONSTRAINT `FK__product__qoh__product__id` FOREIGN KEY (`PRODUCT__ID`) REFERENCES `product` (`PRODUCT__ID`) ) ENGINE=InnoDB AUTO__INCREMENT=1 DEFAULT CHARSET=utf8;
2.製品ビジネスオブジェクト
この ‘
productBo
‘実装では、
save()
メソッドは、
‘productDao
‘クラスを介して ‘
product
‘テーブルにレコードを挿入し、 ‘
productQoh
‘
productQohBo
‘クラスです。
package com.mkyong.product.bo.impl;
import com.mkyong.product.bo.ProductBo;
import com.mkyong.product.bo.ProductQohBo;
import com.mkyong.product.dao.ProductDao;
import com.mkyong.product.model.Product;
import com.mkyong.product.model.ProductQoh;
public class ProductBoImpl implements ProductBo{
ProductDao productDao;
ProductQohBo productQohBo;
public void setProductDao(ProductDao productDao) {
this.productDao = productDao;
}
public void setProductQohBo(ProductQohBo productQohBo) {
this.productQohBo = productQohBo;
}
//this method need to be transactional
public void save(Product product, int qoh){
productDao.save(product);
System.out.println("Product Inserted");
ProductQoh productQoh = new ProductQoh();
productQoh.setProductId(product.getProductId());
productQoh.setQty(qoh);
productQohBo.save(productQoh);
System.out.println("ProductQoh Inserted");
}
}
SpringのBean構成ファイル。
<!-- Product business object -->
<bean id="productBo" class="com.mkyong.product.bo.impl.ProductBoImpl" >
<property name="productDao" ref="productDao"/>
<property name="productQohBo" ref="productQohBo"/>
</bean>
<!-- Product Data Access Object -->
<bean id="productDao" class="com.mkyong.product.dao.impl.ProductDaoImpl" >
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>
それを実行します
Product product = new Product();
product.setProductCode("ABC");
product.setProductDesc("This is product ABC");
ProductBo productBo = (ProductBo)appContext.getBean("productBo");
productBo.save(product, 100);
3.トランザクション管理
Hibernateトランザクションのために ‘
TransactionInterceptor
‘ beanと ‘
HibernateTransactionManager
‘を宣言し、必要なプロパティを渡します。
<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-2.5.xsd">
<bean id="transactionInterceptor"
class="org.springframework.transaction.interceptor.TransactionInterceptor">
<property name="transactionManager" ref="transactionManager"/>
<property name="transactionAttributes">
<props>
<prop key="save">PROPAGATION__REQUIRED</prop>
</props>
</property>
</bean>
<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="dataSource" ref="dataSource"/>
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
</beans>
トランザクション属性
トランザクションインターセプタでは、どのトランザクションの属性 ‘
伝播動作
‘を使用するべきかを定義する必要があります。つまり、トランザクション
‘ProductBoImpl.save()
‘メソッドが ‘
productQohBo.save()
‘という別のメソッドと呼ばれ、トランザクションがどのように伝播されるべきかを意味します。
既存のトランザクション内で引き続き実行する必要がありますか?または独自のトランザクションを開始することができます。
Springでサポートされる伝播には7つのタイプがあります。
-
PROPAGATION__REQUIRED
– 現在のトランザクションをサポートします。新しいを作成します
存在しなければ1つです。
-
PROPAGATION__SUPPORTS
– 現在のトランザクションをサポートします。実行する
存在しなければ非トランザクション的に。
-
PROPAGATION__MANDATORY
– 現在のトランザクションをサポートします。投げる
現在のトランザクションが存在しない場合は例外です。
-
PROPAGATION
REQUIRES
NEW
– 新しいトランザクションを作成し、
現在のトランザクションが存在する場合はそれを返します。
-
PROPAGATION
NOT
SUPPORTED
– 現在のトランザクションをサポートしません。
むしろ常に非トランザクション的に実行されます。
-
PROPAGATION__NEVER
– 現在のトランザクションをサポートしません。投げる
現在のトランザクションが存在する場合は例外です。
-
PROPAGATION__NESTED
– もしネストされたトランザクション内で実行すると、
現在のトランザクションが存在する場合は、PROPAGATION__REQUIRED elseのように動作します。
ほとんどの場合、PROPAGATION__REQUIREDを使用するだけで済みます。
さらに、このトランザクション属性をサポートするメソッドも定義する必要があります。メソッド名は、ワイルドカード形式でサポートされています。
save
** は、save(…)で始まるすべてのメソッド名に一致します。
トランザクションマネージャ
Hibernateトランザクションでは、
HibernateTransactionManager
を使用する必要があります。
純粋なJDBCのみを扱う場合は、
DataSourceTransactionManager
を使用してください。 JTAは
JtaTransactionManager
を使います。
4.プロキシファクトリBean
-
ProductBo
の新しいプロキシファクトリBeanを作成し、 ‘
interceptorNames ** ‘プロパティを設定します。
<!-- Product business object -->
<bean id="productBo" class="com.mkyong.product.bo.impl.ProductBoImpl" >
<property name="productDao" ref="productDao"/>
<property name="productQohBo" ref="productQohBo"/>
</bean>
<!-- Product Data Access Object -->
<bean id="productDao" class="com.mkyong.product.dao.impl.ProductDaoImpl" >
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>
<bean id="productBoProxy"
class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target" ref="productBo"/>
<property name="interceptorNames">
<list>
<value>transactionInterceptor</value>
</list>
</property>
</bean>
それを実行します
Product product = new Product();
product.setProductCode("ABC");
product.setProductDesc("This is product ABC");
ProductBo productBo = (ProductBo)appContext.getBean("productBoProxy");
productBo.save(product, 100);
プロキシBean ‘
productBoProxy
‘を取得し、
save()
メソッドがトランザクションをサポートするようになりました。
productBo.save()
メソッド内の例外によってトランザクション全体がロールバックされ、データはデータベースに挿入されません。
ソースコードをダウンロードする
それをダウンロードする –
Spring-Hibernate-Transaction-Example.zip