使用jdbctemplate / jdbc获取序列生成的主键

时间:2016-05-26 08:26:56

标签: java sql jdbc oracle11g

情况如下:

我有一个表(GUI_FILTER)和一个序列(GUI_FILTER_SEQ) 我使用springjdbctemplate插入数据,也可以使用核心jdbc。 在插入查询中,我正在检索sequence.nextval,并使用keyholder将其提取回java,如下所示。 我尝试了几种方法,比如使用

returnRowCount = namedJdbctmplt.update(sql.toString(), namedParameters, keyHolder, keyColumnNames);

returnRowCount = jdbctemplate.update(psc, keyHolder);

两者都失败了,

org.springframework.jdbc.BadSqlGrammarException: PreparedStatementCallback; bad SQL grammar []; nested exception is java.sql.SQLSyntaxErrorException: ORA-00936: missing expression



StringBuilder sql = new StringBuilder();
        sql.append(" Insert Into MAPS_AMPS.AMPS_GUI_FILTER ");
        sql.append(" (FILTER_PRESET_ID,USER_ID,FILTER_PAGE_TXT,FILTER_DISPLY_NM,FILTER_DATA_TXT,ROW_CREATE_TMS,LAST_UPDT_TMS ) ");
        sql.append(" values(Select MAPS_AMPS.AMPS_GUI_FILTER_SEQ.NEXTVAL,?,?,?,?,CURRENT_TIMESTAMP ,null from dual) ");
        final String sqlQuery = sql.toString();

如果我删除序列生成部分选择MAPS_AMPS.AMPS_GUI_FILTER_SEQ.NEXTVAL为常数大约30左右,它可以正常工作。

有没有办法将序列值作为insert命令获取,同时使用jdbc获取主键?

完整代码如下。

@Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, rollbackFor = DataAccessException.class)
public Long addFilterPreset(final String userId, final String filterPageCd,
        final String filterPresetDisplayName,
        final String serializedTaskBrowserSearchObj) {

    logger.debug("Start of FilterPresetDaoImpl - addFilterPreset() method");

    if(!countSavedFilterPresets(userId,filterPageCd))
        return null;

    //StringBuilder sql = new StringBuilder();
    Map<String, Object> parameterMap = new HashMap<String, Object>();

    //sql.append(" Insert Into MAPS_AMPS.AMPS_GUI_FILTER ");
    //sql.append(" (FILTER_PRESET_ID,USER_ID,FILTER_PAGE_TXT,FILTER_DISPLY_NM,FILTER_DATA_TXT,ROW_CREATE_TMS,LAST_UPDT_TMS ) ");
    //sql.append( "Values( Select MAPS_AMPS.AMPS_GUI_FILTER_SEQ.NEXTVAL,:userId,:filterPageCd,:filterPresetDisplayName,:filterPresetData,CURRENT_TIMESTAMP ,null)" );

    /*parameterMap.put("userId", userId);
    parameterMap.put("filterPageCd", filterPageCd);
    parameterMap.put("filterPresetDisplayName", filterPresetDisplayName);
    parameterMap.put("filterPresetData", serializedTaskBrowserSearchObj);
    */
    StringBuilder sql = new StringBuilder();
    sql.append(" Insert Into MAPS_AMPS.AMPS_GUI_FILTER ");
    sql.append(" (FILTER_PRESET_ID,USER_ID,FILTER_PAGE_TXT,FILTER_DISPLY_NM,FILTER_DATA_TXT,ROW_CREATE_TMS,LAST_UPDT_TMS ) ");
    sql.append(" values(Select MAPS_AMPS.AMPS_GUI_FILTER_SEQ.NEXTVAL,?,?,?,?,CURRENT_TIMESTAMP ,null from dual) ");
    final String sqlQuery = sql.toString();

    logger.info("SQL Add Filter Preset Query : {}", sqlQuery);
    int returnRowCount = 0;
    KeyHolder keyHolder = new GeneratedKeyHolder();
    final String[] keyColumnNames = {"FILTER_PRESET_ID"};
    SqlParameterSource namedParameters = new MapSqlParameterSource(parameterMap);

    PreparedStatementCreator psc = new PreparedStatementCreator()   {
        @Override
        public PreparedStatement createPreparedStatement(Connection connection)
                throws SQLException     {
            PreparedStatement ps = connection.prepareStatement(sqlQuery, keyColumnNames);
            ps.setString(1, userId);
            ps.setString(2, filterPageCd);
            ps.setString(3, filterPresetDisplayName);
            ps.setString(4, serializedTaskBrowserSearchObj);
            return ps;
        }
    };

    try{
        long startValue = System.currentTimeMillis();
        //returnRowCount = namedJdbctmplt.update(sql.toString(), namedParameters, keyHolder, keyColumnNames);
        returnRowCount = jdbctemplate.update(psc, keyHolder);
        long endValue = System.currentTimeMillis();
        logger.info("Filter Preset added in {} seconds", (endValue - startValue)/1000);
    }catch(Exception e){
        logger.info("Exception while adding filter preset - " + "userId : "+userId+" filterPageCd : "+filterPageCd +" filterPresetData : "+serializedTaskBrowserSearchObj);
    }finally{
        logger.debug("End of FilterPresetDaoImpl - addFilterPreset() method");
    }
    if (returnRowCount > 0)
        return keyHolder.getKey().longValue();
    return null;
}

错误

enter image description here

1 个答案:

答案 0 :(得分:1)

从查询中插入结果时,您不需要VALUES关键字。

StringBuilder sql = new StringBuilder();
        sql.append(" Insert Into MAPS_AMPS.AMPS_GUI_FILTER ");
        sql.append(" (FILTER_PRESET_ID,USER_ID,FILTER_PAGE_TXT,FILTER_DISPLY_NM,FILTER_DATA_TXT,ROW_CREATE_TMS,LAST_UPDT_TMS ) ");
        sql.append(" (Select MAPS_AMPS.AMPS_GUI_FILTER_SEQ.NEXTVAL,?,?,?,?,CURRENT_TIMESTAMP ,null from dual) ");
        final String sqlQuery = sql.toString();

要获取插入值,请尝试使用RETURNING子句:本文中将讨论一些详细信息Oracle's RETURNING INTO usage in Java (JDBC, Prepared Statement)

但是,如果使用VALUES关键字,则只能对INSERT使用RETURNING子句,因此不能同时使用这两个子句。正如我们在此讨论的那样:PLSQL Insert into with subquery and returning clause (Oracle)