<sql:transaction>
xmlns:sql="http://java.sun.com/jsp/jstl/sql"

SYNOPSIS

<sql:transaction
dataSource="データソース"
isolation="read_uncommitted|read_committed|repeatable_read|serializable"
/>

説 明

照会及び更新処理のトランザクションスコープを定義します。このタグの中の <sql:query>, <sql:update> が個別にデータソース設定を持っていなければ同一のトランザクションで実行されます。

トランザクションはこのタグの開始から終了まで有効です。タグ内の処理が正常に終了した場合は COMMIT され、例外で終了すると ROLLBACK が行われます。

属 性

dataSource="データソース"
optional

このトランザクションスコープで使用する java.sql.Connection のデータソースを指定します。 <sql:setDataSource> でデータソースを設定した変数名を EL で指定するか、あるいは "jdbc/XXX" 形式のデータソース名を直接指定します。 <sql:setDataSource> で変数名を省略した場合はデフォルトの設定変数 javax.servlet.jsp.jstl.sql.dataSource に格納されているため、このタグの dataSource 属性も省略可能です。

簡易的な手段としてこの値に JDBC URL を直接記述することも出来ますが、各 JSP に接続先をハードコーディングで散在させるのはメンテナンス性が低下するため控えてください (動作検証程度にとどめてください)。

またこの挙動により、JNDI からデータソースが参照できなかった場合に直接接続を試行して「No suitable driver found for jdbc/XXX」という若干見当違い気味な例外が発生するので注意してください (Jakarta Taglib の JSTL 1.1 版 + Tomcat 6 + Commons DBCP を使用した場合)。

isolation="read_uncommitted|read_committed|repeatable_read|serializable"
optional
トランザクション分離レベルを指定します。 Connection.TRANSACTION_XXX に定義されている read_uncommitted, read_committed, repeatable_read, serializable のいずれかを使用することが出来ます (大文字小文字は区別しません)。デフォルトのトランザクション分離レベルはデータソースの実装依存です。

使用例

意図的に例外を発生させる処理を行い、トランザクションが正しくロールバックされるか確認します。
JSP
<c:catch var="ex">
<sql:transaction dataSource="jdbc/MYDS">

<b>現在の状態</b><br>
<sql:query var="rs" sql="SELECT BAR FROM FOO" />
<c:forEach var="r" items="${rs.rows}" varStatus="s">
    <c:out value="${s.count}" />. <c:out value="${r.bar}" /><br>
</c:forEach>

<sql:update sql="INSERT INTO FOO(BAR) VALUES('Gamma')" />
<b>Gamma 挿入後</b><br>
<sql:query var="rs" sql="SELECT BAR FROM FOO" />
<c:forEach var="r" items="${rs.rows}" varStatus="s">
    <c:out value="${s.count}" />. <c:out value="${r.bar}" /><br>
</c:forEach>

<%-- 更新の実行 (失敗) --%>
<sql:update sql="UPDATE FOO SET INVALID SQL SYNTAX :)" />

</sql:transaction>
</c:catch>

<c:if test="${not empty ex}">
<b>例外発生</b><br>
<c:out value="${ex}" /><br>
</c:if>

<b>ロールバック後</b><br>
<sql:transaction dataSource="jdbc/MYDS">
<sql:query var="rs" sql="SELECT BAR FROM FOO" />
<c:forEach var="r" items="${rs.rows}" varStatus="s">
    <c:out value="${s.count}" />. <c:out value="${r.bar}" /><br>
</c:forEach>
</sql:transaction>
上記の実行結果です。例外発生前に行ったレコードの挿入操作がロールバックされています。
実行結果
現在の状態
1. Alpha
2. Beta
Gamma 挿入後
1. Alpha
2. Beta
3. Gamma
例外発生
javax.servlet.jsp.JspException: UPDATE FOO SET INVALID SQL SYNTAX :):
ERROR: syntax error at or near "SQL"
ロールバック後
1. Alpha
2. Beta
dataSource 属性に直接 JDBC URL を指定することも出来ますが:
JSP
<sql:transaction
    dataSource="jdbc:postgresql://server/mydb?user=postgres&password=postgres">
    ...
</sql:transaction>
通常はコンテキストパラメータ (web.xml<context-param>) などで定義した値を EL で参照しておく方が後で一括してデータソースに変更できるため便利です。
web.xml
<context-param>
  <param-name>myDataSource</param-name>
  <param-value>
    jdbc:postgresql://server/mydb?user=postgres&password=postgres
  </param-value>
</context-param>
JSP
<sql:transaction dataSource="${initParam['myDataSource']}">
    ...
</sql:transaction>
CVS 2008/03/09