/** * Validate the named parameters passed to an execute method based on declared parameters. * Subclasses should invoke this method before every {@code executeQuery()} or * {@code update()} method. * @param parameters parameter Map supplied. May be {@code null}. * @throws InvalidDataAccessApiUsageException if the parameters are invalid */ protected void validateNamedParameters(Map<String, ?> parameters) throws InvalidDataAccessApiUsageException { checkCompiled(); Map<String, ?> paramsToUse = (parameters != null ? parameters : Collections.<String, Object> emptyMap()); int declaredInParameters = 0; for (SqlParameter param : this.declaredParameters) { if (param.isInputValueProvided()) { if (!supportsLobParameters() && (param.getSqlType() == Types.BLOB || param.getSqlType() == Types.CLOB)) { throw new InvalidDataAccessApiUsageException( "BLOB or CLOB parameters are not allowed for this kind of operation"); } if (param.getName() != null && !paramsToUse.containsKey(param.getName())) { throw new InvalidDataAccessApiUsageException("The parameter named '" + param.getName() + "' was not among the parameters supplied: " + paramsToUse.keySet()); } declaredInParameters++; } } validateParameterCount(paramsToUse.size(), declaredInParameters); }
@Override public Number getKey() throws InvalidDataAccessApiUsageException, DataRetrievalFailureException { if (this.keyList.size() == 0) { return null; } if (this.keyList.size() > 1 || this.keyList.get(0).size() > 1) { throw new InvalidDataAccessApiUsageException( "The getKey method should only be used when a single key is returned. " + "The current key entry contains multiple keys: " + this.keyList); } Iterator<Object> keyIter = this.keyList.get(0).values().iterator(); if (keyIter.hasNext()) { Object key = keyIter.next(); if (!(key instanceof Number)) { throw new DataRetrievalFailureException( "The generated key is not of a supported numeric type. " + "Unable to cast [" + (key != null ? key.getClass().getName() : null) + "] to [" + Number.class.getName() + "]"); } return (Number) key; } else { throw new DataRetrievalFailureException("Unable to retrieve the generated key. " + "Check that the table has an identity column enabled."); } }
/** * Compile this query. * Ignores subsequent attempts to compile. * @throws InvalidDataAccessApiUsageException if the object hasn't * been correctly initialized, for example if no DataSource has been provided */ public final void compile() throws InvalidDataAccessApiUsageException { if (!isCompiled()) { if (getSql() == null) { throw new InvalidDataAccessApiUsageException("Property 'sql' is required"); } try { this.jdbcTemplate.afterPropertiesSet(); } catch (IllegalArgumentException ex) { throw new InvalidDataAccessApiUsageException(ex.getMessage()); } compileInternal(); this.compiled = true; if (logger.isDebugEnabled()) { logger.debug("RdbmsOperation with SQL [" + getSql() + "] compiled"); } } }
/** * Validate the parameters passed to an execute method based on declared parameters. * Subclasses should invoke this method before every {@code executeQuery()} * or {@code update()} method. * @param parameters parameters supplied (may be {@code null}) * @throws InvalidDataAccessApiUsageException if the parameters are invalid */ protected void validateParameters(Object[] parameters) throws InvalidDataAccessApiUsageException { checkCompiled(); int declaredInParameters = 0; for (SqlParameter param : this.declaredParameters) { if (param.isInputValueProvided()) { if (!supportsLobParameters() && (param.getSqlType() == Types.BLOB || param.getSqlType() == Types.CLOB)) { throw new InvalidDataAccessApiUsageException( "BLOB or CLOB parameters are not allowed for this kind of operation"); } declaredInParameters++; } } validateParameterCount((parameters != null ? parameters.length : 0), declaredInParameters); }
public PreparedStatementCreatorImpl(String actualSql, List<?> parameters) { this.actualSql = actualSql; Assert.notNull(parameters, "Parameters List must not be null"); this.parameters = parameters; if (this.parameters.size() != declaredParameters.size()) { // account for named parameters being used multiple times Set<String> names = new HashSet<String>(); for (int i = 0; i < parameters.size(); i++) { Object param = parameters.get(i); if (param instanceof SqlParameterValue) { names.add(((SqlParameterValue) param).getName()); } else { names.add("Parameter #" + i); } } if (names.size() != declaredParameters.size()) { throw new InvalidDataAccessApiUsageException( "SQL [" + sql + "]: given " + names.size() + " parameters but expected " + declaredParameters.size()); } } }
/** * 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"); } } }
/** * Create the PreparedStatement to be used for insert that have generated keys * * @param con the connection used * @return PreparedStatement to use * @throws SQLException */ private PreparedStatement prepareStatementForGeneratedKeys(Connection con) throws SQLException { 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)"); } 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; }
/** * Add a declared parameter to the list of parameters for the call. * Only parameters declared as {@code SqlParameter} and {@code SqlInOutParameter} * will be used to provide input values. This is different from the {@code StoredProcedure} class * which for backwards compatibility reasons allows input values to be provided for parameters declared * as {@code SqlOutParameter}. * @param parameter the {@link SqlParameter} to add */ public void addDeclaredParameter(SqlParameter parameter) { Assert.notNull(parameter, "The supplied parameter must not be null"); if (!StringUtils.hasText(parameter.getName())) { throw new InvalidDataAccessApiUsageException( "You must specify a parameter name when declaring parameters for \"" + getProcedureName() + "\""); } this.declaredParameters.add(parameter); if (logger.isDebugEnabled()) { logger.debug("Added declared parameter for [" + getProcedureName() + "]: " + parameter.getName()); } }
/** * Compile this JdbcCall 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 call is executed. * @throws org.springframework.dao.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 (getProcedureName() == null) { throw new InvalidDataAccessApiUsageException("Procedure or Function name is required"); } try { this.jdbcTemplate.afterPropertiesSet(); } catch (IllegalArgumentException ex) { throw new InvalidDataAccessApiUsageException(ex.getMessage()); } compileInternal(); this.compiled = true; if (logger.isDebugEnabled()) { logger.debug("SqlCall for " + (isFunction() ? "function" : "procedure") + " [" + getProcedureName() + "] compiled"); } } }
@Override public void init(DataSource dataSource) throws Exception { Assert.notNull(dataSource); Assert.hasLength(selectClause, "selectClause must be specified"); Assert.hasLength(fromClause, "fromClause must be specified"); Assert.notEmpty(sortKeys, "sortKey must be specified"); StringBuilder sql = new StringBuilder(); sql.append("SELECT ").append(selectClause); sql.append(" FROM ").append(fromClause); if (whereClause != null) { sql.append(" WHERE ").append(whereClause); } List<String> namedParameters = new ArrayList<String>(); parameterCount = JdbcParameterUtils.countParameterPlaceholders(sql.toString(), namedParameters); if (namedParameters.size() > 0) { if (parameterCount != namedParameters.size()) { throw new InvalidDataAccessApiUsageException( "You can't use both named parameters and classic \"?\" placeholders: " + sql); } usingNamedParameters = true; } }
private Predicate<?> fromInequalityVariant(Type type, boolean ignoreCase, Iterator<Comparable<?>> iterator) { if (ignoreCase && type != Type.SIMPLE_PROPERTY) { throw new InvalidDataAccessApiUsageException(String.format("Ignore case not supported for '%s'", type)); } switch (type) { case GREATER_THAN: return GreaterLessPredicate.gr(iterator.next()); case GREATER_THAN_EQUAL: return GreaterLessPredicate.ge(iterator.next()); case LESS_THAN: return GreaterLessPredicate.ls(iterator.next()); case LESS_THAN_EQUAL: return GreaterLessPredicate.le(iterator.next()); default: throw new InvalidDataAccessApiUsageException(String.format("Logic error for '%s' in query", type)); } }
@Override protected Object doExecute(final AbstractEbeanQuery ebeanQuery, Object[] values) { if (!SurroundingTransactionDetectorMethodInterceptor.INSTANCE.isSurroundingTransactionActive()) { throw new InvalidDataAccessApiUsageException(NO_SURROUNDING_TRANSACTION); } Object createQuery = ebeanQuery.createQuery(values); if (createQuery instanceof Query) { Query ormQuery = (Query) createQuery; QueryIterator<Object> iter = ormQuery.findIterate(); return StreamUtils.createStreamFromIterator(iter); } else if (createQuery instanceof SqlQuery) { throw new InvalidEbeanQueryMethodException("query must be Query"); } else { throw new InvalidEbeanQueryMethodException("query must be Query or SqlQuery"); } }
/** * 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; }
/** * Compile this JdbcCall using provided parameters and meta data plus other settings. * <p>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 call is executed. * @throws org.springframework.dao.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 (getProcedureName() == null) { throw new InvalidDataAccessApiUsageException("Procedure or Function name is required"); } try { this.jdbcTemplate.afterPropertiesSet(); } catch (IllegalArgumentException ex) { throw new InvalidDataAccessApiUsageException(ex.getMessage()); } compileInternal(); this.compiled = true; if (logger.isDebugEnabled()) { logger.debug("SqlCall for " + (isFunction() ? "function" : "procedure") + " [" + getProcedureName() + "] compiled"); } } }
@Test public void testQueryWithoutEnoughParams() { MappingSqlQuery<Integer> query = new MappingSqlQuery<Integer>() { @Override protected Integer mapRow(ResultSet rs, int rownum) throws SQLException { return rs.getInt(1); } }; query.setDataSource(dataSource); query.setSql(SELECT_ID_WHERE); query.declareParameter(new SqlParameter(COLUMN_NAMES[0], COLUMN_TYPES[0])); query.declareParameter(new SqlParameter(COLUMN_NAMES[1], COLUMN_TYPES[1])); query.compile(); thrown.expect(InvalidDataAccessApiUsageException.class); query.execute(); }
@Test public void testQueryWithMissingMapParams() { MappingSqlQuery<Integer> query = new MappingSqlQuery<Integer>() { @Override protected Integer mapRow(ResultSet rs, int rownum) throws SQLException { return rs.getInt(1); } }; query.setDataSource(dataSource); query.setSql(SELECT_ID_WHERE); query.declareParameter(new SqlParameter(COLUMN_NAMES[0], COLUMN_TYPES[0])); query.declareParameter(new SqlParameter(COLUMN_NAMES[1], COLUMN_TYPES[1])); query.compile(); thrown.expect(InvalidDataAccessApiUsageException.class); query.executeByNamedParam(Collections.singletonMap(COLUMN_NAMES[0], "value")); }
@Test public void convertParamMapToArray() { Map<String, String> paramMap = new HashMap<String, String>(); paramMap.put("a", "a"); paramMap.put("b", "b"); paramMap.put("c", "c"); assertSame(3, NamedParameterUtils.buildValueArray("xxx :a :b :c", paramMap).length); assertSame(5, NamedParameterUtils.buildValueArray("xxx :a :b :c xx :a :b", paramMap).length); assertSame(5, NamedParameterUtils.buildValueArray("xxx :a :a :a xx :a :a", paramMap).length); assertEquals("b", NamedParameterUtils.buildValueArray("xxx :a :b :c xx :a :b", paramMap)[4]); try { NamedParameterUtils.buildValueArray("xxx :a :b ?", paramMap); fail("mixed named parameters and ? placeholders not detected"); } catch (InvalidDataAccessApiUsageException expected) { } }
@Test public void testBatchUpdateWithNoBatchSupportAndSelect() throws Exception { final String[] sql = {"UPDATE NOSUCHTABLE SET DATE_DISPATCHED = SYSDATE WHERE ID = 1", "SELECT * FROM NOSUCHTABLE"}; given(this.statement.execute(sql[0])).willReturn(false); given(this.statement.getUpdateCount()).willReturn(1); given(this.statement.execute(sql[1])).willReturn(true); mockDatabaseMetaData(false); given(this.connection.createStatement()).willReturn(this.statement); JdbcTemplate template = new JdbcTemplate(this.dataSource, false); this.thrown.expect(InvalidDataAccessApiUsageException.class); try { template.batchUpdate(sql); } finally { verify(this.statement, never()).addBatch(anyString()); verify(this.statement).close(); verify(this.connection, atLeastOnce()).close(); } }
@Test public void testNoSuchTable() throws Exception { ResultSet resultSet = mock(ResultSet.class); given(resultSet.next()).willReturn(false); given(databaseMetaData.getDatabaseProductName()).willReturn("MyDB"); given(databaseMetaData.getDatabaseProductName()).willReturn("MyDB"); given(databaseMetaData.getDatabaseProductVersion()).willReturn("1.0"); given(databaseMetaData.getUserName()).willReturn("me"); given(databaseMetaData.storesLowerCaseIdentifiers()).willReturn(true); given(databaseMetaData.getTables(null, null, "x", null)).willReturn(resultSet); SimpleJdbcInsert insert = new SimpleJdbcInsert(dataSource).withTableName("x"); // Shouldn't succeed in inserting into table which doesn't exist thrown.expect(InvalidDataAccessApiUsageException.class); try { insert.execute(new HashMap<String, Object>()); } finally { verify(resultSet).close(); } }
public Response toResponse(Throwable ex, String paramete) { String shortDesc = ex.getMessage() == null ? ex.toString() : ex.getMessage(); String desc = paramete + "\n" + getStackTrace(ex); String title = "系统异常"; String time = GlobalUtils.formartDateTime(new Date()); if (ex instanceof SQLException) { title = "数据库异常"; if (messageManager != null) { messageManager.warnSMS(String.format(phoneDesc, title, shortDesc.substring(0, 40))); } } if (messageManager != null) { if (!(ex instanceof InvalidDataAccessApiUsageException)) { messageManager.warnMail("[java_web]" + title, String.format(mailDesc, time, title, desc)); } } logger.error(desc); ResponseBody resBody = new ResponseBody(); resBody.setCode(RtCodeConst.ERR_CODE); resBody.setMessage(shortDesc); ResponseBuilder rb = Response.status(Response.Status.OK); rb.type("application/json;charset=UTF-8"); rb.entity(resBody); return rb.build(); }
@Test(expected = InvalidDataAccessApiUsageException.class) public void testThreadSafeDeleteKey() { String key = "testThreadSafeDelete"; String newKey = "DEL_" + key; redis.delete(key); redis.delete(newKey); redis.opsForValue().setIfAbsent(key, String.valueOf(System.currentTimeMillis())); redis.expire(key, 10, TimeUnit.MINUTES); Boolean renameRet = redis.renameIfAbsent(key, newKey); Assert.assertTrue(renameRet); Long ttl = redis.getExpire(newKey); log.info("newKey:{} ttl:{}", newKey, ttl); Assert.assertNotNull("ttl not null", ttl); Assert.assertTrue("ttl > 0", ttl > 0); renameRet = redis.renameIfAbsent(key, newKey);//InvalidDataAccessApiUsageException: ERR no such key; nested exception is redis.clients.jedis.exceptions.JedisDataException: ERR no such key Assert.assertFalse(renameRet); redis.delete(newKey); renameRet = redis.renameIfAbsent(key, newKey); Assert.assertFalse(renameRet); }
@Override public void init(DataSource dataSource) throws Exception { Assert.notNull(dataSource, "data source must be specified"); Assert.hasLength(selectClause, "selectClause must be specified"); Assert.hasLength(fromClause, "fromClause must be specified"); Assert.notEmpty(sortKeys, "sortKey must be specified"); StringBuilder sql = new StringBuilder(); sql.append("SELECT ").append(selectClause); sql.append(" FROM ").append(fromClause); if (whereClause != null) { sql.append(" WHERE ").append(whereClause); } List<String> namedParameters = new ArrayList<String>(); parameterCount = JdbcParameterUtils.countParameterPlaceholders(sql.toString(), namedParameters); if (namedParameters.size() > 0) { if (parameterCount != namedParameters.size()) { throw new InvalidDataAccessApiUsageException( "You can't use both named parameters and classic \"?\" placeholders: " + sql); } usingNamedParameters = true; } }
public GigaSpace getClustered() { if (clusteredGigaSpace != null) { return clusteredGigaSpace; } if (this.space.isClustered()) { clusteredGigaSpace = this; } else { final DefaultGigaSpace newClusteredGigaSpace; try { newClusteredGigaSpace = new DefaultGigaSpace(this.space.getDirectProxy().getClusteredProxy(), this); } catch (Exception e) { throw new InvalidDataAccessApiUsageException("Failed to get clustered Space from actual space", e); } //GS-8287: try to assign the created single clustered GigaSpace instance to the volatile reference //but avoid locking at creation - we don't promise a single instance being returned. if (clusteredGigaSpace == null) { clusteredGigaSpace = newClusteredGigaSpace; } } return this.clusteredGigaSpace; }
/** * Compile this JdbcUpdate 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 update is executed. * * @throws org.springframework.dao.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("JdbcUpdate for table [" + getTableName() + "] compiled"); } } }
public Number getKey() throws InvalidDataAccessApiUsageException, DataRetrievalFailureException { if (this.keyList.size() == 0) { return null; } if (this.keyList.size() > 1 || this.keyList.get(0).size() > 1) { throw new InvalidDataAccessApiUsageException( "The getKey method should only be used when a single key is returned. " + "The current key entry contains multiple keys: " + this.keyList); } Iterator<Object> keyIter = this.keyList.get(0).values().iterator(); if (keyIter.hasNext()) { Object key = keyIter.next(); if (!(key instanceof Number)) { throw new DataRetrievalFailureException( "The generated key is not of a supported numeric type. " + "Unable to cast [" + (key != null ? key.getClass().getName() : null) + "] to [" + Number.class.getName() + "]"); } return (Number) key; } else { throw new DataRetrievalFailureException("Unable to retrieve the generated key. " + "Check that the table has an identity column enabled."); } }
public PreparedStatementCreatorImpl(String actualSql, List parameters) { this.actualSql = actualSql; Assert.notNull(parameters, "Parameters List must not be null"); this.parameters = parameters; if (this.parameters.size() != declaredParameters.size()) { // account for named parameters being used multiple times Set<String> names = new HashSet<String>(); for (int i = 0; i < parameters.size(); i++) { Object param = parameters.get(i); if (param instanceof SqlParameterValue) { names.add(((SqlParameterValue) param).getName()); } else { names.add("Parameter #" + i); } } if (names.size() != declaredParameters.size()) { throw new InvalidDataAccessApiUsageException( "SQL [" + sql + "]: given " + names.size() + " parameters but expected " + declaredParameters.size()); } } }