[Seasar-user:12563] Seasar2トランザクションロールバックについて

Tidever Chenglong Tian [E-MAIL ADDRESS DELETED]
2008年 1月 19日 (土) 11:57:11 JST


tomcat6.0
Seasar2.3.19
SqlServer2005
JDK1.6

Seasar2 はtomcatサーバーでSqlServerを接続する時、一つのServiceで2件のUpdate文を実行すると、一番目は成功するが、2番目は失敗する。
ログで、「トランザクションをロールバックしました」というメッセージを出したが、DBで一番目のUpdate文は更新した内容が依然として存在
していて、正常にロールバックしない。これは何故か

グは下記の通り。
2008/01/10 09:26:27.812 [DEBUG] トランザクションを開始しました
2008/01/10 09:26:27.984 [DEBUG] UPDATE dbo.test
SET USER_PWD = 'tcl'
WHERE USER_NO = '15'
2008/01/10 09:26:28.375 [DEBUG] 物理的なコネクションを取得しました
2008/01/10 09:26:28.375 [DEBUG] 論理的なコネクションを取得しました
2008/01/10 09:26:28.531 [DEBUG] 論理的なコネクションを閉じました
2008/01/10 09:26:28.531 [DEBUG] 物理的なコネクションを閉じました
2008/01/10 09:26:28.609 [DEBUG] UPDATE dbo.test1
SET USER_PWD = 'abc'
WHERE USER_NO = '16'
2008/01/10 09:26:28.625 [DEBUG] 物理的なコネクションを取得しました
2008/01/10 09:26:28.625 [DEBUG] 論理的なコネクションを取得しました
2008/01/10 09:26:28.625 [DEBUG] 論理的なコネクションを閉じました
2008/01/10 09:26:28.625 [DEBUG] 物理的なコネクションを閉じました
2008/01/10 09:26:28.625 [DEBUG] トランザクションをロールバックしました
2008/01/10 09:26:28.671 [ERROR] 
org.seasar.framework.exception.SQLRuntimeException:
[ESSR0071]SQLで例外(ErrorCode=208, SQLState=42S02)が発生しました。理由は
org.seasar.framework.exception.SSQLException: [ESSR0072]SQLで例外(SQL=[UPDATE 
dbo.test
....

j2ee.dicon
--------------------------------
<?xml version="1.0" encoding="Shift_JIS"?>
<!DOCTYPE components PUBLIC "-//SEASAR//DTD S2Container//EN"
"http://www.seasar.org/dtd/components.dtd">
<components namespace="j2ee">
<!-- Seasar2トランザクションマネージャ -->
<component name="transactionManager"
class="org.seasar.extension.jta.TransactionManagerImpl"/>
<!-- トランザクション属性 -->
<component name="requiredTx" 
class="org.seasar.extension.tx.RequiredInterceptor">
<initMethod name="addRollbackRule">
<arg>@[E-MAIL ADDRESS DELETED]</arg>
</initMethod>
</component>
<component name="basicResultSetFactory"
class="org.seasar.extension.jdbc.impl.BasicResultSetFactory"/>
<component name="basicStatementFactory"
class="org.seasar.extension.jdbc.impl.BasicStatementFactory"/>
<!-- SQL Server 2005 -->
<component name="sqlConnection" 
class="org.seasar.extension.dbcp.impl.XADataSourceImpl">
<property 
name="driverClassName">"com.microsoft.jdbc.sqlserver.SQLServerDriver"</property>
<property 
name="URL">"jdbc:microsoft:sqlserver://192.168.1.216:1433;DatabaseName=test"</property>
<property name="user">"sa"</property>
<property name="password">"sa"</property>
</component>
<component name="sqlConnectionPool" 
class="org.seasar.extension.dbcp.impl.ConnectionPoolImpl">
<property name="timeout">600</property>
<property name="maxPoolSize">5</property>
<property name="allowLocalTx">true</property>
<property name="XADataSource">sqlConnection</property>
<destroyMethod name="close"/>
</component>
<component name="dataSource" 
class="org.seasar.extension.dbcp.impl.DataSourceImpl">
<arg>sqlConnectionPool</arg>
</component>
</components>

test.dicon
--------------------------------
<components>
<!--Aspect auto regist. -->
<component class="jp.co.business.service.impl.testServiceImpl">
<aspect>j2ee.requiredTx</aspect>
</component>
</components>

testServiceImpl.java
--------------------------------
public class testServiceImpl extends PagerService implements testService {
private testDao dao;
public void setTestDao(testDao dao) {
this.dao = dao;
}
public int updatePassWord(String strNo, String strPwd) {
int iRtnValue = -1;
iRtnValue = dao.updatePassWord("15", "tcl");
iRtnValue = dao.updatePassWord1("16", "abc");
return iRtnValue;
}
================================================================
小林さん

ご回答大変ありがとうございました。
dao を定義している dicon ファイルは下記の通りです。
test.dicon
--------------------------------
<!-- Component auto regist. -->
  <component
      class="org.seasar.framework.container.autoregister.FileSystemComponentAutoRegister">
    <property name="autoNaming">
      <component 
class="org.seasar.framework.container.autoregister.DefaultAutoNaming"/>
    </property>
    <initMethod name="addClassPattern">
      <arg>"jp.co.domain.dao.impl"</arg>
      <arg>".*DaoImpl"</arg>
    </initMethod>
  </component>
  <component
      class="org.seasar.framework.container.autoregister.FileSystemComponentAutoRegister">
    <property name="autoNaming">
      <component 
class="org.seasar.framework.container.autoregister.DefaultAutoNaming"/>
    </property>
    <initMethod name="addClassPattern">
      <arg>"jp.co.business.service.impl"</arg>
      <arg>".*ServiceImpl"</arg>
    </initMethod>
  </component>
  <component
      class="org.seasar.framework.container.autoregister.FileSystemComponentAutoRegister">
    <property name="instanceDef">
      @[E-MAIL ADDRESS DELETED]
    </property>
    <property name="autoNaming">
      <component 
class="org.seasar.framework.container.autoregister.DefaultAutoNaming"/>
    </property>
    <initMethod name="addClassPattern">
      <arg>"jp.co.web.action"</arg>
      <arg>".*Action"</arg>
    </initMethod>
  </component>

testService を呼び出しているコード
--------------------------------
public class LoginAction extends BaseAction{
 private testService service;
 public void setTestService(testService service) {
  this.service = service;
 }
 public String doExecute(ActionMapping mapping,
   ActionForm form,
   HttpServletRequest request,
   HttpServletResponse response) {
  int iUpdateFlg = -1;
  iUpdateFlg = service.updatePassWord("15", "tcl");
  return SUCCESS;
 }
}
「トランザクションを開始しているコード」はソースで書いていません。
トランザクションの管理はS2基底より実行されるのでしょうか、ソースで明文に記述する必要がありますか。
尚、S2Containerが作成されたかをどのように判断しますか。
================================================================
ひがさん

ご回答大変ありがとうございました。
web.xmlに下記の配置があります。
web.xml
--------------------------------
<servlet>
 <servlet-name>s2servlet</servlet-name>
 <servlet-class>org.seasar.framework.container.servlet.S2ContainerServlet</servlet-class> <init-param>  <param-name>configPath</param-name>  <param-value>app.dicon</param-value> </init-param> <init-param>  <param-name>debug</param-name>  <param-value>false</param-value> </init-param> <load-on-startup>1</load-on-startup></servlet><servlet-mapping> <servlet-name>s2servlet</servlet-name> <url-pattern>/s2servlet</url-pattern></servlet-mapping>>S2Containerの生成は、S2ContainerServletに任せてください。それでは、既にS2Containerの生成はS2ContainerServletに任せたことを説明するのでしょうか。ほかに何かの配置が要りますか。================================================================今田さんご回答大変ありがとうございました。DaoImpl:--------------------------------public class TestDaoImpl extends BaseDao implements TestDao { public int updatePassWord(String strNo, String strPwd) {  Object[] args=new Object[]{strPwd, strNo};  return super.updateSQL("updatePassWord", args); } public int updatePassWord1(String strNo, String strPwd) {  Object[] args=new Object[]{strPwd, strNo};  return super.updateSQL("updatePassWord1", args); }}BaseDao:--------------------------------public abstract class BaseDao { private final static String DICON_DIR = "jp/co/dicon/"; private final static String DICON_EX = ".dicon"; public int updateSQL(String component, Object[] args) {  int result;  String classFullName = this.getClass().getName();  String diconPath = getDiconPath(classFullName);  S2Container container = S2ContainerFactory.create(diconPath);        container.init();        try {         Object obj = container.getComponent(component);         UpdateHandler handler = (UpdateHandler)obj;            result = handler.execute(args);        } finally {            container.destroy();        } return result;}トランザクションの処理はソースで明文に記述しない、もうS2Containerに任せる。何問題があれば、教えてお願いします。どうしてログで「物理的なコネクションを閉じました」を表示しますか。
-------------- next part --------------
HTMLの添付ファイルを保管しました...
URL: http://ml.seasar.org/archives/seasar-user/attachments/20080119/bf182c01/attachment-0001.html 


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