6
回答
JFinal 1.4 + druid 0.2.26 model.save()保存怪事
终于搞明白,存储TCO原来是这样算的>>>   
//方法1,用model.save()方式。
	private void saveClickNum(Integer type,Long click_pkid,Integer click_num){
		SysClick sc = new SysClick().set("click_id", "s_system_click.nextval").set("click_type", type).set("click_pkid", click_pkid).set("click_num", click_num).set("click_date", "to_char(sysdate,'yyyy-MM-dd')");
		sc.save();
	}
	//方法2,用Db.update()方式
	private void insertClickNum(Integer type,Long click_pkid,Integer click_num){
		String sql = "insert into t_system_click (click_id,click_type,click_pkid,click_num,click_date)values(s_system_click.nextval,?,?,?,to_char(sysdate,'yyyy-MM-dd'))";
		Db.update(sql, type,click_pkid,click_num);
	}
	
	public void test1 (){
		for(int i=0;i<3;i++){
			saveClickNum(1,1L,i);
		}
	}
	public void test2 (){
		for(int i=0;i<3;i++){
			insertClickNum(1,1L,i);
		}
	}

调用test2都可以成功入库。

调用test1时,只有第一次(i=0)时能入库,第二次开始就会报错:

com.jfinal.plugin.activerecord.ActiveRecordException: java.sql.SQLException: 索引中丢失  IN 或 OUT 参数:: 5
    at com.jfinal.plugin.activerecord.Model.save(Model.java:298)
    at net.evecom.web.core.service.VisitStatService.saveClickNum(VisitStatService.java:144)
    at net.evecom.web.core.service.VisitStatService._flush(VisitStatService.java:122)
    at net.evecom.web.core.service.VisitStatService.run(VisitStatService.java:86)
    at java.util.TimerThread.mainLoop(Timer.java:512)
    at java.util.TimerThread.run(Timer.java:462)
Caused by: java.sql.SQLException: 索引中丢失  IN 或 OUT 参数:: 5
    at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:112)
    at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:146)
    at oracle.jdbc.driver.OraclePreparedStatement.processCompletedBindRow(OraclePreparedStatement.java:1704)
    at oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedStatement.java:3280)
    at oracle.jdbc.driver.OraclePreparedStatement.executeUpdate(OraclePreparedStatement.java:3368)
    at com.alibaba.druid.filter.FilterChainImpl.preparedStatement_executeUpdate(FilterChainImpl.java:2721)
    at com.alibaba.druid.wall.WallFilter.preparedStatement_executeUpdate(WallFilter.java:592)
    at com.alibaba.druid.filter.FilterChainImpl.preparedStatement_executeUpdate(FilterChainImpl.java:2719)
    at com.alibaba.druid.filter.FilterAdapter.preparedStatement_executeUpdate(FilterAdapter.java:1069)
    at com.alibaba.druid.filter.FilterEventAdapter.preparedStatement_executeUpdate(FilterEventAdapter.java:491)
    at com.alibaba.druid.filter.FilterChainImpl.preparedStatement_executeUpdate(FilterChainImpl.java:2719)
    at com.alibaba.druid.proxy.jdbc.PreparedStatementProxyImpl.executeUpdate(PreparedStatementProxyImpl.java:145)
    at com.alibaba.druid.pool.DruidPooledPreparedStatement.executeUpdate(DruidPooledPreparedStatement.java:253)
    at com.jfinal.plugin.activerecord.Model.save(Model.java:292)
    ... 5 more

1。如果是参数不对,那第一次也无法入库吧。我下了druid源码,断点到com.alibaba.druid.pool.DruidPooledPreparedStatement.executeUpdate,查看参数,几次的参数个数,参数类型都是一样的,

2.如果使用C3P0做连接池,就不会出现这种情况。

举报
i十十
发帖于4年前 6回/802阅

以下是问题补充:

  • @i十十 :我用的数据库是oracle10.2 驱动:ojdbc14 (4年前)
共有6个答案 最后回答: 2年前

druid什么版本?你用druid-0.2.26试试看

--- 共有 5 条评论 ---
i十十回复 @wenshao : 你好,麻烦看下这个BUG怎么改。谢谢,实在不行我的项目只好用C3P0了 4年前 回复
wenshao@robin69 最近很忙,国庆期间再跟进 4年前 回复
i十十请问这个问题要怎么解决啊。算bug不? 4年前 回复
ddatsh真的有问题,0.2.26一样错 4年前 回复
红星xx怎么不认真看呢? 那么大的一个标题 4年前 回复

用简单的  NamedParameterJdbcTemplate 重现了,org.springframework.jdbc.datasource.DriverManagerDataSource OK,druid会错

oracle下

https://github.com/alibaba/druid/issues/453

ojdbc14 +DriverManagerDataSource OK

ojdbc14 +com.alibaba.druid.pool.DruidDataSource ERROR

ojdbc6 的话,都OK

但既然DriverManagerDataSource是OK的,所以应该还要从 druid下手修复


@JFinal这个问题在最新的JFinal中依然存在,我在ORACLE抓取了对应的SQL,发现后面有这么一截:insert into ghtc_task_ret(FUNC_RETDESC, FUNC_RETNUM, TASK_SEQ, RET_ID, EXEC_TIME, FUNC_NO, TASK_ID) values(:1, :2, :3, :4, :5, :6, :7) RETURNING ret_id INTO :8,注意RETURNING ret_id INTO :8这一段,问题应该就出在这里,当进行循环插入的时候,插入第二条的时候就报:索引中丢失  IN 或 OUT 参数:: 8

简单跟了下代码,感觉大概是fillstatement这个地方,也就是预编译语句进行绑定变量的时候出了问题,目前暂时用db.batch来操作,后面有时间再分析代码。

顶部