Java中关于事务的提交问题

iamcooln 2010-02-10 04:35:10
通过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,依然能把在第二步中提交的,虽然这个时候第二步中建立的连接已经关闭了。所以我感觉说连接被关闭导致无法提交也不大说得通。

...全文
640 16 打赏 收藏 转发到动态 举报
写回复
用AI写文章
16 条回复
切换为时间正序
请发表友善的回复…
发表回复
soulx 2010-02-13
  • 打赏
  • 举报
回复
方法可以根据情况自己决定。

我举两个例子看对LZ有没有帮助
1.可以在A和B的这两个Service类实例化时把 Conn注入到其中,那么在这两个里面的Conn就是一个了。
2.可以把Conn存储到ThreadLocal中,用时在获得。
iamcooln 2010-02-13
  • 打赏
  • 举报
回复
年后回公司试下。Thank you all, happy new year!
yuxiaobai1015 2010-02-13
  • 打赏
  • 举报
回复
现在要出去,晚点回来再回答,做个记号
iamcooln 2010-02-13
  • 打赏
  • 举报
回复
引用 12 楼 soulx 的回复:
在A和B你获得的Connection可能并不是一个,导致了只提交了B的Connection而A的Connection没有被提交。

如果是进行类似这样事务管理的话,最好是用一个Connection来进行处理。

现在那么怎样定位一个具体的connection呢?比如我在A中使用了Connection后,在连接池中把它锁定,不然其他类用,只让B用,然后在B中使用这个Connection。现在问题是我不知道怎么标记一个Connection。。。我看Oracle的JDBC驱动里面OracleConnection倒是有个类似ClientID的东东。但是我Debug的时候发现得到的连接里面这个值是null。不知道还有没有其他属性能唯一地定位一个Connection的?如果没有的话我就只有手动添加一个ConnectionID了,但是这样总感觉不大合适,底层东西改太多了。
vcshcn 2010-02-11
  • 打赏
  • 举报
回复
jdbc事物是面向连接的
dickli1986 2010-02-11
  • 打赏
  • 举报
回复
两个操作使用同一个连接,操作都成功后提交事务
soulx 2010-02-11
  • 打赏
  • 举报
回复
在A和B你获得的Connection可能并不是一个,导致了只提交了B的Connection而A的Connection没有被提交。

如果是进行类似这样事务管理的话,最好是用一个Connection来进行处理。
iamcooln 2010-02-11
  • 打赏
  • 举报
回复
引用 2 楼 inhibitory 的回复:
把两个的数据库插入语句都放在一个try catch能捕捉到异常的块中,然后rollback也放在同一个catch中,这样就可以了。
不管是谁发生了异常,最后两个都会回滚的。

可是现在这A和B的数据插入语句是在两个不同的类中,并且B是分成了几个程序块,先是在一个程序块中对A调用(在A里面插入第一次数据),然后才是B在另一个程序块中插入数据库,我想实现B在插入数据库后提交事务的同时提交A中的事务。
iamcooln 2010-02-11
  • 打赏
  • 举报
回复
以下是我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_remarks= 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
iamcooln 2010-02-11
  • 打赏
  • 举报
回复
引用 9 楼 dinghun8leech 的回复:
这是模块设计问题。
ab两处对数据库的操作都只用同一条连接,并且b调用a的方法要抛出sql异常,b作为调用端即可判断数据库操作是否正常,来决定是否回滚。


嗯,我现在通过让这两个模块调用同一个连接解决了。现在问题是在管理连接池中的连接时如何标记处这些连接?每个和Oracle建立的连接应该有一个唯一的ID吧?
dinghun8leech 2010-02-11
  • 打赏
  • 举报
回复
这是模块设计问题。
ab两处对数据库的操作都只用同一条连接,并且b调用a的方法要抛出sql异常,b作为调用端即可判断数据库操作是否正常,来决定是否回滚。
iamcooln 2010-02-11
  • 打赏
  • 举报
回复
补充一下,我说的SID是在PL/SQL中
select * from v$session s where s.username is NOT Null
搜索出的那个SID,不是jdbc连接字符串中的SID
iamcooln 2010-02-11
  • 打赏
  • 举报
回复
引用 5 楼 dickli1986 的回复:
两个操作使用同一个连接,操作都成功后提交事务

刚在第一次提交数据后没有销毁连接,而是把它重新放回连接池。这样就是使用的同一个连接,刚试了下成功了。
现在还有个问题,就是连接池中连接的管理。我在数据插入数据库但未提交的时候,用PL/SQL查锁表能查到锁表session 的SID和一个SERIAL#,现在我想在程序中定位这个SID,应该怎么找呢?我Debug看connection的属性一直都没找到。
SambaGao 2010-02-10
  • 打赏
  • 举报
回复
来年再看。回家。。。
Inhibitory 2010-02-10
  • 打赏
  • 举报
回复
把两个的数据库插入语句都放在一个try catch能捕捉到异常的块中,然后rollback也放在同一个catch中,这样就可以了。
不管是谁发生了异常,最后两个都会回滚的。
iamcooln 2010-02-10
  • 打赏
  • 举报
回复
刚又看了一下,在第二步和第四步中并没有关闭连接,是我弄错了。连接是从连接池中获取的。现在问题是怎么才能实现这个在B中把AB的事务同时提交的功能?

67,513

社区成员

发帖
与我相关
我的任务
社区描述
J2EE只是Java企业应用。我们需要一个跨J2SE/WEB/EJB的微容器,保护我们的业务核心组件(中间件),以延续它的生命力,而不是依赖J2SE/J2EE版本。
社区管理员
  • Java EE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧