P.S 這裡很多Hibernate和Spring組態檔案是隱藏的,只有一些重要的檔案顯示,如果你想看全部檔案,請在文章的結尾下載完整的專案程式碼。
CREATE TABLE `yiibai`.`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 `yiibai`.`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;
package com.yiibai.product.bo.impl; import com.yiibai.product.bo.ProductBo; import com.yiibai.product.bo.ProductQohBo; import com.yiibai.product.dao.ProductDao; import com.yiibai.product.model.Product; import com.yiibai.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"); } }
<!-- Product business object --> <bean id="productBo" class="com.yiibai.product.bo.impl.ProductBoImpl" > <property name="productDao" ref="productDao" /> <property name="productQohBo" ref="productQohBo" /> </bean> <!-- Product Data Access Object --> <bean id="productDao" class="com.yiibai.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);
假設save() 不具有事務功能,如果異常丟擲由productQohBo.save(),鈄只插入一條記錄到「product」表,沒有記錄將被插入到「productQoh'表。這是一個嚴重的問題,在資料庫中打破資料一致性。
<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()'方法,事務應該怎麼傳播?它能繼續在現有的事務中執行?或者為自己開始一個新的事務。
在Hibernate事務,需要使用 HibernateTransactionManager 。 如果只對付純JDBC,useDataSourceTransactionManager; 而如果是 JTA,需要使用 JtaTransactionManager 。
<!-- Product business object --> <bean id="productBo" class="com.yiibai.product.bo.impl.ProductBoImpl" > <property name="productDao" ref="productDao" /> <property name="productQohBo" ref="productQohBo" /> </bean> <!-- Product Data Access Object --> <bean id="productDao" class="com.yiibai.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);