JdbcTemplate插入一条数据到Oracle数据库并返回自增长ID

问题描述

我的需求就是需要循环插入一组数据,因为数据库是按照自增长ID关联的,所以每插入一条数据,都要返回自增长的ID,用来设置关联关系,我用JdbcTemplate可以实现一组数据的插入并返回ID,但是循环两次以上就出错了:org.springframework.jdbc.UncategorizedSQLException:PreparedStatementCallback;uncategorizedSQLExceptionforSQL[insertintoT_METADATA_ABSTRACT(STATIONCODE,ARCHIVETYPE,ENTITYID,ENTITYNAME,ABS,KEYWORDS,CREATOR,CONTRI,BTIME,ETIME,SPATIALCOV,DBCODE,SHARINGLEVEL,TYPE,ISDELETED,ENTITYUPDATEDATE)values(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)];SQLstate[null];errorcode[17041];索引中丢失IN或OUT参数::17;nestedexceptionisjava.sql.SQLException:索引中丢失IN或OUT参数::17atorg.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:83)atorg.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:80)atorg.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:603)atorg.springframework.jdbc.core.JdbcTemplate.update(JdbcTemplate.java:843)atcn.csdb.DataCollection.SynDaoTest.insertTest(SynDaoTest.java:48)atsun.reflect.NativeMethodAccessorImpl.invoke0(NativeMethod)atsun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)atsun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)atorg.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)atorg.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)atorg.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)atorg.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)atorg.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:74)atorg.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:83)atorg.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:72)atorg.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:231)atorg.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:88)atorg.junit.runners.ParentRunner$3.run(ParentRunner.java:193)atorg.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)atorg.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)atorg.junit.runners.ParentRunner.access$000(ParentRunner.java:42)atorg.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)atorg.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)atorg.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:71)atorg.junit.runners.ParentRunner.run(ParentRunner.java:236)atorg.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:174)atorg.junit.runner.JUnitCore.run(JUnitCore.java:157)atcom.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:74)atcom.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:211)atcom.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:67)atsun.reflect.NativeMethodAccessorImpl.invoke0(NativeMethod)atsun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)atcom.intellij.rt.execution.application.AppMain.main(AppMain.java:120)Causedby:java.sql.SQLException:索引中丢失IN或OUT参数::17atoracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:112)atoracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:146)atoracle.jdbc.driver.OraclePreparedStatement.processCompletedBindRow(OraclePreparedStatement.java:1704)atoracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedStatement.java:3280)atoracle.jdbc.driver.OraclePreparedStatement.executeUpdate(OraclePreparedStatement.java:3368)atcom.alibaba.druid.filter.FilterChainImpl.preparedStatement_executeUpdate(FilterChainImpl.java:2721)atcom.alibaba.druid.wall.WallFilter.preparedStatement_executeUpdate(WallFilter.java:566)atcom.alibaba.druid.filter.FilterChainImpl.preparedStatement_executeUpdate(FilterChainImpl.java:2719)atcom.alibaba.druid.filter.FilterAdapter.preparedStatement_executeUpdate(FilterAdapter.java:1069)atcom.alibaba.druid.filter.FilterEventAdapter.preparedStatement_executeUpdate(FilterEventAdapter.java:491)atcom.alibaba.druid.filter.FilterChainImpl.preparedStatement_executeUpdate(FilterChainImpl.java:2719)atcom.alibaba.druid.proxy.jdbc.PreparedStatementProxyImpl.executeUpdate(PreparedStatementProxyImpl.java:145)atcom.alibaba.druid.pool.DruidPooledPreparedStatement.executeUpdate(DruidPooledPreparedStatement.java:253)atorg.springframework.jdbc.core.JdbcTemplate$3.doInPreparedStatement(JdbcTemplate.java:845)atorg.springframework.jdbc.core.JdbcTemplate$3.doInPreparedStatement(JdbcTemplate.java:1)atorg.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:587)我的代码:finalStringsql="insertintoT_METADATA_ABSTRACT(STATIONCODE,ARCHIVETYPE,ENTITYID,ENTITYNAME,ABS,KEYWORDS,"+"CREATOR,CONTRI,BTIME,ETIME,SPATIALCOV,DBCODE,SHARINGLEVEL,TYPE,ISDELETED,ENTITYUPDATEDATE)values(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)";for(finalMap<String,Object>map:list){KeyHolderkeyHolder=newGeneratedKeyHolder();serviceSysTemplate.update(newPreparedStatementCreator(){@OverridepublicPreparedStatementcreatePreparedStatement(Connectionconnection)throwsSQLException{PreparedStatementps=connection.prepareStatement(sql,newString[]{"ID"});ps.setString(1,map.get("CERNURI").toString());ps.setString(2,map.get("ENTTYPE").toString());ps.setString(3,map.get("ENTID").toString());ps.setString(4,map.get("ENTNAME").toString());if(map.get("ABS")!=null)ps.setString(5,map.get("ABS").toString());elseps.setNull(5,Types.VARCHAR);if(map.get("KEYWORDS")!=null)ps.setString(6,map.get("KEYWORDS").toString());elseps.setNull(6,Types.VARCHAR);ps.setString(7,map.get("CREATOR").toString());if(map.get("CONTRI")!=null)ps.setString(8,map.get("CONTRI").toString());elseps.setNull(8,Types.VARCHAR);if(map.get("BTIME")!=null)ps.setString(9,map.get("BTIME").toString());elseps.setNull(9,Types.VARCHAR);if(map.get("ETIME")!=null)ps.setString(10,map.get("ETIME").toString());elseps.setNull(10,Types.VARCHAR);if(map.get("SPATIALCOV_GEONAME")!=null)ps.setString(11,map.get("SPATIALCOV_GEONAME").toString());elseps.setNull(11,Types.VARCHAR);ps.setString(12,"dbcode2");ps.setString(13,map.get("RESTRCATEGORY").toString());ps.setString(14,map.get("DATACATEGORY").toString());ps.setInt(15,Integer.parseInt(map.get("ISDELETED").toString()));ps.setString(16,map.get("HARVESTDATE").toString());returnps;}},keyHolder);System.out.println(keyHolder.getKey().longValue());}

关键是,如果循环一次,运行正常,循环两次,第二次插入就出现了上面的错误,让我很费解!我还尝试用PreparedStatementCreatorFactory来实现,代码如下:finalStringsql="insertintoT_METADATA_ABSTRACT(STATIONCODE,ARCHIVETYPE,ENTITYID,ENTITYNAME,ABS,KEYWORDS,"+"CREATOR,CONTRI,BTIME,ETIME,SPATIALCOV,DBCODE,SHARINGLEVEL,TYPE,ISDELETED,ENTITYUPDATEDATE)values(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)";PreparedStatementCreatorFactoryfactory=newPreparedStatementCreatorFactory(sql,newint[]{Types.VARCHAR,Types.VARCHAR,Types.VARCHAR,Types.VARCHAR,Types.VARCHAR,Types.VARCHAR,Types.VARCHAR,Types.VARCHAR,Types.VARCHAR,Types.VARCHAR,Types.VARCHAR,Types.VARCHAR,Types.VARCHAR,Types.VARCHAR,Types.NUMERIC,Types.VARCHAR});factory.setGeneratedKeysColumnNames(newString[]{"ID"});for(finalMap<String,Object>map:list){PreparedStatementCreatorcreator=factory.newPreparedStatementCreator(newObject[]{map.get("CERNURI"),map.get("ENTTYPE"),map.get("ENTID"),map.get("ENTNAME"),map.get("ABS"),map.get("KEYWORDS"),map.get("CREATOR"),map.get("CONTRI"),map.get("BTIME"),map.get("ETIME"),map.get("SPATIALCOV_GEONAME"),"dbcode2",map.get("RESTRCATEGORY"),map.get("DATACATEGORY"),map.get("ISDELETED"),map.get("HARVESTDATE")});KeyHolderkeyHolder=newGeneratedKeyHolder();serviceSysTemplate.update(creator,keyHolder);System.out.println(keyHolder.getKey().longValue());}

依然出现上面的错误,求大神来解决!

解决方案

解决方案二:
你这个感觉也没多大必要.....要实现插入数据库并返回自增长ID,有个简单的办法1、在插入之前,你先查询你的自增长的nextval,当然,前提是你的这个nextval的值不能与之前重复,如果不存在脏数据,是不会有问题的。2、然后把你查询出来的nextval的值,当做你 T_METADATA_ABSTRACT表的主键ID插入进去不就行了么?而且你查出来的nextval的值可以随时用,也可以返回出去
解决方案三:
是不是该提前备好,你插入之后再查询吗?
解决方案四:
引用1楼shijing266的回复:

你这个感觉也没多大必要.....要实现插入数据库并返回自增长ID,有个简单的办法1、在插入之前,你先查询你的自增长的nextval,当然,前提是你的这个nextval的值不能与之前重复,如果不存在脏数据,是不会有问题的。2、然后把你查询出来的nextval的值,当做你 T_METADATA_ABSTRACT表的主键ID插入进去不就行了么?而且你查出来的nextval的值可以随时用,也可以返回出去

这个方法是我在用的,但是Jdbctemplate既然有这个功能,我觉得至少比这个方法效率高一些吧,因为我要插入很多数据,每条数据都要两条sql语句,有点浪费啊
解决方案五:
引用2楼rui888的回复:

是不是该提前备好,你插入之后再查询吗?

Oracle数据库里面有一个触发器,插入时自动设置ID
解决方案六:
引用3楼ZSMJ_2011的回复:

Quote: 引用1楼shijing266的回复:
你这个感觉也没多大必要.....要实现插入数据库并返回自增长ID,有个简单的办法1、在插入之前,你先查询你的自增长的nextval,当然,前提是你的这个nextval的值不能与之前重复,如果不存在脏数据,是不会有问题的。2、然后把你查询出来的nextval的值,当做你 T_METADATA_ABSTRACT表的主键ID插入进去不就行了么?而且你查出来的nextval的值可以随时用,也可以返回出去

这个方法是我在用的,但是Jdbctemplate既然有这个功能,我觉得至少比这个方法效率高一些吧,因为我要插入很多数据,每条数据都要两条sql语句,有点浪费啊

恩,我也就提个建议~嘿嘿能搞清jdbcTemplate更好~

时间: 2024-10-27 22:45:41

JdbcTemplate插入一条数据到Oracle数据库并返回自增长ID的相关文章

从excel导入1000多条数据到oracle数据库时,java内存溢出,tomcat报错

问题描述 tomcat错误日志如下:## An unexpected error has been detected by HotSpot Virtual Machine:## EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x7c930a19, pid=1168, tid=1936## Java VM: Java HotSpot(TM) Client VM (1.5.0_16-b02 mixed mode)# Problematic frame:#

oracle 数据库...-oracle 数据库插入一条数据,某字段如何自动递增1

问题描述 oracle 数据库插入一条数据,某字段如何自动递增1 oracle 数据库插入一条数据,某字段如何自动递增1,oracle 数据库插入一条数据,某字段如何自动递增1,在线等.急急急.求大指点 解决方案 1,使用序列 2,手动使用变量++然后执行插入数据库记录 解决方案二: oracle 字段递增 表插入数据,id自动增1 解决方案三: Oracle里有序列,使用序列来实现 解决方案四: 序列: 是oacle提供的用于产生一系列唯一数字的数据库对象. l 自动提供唯一的数值 l 共享对

string-关于数据库中插入多条数据,其中有一项关于to_date的问题

问题描述 关于数据库中插入多条数据,其中有一项关于to_date的问题 String sql = "insert into TestInfo(tiName, to_date('tiStartTime','YYYY-MM-DD' ),tiState,TiGrade) values(?,?,?,?)"; 这句数据库语句关于to_date的地方有哪里不对?为什么会报错说缺失逗号 解决方案 to_date('tiStartTime','YYYY-MM-DD' ) 这个位置应该是一个字段名称,怎

数据库-如何实现一个触发器:在插入一条数据前创建一个表,表名由插入的数据决定?

问题描述 如何实现一个触发器:在插入一条数据前创建一个表,表名由插入的数据决定? MySQL数据库的触发器能不能实现创建表,表名用变量指定? 这个变量该如何表示? 谢谢. 解决方案 可以的,使用动态sql就可以,参考如下链接 http://www.2cto.com/database/201209/156678.html

java jdbc-向mysql中插入50000条数据怎么那么慢。。。

问题描述 向mysql中插入50000条数据怎么那么慢... package cn.itcast.bath; import java.sql.Connection; import java.sql.PreparedStatement; import org.junit.Test; import cn.itcast.jdbc.JDBCUtils; public class Bath { @Test public void demo1() { Connection conn=null; Prepar

oracle-怎么插入多条数据。各路大神!

问题描述 怎么插入多条数据.各路大神! 像发邮件那样,多个用户名,用:隔开,存同一条信息.怎么插入到数据库中啊!各路大神. 解决方案 1.如果你用程序往里存的话,比较简单,将这些用户按照";"截取,然后批量存入数据库,或者单条循环存入数据库. 2.如果直接写sql语句往数据库存的话,可以借助一下notePad软件功能: 1)在在文本上写一条插入语句,如:insert into table(userName, content, createTime) values('', '测试', '

插入多条数据回滚-hibernate 手动控制事务回滚失败

问题描述 hibernate 手动控制事务回滚失败 spring配置: 5201005100 <bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"> <property name="dataSource" ref="dataSource" />

一个关于插入一条数据如何拿该条数据主键的问题

问题描述 一个关于插入一条数据如何拿该条数据主键的问题 String action=request.getParameter("action"); if(action !=null && action.trim().equals("post")){ String title=request.getParameter("title"); System.out.println(title); String cont=request.g

用一条mysql语句插入多条数据_Mysql

       假如有一个数据表A: id name title addtime         如果需要插入n条数据 : $time= time(); $data = array( array( 'name'=>'name1','title'=>'title1','addtime'=>$time; ), array( 'name'=>'name2','title'=>'title2','addtime'=>$time; ), array( 'name'=>'nam