iBatis批量插入失败,出现套接字写入错误

时间:2011-09-06 10:22:40

标签: java jboss ibatis

在过去的几天里,我面临一个相当令人沮丧的问题。我试图通过使用iBatis批量插入来提高性能。但是我发现批量插入失败并出现以下错误之一 - java.sql.BatchUpdateException:IO错误:软件导致连接中止:套接字写入错误 - java.sql.BatchUpdateException:ORA-12161:TNS:内部错误:收到的部分数据 - java.sql.BatchUpdateException:IO错误:软件导致连接中止:recv失败

设置细节如下 - 应用程序服务器是Jboss 5.0.1 - iBatis 2.3.4.732.1 - 春季2.5.6

我的批量插入代码如下

    try
    {
        final String finalStatement = statementName;
        int size = parameterList.size();
        int batchSize = 100;

        for(int ii=0; ii < size;)
        {
            int toIndex = ((ii + batchSize) > size ? size : (ii+batchSize));

            final List<Object> subList = parameterList.subList(ii, toIndex);
            ii += batchSize;
            count = getSqlMapClientTemplate().execute(new SqlMapClientCallback() 
            {
                public Object doInSqlMapClient(SqlMapExecutor executor) throws SQLException 
                {
                    executor.startBatch();
                    for(Object finalParameterObject : subList)
                    {                   
                        executor.insert(finalStatement, finalParameterObject);
                    }
                    Integer retCount = new Integer(executor.executeBatch());
                    return retCount;
                }
            });                       
        }

这偶尔会起作用,而在其他时候会出现上述错误之一。 我们正在使用连接池,并且我确保阻塞超时毫秒足够高,尽管我不相信这个值在这里引起了问题。 我已经禁用了防火墙,但仍然看到了同样的问题。 在我看来,连接正在被数据库终止,我通过警报日志(我们正在使用oracle),但没有看到该日志文件上的任何错误。看起来这是一个配置问题,但我不确定需要改变什么,因为我已经尝试了我能想到的一切。 我有什么遗漏的东西吗?

编辑 - 如果我在上面的代码中批量大小为10(batchSize = 10),那么批量插入工作正常。

1 个答案:

答案 0 :(得分:0)

无法发表评论,答案基于一些假设:

您使用的是ibatis 2.3还是3.x?如果它是2.3,你是将jdbcType设置为NUMERIC但支持java字段是Double / double吗?或ibatis映射中实际java类型和jdbc类型之间的类似不匹配?

我遇到了与ibatis 2.3,spring-orm和postgresql类似的批处理套接字死锁问题。打开Postgresql JDBC驱动程序的调试日志记录后,找到一批假设为一个的批量解析消息。事实证明,ibatis在同一列上为null值/ not null值设置了不同的jdbc类型。根本原因是ibatis映射将一个参数的jdbcType作为数字但对应的java类型为Double。

通过ibatis的ParameterMap步骤#setParameter(PreparedStatement,ParameterMapping,Object [],int),你会发现当值为null时,ibatis将使用jdbcType从你的映射读取setNull。当值不为null时,它将使用typeHandler来设置值。如果没有提供自定义类型处理程序,则typeHandler由TypeHandlerFactory#getTypeHandler(类类型,字符串jdbcType)确定。它由java类型而不是jdbcType驱动。