/** * Method that provides execution of the insert using the passed-in * {@link SqlParameterSource} and returning a generated key. * @param parameterSource parameter names and values to be used in insert * @return the key generated by the insert */ protected Number doExecuteAndReturnKey(SqlParameterSource parameterSource) { checkCompiled(); List<Object> values = matchInParameterValuesWithInsertColumns(parameterSource); return executeInsertAndReturnKeyInternal(values); }
/** * Specify the name of a single generated key column. */ public void setGeneratedKeyName(String generatedKeyName) { checkIfConfigurationModificationIsAllowed(); this.generatedKeyNames = new String[] {generatedKeyName}; }
/** * Check whether this operation has been compiled already; * lazily compile it if not already compiled. * <p>Automatically called by {@code validateParameters}. */ protected void checkCompiled() { if (!isCompiled()) { logger.debug("JdbcInsert not compiled before execution - invoking compile"); compile(); } }
/** * Method that provides execution of the insert using the passed-in * {@link SqlParameterSource} and returning all generated keys. * @param parameterSource parameter names and values to be used in insert * @return the KeyHolder containing keys generated by the insert */ protected KeyHolder doExecuteAndReturnKeyHolder(SqlParameterSource parameterSource) { checkCompiled(); List<Object> values = matchInParameterValuesWithInsertColumns(parameterSource); return executeInsertAndReturnKeyHolderInternal(values); }
/** * Delegate method that executes the insert using the passed-in Map of parameters. * @param args a Map with parameter names and values to be used in insert * @return the number of rows affected */ protected int doExecute(Map<String, ?> args) { checkCompiled(); List<Object> values = matchInParameterValuesWithInsertColumns(args); return executeInsertInternal(values); }
logger.debug("The following parameters are used for call " + getInsertString() + " with: " + values); getJdbcTemplate().update( con -> { PreparedStatement ps = prepareStatementForGeneratedKeys(con); setParameterValues(ps, values, getInsertTypes()); return ps; }, if (getGeneratedKeyNames().length < 1) { throw new InvalidDataAccessApiUsageException("Generated Key Name(s) not specified. " + "Using the generated keys features requires specifying the name(s) of the generated column(s)"); if (getGeneratedKeyNames().length > 1) { throw new InvalidDataAccessApiUsageException( "Current database only supports retrieving the key for a single column. There are " + getGeneratedKeyNames().length + " columns specified: " + Arrays.asList(getGeneratedKeyNames())); Assert.state(getTableName() != null, "No table name set"); final String keyQuery = this.tableMetaDataContext.getSimpleQueryForGetGeneratedKey( getTableName(), getGeneratedKeyNames()[0]); Assert.state(keyQuery != null, "Query for simulating get generated keys must not be null"); Long key = getJdbcTemplate().queryForObject( getInsertString() + " " + keyQuery, values.toArray(), Long.class); Map<String, Object> keys = new HashMap<>(2); keys.put(getGeneratedKeyNames()[0], key); keyHolder.getKeyList().add(keys);
/** * Delegate method to perform the actual compilation. * <p>Subclasses can override this template method to perform their own compilation. * Invoked after this base class's compilation is complete. */ protected void compileInternal() { DataSource dataSource = getJdbcTemplate().getDataSource(); Assert.state(dataSource != null, "No DataSource set"); this.tableMetaDataContext.processMetaData(dataSource, getColumnNames(), getGeneratedKeyNames()); this.insertString = this.tableMetaDataContext.createInsertString(getGeneratedKeyNames()); this.insertTypes = this.tableMetaDataContext.createInsertTypes(); if (logger.isDebugEnabled()) { logger.debug("Compiled insert object: insert string is [" + this.insertString + "]"); } onCompileInternal(); }
/** * Delegate method that executes a batch insert using the passed-in {@link SqlParameterSource SqlParameterSources}. * @param batch array of SqlParameterSource with parameter names and values to be used in insert * @return array of number of rows affected */ protected int[] doExecuteBatch(SqlParameterSource... batch) { checkCompiled(); List<List<Object>> batchValues = new ArrayList<>(batch.length); for (SqlParameterSource parameterSource : batch) { batchValues.add(matchInParameterValuesWithInsertColumns(parameterSource)); } return executeBatchInternal(batchValues); }
/** * Compile this JdbcInsert using provided parameters and meta-data plus other settings. * This finalizes the configuration for this object and subsequent attempts to compile are * ignored. This will be implicitly called the first time an un-compiled insert is executed. * @throws InvalidDataAccessApiUsageException if the object hasn't been correctly initialized, * for example if no DataSource has been provided */ public final synchronized void compile() throws InvalidDataAccessApiUsageException { if (!isCompiled()) { if (getTableName() == null) { throw new InvalidDataAccessApiUsageException("Table name is required"); } try { this.jdbcTemplate.afterPropertiesSet(); } catch (IllegalArgumentException ex) { throw new InvalidDataAccessApiUsageException(ex.getMessage()); } compileInternal(); this.compiled = true; if (logger.isDebugEnabled()) { logger.debug("JdbcInsert for table [" + getTableName() + "] compiled"); } } }
ps = con.prepareStatement(getInsertString()); setParameterValues(ps, values, getInsertTypes()); ps.executeUpdate(); if (rs.next()) { long key = rs.getLong(1); keys.put(getGeneratedKeyNames()[0], key); keyHolder.getKeyList().add(keys);
logger.debug("The following parameters are used for call " + getInsertString() + " with: " + values); getJdbcTemplate().update( new PreparedStatementCreator() { public PreparedStatement createPreparedStatement(Connection con) throws SQLException { "The getGeneratedKeys feature is not supported by this database"); if (getGeneratedKeyNames().length < 1) { throw new InvalidDataAccessApiUsageException("Generated Key Name(s) not specificed. " + "Using the generated keys features requires specifying the name(s) of the generated column(s)"); if (getGeneratedKeyNames().length > 1) { throw new InvalidDataAccessApiUsageException( "Current database only supports retreiving the key for a single column. There are " + getGeneratedKeyNames().length + " columns specified: " + Arrays.asList(getGeneratedKeyNames())); this.tableMetaDataContext.getTableName(), getGeneratedKeyNames()[0]); Assert.notNull(keyQuery, "Query for simulating get generated keys can't be null"); if (keyQuery.toUpperCase().startsWith("RETURNING")) { Long key = getJdbcTemplate().queryForObject(getInsertString() + " " + keyQuery, values.toArray(new Object[values.size()]), Long.class); Map<String, Object> keys = new HashMap<String, Object>(1); keys.put(getGeneratedKeyNames()[0], key); keyHolder.getKeyList().add(keys); getJdbcTemplate().execute(new ConnectionCallback<Object>() { public Object doInConnection(Connection con) throws SQLException, DataAccessException {
/** * Delegate method to execute the insert, generating a single key. */ private Number executeInsertAndReturnKeyInternal(final List<?> values) { KeyHolder kh = executeInsertAndReturnKeyHolderInternal(values); if (kh.getKey() != null) { return kh.getKey(); } else { throw new DataIntegrityViolationException( "Unable to retrieve the generated key for the insert: " + getInsertString()); } }
/** * Create a PreparedStatement to be used for an insert operation with generated keys. * @param con the Connection to use * @return the PreparedStatement */ private PreparedStatement prepareStatementForGeneratedKeys(Connection con) throws SQLException { if (getGeneratedKeyNames().length < 1) { throw new InvalidDataAccessApiUsageException("Generated Key Name(s) not specified. " + "Using the generated keys features requires specifying the name(s) of the generated column(s)."); } PreparedStatement ps; if (this.tableMetaDataContext.isGeneratedKeysColumnNameArraySupported()) { if (logger.isDebugEnabled()) { logger.debug("Using generated keys support with array of column names."); } ps = con.prepareStatement(getInsertString(), getGeneratedKeyNames()); } else { if (logger.isDebugEnabled()) { logger.debug("Using generated keys support with Statement.RETURN_GENERATED_KEYS."); } ps = con.prepareStatement(getInsertString(), Statement.RETURN_GENERATED_KEYS); } return ps; }
logger.debug("The following parameters are used for call " + getInsertString() + " with: " + values); getJdbcTemplate().update( con -> { PreparedStatement ps = prepareStatementForGeneratedKeys(con); setParameterValues(ps, values, getInsertTypes()); return ps; }, if (getGeneratedKeyNames().length > 1) { throw new InvalidDataAccessApiUsageException( "Current database only supports retrieving the key for a single column. There are " + getGeneratedKeyNames().length + " columns specified: " + Arrays.asList(getGeneratedKeyNames())); getTableName(), getGeneratedKeyNames()[0]); Assert.state(keyQuery != null, "Query for simulating get generated keys must not be null"); Long key = getJdbcTemplate().queryForObject( getInsertString() + " " + keyQuery, values.toArray(), Long.class); Map<String, Object> keys = new HashMap<>(2); keys.put(getGeneratedKeyNames()[0], key); keyHolder.getKeyList().add(keys); getJdbcTemplate().execute((ConnectionCallback<Object>) con -> { ps = con.prepareStatement(getInsertString()); setParameterValues(ps, values, getInsertTypes()); ps.executeUpdate();
/** * Method to perform the actual compilation. Subclasses can override this template method * to perform their own compilation. Invoked after this base class's compilation is complete. */ protected void compileInternal() { this.tableMetaDataContext.processMetaData( getJdbcTemplate().getDataSource(), getColumnNames(), getGeneratedKeyNames()); this.insertString = this.tableMetaDataContext.createInsertString(getGeneratedKeyNames()); this.insertTypes = this.tableMetaDataContext.createInsertTypes(); if (logger.isDebugEnabled()) { logger.debug("Compiled insert object: insert string is [" + getInsertString() + "]"); } onCompileInternal(); }
/** * Method that provides execution of the insert using the passed-in * Map of parameters and returning all generated keys. * @param args a Map with parameter names and values to be used in insert * @return the KeyHolder containing keys generated by the insert */ protected KeyHolder doExecuteAndReturnKeyHolder(Map<String, ?> args) { checkCompiled(); List<Object> values = matchInParameterValuesWithInsertColumns(args); return executeInsertAndReturnKeyHolderInternal(values); }
/** * Delegate method that executes the insert using the passed-in {@link SqlParameterSource}. * @param parameterSource parameter names and values to be used in insert * @return the number of rows affected */ protected int doExecute(SqlParameterSource parameterSource) { checkCompiled(); List<Object> values = matchInParameterValuesWithInsertColumns(parameterSource); return executeInsertInternal(values); }
/** * Delegate method that executes a batch insert using the passed-in Maps of parameters. * @param batch array of Maps with parameter names and values to be used in batch insert * @return array of number of rows affected */ @SuppressWarnings("unchecked") protected int[] doExecuteBatch(Map<String, ?>... batch) { checkCompiled(); List<List<Object>> batchValues = new ArrayList<>(batch.length); for (Map<String, ?> args : batch) { batchValues.add(matchInParameterValuesWithInsertColumns(args)); } return executeBatchInternal(batchValues); }
/** * Compile this JdbcInsert using provided parameters and meta data plus other settings. * This finalizes the configuration for this object and subsequent attempts to compile are * ignored. This will be implicitly called the first time an un-compiled insert is executed. * @throws InvalidDataAccessApiUsageException if the object hasn't been correctly initialized, * for example if no DataSource has been provided */ public synchronized final void compile() throws InvalidDataAccessApiUsageException { if (!isCompiled()) { if (getTableName() == null) { throw new InvalidDataAccessApiUsageException("Table name is required"); } try { this.jdbcTemplate.afterPropertiesSet(); } catch (IllegalArgumentException ex) { throw new InvalidDataAccessApiUsageException(ex.getMessage()); } compileInternal(); this.compiled = true; if (logger.isDebugEnabled()) { logger.debug("JdbcInsert for table [" + getTableName() + "] compiled"); } } }
/** * Method to execute the insert generating single key */ private Number executeInsertAndReturnKeyInternal(final List<Object> values) { KeyHolder kh = executeInsertAndReturnKeyHolderInternal(values); if (kh != null && kh.getKey() != null) { return kh.getKey(); } else { throw new DataIntegrityViolationException( "Unable to retrieve the generated key for the insert: " + getInsertString()); } }