[問題] 請問 Spring transaction 設定

看板java作者 (DFL)時間8年前 (2017/01/30 17:04), 8年前編輯推噓0(001)
留言1則, 1人參與, 最新討論串1/1
最近想搞懂 Spring 怎麼管理 transaction 的 先從程式可以開始跑開始,照書上設定了幾個範例 目前在試 @Transactional,遇到無法 rollback 的問題,想請教 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:context="http://www.springframework.org/schema/context" xmlns:jee="http://www.springframework.org/schema/jee" 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/jee http://www.springframework.org/schema/jee/spring-jee.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd "> <context:property-placeholder location="classpath:idv/sql/jdbc.properties" /> <context:component-scan base-package="idv.spring.tx.dao, idv.spring.tx.ch02_spring.e_annotation.service" /> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="${jdbc.driverClassName}" /> <property name="url" value="${jdbc.url}" /> <property name="username" value="${jdbc.username}" /> <property name="password" value="${jdbc.password}" /> </bean> <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource" /> </bean> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="dataSource" /> </bean> <tx:annotation-driven transaction-manager="txManager" /> </beans> Service.java @Service("spring_annotation_memberService") public class MemberService { @Autowired @Qualifier("jdbc_tx_memberDao") private MemberDao memberDao; @Autowired @Qualifier("jdbc_tx_memberDetailDao") private MemberDetailDao memberDetailDao; @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class) public void saveMember(Member member, MemberDetail memberDetail) { try { memberDao.addMember(member); memberDetailDao.addMemberDetail(memberDetail); } catch (Exception ex) { ex.printStackTrace(); } } } Main.java public class SpringTxMain { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("classpath:idv/spring/tx/ch02_spring/e_annotation/applicationContext.xml"); Member member = new Member(); member.setId("xxxxx"); member.setAccount("xxxxx"); member.setNickName("Xxxxx"); member.setStatus(Status.ACTIVE); MemberDetail memberDetail = new MemberDetail(); memberDetail.setId("00001"); // memberDetail.setMemberId(member.getId()); memberDetail.setMemberId(member.getId() + "xxxxxxxxxxxxxxxx"); // this would cause SQLException memberDetail.setFirstName("YYYY"); memberDetail.setLastName("ZZZZ"); memberDetail.setIdNum("asdfghjkl"); MemberService memberService = context.getBean("spring_annotation_memberService", MemberService.class); memberService.saveMember(member, memberDetail); ((AbstractApplicationContext) context).close(); } } Dao 的部份應該不用附程式吧,就是直接用 jdbcTemplate 而已 故意在 service 的 memberDetailDao.addMemberDetail(memberDetail); 出錯 不過 memberDao.addMember(member); 還是成功寫入資料庫了 測試的 DB 是 H2 和 MySQL(community-5.7.14.0) 一開始在練習由程式控制 transaction 時 有遇到 org.springframework.jdbc.datasource.DriverManagerDataSource 不能 disable auto-commit,所以一直失敗 改為 org.apache.commons.dbcp.BasicDataSource 並設定 <property name="defaultAutoCommit" value="false" /> 就成功 不過接著試了 1. DataSourceTransactionManager 2. TransactionTemplate 都是只用 org.springframework.jdbc.datasource.DriverManagerDataSource 也有成功 rollback 再試 3. TransactionProxyFactoryBean 4. <tx:advice> 也是失敗 其中 TransactionProxyFactoryBean 管理 transaction 設定比較複雜 所以先跳過不看 <tx:advice> 則應該是 <aop:pointcut> 的部份設定有錯 這要回頭去補 AOP 的設定方式,也是後續把 AOP 設定搞懂後再說 現在是試 @Transactional 的方式時也失敗了,但是找不到錯在哪 想請教先進問題在哪? 另外想請教想知道 Spring 怎麼實做的 比如 AOP,大概只知道 proxy pattern 但想知道諸如 @Aspect,@Before,<aop:config>... 如何爬原始碼會比較好 -- ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 114.36.74.251 ※ 文章網址: https://www.ptt.cc/bbs/java/M.1485767090.A.F35.html

01/31 03:03, , 1F
rollbackFor = Exception.class,但是你把例外全catch了?
01/31 03:03, 1F
感謝先進,把ex再拋出去就可以rollback了 之前找詢相關的問題時,看到的都是設定上的問題 檢查了很多次還是沒有頭緒 因為在練習 programmatic transaction management 當時的service都有try-catch,也就直接複製來用 沒想到是exception被自己擋掉了 TransactionProxyFactoryBean 和 <tx:advice> 看來也是一樣的問題 <tx:advice> 裡面也是有指定rollback-for可以理解 TransactionProxyFactoryBean就不知道了,因為也只有設定 <property name="transactionAttributes"> <props> <prop key="load*">PROPAGATION_REQUIRED,readOnly</prop> <prop key="save*">PROPAGATION_REQUIRED</prop> </props> </property> 自己在學Spring總覺得不是很踏實,很多設定背後如何實做沒弄清楚 一有問題有時候就卡很久,有時也只是找到正確的設定方式,還是不知為什麼 Spring MVC是有追一下source code,從 DispatcherServlet 開始看 不過大概也只看了一成而已吧,還有很多待查 Spring AOP就有一種不知從何開始追的感覺 ※ 編輯: jtorngl (114.36.74.251), 01/31/2017 12:01:38
文章代碼(AID): #1OZm6oyr (java)
文章代碼(AID): #1OZm6oyr (java)