只执行 预准备语句的executeUpdate方法, 但没有提交事务 ,为什么 也能对数据库更新??

时间:2022-09-08 14:51:33
向各位高手请教(初级问题 莫要见笑)
	public void insert() throws Exception {
// 得到数据库连接
Connection con = DbUtil.connectToDb();
PreparedStatement pStmt = null;
try {
pStmt = con
.prepareStatement("INSERT INTO "
+ Constants.TABLENAME
+ " (addressbookId,addressbookName,addressbookPhone,addressbookAddress)"
+ " values(?,?,?,?)");
con.setAutoCommit(false);
pStmt.setInt(1, addressbookId);
pStmt.setString(2, addressbookName);
pStmt.setString(3, addressbookPhone);
pStmt.setString(4, addressbookAddress);
pStmt.executeUpdate();
//con.commit();

              } catch (Exception ex) {
try {
con.rollback();
} catch (SQLException sqlex) {
sqlex.printStackTrace(System.out);
}
throw ex;
} finally {
try {
DbUtil.releaseConnection(con, pStmt);
} catch (Exception e) {
e.printStackTrace();
}
}


标红的代码将 commit 注释掉后,依然可以向数据库插入数据,原因是什么? jdbc 中  怎样进行事物的开启?
能帮我解答一下吗? 谢谢

20 个解决方案

#1


该回复于2015-05-26 11:15:22被管理员删除

#2


 pStmt.executeUpdate();

被调用 就会执行sql语句  insert();

#3


该回复于2008-07-10 16:09:19被版主删除

#4


不可能有这样的问题啊。。。

没发现你哪写错  只是AUTOCOMMIT用完后没设回默认值

#5


jdbc启动事务:
Transaction transaction = session.beginTransaction();
一般在try块里面实现了,结束后关闭就可以了:
transaction.close;
你的问题可能是:jdbc的事务隔离级别的,你不妨试试隔离级别的设置。也许管点用,我也不大肯定这方面的,做个参考。

#6


con.setAutoCommit(false);放到prepareStatement前面去

#7


关注中

#8


Connection con =null;
String sql1  = "insert into (a,b,c,d)values(?,?,?,?)";
// String sql2 = "update user set name ="adb" where id =1 ";
PreparedStatement pstmt =con.prepareStatement(sql1);
// pstmt.addBatch(sql1);
// pstmt.addBatch(sql2);
con.setAutoCommit(false);

pstmt.setInt(1, 90);
pstmt.setString(2,"preparedstatement");
pstmt.setBoolean(3,false);
pstmt.setDouble(4,6.7);
pstmt.executeUpdate();

con.commit();
con.setAutoCommit(true);

#9


按照六楼说的 还是 可以和数据库交互

#10


谢谢 5楼 提醒 你不说 我还不知道 隔离级的概念呢 (莫笑 莫笑)
查了一下资料  关于 隔离级 的简介 
如下
如果 DBMS 支持事务处理,它必须有某种途径来管理两个事务同时对一个数据库进行操作时可能发生的冲突。用户可指定事务隔离级别,以指明 DBMS 应该花多大精力来解决潜在冲突。例如,当事务更改了某个值而第二个事务却在该更改被提交或还原前读取该值时该怎么办? 假设第一个事务被还原后,第二个事务所读取的更改值将是无效的,那么是否可允许这种冲突? JDBC 用户可用以下代码来指示 DBMS 允许在值被提交前读取该值(“dirty 读取”),其中 con 是当前连接: 

    con.setTransactionIsolation(TRANSACTION_READ_UNCOMMITTED);

事务隔离级别越高,为避免冲突所花的精力也就越多。Connection 接口定义了五级,其中最低级别指定了根本就不支持事务,而*别则指定当事务在对某个数据库进行操作时,任何其它事务不得对那个事务正在读取的数据进行任何更改。通常,隔离级别越高,应用程序执行的速度也就越慢(由于用于锁定的资源耗费增加了,而用户间的并发操作减少了)。在决定采用什么隔离级别时,开发人员必须在性能需求和数据一致性需求之间进行权衡。当然,实际所能支持的级别取决于所涉及的 DBMS 的功能。

当创建 Connection 对象时,其事务隔离级别取决于驱动程序,但通常是所涉及的数据库的缺省值。用户可通过调用 setIsolationLevel 方法来更改事务隔离级别。新的级别将在该连接过程的剩余时间内生效。要想只改变一个事务的事务隔离级别,必须在该事务开始前进行设置,并在该事务结束后进行复位。我们不提倡在事务的中途对事务隔离级别进行更改,因为这将立即触发 commit 方法的调用,使在此之前所作的任何更改变成永久性的。



程序中 隔离级 为 2 
谢谢 回复我帖子的 好心人

#11


引用 2 楼 huangyangweiyue 的回复:
pStmt.executeUpdate(); 

被调用 就会执行sql语句  insert(); 

#12


close
void close()
           throws SQLException立即释放此 Connection 对象的数据库和 JDBC 资源,而不是等待它们被自动释放。 
在已经关闭的 Connection 对象上调用 close 方法无操作 (no-op)。 

建议最好在调用 close 方法之前,应用程序显式提交或回滚一个活动事务。如果调用 close 方法并且有一个活动事务,那么结果将由实现定义。

抛出: 
SQLException - 如果发生数据库访问错误



如果调用 close 方法并且有一个活动事务,那么结果将由实现定义。 

应该是在调用close() 方法的时候,自动进行了事务的提交了.具体要看你用的数据库驱动是怎么实现close() 方法的.

#13


感谢 2 楼 11 楼 回帖 
 正如 所说 
pStmt.executeUpdate(); 
被调用 就会执行sql语句  insert(); 
执行sql语句  insert()  而不提交事务 数据库会有 交互吗?
事务 的概念  我浅显的理解 就是 N (n>=1)条 sql  的执行  只有事务提交后  数据库的数值 才真正 改变.

 不知道 理解的正确不正确  请 热心人 指教 稍晚 我会 再查一些资料 贴上来。

#14


感谢 12楼 回帖 
下面 是 连接数据库的 工具类
 

public class DbUtil {
static String driverName = "oracle.jdbc.driver.OracleDriver";

static String dbUrl = "jdbc:oracle:thin:@172.16.1.12:1521:ORCL";

public static String user = "test";

public static String password = "test";

public DbUtil() {

}

public static Connection connectToDb() {

try {
Class.forName(driverName);
return DriverManager.getConnection(dbUrl, user, password);
} catch (ClassNotFoundException e) {
e.printStackTrace();
return null;
} catch (SQLException e) {
e.printStackTrace();
return null;
}
}

public static void releaseConnection(Connection conn, Statement st,
ResultSet rs) {

if (rs != null) {
try {
rs.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (st != null) {
try {
st.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

public static void releaseConnection(Connection conn, Statement st) {

if (st != null) {
try {
st.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
我的推测 和 12 楼 的有些相似
可能 是在 释放资源  在这里 可能 是 连接池 也可能 是 预准备语句 
默认 提交 事务 
但是
下面的问题是 
那事务的开启呢?
代码里并没有 明显的 事务开启 的 语句?
再次 感谢 大家对菜鸟的指点

#15


con.commit();是自己手动提交事务   
  con.setAutoCommit(true);是让JDBC自动提交事务。   
  con.rollback();是取消提交回滚数据   
    
  如果con.setAutoCommit(true),在对数据库操作后,数据已真实的更新到数据库里,不需要再用commit,此时调用con.rollback()也不起用了   
    
  如果设成false,那就是JDBC不自动提交,需要手动的使用commit或者rollback来进行提交或者回滚数据.   
    
  查询的时候是不需要进行事务控制的,只要在对数据库多个不同数据需要同步处理的时候才需要事务控制.比如银行取款,他必须有一个取款记录和帐户变化记录一起发生,单独发生一个是不行的,这时候就可以设成false,在两个操作都完成以后使用commit来一起提交.如果其中一个出现问题了,那就直接用rollback把两个都进行回滚,以保证数据一直性

#16


try   {   
              con   =   ConnectionManager.getConnction();   
              con.setAutoCommit(false);//false是什么意思     --设定不自动提交,即只有commit才生效   
     ....   
              pStatement.executeUpdate();   
              con.commit();//commit是什么意思       --提交使在操作在数据库中生效,其他事物可见刚才所做的操作   
              con.setAutoCommit(true);//这里又来个true又是什么意思     --设定自动提交,每次执行自动commit   
    
          }   catch   (SQLException   sqlE)   {   
              sqlE.printStackTrace();   
              try   {   
                  con.rollback();//是不是当操作失败的时就回滚呀     --当设为false时有用,失败回滚   
    
              }   catch   (Exception   e)   {   
                  e.printStackTrace();   
              }   
          }   finally   {   
              try   {   
                      pStatement.close();   
                    con.close();   
              }   catch   (SQLException   e)   {   
                  e.printStackTrace();   
              }   
    
          }       }  

#17


15 楼费心了

在 我 第一次 提出的代码 中 以有语句
            con.setAutoCommit(false);
为什么 还会 不进行事务 提交 就交互数据库
是不是 就因为 压根儿没有 开启事务

 

#18


引用 17 楼 nttwbd 的回复:
15 楼费心了 

在 我 第一次 提出的代码 中 以有语句 
            con.setAutoCommit(false); 
为什么 还会 不进行事务 提交 就交互数据库 
是不是 就因为 压根儿没有 开启事务 


有没有看12楼?
你别close() 看看会不会导致新增一条记录。如果没有,那肯定就是在close()的时候,进行了事务的提交了。

#19


12 楼 不好意思

如你所说 结账去

再次感谢  

#20


 pStmt.executeUpdate();~~~

#1


该回复于2015-05-26 11:15:22被管理员删除

#2


 pStmt.executeUpdate();

被调用 就会执行sql语句  insert();

#3


该回复于2008-07-10 16:09:19被版主删除

#4


不可能有这样的问题啊。。。

没发现你哪写错  只是AUTOCOMMIT用完后没设回默认值

#5


jdbc启动事务:
Transaction transaction = session.beginTransaction();
一般在try块里面实现了,结束后关闭就可以了:
transaction.close;
你的问题可能是:jdbc的事务隔离级别的,你不妨试试隔离级别的设置。也许管点用,我也不大肯定这方面的,做个参考。

#6


con.setAutoCommit(false);放到prepareStatement前面去

#7


关注中

#8


Connection con =null;
String sql1  = "insert into (a,b,c,d)values(?,?,?,?)";
// String sql2 = "update user set name ="adb" where id =1 ";
PreparedStatement pstmt =con.prepareStatement(sql1);
// pstmt.addBatch(sql1);
// pstmt.addBatch(sql2);
con.setAutoCommit(false);

pstmt.setInt(1, 90);
pstmt.setString(2,"preparedstatement");
pstmt.setBoolean(3,false);
pstmt.setDouble(4,6.7);
pstmt.executeUpdate();

con.commit();
con.setAutoCommit(true);

#9


按照六楼说的 还是 可以和数据库交互

#10


谢谢 5楼 提醒 你不说 我还不知道 隔离级的概念呢 (莫笑 莫笑)
查了一下资料  关于 隔离级 的简介 
如下
如果 DBMS 支持事务处理,它必须有某种途径来管理两个事务同时对一个数据库进行操作时可能发生的冲突。用户可指定事务隔离级别,以指明 DBMS 应该花多大精力来解决潜在冲突。例如,当事务更改了某个值而第二个事务却在该更改被提交或还原前读取该值时该怎么办? 假设第一个事务被还原后,第二个事务所读取的更改值将是无效的,那么是否可允许这种冲突? JDBC 用户可用以下代码来指示 DBMS 允许在值被提交前读取该值(“dirty 读取”),其中 con 是当前连接: 

    con.setTransactionIsolation(TRANSACTION_READ_UNCOMMITTED);

事务隔离级别越高,为避免冲突所花的精力也就越多。Connection 接口定义了五级,其中最低级别指定了根本就不支持事务,而*别则指定当事务在对某个数据库进行操作时,任何其它事务不得对那个事务正在读取的数据进行任何更改。通常,隔离级别越高,应用程序执行的速度也就越慢(由于用于锁定的资源耗费增加了,而用户间的并发操作减少了)。在决定采用什么隔离级别时,开发人员必须在性能需求和数据一致性需求之间进行权衡。当然,实际所能支持的级别取决于所涉及的 DBMS 的功能。

当创建 Connection 对象时,其事务隔离级别取决于驱动程序,但通常是所涉及的数据库的缺省值。用户可通过调用 setIsolationLevel 方法来更改事务隔离级别。新的级别将在该连接过程的剩余时间内生效。要想只改变一个事务的事务隔离级别,必须在该事务开始前进行设置,并在该事务结束后进行复位。我们不提倡在事务的中途对事务隔离级别进行更改,因为这将立即触发 commit 方法的调用,使在此之前所作的任何更改变成永久性的。



程序中 隔离级 为 2 
谢谢 回复我帖子的 好心人

#11


引用 2 楼 huangyangweiyue 的回复:
pStmt.executeUpdate(); 

被调用 就会执行sql语句  insert(); 

#12


close
void close()
           throws SQLException立即释放此 Connection 对象的数据库和 JDBC 资源,而不是等待它们被自动释放。 
在已经关闭的 Connection 对象上调用 close 方法无操作 (no-op)。 

建议最好在调用 close 方法之前,应用程序显式提交或回滚一个活动事务。如果调用 close 方法并且有一个活动事务,那么结果将由实现定义。

抛出: 
SQLException - 如果发生数据库访问错误



如果调用 close 方法并且有一个活动事务,那么结果将由实现定义。 

应该是在调用close() 方法的时候,自动进行了事务的提交了.具体要看你用的数据库驱动是怎么实现close() 方法的.

#13


感谢 2 楼 11 楼 回帖 
 正如 所说 
pStmt.executeUpdate(); 
被调用 就会执行sql语句  insert(); 
执行sql语句  insert()  而不提交事务 数据库会有 交互吗?
事务 的概念  我浅显的理解 就是 N (n>=1)条 sql  的执行  只有事务提交后  数据库的数值 才真正 改变.

 不知道 理解的正确不正确  请 热心人 指教 稍晚 我会 再查一些资料 贴上来。

#14


感谢 12楼 回帖 
下面 是 连接数据库的 工具类
 

public class DbUtil {
static String driverName = "oracle.jdbc.driver.OracleDriver";

static String dbUrl = "jdbc:oracle:thin:@172.16.1.12:1521:ORCL";

public static String user = "test";

public static String password = "test";

public DbUtil() {

}

public static Connection connectToDb() {

try {
Class.forName(driverName);
return DriverManager.getConnection(dbUrl, user, password);
} catch (ClassNotFoundException e) {
e.printStackTrace();
return null;
} catch (SQLException e) {
e.printStackTrace();
return null;
}
}

public static void releaseConnection(Connection conn, Statement st,
ResultSet rs) {

if (rs != null) {
try {
rs.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (st != null) {
try {
st.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

public static void releaseConnection(Connection conn, Statement st) {

if (st != null) {
try {
st.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
我的推测 和 12 楼 的有些相似
可能 是在 释放资源  在这里 可能 是 连接池 也可能 是 预准备语句 
默认 提交 事务 
但是
下面的问题是 
那事务的开启呢?
代码里并没有 明显的 事务开启 的 语句?
再次 感谢 大家对菜鸟的指点

#15


con.commit();是自己手动提交事务   
  con.setAutoCommit(true);是让JDBC自动提交事务。   
  con.rollback();是取消提交回滚数据   
    
  如果con.setAutoCommit(true),在对数据库操作后,数据已真实的更新到数据库里,不需要再用commit,此时调用con.rollback()也不起用了   
    
  如果设成false,那就是JDBC不自动提交,需要手动的使用commit或者rollback来进行提交或者回滚数据.   
    
  查询的时候是不需要进行事务控制的,只要在对数据库多个不同数据需要同步处理的时候才需要事务控制.比如银行取款,他必须有一个取款记录和帐户变化记录一起发生,单独发生一个是不行的,这时候就可以设成false,在两个操作都完成以后使用commit来一起提交.如果其中一个出现问题了,那就直接用rollback把两个都进行回滚,以保证数据一直性

#16


try   {   
              con   =   ConnectionManager.getConnction();   
              con.setAutoCommit(false);//false是什么意思     --设定不自动提交,即只有commit才生效   
     ....   
              pStatement.executeUpdate();   
              con.commit();//commit是什么意思       --提交使在操作在数据库中生效,其他事物可见刚才所做的操作   
              con.setAutoCommit(true);//这里又来个true又是什么意思     --设定自动提交,每次执行自动commit   
    
          }   catch   (SQLException   sqlE)   {   
              sqlE.printStackTrace();   
              try   {   
                  con.rollback();//是不是当操作失败的时就回滚呀     --当设为false时有用,失败回滚   
    
              }   catch   (Exception   e)   {   
                  e.printStackTrace();   
              }   
          }   finally   {   
              try   {   
                      pStatement.close();   
                    con.close();   
              }   catch   (SQLException   e)   {   
                  e.printStackTrace();   
              }   
    
          }       }  

#17


15 楼费心了

在 我 第一次 提出的代码 中 以有语句
            con.setAutoCommit(false);
为什么 还会 不进行事务 提交 就交互数据库
是不是 就因为 压根儿没有 开启事务

 

#18


引用 17 楼 nttwbd 的回复:
15 楼费心了 

在 我 第一次 提出的代码 中 以有语句 
            con.setAutoCommit(false); 
为什么 还会 不进行事务 提交 就交互数据库 
是不是 就因为 压根儿没有 开启事务 


有没有看12楼?
你别close() 看看会不会导致新增一条记录。如果没有,那肯定就是在close()的时候,进行了事务的提交了。

#19


12 楼 不好意思

如你所说 结账去

再次感谢  

#20


 pStmt.executeUpdate();~~~

#21