Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

调用Informix数据库存储过程, 当存储过程抛出异常后, 再次调用此存储过程一直报错 #1498

Closed
imfuxiao opened this issue Nov 21, 2016 · 6 comments
Labels
Milestone

Comments

@imfuxiao
Copy link

最近项目中后台使用Informix数据库, 某次测试发现, 当存储过程抛出异常后, 再次调用此存储过程一直报错.

此存储过程参数中有一个String类型参数, 在过程内, 会将此参数转为Int类型.

在反向测试的时候, 故意输入了一些字母, 强制转换int后, 存储过程会抛出异常.

java.sql.SQLException: A character to numeric conversion process failed

此时在正向测试, 输入参数正确的情况下, 继续抛出异常:

java.sql.SQLException: Invalid cursor received by sqlexec.

此时不论怎么调用此存储过程都会报错. 但调用其他存储过程不会报错.

开始以为是自己代码错误, 排查后不是, 直接使用JDBC连接调用, 一切正常, 使用DBCP数据源测试, 也正常. 不知道到问题出在duird的哪里.

debug:
报错点一直在: DruidPooledPreparedStatement类的227行: ResultSet rs = stmt.executeQuery();

框架使用的是Spirng4.3.2版本

dao层调用大致代码如下:

   // 开始是用JDBCTemplate对象, 排查错误的时候, 直接使用dataSource了
    @Autowired
    @Qualifier("dataSource")
    private DataSource dataSource;


    /**
     * 调用存储过程 获取存储过程返回值,
     *
     * @param name   存储过程名称
     * @param params 存储过程参数
     * @param <T>    参数类型泛型
     *
     * @return 存储过程返回值: 返回值为Map集合, key为行号, 从数字1开始, value是列的Map集合, 其中key为列号, 从数字1开始. value为列对应的值,
     * 这里统一封装为String类型.
     */
    @Override
    public <T> Optional<Map<Integer, Map<Integer, String>>> procedure(String name, Collection<T> params) {

        if (name == null) return Optional.empty();
        if (params == null) return Optional.empty();
        final String sql = getSql(name, params.size());
        logger.debug(() -> "informix procedure sql : " + sql);

        try (Connection conn = this.dataSource.getConnection();
             CallableStatement cs = conn.prepareCall(sql)
        ) {
            Object[] paramsArray = params.toArray();
            IntStream.range(0, params.size()).forEach(index -> {
                logger.debug(() -> "Informix procedure sql param: " + (index + 1) + " = " + paramsArray[index]);
                try {
                    cs.setObject(index + 1, paramsArray[index]);
                } catch (SQLException e) {
                    logger.error(LogUtil.expInfoToString(e));
                    throw new RuntimeException(e);
                }
            });

           // debug时发现此处在调用: DruidPooledPreparedStatement类217行executeQuery方法, 然后一直在此方法的 ResultSet rs = stmt.executeQuery(); 会一直报错.
            try (ResultSet rs = cs.executeQuery()) {
                ImmutableMap.Builder<Integer, Map<Integer, String>> builder = ImmutableMap.builder();
                while (rs.next()) {
                    ImmutableMap.Builder<Integer, String> columns = ImmutableMap.builder();
                    IntStream.range(1, rs.getMetaData().getColumnCount() + 1).forEach(index -> {
                        try {
                            columns.put(index, Strings.nullToEmpty(rs.getString(index)));
                        } catch (SQLException e) {
                            logger.error(LogUtil.expInfoToString(e));
                            throw new RuntimeException(e);
                        }
                    });

                    builder.put(rs.getRow(), columns.build());
                }
                return Optional.of(builder.build());
            } catch (SQLException sqlExp) {
                logger.error(LogUtil.expInfoToString(sqlExp));
                throw new RuntimeException(sqlExp);
            }
        } catch (SQLException e) {
            logger.error(LogUtil.expInfoToString(e));
            throw new RuntimeException(e);
        }
    }
@wenshao wenshao added the Bug label Nov 23, 2016
@wenshao wenshao added this to the 1.0.27 milestone Nov 23, 2016
@wenshao
Copy link
Member

wenshao commented Nov 23, 2016

这个应该是因为PSCache引起的,我尽快处理吧

@wenshao
Copy link
Member

wenshao commented Nov 23, 2016

94638ad

@wenshao
Copy link
Member

wenshao commented Nov 26, 2016

已经修复,请使用1.0.27版本 https://github.com/alibaba/druid/releases/tag/1.0.27

@wenshao wenshao closed this as completed Nov 26, 2016
@imfuxiao
Copy link
Author

你好, 这个问题没有彻底修改好. 每次存储过程异常, 第一次调用都会报: 'Statement' already closed. 具体异常栈信息:

Caused by: java.sql.SQLException: 'Statement' already closed.
	at com.informix.util.IfxErrMsg.getSQLException(Unknown Source)
	at com.informix.jdbc.IfxPreparedStatement.setObject(Unknown Source)
	at com.alibaba.druid.filter.FilterChainImpl.preparedStatement_setObject(FilterChainImpl.java:2923)
	at com.alibaba.druid.filter.FilterAdapter.preparedStatement_setObject(FilterAdapter.java:1298)
	at com.alibaba.druid.filter.FilterChainImpl.preparedStatement_setObject(FilterChainImpl.java:2920)
	at com.alibaba.druid.proxy.jdbc.PreparedStatementProxyImpl.setObject(PreparedStatementProxyImpl.java:411)
	at com.alibaba.druid.pool.DruidPooledPreparedStatement.setObject(DruidPooledPreparedStatement.java:476)

digitalsonic added a commit to digitalsonic/druid that referenced this issue Feb 23, 2017
While the pooled PreparedStatement threw an exception, remove it from
the pool, and then close it.

The commit 94638ad didn’t fix issue alibaba#1498 . Try this one.
@cqlala
Copy link

cqlala commented Mar 20, 2017

do you have solve it, we have recurrence in 1.0.28 @wenshao

@AVANZHAOYONG
Copy link

The problem remains in druid-1.1.16 。apache/incubator-seata#2797 (comment)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants