/** * Create a new ArgTypePreparedStatementSetter for the given arguments. * @param args the arguments to set * @param argTypes the corresponding SQL types of the arguments */ public ArgumentTypePreparedStatementSetter(@Nullable Object[] args, @Nullable int[] argTypes) { if ((args != null && argTypes == null) || (args == null && argTypes != null) || (args != null && args.length != argTypes.length)) { throw new InvalidDataAccessApiUsageException("args and argTypes parameters must match"); } this.args = args; this.argTypes = argTypes; }
@Override @Nullable public Map<String, Object> getKeys() throws InvalidDataAccessApiUsageException { if (this.keyList.isEmpty()) { return null; } if (this.keyList.size() > 1) { throw new InvalidDataAccessApiUsageException( "The getKeys method should only be used when keys for a single row are returned. " + "The current key list contains keys for multiple rows: " + this.keyList); } return this.keyList.get(0); }
/** * Set whether prepared statements should be capable of returning * auto-generated keys. * @see java.sql.Connection#prepareStatement(String, int) */ public void setReturnGeneratedKeys(boolean returnGeneratedKeys) { if (isCompiled()) { throw new InvalidDataAccessApiUsageException( "The returnGeneratedKeys flag must be set before the operation is compiled"); } this.returnGeneratedKeys = returnGeneratedKeys; }
/** * Method to check whether we are allowed to make any configuration changes at this time. * If the class has been compiled, then no further changes to the configuration are allowed. */ protected void checkIfConfigurationModificationIsAllowed() { if (isCompiled()) { throw new InvalidDataAccessApiUsageException( "Configuration cannot be altered once the class has been compiled or used"); } }
/** * Validate the given parameter count against the given declared parameters. * @param suppliedParamCount the number of actual parameters given * @param declaredInParamCount the number of input parameters declared */ private void validateParameterCount(int suppliedParamCount, int declaredInParamCount) { if (suppliedParamCount < declaredInParamCount) { throw new InvalidDataAccessApiUsageException(suppliedParamCount + " parameters were supplied, but " + declaredInParamCount + " in parameters were declared in class [" + getClass().getName() + "]"); } if (suppliedParamCount > this.declaredParameters.size() && !allowsUnusedParameters()) { throw new InvalidDataAccessApiUsageException(suppliedParamCount + " parameters were supplied, but " + declaredInParamCount + " parameters were declared in class [" + getClass().getName() + "]"); } }
/** * Set whether to use statements that are capable of returning * updatable ResultSets. * @see java.sql.Connection#prepareStatement(String, int, int) */ public void setUpdatableResults(boolean updatableResults) { if (isCompiled()) { throw new InvalidDataAccessApiUsageException( "The updateableResults flag must be set before the operation is compiled"); } this.updatableResults = updatableResults; }
/** * Set the column names of the auto-generated keys. * @see java.sql.Connection#prepareStatement(String, String[]) */ public void setGeneratedKeysColumnNames(@Nullable String... names) { if (isCompiled()) { throw new InvalidDataAccessApiUsageException( "The column names for the generated keys must be set before the operation is compiled"); } this.generatedKeysColumnNames = names; }
/** * Set the class that each row should be mapped to. */ public void setMappedClass(Class<T> mappedClass) { if (this.mappedClass == null) { initialize(mappedClass); } else { if (this.mappedClass != mappedClass) { throw new InvalidDataAccessApiUsageException("The mapped class can not be reassigned to map to " + mappedClass + " since it is already providing mapping for " + this.mappedClass); } } }
/** * Add one or more declared parameters. Used for configuring this operation * when used in a bean factory. Each parameter will specify SQL type and (optionally) * the parameter's name. * @param parameters an array containing the declared {@link SqlParameter} objects * @see #declaredParameters */ public void setParameters(SqlParameter... parameters) { if (isCompiled()) { throw new InvalidDataAccessApiUsageException("Cannot add parameters once the query is compiled"); } for (int i = 0; i < parameters.length; i++) { if (parameters[i] != null) { this.declaredParameters.add(parameters[i]); } else { throw new InvalidDataAccessApiUsageException("Cannot add parameter at index " + i + " from " + Arrays.asList(parameters) + " since it is 'null'"); } } }
/** * Declare a parameter for this operation. * <p>The order in which this method is called is significant when using * positional parameters. It is not significant when using named parameters * with named SqlParameter objects here; it remains significant when using * named parameters in combination with unnamed SqlParameter objects here. * @param param the SqlParameter to add. This will specify SQL type and (optionally) * the parameter's name. Note that you typically use the {@link SqlParameter} class * itself here, not any of its subclasses. * @throws InvalidDataAccessApiUsageException if the operation is already compiled, * and hence cannot be configured further */ public void declareParameter(SqlParameter param) throws InvalidDataAccessApiUsageException { if (isCompiled()) { throw new InvalidDataAccessApiUsageException("Cannot add parameters once the query is compiled"); } this.declaredParameters.add(param); }
/** * Add a declared parameter to the list of parameters for the call. * <p>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()); } }
/** * Declare a parameter. Overridden method. * Parameters declared as {@code SqlParameter} and {@code SqlInOutParameter} * will always be used to provide input values. In addition to this any parameter declared * as {@code SqlOutParameter} where an non-null input value is provided will also be used * as an input paraneter. * <b>Note: Calls to declareParameter must be made in the same order as * they appear in the database's stored procedure parameter list.</b> * Names are purely used to help mapping. * @param param parameter object */ @Override public void declareParameter(SqlParameter param) throws InvalidDataAccessApiUsageException { if (param.getName() == null) { throw new InvalidDataAccessApiUsageException("Parameters to stored procedures must have names as well as types"); } super.declareParameter(param); }
/** * Add anonymous parameters, specifying only their SQL types * as defined in the {@code java.sql.Types} class. * <p>Parameter ordering is significant. This method is an alternative * to the {@link #declareParameter} method, which should normally be preferred. * @param types array of SQL types as defined in the * {@code java.sql.Types} class * @throws InvalidDataAccessApiUsageException if the operation is already compiled */ public void setTypes(@Nullable int[] types) throws InvalidDataAccessApiUsageException { if (isCompiled()) { throw new InvalidDataAccessApiUsageException("Cannot add parameters once query is compiled"); } if (types != null) { for (int type : types) { declareParameter(new SqlParameter(type)); } } }
/** * Check whether write operations are allowed on the given Session. * <p>Default implementation throws an InvalidDataAccessApiUsageException in * case of {@code FlushMode.MANUAL}. Can be overridden in subclasses. * @param session current Hibernate Session * @throws InvalidDataAccessApiUsageException if write operations are not allowed * @see #setCheckWriteOperations * @see Session#getFlushMode() * @see FlushMode#MANUAL */ protected void checkWriteOperationAllowed(Session session) throws InvalidDataAccessApiUsageException { if (isCheckWriteOperations() && SessionFactoryUtils.getFlushMode(session).lessThan(FlushMode.COMMIT)) { throw new InvalidDataAccessApiUsageException( "Write operations are not allowed in read-only mode (FlushMode.MANUAL): "+ "Turn your Session into FlushMode.COMMIT/AUTO or remove 'readOnly' marker from transaction definition."); } }
@Override public void discard() { if (isQueueing()) { syncFuture(executorService.writeAsync(null, RedisCommands.DISCARD)); resetConnection(); } else { throw new InvalidDataAccessApiUsageException("Not in transaction mode. Please invoke multi method"); } }
@Override public void discard() { if (isQueueing()) { syncFuture(executorService.writeAsync(null, RedisCommands.DISCARD)); resetConnection(); } else { throw new InvalidDataAccessApiUsageException("Not in transaction mode. Please invoke multi method"); } }
/** * Method to execute the update given arguments and * retrieve the generated keys using a KeyHolder. * @param params array of parameter objects * @param generatedKeyHolder the KeyHolder that will hold the generated keys * @return the number of rows affected by the update */ public int update(Object[] params, KeyHolder generatedKeyHolder) throws DataAccessException { if (!isReturnGeneratedKeys() && getGeneratedKeysColumnNames() == null) { throw new InvalidDataAccessApiUsageException( "The update method taking a KeyHolder should only be used when generated keys have " + "been configured by calling either 'setReturnGeneratedKeys' or " + "'setGeneratedKeysColumnNames'."); } validateParameters(params); int rowsAffected = getJdbcTemplate().update(newPreparedStatementCreator(params), generatedKeyHolder); checkRowsAffected(rowsAffected); return rowsAffected; }
@Test public void exceptionTranslationWithTranslation() { MapPersistenceExceptionTranslator mpet = new MapPersistenceExceptionTranslator(); RuntimeException in = new RuntimeException("in"); InvalidDataAccessApiUsageException out = new InvalidDataAccessApiUsageException("out"); mpet.addTranslation(in, out); assertSame(out, DataAccessUtils.translateIfNecessary(in, mpet)); }
protected RepositoryInterface createProxy(RepositoryInterfaceImpl target) { MapPersistenceExceptionTranslator mpet = new MapPersistenceExceptionTranslator(); mpet.addTranslation(persistenceException1, new InvalidDataAccessApiUsageException("", persistenceException1)); ProxyFactory pf = new ProxyFactory(target); pf.addInterface(RepositoryInterface.class); addPersistenceExceptionTranslation(pf, mpet); return (RepositoryInterface) pf.getProxy(); }
@Test public void testExecuteClosed() throws Exception { given(this.resultSet.next()).willReturn(true); given(this.callableStatement.execute()).willReturn(true); given(this.callableStatement.getUpdateCount()).willReturn(-1); SqlParameter param = new SqlReturnResultSet("", (RowCallbackHandler) rs -> { throw new InvalidDataAccessApiUsageException(""); }); this.thrown.expect(InvalidDataAccessApiUsageException.class); try { this.template.call(conn -> conn.prepareCall("my query"), Collections.singletonList(param)); } finally { verify(this.resultSet).close(); verify(this.callableStatement).close(); verify(this.connection).close(); } }