1つだけ過去を変えられるとしたら?

現在、下記の書籍を参考にしHibernate&Springを利用したアプリを開発しているのですが、宣言的トランザクション管理がうまく機能していません。

オープンソースJavaプロダクツ

http://www.gihyo.co.jp/books/syoseki-query.php/4 …

試しに、特集5のサンプルを動かしテストしてみたのですが、やはりトランザクションが思った通りに機能しませんでした。
どなたかサンプルを実行した方はいらっしゃいますでしょうか?また、その際トランザクションがちゃんと機能していたか教えていただけないでしょうか?

ちなみにテストの仕方としては、
1
CustomerDAOにてsaveメソッドを定義
2
CustomerImplでオーバーライド
3
save()内でgetHibernateTemplate().save()を実行。その際引数として適当な文字列を渡す。
例 : getHibernateTemplate().save("test")
4
SaveCustomerAction.executeで以下のコードを実行

customerDAO.saveOrUpdate(customer);
customerDAO.save(customer);

この時updateで例外が発生するのでrollbackして欲しいのですが、commitしてしまいます。

テストの仕方もこんなやり方でいいのか?と思いましたが、何か分かる方がいらっしゃいましたら情報の提供よろしくお願い致します。

A 回答 (1件)

サンプルのcustomerDAOを確認してみました。



トランザクションはこの場合、customerDAOのメソッド内で有効となります。
つまり、あなたの使い方では
customerDAO.saveOrUpdate(customer);
を実行時に、内部でエラーが発生するとrollbackされるということです。

あなたが想像している動作をさせるには、applicationContext.xmlに以下を追加して

<bean id="customerService"
class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="transactionManager"><ref local="transactionManager"/></property>
<property name="target"><ref local="customerServiceTarget"/></property>
<property name="transactionAttributes">
<props>
<prop key="*">PROPAGATION_REQUIRED</prop>
</props>
</property>
</bean>

<bean id="customerServiceTarget"
class="net.hoge.CustomerServiceImpl">
<property name="customerDAO"><ref local="customerDAO"/></property>
</bean>

以下のような感じでクラスを作成します。

-- CustomerService.java

package net.hoge;
public interface CustomerService {
public void doTest() throws Exception;
public void doTestRollback() throws Exception;
}


-- CustomerServiceImpl.java

package net.hoge;
import jp.programmers.pizza.model.Customer;
import jp.programmers.pizza.dao.CustomerDAO;
public class CustomerServiceImpl implements CustomerService {
private CustomerDAO customerDAO;
public void doTest() throws Exception {
Customer customer = new Customer();
customer.setName("hoge");
customer.setAddress("hage");
customer.setPhone("117");
customerDAO.saveOrUpdate(customer);
}
public void doTestRollback() throws Exception {
Customer customer = new Customer();
customer.setName("fuga");
customer.setAddress("fugo");
customer.setPhone("177");
customerDAO.saveOrUpdate(customer);
throw new Exception();
}
public void setCustomerDAO(CustomerDAO customerDAO) {
this.customerDAO = customerDAO;
}
}

と、こんな感じでやると、doTest()を実行するとcommitされ、doTestRollback()を実行するとrollbackされているはずです。
今即席で作ったので間違ってるかも知れませんが、イメージ的にはこういうことです。
    • good
    • 0
この回答へのお礼

s2tさん回答ありがとうございます。

早速サンプルを参考にし試しにCustomerDAOImpl.saveOrUpdate()を、以下のように修正してみたところ、思った通りに動作させることが出来ました。私の考え方が少し間違ってたみたいですね。

public void saveOrUpdate(Customer customer) {
getHibernateTemplate().saveOrUpdate(customer);
getHibernateTemplate().save("test");
}

本当に助かりました。ありがとうございました。

お礼日時:2004/12/09 11:54

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!