java打开游标,Java-超出打开游标的最大数

java里每次打开一个statement对象jdbc都会在数据库中打开一个游标来执行操作,做完业务后必须马上关闭,否则一旦多次打开且不关闭就会造成ORA-01000: 超出打开游标的最大数错误,如果需要循环建立statement对象最后统一提交,可以在循环里执行完活动马上关闭,关闭后业务处于未提交状态,直到执行connection.commit事件时活动才会提交.

oracle数据库中open_cursors默认值为300,正常情况都够用了,出现ORA-01000错误基本都是有程序没关闭游标,多出现于java程序使用连接池连接数据库的情况下,打开了statement没关闭就把连接放回了连接池或者循环打开statement对象而不关闭,请仔细检查自己的程序代码

比如这段代码:

for (int j = 0; j < count; j++) {

DataObject d = dataObjects.get(j);

String sql = d.getSql();

statement = conn.prepareStatement(sql);

List dataCells = d.getDataArray();

if (d.getSheetType() == SheetType.EXT) {

batchExecExtSQL(d, statement, dataCells);

} else {

statement = conn.prepareStatement(sql);

for (int i = 0; i < dataCells.size(); i++) {

DataCell dataCell = dataCells.get(i);

Object val = dataCell.getValue();

setSqlValue(statement, dataCell.getDataType(), val, i + 1);

}

statement.execute();

}

}

} finally {

if (statement != null) {

//statement.clearBatch();

statement.close();

}

变成表多行数据插入,for循环中的statement是每次一个new对象,这个对象在数据库中会产生一个游标,finanlly最后实际只关闭了其中一个statement。剩下的只能交予jvm垃圾回收机制完成了。如果上上面代码改为:

PreparedStatement statement = null;

try {

Connection conn = session.connection();

// session.setFlushMode(FlushMode.ALWAYS);

// 并发测试希望有所提升,加入事务隔离级别(有部分作用),后期更改读操作的事务要素有效

// conn.setTransactionIsolation(TransactionDefinition.ISOLATION_READ_COMMITTED);

int count = dataObjects.size();

for (int j = 0; j < count; j++) {

DataObject d = dataObjects.get(j);

String sql = d.getSql();

statement = conn.prepareStatement(sql);

List dataCells = d.getDataArray();

if (d.getSheetType() == SheetType.EXT) {

batchExecExtSQL(d, statement, dataCells);

} else {

for (int i = 0; i < dataCells.size(); i++) {

DataCell dataCell = dataCells.get(i);

Object val = dataCell.getValue();

setSqlValue(statement, dataCell.getDataType(), val, i + 1);

}

statement.execute();

if (statement != null) {

statement.close();

}

}

}

} finally {

if (statement != null) {

statement.clearBatch();

statement.close();

}

}

这样就不会出现这种问题,而且这问题只有在并发操作或一个事务多操作下出现,一般小量会经过java回收,而且数据库游标也够用。

再看下面一段代码的写法,虽然是批处理,但是不符合Java JDBC操作的规范,同样会导致游标不够的问题。

public void batchExecSqlWithArray(final String Insertsql,

final List dataObjects) throws SQLException {

this.getHibernateTemplate().execute(new HibernateCallback() {

@SuppressWarnings("deprecation")

public Object doInHibernate(Session session) throws HibernateException, SQLException {

PreparedStatement statement = null;

try {

Connection conn = session.connection();

int count = dataObjects.size();

for (int j = 0; j < count; j++) {

SystemLog log = dataObjects.get(j);

statement = conn.prepareStatement(Insertsql);

UUID uuids = UUID.randomUUID();

String uuid = uuids.toString().replaceAll("-", "");

statement.setString(1, uuid);

statement.setString(2, log.getIPAdress());

statement.setInt(3, log.getLogType().getId());

statement.setString(4, log.getLogdate());

statement.setString(5, log.getMemo());

statement.setString(6, log.getMessage());

statement.setInt(7, log.getModule().getId());

statement.setInt(8, log.getRelease());

statement.setString(9, log.getUserid());

statement.addBatch();

}

dataObjects.clear();

statement.executeBatch();

} finally {

if (statement != null) {

statement.clearBatch();

statement.close();

}

}

return null;

}

});

}

statement = conn.prepareStatement(Insertsql); 在for循环里面同样也是一种错误写法,应该是卸载外面只有一个对象。

数据库相关关闭连接资源比较常见,开发过程中发现的,引以为鉴……

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值