在一个connection上可以创建多个Statement 并且同时执行不同的SQL语句(这句话到底对不对? )

oneonone 2005-03-13 07:51:03
曾向treeroot请教此问题,他说后半句是不对的,因为在多线程情况下是不能同时执行的.
我用程序试过了,确实可以.
各位高手也可以帮忙解答,多谢!~

附我的测试代码,有些乱
__________________

package testtitles;

import java.sql.DriverManager;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.ResultSet;
import java.lang.Thread;
import java.sql.PreparedStatement;

public class TestOracle {
public static int i = 0;

public static void main(String[] args) {
Connection con = null;
try {
Class.forName("oracle.jdbc.driver.OracleDriver");
con = DriverManager.getConnection(
"jdbc:oracle:thin:@138.54.252.68:1521:ora", "system",
"admin");
con.setAutoCommit(true);
if(con.isClosed()) System.out.println("Connection closed");

Thread t1 = new TestSZThread(con,1);
Thread t2 = new TestHKThread(con,1);
Thread t3 = new TestSZThread(con,1);
Thread t4 = new TestHKThread(con,1);
Thread t5 = new TestSZThread(con,1);
Thread t6 = new TestHKThread(con,1);
Thread t7 = new TestSZThread(con,1);
Thread t8 = new TestHKThread(con,1);


} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
System.out.println("Main Exception");
e.printStackTrace();
try {
con.close();
} catch (SQLException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}

return;
}
}
private String sample = "Start value";

//Access sample property
public String getSample() {
return sample;
}
public boolean mysql2SqlServlerTransform() {
return false;
}

}

class TestSZThread extends Thread {
Connection con = null;
long sleepMillSec = 0;
public TestSZThread(Connection con, long sleepMillSec) {
this.con = con;
try {
if(con.isClosed()) System.out.println("Connection closed1");
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
this.sleepMillSec = sleepMillSec;
this.start();
}

public void run() {
while (true) {
try {
if(con.isClosed()) System.out.println("Connection closed1");
PreparedStatement stmt = con
.prepareStatement("update info.t_userinfo set marktid=? where subscrbid='U010000035'");
stmt.setString(1, "SZ");
stmt.executeUpdate();
stmt.close();
System.out.println("update to SZ " + ++TestOracle.i);
} catch (Exception e) {
System.out.println("SZ Exception "+TestOracle.i);
e.printStackTrace();
break;
}

try {
Thread.sleep(sleepMillSec);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}

class TestHKThread extends Thread {
Connection con = null;
long sleepMillSec = 0;
public TestHKThread(Connection con, long sleepMillSec) {
this.con = con;
this.sleepMillSec = sleepMillSec;
this.start();
}

public void run() {
while (true) {
try {
PreparedStatement stmt = con
.prepareStatement("update info.t_userinfo set marktid=? where subscrbid='U010000035'");
System.out.println("update to HK "+ ++TestOracle.i);
stmt.setString(1, "HK");
stmt.executeUpdate();
stmt.close();

} catch (Exception e) {
System.out.println("HK Exception "+TestOracle.i);
e.printStackTrace();
break;
}

try {
Thread.sleep(sleepMillSec);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
...全文
2055 11 打赏 收藏 转发到动态 举报
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
oneonone 2005-03-17
  • 打赏
  • 举报
回复
无论如何, 一个connection上是可以同时执行statement的.
allenhe 2005-03-17
  • 打赏
  • 举报
回复
oneonone():
rollback也是同步的,不要多此一举。

treeroot(旗鲁特):
你说的这种情况一般来说在Oracle上只有通过锁表实现,因为各个数据库不同嘛,所以这个和同步已经没有多大关系了。
即便是Thread1,Thread2用2个Connection来做操作
假设插入的是同一个数据
如果顺序是412356
也是一样报错。
但是我想你不能用这个来证明不能同时执行不同的sql。逻辑错误应该是由程序员承担的说。
treeroot 2005-03-16
  • 打赏
  • 举报
回复
同步有什么用???
这个道理很浅显!!

Thread 1:
delete(); 1
insert(); 2
commit(); 3

Thread 2:
delete(); 4
insert(); 5
rollback();6


假设顺序是 124356
Thread 1:希望的结果是对的
Thread 2:应该什么都没做的,delete被Thread1 提交了,显然是逻辑上的错误!





oneonone 2005-03-16
  • 打赏
  • 举报
回复
class12.jar, ojdbc14.jar我都把反编译了

其中的commit方法前都加上了synchronized关键字,但是这样只能保证两个线程必须同步地调用commit方法, 而不能保证两个线程不会分别同时执行commit和rollback.

所以我认为必须在我们自己的应用里面加上
synchronized(con){
conection.commit();
}
synchronized(con){
conection.rollback();
}

即便如此,还是可以说一个connection上可以同时执行不同的sql语句. 因为在反编译后的PreparedStatement.executeUpdate()方法中存在着synchronized:


public int executeUpdate()
throws SQLException
{
label0:
{
int i;
synchronized(connection)
{
synchronized(this)
{
allenhe 2005-03-15
  • 打赏
  • 举报
回复
补充点,刚才也看了mysql driver的src,从java语义来说,一般都提供了同步,保证不会出错。
但是数据的同步方面,显然应该通过锁表等等来完成,和这个无关。
allenhe 2005-03-15
  • 打赏
  • 举报
回复
尝试回答下。
假设conn的自动提交设置为false.
那么产生的多个Statement如何保证同步,比如线程1希望提交,线程2希望回滚!

----
回答:
首先有一个前提,就是数据库方面的对线程1,2的操作不考虑在内,我们只谈java方面的
我的回答是应该是同步的。
具体的我想也不用太详细说明,以Oracle为例,反编译class12.jar。在oracle.jdbc.driver.OracleConnection里面,commit是加了
synchronized关键字了
再看创建Statement,是调用private Statement privateCreateStatement(int i, int j)
在代码可以看见,无论如何都是new出一个statement的,虽然至此已经可以结束了,
不过在oracle.jdbc.driver.OracleStatement中的executeQuery等方法中
都加了synchronized(connection) {
synchronized(this) {
这样的对象锁,应该说没有问题了。
zxmzfbdc 2005-03-14
  • 打赏
  • 举报
回复
一个connection的确可以创建多个Statement,至于线程的同步,在这里不但和线程有关系,还和数据库的工作方式有关系。
treeroot 2005-03-14
  • 打赏
  • 举报
回复
我问楼主这样一个问题,假设conn的自动提交设置为false.
那么产生的多个Statement如何保证同步,比如线程1希望提交,线程2希望回滚!
结果到底如何??
oneonone 2005-03-14
  • 打赏
  • 举报
回复
synchronized(con){
conection.commit();
}


synchronized(con){
conection.rollback();
}

同步和同时应该不是一个意思吧

我有点不太明白这个题目到底在考什么.
oneonone 2005-03-13
  • 打赏
  • 举报
回复
此题是多选题,题目描述不太清楚
我认为
a 正确
b 正确 考 connection.setAutoCommit(true);
c 错误
d 正确 存在可更新的ResultSet
oneonone 2005-03-13
  • 打赏
  • 举报
回复
我的问题来源于这样一道题目

2. 关于jdbc正确说法:

A 在一个connection上可以创建多个Statement 并且同时执行不同的SQL语句
B 通过设置一个connection属性就可以做一个数据库事务
C 通过设置一个Statement属性就可以做一个数据库事务
D 可以直接在在线结果集Resuleset中更新数据库记录

62,612

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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