通过JDBC连接Oracle数据库。
现在我想实现的功能是:
有两个类:A和B。在B中调用A的方法
1:在A中建立连接,从表A1中查出一条数据,关闭连接;
2:对A1中查出的这条数据处理后,建立连接,插入数据库,但不提交,然后关闭连接。(建立连接的时候con.setAutoCommit(false);)
3: 在A中建立连接,从表A1中查出第二条数据,关闭连接;
4:对A1中查出的这条数据处理后,建立连接,插入数据库,但不提交,然后关闭连接。(建立连接的时候con.setAutoCommit(false);)
5:回到B中,在B中创建连接,插入一条数据到B1表,如果成功,则A和B中的数据同时提交给数据库。现在我遇到的问题是:我在B中插入数据后用con.commit();的时候,只提交了我在B中插的数据,而在A中插入的数据并没有提交。(通过看数据库锁表的sid可以看出来)如果是因为在B中提交的时候A中的连接已被关闭导致无法提交的话,我试过在第三步,查询出第二条数据后,手动commit,依然能把在第二步中提交的,虽然这个时候第二步中建立的连接已经关闭了。所以我感觉说连接被关闭导致无法提交也不大说得通。

解决方案 »

  1.   

    刚又看了一下,在第二步和第四步中并没有关闭连接,是我弄错了。连接是从连接池中获取的。现在问题是怎么才能实现这个在B中把AB的事务同时提交的功能?
      

  2.   

    把两个的数据库插入语句都放在一个try catch能捕捉到异常的块中,然后rollback也放在同一个catch中,这样就可以了。
    不管是谁发生了异常,最后两个都会回滚的。
      

  3.   

    可是现在这A和B的数据插入语句是在两个不同的类中,并且B是分成了几个程序块,先是在一个程序块中对A调用(在A里面插入第一次数据),然后才是B在另一个程序块中插入数据库,我想实现B在插入数据库后提交事务的同时提交A中的事务。
      

  4.   

    刚在第一次提交数据后没有销毁连接,而是把它重新放回连接池。这样就是使用的同一个连接,刚试了下成功了。
    现在还有个问题,就是连接池中连接的管理。我在数据插入数据库但未提交的时候,用PL/SQL查锁表能查到锁表session 的SID和一个SERIAL#,现在我想在程序中定位这个SID,应该怎么找呢?我Debug看connection的属性一直都没找到。
      

  5.   

    补充一下,我说的SID是在PL/SQL中
    select * from  v$session s where s.username is NOT Null
    搜索出的那个SID,不是jdbc连接字符串中的SID
      

  6.   

    这是模块设计问题。
    ab两处对数据库的操作都只用同一条连接,并且b调用a的方法要抛出sql异常,b作为调用端即可判断数据库操作是否正常,来决定是否回滚。
      

  7.   


    嗯,我现在通过让这两个模块调用同一个连接解决了。现在问题是在管理连接池中的连接时如何标记处这些连接?每个和Oracle建立的连接应该有一个唯一的ID吧?
      

  8.   

    以下是我Debug时观察的con的属性。那个id=164不知道怎么在程序中获取。貌似这不是con的一个属性?
    con= OracleConnection  (id=164)
    auto_commit= false
    big_endian= null
    closed= false
    conversion= TTCConversion  (id=170)
    database= "10.10.165.153:1521:lis"
    count= 22
    hash= 0
    offset= 18
    value= char[70]  (id=221)
    db_access= TTC7Protocol  (id=175)
    accessWarning= null
    all7= Oall7  (id=223)
    close= Oclose  (id=225)
    commoncall= Ocommoncall  (id=227)
    DEBUG= false
    describe= v8Odscrarr  (id=229)
    dty= v8TTIdty  (id=232)
    EMPTY_BYTE= byte[0]  (id=235)
    log1= O3log  (id=236)
    log2= O3log  (id=239)
    LOGON_MODE= 0
    MEngine= MAREngine  (id=241)
    net= NSProtocol  (id=245)
    opencall= Oopen  (id=248)
    pro= v8TTIpro  (id=250)
    rxd= null
    state= 1
    TTC_LOGGEDON= 1
    TTC_NOTLOGGEDON= 0
    ver= Oversion  (id=253)
    default_batch= 50
    default_row_prefetch= 50
    defaultFixedString= false
    descriptorCache= Hashtable  (id=178)
    count= 0
    entrySet= null
    keySet= null
    loadFactor= 0.75
    modCount= 0
    table= Hashtable$Entry[10]  (id=184)
    threshold= 7
    values= null
    fdo= null
    include_synonyms= false
    lob_dbaccess= null
    logicalHandle= false
    m_accumulateBatchResult= true
    m_clientData= null
    m_clientId= null
    m_clientIdSet= false
    m_dbMetaData= null
    m_dbTzCalendar= null
    m_defaultAutoRefetch= true
    m_javaObjectMap= Hashtable  (id=189)
    m_occ= null
    m_opc= null
    m_opc_oc= null
    m_privData= null
    m_sessionTimeZone= null
    m_stmtCache= null
    m_stmtCacheSize= 0
    m_stmtClearMetaData= false
    m_warning= null
    map= Hashtable  (id=190)
    password= null
    physicalStatus= true
    protocol= "thin"
    report_res= false
    restrict_getTables= false
    statement_holding_line= null
    statement_table= Hashtable  (id=193)
    trans_level= 2
    url= "jdbc:oracle:thin:@10.10.165.153:1521:lis"
    user= "LIS"
    UsingXA= false
    XA_wants_error= false
      

  9.   

    在A和B你获得的Connection可能并不是一个,导致了只提交了B的Connection而A的Connection没有被提交。如果是进行类似这样事务管理的话,最好是用一个Connection来进行处理。
      

  10.   

    现在那么怎样定位一个具体的connection呢?比如我在A中使用了Connection后,在连接池中把它锁定,不然其他类用,只让B用,然后在B中使用这个Connection。现在问题是我不知道怎么标记一个Connection我看Oracle的JDBC驱动里面OracleConnection倒是有个类似ClientID的东东。但是我Debug的时候发现得到的连接里面这个值是null。不知道还有没有其他属性能唯一地定位一个Connection的?如果没有的话我就只有手动添加一个ConnectionID了,但是这样总感觉不大合适,底层东西改太多了。
      

  11.   

    方法可以根据情况自己决定。我举两个例子看对LZ有没有帮助
    1.可以在A和B的这两个Service类实例化时把 Conn注入到其中,那么在这两个里面的Conn就是一个了。
    2.可以把Conn存储到ThreadLocal中,用时在获得。
      

  12.   

    年后回公司试下。Thank you all, happy new year!