问题描述:
public class A{StatusDAO statusDAO; 
FooDAO fooDAO;
BarDAO barDAO:
Long id = 111111;public void  exec(){
int status = statusDAO.getStatus(id);
if(status > ){
   //在数据库的foo表中插入一条记录
   long id = fooDAO.insert(id);
   //在数据库的bar表中删除一条记录
   barDAO.delete(id);
}
......
}}现在问题是,
1.怎样保证
long id = fooDAO.insert(id);
barDAO.delete(id);
这两句的原子性。即这两个操作要么都执行,要么都不执行()。
2.还要考虑多线程对status的读取存在的安全问题我知道用事务可以解决原子性问题,但我现在的环境里,人工无法干预事务,即得不到Transaction的上下文。

解决方案 »

  1.   

    long id = fooDAO.insert(id);
    barDAO.delete(id);
    这两句是同一个事务吗?我想应该不是吧,在你DAO的程序里肯定是一个方法一个事务
    这两个方法不会干扰对方吧
    在调用delete方法之前insert方法一定是执行完了的,insert方法的事务也commit了
      

  2.   

    难道你的DAO里每一个方法不是单独的事务?
      

  3.   


    怎么可能得不到?不大可能吧。
    事务要不是你亲自管理的,即你用代码来控制开启事务,提交事务,提交事务的时机。
    要不你的事务就是通过Spring这种框架来用切面进行管理的。看你用dao方法的返回值来表示数据库操作的成败,我判断你可能是个新手。
    (如果说错了,望楼主海涵。)
    那不妨把这个问题先放一放,等熟悉了Spring和jdbc以后再说。要不你这个程序的结构改一改。
    在exec方法里面得到一个 Connection; 关闭自动提交;然后再把Connection传给fooDao,barDao
    等fooDao.insert() 和 barDao.delete() 两个方法都结束以后,判断两个个方法的返回值。都成功了则
    提交。 其中之一失败了,回滚。
      

  4.   

    你的事务不应该放在DAO 应该放在service层~~在service的一个方法中 调用 insert和delete你所说的多线程 请详细说下 什么情况下的影响~
      

  5.   


    import java.sql.Connection;
    import java.sql.DriverManager;public final class DBHelper {

    private static ThreadLocal<Connection> tl = new ThreadLocal<Connection>(); public static synchronized Connection getConnection() throws Exception {
    Connection conn = tl.get();
    if (conn == null) {
    String username = "****";
    String password = "****";
    String url = "**************************";
    Class.forName("****");
    conn = DriverManager.getConnection(url, username, password);
    conn.setAutoCommit(false);
    tl.set(conn);
    }
    return conn;
    }

    public static void commit() throws Exception {
    getConnection().commit();
    }

    public static void rollback() throws Exception {
    getConnection().rollback();
    }
    }
    一个工具类,希望对你有帮助。
      

  6.   

    采用 open-session-in-view 模式呗,一个请求一个事物。
      

  7.   

    感谢你的回复,确实对我有些启发,但对有你提到的用dao方法的返回值来表示数据库操作的成败,是不良的方法,对此,不知道你都是怎么处理,类似数据库重复插入时,怎样判断,(总不能先select一次表,再插入吧)
      

  8.   

    多线程是指,假定这段代码
    public void exec(){
    int status = statusDAO.getStatus(id);
    if(status > 0){
      //把status置为0 
      statusDAO.setStatus(0);
      //在数据库的foo表中插入一条记录
      long id = fooDAO.insert(id);
      //在数据库的bar表中删除一条记录
      barDAO.delete(id);
     
    }
    ......
    }
    同时被两个线程ThreadA,ThreadB访问,
    当ThreadA执行到if(status > 0)时,被阻塞,然后ThreadB执行到if(status > 0)。这样ThreadA,ThreadB都会因status > 0而继续执行{}内的代码。
    而且这个类被放在多台服务器组成的集群上。
      

  9.   

    一般企业上都是看异常,而不是检查返回值的。像EJB 的 持久层,默认规则如下。1) 如果抛出未检查异常,事务立即回滚。
    2) 如果抛出已检查异常,事务立即提交。这种东西设计成这样到底有什么好处,不是一两句话可以说清楚的。我看来,你的程序结构就是有严重问题的。 
    如楼上的几位朋友说的,事务的管理不应该在dao层,而是在service层的。
    但是从你的代码看,很难看清你的代码在什么层次上,有点不伦不类的。
      

  10.   

    设为手动提交事务,当两个都成时 才commit。否则不提交。