S2DBCPの機能を使って、コネクションプーリングを実現できます。JTAと連動するので、トランザクション中にコネクションを取得し閉じるということを何度か行っても、トランザクションは維持されます。JDBCで行っていたようなトランザクションを維持したいがために複数のクラスでコネクションを持ちまわるようなことはもう必要なくなります。S2Txを使えば、トランザクションもAspectで自動的に処理することができます。
XADataSource、ConnectionPoolの設定をおこないます。JDBC DriverがXADataSourceの機能を提供している場合は、 それをそのまま使えますが、提供されていない場合、S2で用意しているXADataSourceImplを使って、XAの機能をエミュレートします。
XADataSourceのインスタンスを設定します。S2Containerで設定する場合は、XADataSourceのコンポーネント名を設定します。
コンポーネントの設定は以下のようになります。環境に合わせて書き換えてください。
<components namespace="j2ee"> <component name="transactionManager" class="org.seasar.extension.jta.TransactionManagerImpl"/> <component name="requiredTx" class="org.seasar.extension.tx.RequiredAdvice"/> <component name="requiresNewTx" class="org.seasar.extension.tx.RequiresNewAdvice"/> <component name="mandatoryTx" class="org.seasar.extension.tx.MandatoryAdvice"/> <component name="xaDataSource" class="org.seasar.extension.dbcp.impl.XADataSourceImpl"> <property name="driverClassName"> "oracle.jdbc.driver.OracleDriver" </property> <property name="URL"> "jdbc:oracle:thin:@xxx:1521:yyy" </property> <property name="user">"aaa"</property> <property name="password">"bbb"</property> </component> <component name="connectionPool" class="org.seasar.extension.dbcp.impl.ConnectionPoolImpl"> <property name="timeout">600</property> <property name="maxPoolSize">10</property> <destroyMethod name="close"/> </component> <component name="dataSource" class="org.seasar.extension.dbcp.impl.DataSourceImpl"/> </components>
package examples.dbcp; import java.sql.SQLException; public interface EmployeeDao { public String getEmployeeName(int empno) throws SQLException; }
package examples.dbcp; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import javax.sql.DataSource; public class EmployeeDaoImpl implements EmployeeDao { private DataSource dataSource_; public EmployeeDaoImpl(DataSource dataSource) { dataSource_ = dataSource; } public String getEmployeeName(int empno) throws SQLException { String ename = null; Connection con = dataSource_.getConnection(); try { PreparedStatement ps = con.prepareStatement( "SELECT ename FROM emp WHERE empno = ?"); try { ps.setInt(1, empno); ResultSet rs = ps.executeQuery(); try { if (rs.next()) { ename = rs.getString("ename"); } } finally { rs.close(); } } finally { ps.close(); } } finally { con.close(); } return ename; } }
package examples.dbcp; import java.sql.SQLException; public interface EmployeeService { public String getEmployeeName(int empno) throws SQLException; }
package examples.dbcp; import java.sql.SQLException; public class EmployeeServiceImpl implements EmployeeService { private EmployeeDao dao_; public EmployeeServiceImpl(EmployeeDao dao) { dao_ = dao; } public String getEmployeeName(int empno) throws SQLException { return dao_.getEmployeeName(empno); } }
<components> <include path="j2ee.dicon"/> <component class="examples.dbcp.EmployeeDaoImpl"/> <component class="examples.dbcp.EmployeeServiceImpl"> <aspect>j2ee.requiredTx</aspect> </component></components>
package examples.dbcp; import java.sql.SQLException; import org.seasar.framework.container.S2Container; import org.seasar.framework.container.factory.S2ContainerFactory; public class EmployeeClient { private static final String PATH = "examples/dbcp/Employee.dicon"; public static void main(String[] args) { S2Container container = S2ContainerFactory.create(PATH); container.init(); try { EmployeeService service = (EmployeeService) container.getComponent(EmployeeService.class); System.out.println(service.getEmployeeName(7788)); } catch (SQLException ex) { ex.printStackTrace(); } finally { container.destroy(); } } }
DEBUG 2004-03-21 12:51:35,653 [main] Transaction.begin() DEBUG 2004-03-21 12:51:37,075 [main] Transaction.commit() SCOTT
これまで、JTAやJTAと連動したコネクションプールに対して、敷居が高いなぁと感じていた方も、POJOでこんなに簡単に利用できるということが分かっていただけたと思います。