linpyi 2009-01-09 11:16
浏览 536
已采纳

搭建一个框架,如何做到事务在service层处理

想搭一个基础的框架,不想用spring和hibernate那些东西....

自己写连接池连接(连接池代码就不想多说,主要是能获取一个connection对象).

想自己写事务处理.service和dao层尽量解耦合(所有的关于业务的事务处理都在service层解决,dao层只做数据库操作)
[code="java"]
import java.io.*;
import java.util.*;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;
import javax.transaction.*;
import java.sql.ResultSet;

/**基类**/
public class BaseDAL implements java.io.Serializable
{
protected java.sql.Connection myConn=null;
public java.sql.Statement stmt = null ;
protected java.sql.PreparedStatement pstmt = null;
//public java.sql.ResultSet rs = null;
private javax.sql.DataSource ds =null;
private javax.transaction.UserTransaction transaction =null;
private Context ctx =null;
public int makeTrans=0; //表示是否启动了事务,为0表示没有启动事务,1表示有启动事务
public int connCount =0; //表示数据库连接的次数,每调用一次Connection,加1,每调用一次Disconnect,减1
protected java.lang.String JNDIName;
public BaseDAL() throws Exception
{
try
{
JNDIName ="jdbc/TripDataSource";
ctx =new InitialContext();
}
catch (Exception e)
{
throw e;
}
}

public void setTransactionTimeOut(int time)
{
try
{
this.transaction.setTransactionTimeout(time);
}
catch (Exception e)
{
}
}

/**修改JNDIName**/
public void setJNDIName(String JNDIName)
{
this.JNDIName = JNDIName;
myConn = null;
}

/**事务创建**/
public void begin() throws Exception
{
try
{
if (transaction == null)
{
transaction =(javax.transaction.UserTransaction)
ctx.lookup("javax.transaction.UserTransaction");
transaction.setTransactionTimeout(120);
}
if (ds==null)
{
ds = (javax.sql.DataSource) ctx.lookup(JNDIName);
}
//获得当前的事务状态,如果不为0,表示当前没有事务在处理
int tranStatus = transaction.getStatus();
if ( tranStatus != 0)
{
//启动一个事务,记录当前有事务处理
makeTrans = 1;
transaction.begin();
}
}
catch( Exception E)
{
throw E;
}
}

/**事务提交**/
public void commit() throws Exception
{
try
{
//如果当前有提交事务
if ( makeTrans != 0)
{
transaction.commit();
makeTrans = 0;
}
}
catch(Exception E)
{
throw E;
}
}

/**事务回滚**/
public void rollback() throws Exception
{
try
{
//如果当前有提交事务
if ( makeTrans != 0)
{
transaction.rollback();
makeTrans = 0;
}
}
catch(Exception E)
{
throw E;
}
}

/**连接数据库**/
protected void connection() throws Exception
{
try
{
if (ds==null)
{
ds = (javax.sql.DataSource) ctx.lookup(JNDIName);
}

  //如果连接计数为0,连接数据库
  if (connCount==0)
  {
    myConn = ds.getConnection();
    stmt = myConn.createStatement();
  }
  connCount ++;
}
catch (Exception E)
{
  throw E;
}

}

/**断开数据库**/
protected void disConnection() throws Exception
{
try
{
connCount --;
if (connCount == 0)
{
try
{
if (stmt != null)
stmt.close();
myConn.close();
}
catch ( Exception e)
{
e.printStackTrace();
}
}
}
catch (Exception E)
{
throw E;
}
}

/**创建事务,包括数据连接**/
public void transactionBegin() throws Exception
{
begin();
connection();
}

/**事务提交,包括断开数据库**/
public void transactionCommit() throws Exception
{
disConnection();
commit();
}

/**事务回滚、包括断开数据库**/
public void transactionRollback() throws Exception
{
disConnection();
rollback();
}

public void showmessage(String str)
{
}
[/code]

上面是一个事务处理的基类,以前写的dao都是继承这个基类再实现一个接口

[code="java"]
this.transactionBegin();
/**
处理SQL,如果有多样执行的话,多条SQL涉及多张表
**/
this.stmt.executeUpdate(sql);
this.transactionCommit();

失败
this.transactionRollback();
[/code]

以前写的service是使用实现接口的dao来访问dao层

现在脑袋进入死锁状态,想不出,该如何解开这块事物,也就是把事务处理放在service..

怎么设计,该使用什么事务处理..
[b]问题补充:[/b]
如果用spring和hibernate我就自己去看书了..希望各位别在用框架回答了...
[b]问题补充:[/b]
谢谢抛出异常的爱

大概意思我明白..
[code="java"]
public Object invoke(Object proxy, Method method, Object[] args)

throws Throwable {

Object result = null;

try {

//事务开始

begin();
result = method.invoke(this.delegate, args);

//执行原来的方法之后记录日志

commit(); //事务结束
} catch (Exception e) {

rollback();
e.printStackTrace();

}finally{

logger.error("finally运行");

}

//返回方法返回值给调用者

return result;

}

public static  void main(String arg[]) throws SQLException, InterruptedException{   
    MixUpper mx = (MixUpper) new DynaProxyHello().bind(new Tmalple());   
    mx.sonMother();   
    mx.updateFather();   
}   

[/code]

这样当mx.sonMonther()的时候就执行一次事务.
mx.updateFather()的时候又执行一次事务,如果updateFather的时候失败,不会回滚回mx.sonMonther()
还是说我理解错误
[b]问题补充:[/b]
如果涉及到多张表操作..

因为我想,每张表都有自己的dao处理方式,不会耦合在一起....

如何用一个代理类实现多个代理方法
[b]问题补充:[/b]
尝试了下代理,好象没什么效果..可能是我写错了
代理类
[code="java"]
import javax.transaction.UserTransaction;
import javax.naming.NamingException;
import javax.naming.InitialContext;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.InvocationHandler;
import javax.naming.Context;

public class DynaProxyTransaction
implements InvocationHandler {
private Object object;

public Object bind(Object obj) {

    this.object = obj;
    return Proxy.newProxyInstance(this.object.getClass().getClassLoader(),
                                  this.object.getClass().getInterfaces(), this);
}

public Object invoke(Object proxy, Method method, Object[] args) throws
    Throwable {
    Object result = null;
    InitialContext ic = null;
    UserTransaction ut = null;
    ic = getContext();
    ut = getUserTransaction();
    try {
        System.out.println("事务开始");
        ut.begin();
        // JVM通过这条语句执行原来的方法(反射机制)
        result = method.invoke(this.object, args);
        ut.commit();
        System.out.println("事务提交");
    }
    catch (Exception e) {
        System.out.println("事务回滚");
        ut.rollback();
        e.printStackTrace();
    }
    // 返回方法返回值给调用者
    return result;
}

private InitialContext getContext() {
    InitialContext ic = null;
    try {
        ic = new InitialContext();
    }
    catch (NamingException e) {
        e.printStackTrace();
    }
    return ic;

}

private UserTransaction getUserTransaction() {
    UserTransaction ut = null;
    try {
        ut = (UserTransaction) getContext().lookup(
            "javax.transaction.UserTransaction");
    }
    catch (NamingException e) {
        e.printStackTrace();
    }
    return ut;

}

}
[/code]

dao层
[code="java"]
public class AdminDALImpl
implements AdminDAL {
Connection con = null;
private Context ctx = null;
private javax.sql.DataSource ds = null;
public AdminDALImpl() {
String JNDIName = "***";
try {
ctx = new InitialContext();
ds = (javax.sql.DataSource) ctx.lookup(JNDIName);
try {
con = ds.getConnection();
}
catch (SQLException ex1) {
ex1.getMessage();
}
}
catch (NamingException ex) {
ex.getMessage();
}

}

public void saveBean(String name, String pwd) throws Exception {
    java.sql.Statement st = null;
    String sql = "insert into t_admin (name,pwd) values ('" + name
        + "','" + pwd + "')";
    try {
        st = con.createStatement();
        st.executeUpdate(sql);
    }
    catch (Exception e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
        throw new Exception(e.getMessage());
    }
    finally {
        con.close();
        st.close();
    }
}

}
[/code]

dao层
[code="java"]
public class TestDALImpl
implements TestDAL {
Connection con = null;
private Context ctx = null;
private javax.sql.DataSource ds = null;

public TestDALImpl() {
    String JNDIName = "***";
    try {
        ctx = new InitialContext();
        ds = (javax.sql.DataSource) ctx.lookup(JNDIName);
        try {
            con = ds.getConnection();
        }
        catch (SQLException ex1) {
            ex1.getMessage();
        }
    }
    catch (NamingException ex) {
        ex.getMessage();
    }

}

public void saveBean(String id, String name) throws Exception {
    java.sql.Statement st = null;
    String sql = "insert into test (id,name) values ('" +
        id
        + "','" + name + "')";
    try {
        st = con.createStatement();
        st.executeUpdate(sql);
    }
    catch (Exception e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
        throw new Exception(e.getMessage());
    }
    finally {
        st.close();
        con.close();

    }
}

}
[/code]

服务层
[code="java"]
public class TestBusinessImpl implements TestBusiness{
public TestBusinessImpl() {
}

public void saveTest() throws Exception {
    AdminDAL adminDal = new AdminDALImpl();
    TestDAL testDal = new TestDALImpl();
        adminDal.saveBean("abcd", "abcd");
        testDal.saveBean("test","testtesttesttesttesttesttesttesttesttesttesttesttesttesttesttest");
}

}
[/code]

servlet 类
[code="java"]
public class TestServlet
extends HttpServlet {
public TestServlet() {
}

protected void doGet(HttpServletRequest request,
                     HttpServletResponse response) throws ServletException,
    IOException {
    System.out.println("**进入servlet**");
    TestBusiness business = (TestBusiness)new DynaProxyTransaction().bind(new TestBusinessImpl());
    try {
        business.saveTest();
    }
    catch (Exception ex) {
        ex.getMessage();
    }
}

protected void doPost(HttpServletRequest request,
                      HttpServletResponse response) throws ServletException,
    IOException {
    // TODO Auto-generated method stub
    doGet(request, response);
}

[/code]

随便搭了一个平台,接口类我就没写了...
试了好多次..保存test的时候执行SQL是错误的,应该执行事务回滚.第一条好是插入进去了

sdh5724说的Anotation还没去研究

谢谢
[b]问题补充:[/b]
可能你们没看到我这样写是错误的...

我也知道没关联上.但是我不知道该如何关联上...
[b]问题补充:[/b]
既然决定发这个贴,就不怕受打击了...

但是还是请多多指教.既然不需要.为什么希望指明点,对事务处理这块碰到的比较少..
[b]问题补充:[/b]
[quote]
单一数据库, Connetion就能完成事务了, 也就是所说的数据库自身的事务管理:)
[/quote]

你是说jdbc自带的事务处理?

con.setAutoCommit(false);设置为手动提交?

那是如何让dao只执行数据库操作

难道把connection做参数传进去?
[b]问题补充:[/b]
我只是想理解这块的设计方式,如何设计是比较OK的,代码如何写才是比较好的.如何解决类似这样的问题..

抛出异常的爱让我知道可以用代理模式(很早以前就看过代理,一直没想到该用在什么地方)

sdh5724也让我知道我还有好都东西搞的乱七八糟,现在恶补中...

谢谢几位,

大家有什么意见还可以提,这并不是说要解决具体什么问题,只是一个想了解设计

思路来彻底的解开这耦合.我会准时结帖...

备注:Anotation应该是Annotation

  • 写回答

18条回答 默认 最新

  • m_m1m2m3m4m5 2009-01-09 15:02
    关注

    [code="java"] MixUpper mx = (MixUpper) new DynaProxyHello().bind(new Tmalple()); [/code]

    你要把所有事务的边界定制在service的一个方法内
    这就是为什么三层架构了,
    dao不含事务,
    service的一个方法为一个事务.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(17条)

报告相同问题?

悬赏问题

  • ¥15 arduino控制ps2手柄一直报错
  • ¥15 使用rabbitMQ 消息队列作为url源进行多线程爬取时,总有几个url没有处理的问题。
  • ¥85 maple软件,solve求反函数,出现rootof怎么办?
  • ¥15 求chat4.0解答一道线性规划题,用lingo编程运行,第一问要求写出数学模型和lingo语言编程模型,第二问第三问解答就行,我的ddl要到了谁来求了
  • ¥15 Ubuntu在安装序列比对软件STAR时出现报错如何解决
  • ¥50 树莓派安卓APK系统签名
  • ¥15 maple软件,用solve求反函数出现rootof,怎么办?
  • ¥65 汇编语言除法溢出问题
  • ¥15 Visual Studio问题
  • ¥20 求一个html代码,有偿