这样的错误,真的还是第一次看到,一时摸不到头脑了!不过在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)


问题探索:

上进行相关问题的检索,没有找到适合的解决方法,发生这个问题的主要原因是由于ODBC与Access的连接在执行一次操作时还没有完全释放时,再次给该连接发起了操作请求造成的。

Java程序通过JDBC ODBC桥的方式来访问Access数据库,该问题就会经常发生(可能和操作系统的某些机制相关,可能换一台计算机就不出现这个问题),原因是,JDBC ODBC桥通过Java的本地接口调用Windows操作系统的ODBC驱动管理器然后由ODBC访问Access数据库,真正实现了桥的功能;然而可能因为桥的两边在某个地方不同步(主要是操作请求),造成一个正在执行中的连接再次收到操作请求。

在Google上搜索到一个第三方的Access的JDBC驱动程序:HXTT Access JDBC3.0  使用这驱动程序没有出现“不能更新;当前正在被机器 '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;
    }