[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[jfriends-ml 10511] Re: DB トランザク ション (度々 commit/rollback を書きたくない)
- From: muimi admin <mui@xxxxxxxxx>
- Date: Sun, 23 Feb 2003 00:56:07 +0900
宮本@muimiです。
案2
別の方向からせめてみました。
DinamicProxy + ThreadLocal
ex.
-----------------------------------------------
ISomeLogic logic = (ISomeLogic)TransProxy.newInstance(new SomeLogic());
logic.doSomething();
-----------------------------------------------
イチイチCommandを作る手間がはぶます
(でもインターフェイスを作る手間はいる)
それなりに(クライアント)コードも見やすい。
でもこんなの自分で実装するぐらいなら、
EJBとか使った方が安全ですね。。。
JDKに
Collection#unmodifiedSet(Set)みたいな感じで、
ConnectionUtil#transactionMethod(Method)みたいなのあるといいのに
#みなさんは、どうやってコネクションを厳重に管理していますか?
#try/catchか?
#EJBか?
#はたまたAspectJか?
※以下、コード。度々長くてすんまそん
長いと見る気しないっすね。
でも今日が旬だったので、投稿します。
=============================
RequiredTransaction
スレッドにトランザクションをひもづけ
=============================
package db3;
import java.sql.*;
/**
* CMTのRequiredライクなトランザクション
*/
public class RequiredTransaction {
private Connection con;
private int depth;
private boolean isRollbackOnly = false;
private static final ThreadLocal tl = new ThreadLocal();
private RequiredTransaction(){
try {
con = ConnectionManager.getConnection();
} catch (SQLException e) {
e.printStackTrace();
throw new IllegalStateException(e.toString());
}
}
public void beginTransaction() throws SQLException{
depth++;
}
public void endTransaction() throws SQLException{
depth--;
if(depth == 0){
try{
con.commit();
}finally{
try{
con.close();
}catch(SQLException e){
//お手上げ
}
}
}
}
public static RequiredTransaction getTransaction(){
RequiredTransaction trans = (RequiredTransaction)tl.get();
if(trans == null){
trans = new RequiredTransaction();
}
return trans;
}
public void setRollbackOnly(boolean b){
isRollbackOnly = b;
}
public static Connection getConnection(){
return getTransaction().con;
}
}
=============================
TransProxy
トランザクションをかけるDynamicProxy
=============================
package db3;
import java.lang.reflect.*;
import java.sql.SQLException;
public class TransProxy implements InvocationHandler {
private Object obj;
public static Object newInstance(Object obj) {
return java.lang.reflect.Proxy.newProxyInstance(
obj.getClass().getClassLoader(),
obj.getClass().getInterfaces(),
new TransProxy(obj));
}
private TransProxy(Object obj) {
this.obj = obj;
}
public Object invoke(Object proxy, Method m, Object[] args)
throws Throwable {
Object result;
try {
System.out.println("before method " + m.getName());
doStart();
result = m.invoke(obj, args);
} catch (Throwable e) {
doCatch();
throw e;
} finally {
System.out.println("after method " + m.getName());
doFinally();
}
return result;
}
void doStart(){
try {
RequiredTransaction.getTransaction().beginTransaction();
} catch (SQLException e) {
e.printStackTrace();
}
}
void doCatch(){
RequiredTransaction.getTransaction().setRollbackOnly(true);
}
void doFinally(){
try {
RequiredTransaction.getTransaction().endTransaction();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
↑ここまで
以下補足
=============================
クライアント側
=============================
package db3;
public class Main {
public static void main(String[] args) {
//普通
//SomeLogic logic1 = new SomeLogic();
//logic1.doSomething();
//トランザクション境界付
ISomeLogic logic2 = (ISomeLogic)TransProxy.newInstance(new SomeLogic
());
logic2.doSomething();
System.out.println("END");
}
}
=============================
クライアント側
DBアクセスビジネスロジック
=============================
package db3;
import java.sql.*;
public class SomeLogic implements ISomeLogic{
public void doSomething(){
Connection con = RequiredTransaction.getConnection();
try{
Statement smt = con.createStatement();
smt.executeUpdate(
"insert into cd values('sss2','sss2')"
);
}catch(SQLException e){
e.printStackTrace();
}
}
}
=============================
クライアント側
DBアクセスビジネスロジックのインターフェイス
=============================
package db3;
public interface ISomeLogic {
public void doSomething();
}