Search in sources :

Example 1 with InvalidDataAccessResourceUsageException

use of org.springframework.dao.InvalidDataAccessResourceUsageException in project spring-framework by spring-projects.

the class AbstractJdbcInsert method executeInsertAndReturnKeyHolderInternal.

/**
	 * Delegate method to execute the insert, generating any number of keys.
	 */
private KeyHolder executeInsertAndReturnKeyHolderInternal(final List<?> values) {
    if (logger.isDebugEnabled()) {
        logger.debug("The following parameters are used for call " + getInsertString() + " with: " + values);
    }
    final KeyHolder keyHolder = new GeneratedKeyHolder();
    if (this.tableMetaDataContext.isGetGeneratedKeysSupported()) {
        getJdbcTemplate().update(new PreparedStatementCreator() {

            @Override
            public PreparedStatement createPreparedStatement(Connection con) throws SQLException {
                PreparedStatement ps = prepareStatementForGeneratedKeys(con);
                setParameterValues(ps, values, getInsertTypes());
                return ps;
            }
        }, keyHolder);
    } else {
        if (!this.tableMetaDataContext.isGetGeneratedKeysSimulated()) {
            throw new InvalidDataAccessResourceUsageException("The getGeneratedKeys feature is not supported by this database");
        }
        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()));
        }
        // This is a hack to be able to get the generated key from a database that doesn't support
        // get generated keys feature. HSQL is one, PostgreSQL is another. Postgres uses a RETURNING
        // clause while HSQL uses a second query that has to be executed with the same connection.
        final String keyQuery = this.tableMetaDataContext.getSimulationQueryForGetGeneratedKey(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<>(1);
            keys.put(getGeneratedKeyNames()[0], key);
            keyHolder.getKeyList().add(keys);
        } else {
            getJdbcTemplate().execute(new ConnectionCallback<Object>() {

                @Override
                public Object doInConnection(Connection con) throws SQLException, DataAccessException {
                    // Do the insert
                    PreparedStatement ps = null;
                    try {
                        ps = con.prepareStatement(getInsertString());
                        setParameterValues(ps, values, getInsertTypes());
                        ps.executeUpdate();
                    } finally {
                        JdbcUtils.closeStatement(ps);
                    }
                    //Get the key
                    Statement keyStmt = null;
                    ResultSet rs = null;
                    Map<String, Object> keys = new HashMap<>(1);
                    try {
                        keyStmt = con.createStatement();
                        rs = keyStmt.executeQuery(keyQuery);
                        if (rs.next()) {
                            long key = rs.getLong(1);
                            keys.put(getGeneratedKeyNames()[0], key);
                            keyHolder.getKeyList().add(keys);
                        }
                    } finally {
                        JdbcUtils.closeResultSet(rs);
                        JdbcUtils.closeStatement(keyStmt);
                    }
                    return null;
                }
            });
        }
        return keyHolder;
    }
    return keyHolder;
}
Also used : SQLException(java.sql.SQLException) HashMap(java.util.HashMap) PreparedStatement(java.sql.PreparedStatement) Statement(java.sql.Statement) Connection(java.sql.Connection) PreparedStatement(java.sql.PreparedStatement) KeyHolder(org.springframework.jdbc.support.KeyHolder) GeneratedKeyHolder(org.springframework.jdbc.support.GeneratedKeyHolder) GeneratedKeyHolder(org.springframework.jdbc.support.GeneratedKeyHolder) InvalidDataAccessApiUsageException(org.springframework.dao.InvalidDataAccessApiUsageException) PreparedStatementCreator(org.springframework.jdbc.core.PreparedStatementCreator) ResultSet(java.sql.ResultSet) InvalidDataAccessResourceUsageException(org.springframework.dao.InvalidDataAccessResourceUsageException) HashMap(java.util.HashMap) Map(java.util.Map) DataAccessException(org.springframework.dao.DataAccessException)

Aggregations

Connection (java.sql.Connection)1 PreparedStatement (java.sql.PreparedStatement)1 ResultSet (java.sql.ResultSet)1 SQLException (java.sql.SQLException)1 Statement (java.sql.Statement)1 HashMap (java.util.HashMap)1 Map (java.util.Map)1 DataAccessException (org.springframework.dao.DataAccessException)1 InvalidDataAccessApiUsageException (org.springframework.dao.InvalidDataAccessApiUsageException)1 InvalidDataAccessResourceUsageException (org.springframework.dao.InvalidDataAccessResourceUsageException)1 PreparedStatementCreator (org.springframework.jdbc.core.PreparedStatementCreator)1 GeneratedKeyHolder (org.springframework.jdbc.support.GeneratedKeyHolder)1 KeyHolder (org.springframework.jdbc.support.KeyHolder)1