这样的错误,真的还是第一次看到,一时摸不到头脑了!不过在Google中搜索一会找到了一篇不错的解决方法!如下:(谢谢本文的作者)
先声明这不是我们编程的错误,因为如果再次(再再次)提交的话就会成功的插入或修改数据的。
问题描述:
在使用JDBC ODBC连接MS Access数据库时,插入Insert或更新Update数据时经常会发生如下错误:
java.sql.SQLException: [Microsoft][ODBC Microsoft Access Driver] 不能更新;当前正在被机器 'SN0101' 上的用户 'admin' 锁定。
at sun.jdbc.odbc.JdbcOdbc.createSQLException(JdbcOdbc.java:6958)
at sun.jdbc.odbc.JdbcOdbc.standardError(JdbcOdbc.java:7115)
at sun.jdbc.odbc.JdbcOdbc.SQLExecute(JdbcOdbc.java:3150)
at sun.jdbc.odbc.JdbcOdbcPreparedStatement.execute(JdbcOdbcPreparedStatement.java:214)
at sun.jdbc.odbc.JdbcOdbcPreparedStatement.executeUpdate(JdbcOdbcPreparedStatement.java:136)
at com.snsoft.aest.Untitled1.saveDownloadData(Untitled1.java:79)
at com.snsoft.aest.Untitled1.main(Untitled1.java:28)
问题探索:
在www.baidu.com和www.google.com上进行相关问题的检索,没有找到适合的解决方法,发生这个问题的主要原因是由于ODBC与Access的连接在执行一次操作时还没有完全释放时,再次给该连接发起了操作请求造成的。
Java程序通过JDBC ODBC桥的方式来访问Access数据库,该问题就会经常发生(可能和操作系统的某些机制相关,可能换一台计算机就不出现这个问题),原因是,JDBC ODBC桥通过Java的本地接口调用Windows操作系统的ODBC驱动管理器然后由ODBC访问Access数据库,真正实现了桥的功能;然而可能因为桥的两边在某个地方不同步(主要是操作请求),造成一个正在执行中的连接再次收到操作请求。
在Google上搜索到一个第三方的Access的JDBC驱动程序:HXTT Access JDBC3.0 参阅:www.hxtt.com 使用这驱动程序没有出现“不能更新;当前正在被机器 'XXX' 上的用户 'admin' 锁定”问题,不过这个JDBC驱动程序需要付费,Free版只允许50个查询(一次),多余50个查询的操作将失败,付费后可去掉限制,但对于我们来说100多欧元的价格太多了。
“自己动手、丰衣足食”在经过N次失败后,不断摸索经验,曾试过“ODBC数据源”方式(这个有点儿傻,JDBC ODBC就是调用的Windows的数据源,因此如果是用JDBC ODBC桥的话,建数据源无济于事);换不同的Access驱动(在Google、BaiDu中查阅最后的答案是Access的三种驱动Microsoft Access Driver (*.mdb)、Driver do Microsoft Access (*.mdb)和Microsoft Access-Treiber (*.mdb)类似,没有什么差别只是语法问题);最后想到一个方法,延时等ODBC完全完成操作再请求下一次操作,这个方法降低了程序整体速度和数据吞吐量,但基本解决问题。
经验解决:
(1)一次Connection连接,尽可能多的执行操作(插入、更新),如果能使用批处理的话,最好使用批处理;
(2)释放一个Connection连接后让程序(或循环)暂停100毫秒以上,然后在取得连接执行下一组操作。
注:在CPU P4 2.4G 内存1G的环境下测试过,如果硬件环境较差,增大暂停时间,一定要在释放连接后进入暂停状态,让Java程序Sleep一段时间。
// 示例代码
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public static void main(String[] args) {
Untitled1 u=new Untitled1();
XmlRecordSetParser parser=new XmlRecordSetParser();
try {
for(int i=0;i<100;i++){
parser.parse(new File("cesdowninfo.xml"));
XmlRecordSet record = parser.getXmlRecordSet();
u.saveDownloadData(record);
System.out.println(i+1);
Thread.sleep(100);
}
System.out.print("============OK===================");
}
catch (Exception ex) {
ex.printStackTrace();
}
}
/**
*
* @param record XmlRecordSet
* @return boolean
*/
public boolean saveDownloadData(XmlRecordSet record){
boolean result=false;
Connection conn=getConnection();
PreparedStatement stem=null;
try {
stem = conn.prepareStatement("insert into SN_CUSTOM_ES_DAT (MD5_VALUE,COLUMN_NAME,COLUMN_ID,INFO_TITLE,INFO_CONTENT,INFO_FROM,CREATE_USER,INFO_TYPE,INFO_ID,IS_LCOCAL) values(?,?,?,?,?,?,?,?,?,?)");
if(record!=null) {
while (record.next()) {
stem.setString(1,record.getString("md5"));
stem.setString(2,record.getString("Cid"));
stem.setString(3,record.getString("Column"));
stem.setString(4,record.getString("Title"));
stem.setString(5,record.getString("Content"));
stem.setString(6,record.getString("Form"));
stem.setString(7,record.getString("Author"));
stem.setInt(8,0);
stem.setInt(9,record.getInteger("ID"));
stem.setInt(10,0);
//result=(stem.executeUpdate()==1);
stem.addBatch();
}
stem.executeBatch();
}
}
catch (SQLException ex) {
ex.printStackTrace();
}
finally{
try {
if (stem !=null) stem.close();
if (conn !=null) freeConnection(conn);
}catch (SQLException ex) {
}
}
return result;
}