[Seasar-user:682] s2hibernateのロールバックについて

B ntt-syscom.co.jp M.Kondo match
2004年 4月 19日 (月) 13:53:38 JST


はじめまして。
近藤と申します。

実務でJavaを使用した事のない初心者ですが、よろしくお願いいたします。
s2hibernateのサンプルをちょこちょこ変更してお勉強(お遊び?)中です。
(もちろんhibernateも初めてです・・)

s2hibernateでのロールバックの動作を確認したくて、サンプルを以下のように変更しました。
(WindowsXP、j2sdk1.4.2_03、Eclipse2.1.1です)

〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
package examples.hibernate.client;

import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

import org.seasar.framework.container.S2Container;
import org.seasar.framework.container.factory.S2ContainerFactory;

import examples.hibernate.entity.Employee;
import examples.hibernate.service.EmployeeService;

public class EmployeeClient {

	private static final String PATH =
		"examples/hibernate/client/Employee-config.xml";

	public static void main(String[] args) {
		S2Container container = S2ContainerFactory.create(PATH);
		container.init();
		try {
			EmployeeService service =
				(EmployeeService) container.getComponent(EmployeeService.class);
			
			printAllEmployees(service);
			saveEmployees(service);
			printAllEmployees(service);
			
		} catch (Exception ex) {
			System.out.println("異常発生");
			ex.printStackTrace();
		} finally {
			container.destroy();
		}

	}
	
	private static void printAllEmployees(EmployeeService service) {
		List allEmployees = service.getAllEmployees();
		for (Iterator it = allEmployees.iterator(); it.hasNext();) {
			Employee emp = (Employee) it.next();
			System.out.println(emp.getEmpno() + " :" + emp.getEname());
		}
	}

	private static void saveEmployees(EmployeeService service) {
		Employee emp1 = new Employee(
			1111,
			"match1",
			"AAA",
			new Short("111"),
			new Date(),
			new Float(111),
			new Float(111),
			(short)1);		
		Employee emp2 = new Employee(
			7369,
			"match2",
			"BBB",
			new Short("222"),
			new Date(),
			new Float(222),
			new Float(222),
			(short)2);		
		List employees = new ArrayList();
		employees.add(emp1);
		employees.add(emp2);
		service.saveEmployees(employees);
	}
}
〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜

(実際にはEmployeeService、EmployeeServiceImpl、EmployeeDao、EmployeeDaoImplも
EmployeeClientに沿って変更しています。その他のソース・設定ファイル・DBの内容はサンプルのままです)

予想していた動作としては
1.emp2のempno(主キー)「7369」がすでにDBに登録されているため、hibernateで例外発生。
2.ログ上には「トランザクションをロールバックしました」と表示される。
3.emp1、emp2は同一トランザクションなので両方ともロールバックされる。
4.EmployeeClient#mainで例外をキャッチし、「異常発生」と出力される。

しかし、実際に実行したところ下記のような結果になってしまいました。
1.emp2のempno(主キー)「7369」がすでにDBに登録されているため、hibernateで例外発生。
2.ログ上には「トランザクションをコミットしました」と表示される。
3.emp1はDBに登録されてしまった。
4.EmployeeClient#mainに例外はスローされてこなかった。

emp2のempno(主キー)を「7369」以外にした場合は、emp1・emp2とも正常に登録されたので
(たぶん)EmployeeService、EmployeeServiceImpl、EmployeeDao、EmployeeDaoImpl等で
変なコーディングはしていないと思うのですが・・・

使用方法とかコーディングに誤りがありましたらご教授ください。

以下は実行時のログです。

〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
DEBUG 2004-04-19 11:28:49,343 [main] トランザクションを開始しました
DEBUG 2004-04-19 11:28:50,359 [main] 物理的なコネクションを取得しました
DEBUG 2004-04-19 11:28:50,375 [main] 論理的なコネクションを取得しました
Hibernate: select employee0_.EMPNO as EMPNO, employee0_.ENAME as ENAME, employee
0_.JOB as JOB, employee0_.MGR as MGR, employee0_.HIREDATE as HIREDATE, employee0
_.SAL as SAL, employee0_.COMM as COMM, employee0_.DEPTNO as DEPTNO from EMP empl
oyee0_
DEBUG 2004-04-19 11:28:50,718 [main] 論理的なコネクションを閉じました
DEBUG 2004-04-19 11:28:50,734 [main] トランザクションをコミットしました
7369 :SMITH
7499 :ALLEN
7521 :WARD
7566 :JONES
7654 :MARTIN
7698 :BLAKE
7782 :CLARK
7788 :SCOTT
7839 :KING
7844 :TURNER
7876 :ADAMS
7900 :JAMES
7902 :FORD
7934 :MILLER
DEBUG 2004-04-19 11:28:50,734 [main] トランザクションを開始しました
DEBUG 2004-04-19 11:28:50,734 [main] 論理的なコネクションを取得しました
Hibernate: insert into EMP (ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO, EMPNO)
 values (?, ?, ?, ?, ?, ?, ?, ?)
DEBUG 2004-04-19 11:28:50,796 [main] 論理的なコネクションを閉じました
ERROR 2004-04-19 11:28:50,812 [main] [EHBN0001]Hibernateで例外が発生しました。理由はnet.sf.hib
ernate.JDBCException: could not insert: [examples.hibernate.entity.Employee#7369]
org.seasar.hibernate.HibernateRuntimeException: [EHBN0001]Hibernateで例外が発生しました。理由
はnet.sf.hibernate.JDBCException: could not insert: [examples.hibernate.entity.Em
ployee#7369]
	at org.seasar.hibernate.impl.S2SessionImpl.flush(S2SessionImpl.java:52)
	at org.seasar.hibernate.impl.S2SessionFactoryImpl.closeSession(S2SessionFactory
Impl.java:147)
	at org.seasar.hibernate.impl.S2SessionFactoryImpl.beforeCompletion(S2SessionFac
toryImpl.java:129)
	at org.seasar.extension.jta.TransactionImpl.beforeCompletion(TransactionImpl.ja
va:170)
	at org.seasar.extension.jta.TransactionImpl.commit(TransactionImpl.java:133)
	at org.seasar.extension.jta.TransactionManagerImpl.commit(TransactionManagerImp
l.java:47)
	at org.seasar.extension.tx.AbstractTxAdvice.commit(AbstractTxAdvice.java:52)
	at org.seasar.extension.tx.RequiredAdvice.invoke(RequiredAdvice.java:30)
	at org.seasar.framework.aop.impl.JoinpointImpl.proceed(JoinpointImpl.java:96)
	at org.seasar.framework.aop.proxy.AopProxy.intercept(AopProxy.java:96)
	at examples.hibernate.service.EmployeeServiceImpl$$EnhancerByCGLIB$$76e5a108.sa
veEmployees(<generated>)
	at examples.hibernate.client.EmployeeClient.saveEmployees(EmployeeClient.java:6
9)
	at examples.hibernate.client.EmployeeClient.main(EmployeeClient.java:27)
Caused by: net.sf.hibernate.JDBCException: could not insert: [examples.hibernate
..entity.Employee#7369]
	at net.sf.hibernate.persister.EntityPersister.insert(EntityPersister.java:478)
	at net.sf.hibernate.persister.EntityPersister.insert(EntityPersister.java:442)
	at net.sf.hibernate.impl.ScheduledInsertion.execute(ScheduledInsertion.java:29)
	at net.sf.hibernate.impl.SessionImpl.executeAll(SessionImpl.java:2382)
	at net.sf.hibernate.impl.SessionImpl.execute(SessionImpl.java:2335)
	at net.sf.hibernate.impl.SessionImpl.flush(SessionImpl.java:2204)
	at org.seasar.hibernate.impl.S2SessionImpl.flush(S2SessionImpl.java:50)
	... 12 more
Caused by: java.sql.SQLException: Violation of unique index: SYS_PK_EMP in state
ment [insert into EMP (ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO, EMPNO) valu
es ('match2', 'BBB', 222, '2004-04-19 11:28:50.734', 222.0E0, 222.0E0, 2, 7369)]
	at org.hsqldb.Trace.getError(Unknown Source)
	at org.hsqldb.Result.<init>(Unknown Source)
	at org.hsqldb.jdbcConnection.executeHSQL(Unknown Source)
	at org.hsqldb.jdbcConnection.execute(Unknown Source)
	at org.hsqldb.jdbcStatement.fetchResult(Unknown Source)
	at org.hsqldb.jdbcStatement.executeUpdate(Unknown Source)
	at org.hsqldb.jdbcPreparedStatement.executeUpdate(Unknown Source)
	at net.sf.hibernate.impl.NonBatchingBatcher.addToBatch(NonBatchingBatcher.java:
22)
	at net.sf.hibernate.persister.EntityPersister.insert(EntityPersister.java:468)
	... 18 more
DEBUG 2004-04-19 11:28:50,812 [main] トランザクションをコミットしました
DEBUG 2004-04-19 11:28:50,812 [main] トランザクションを開始しました
DEBUG 2004-04-19 11:28:50,812 [main] 論理的なコネクションを取得しました
Hibernate: select employee0_.EMPNO as EMPNO, employee0_.ENAME as ENAME, employee
0_.JOB as JOB, employee0_.MGR as MGR, employee0_.HIREDATE as HIREDATE, employee0
_.SAL as SAL, employee0_.COMM as COMM, employee0_.DEPTNO as DEPTNO from EMP empl
oyee0_
DEBUG 2004-04-19 11:28:50,828 [main] 論理的なコネクションを閉じました
DEBUG 2004-04-19 11:28:50,828 [main] トランザクションをコミットしました
1111 :match1
7369 :SMITH
7499 :ALLEN
7521 :WARD
7566 :JONES
7654 :MARTIN
7698 :BLAKE
7782 :CLARK
7788 :SCOTT
7839 :KING
7844 :TURNER
7876 :ADAMS
7900 :JAMES
7902 :FORD
7934 :MILLER
DEBUG 2004-04-19 11:28:50,828 [main] 物理的なコネクションを閉じました
〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜

----
M.Kondo  [E-MAIL ADDRESS DELETED]



Seasar-user メーリングリストの案内