[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 メーリングリストの案内