I trying to use spring batch with storedProcedureItemReader
and always i get this exception
and i cant found the error i use Sybase at BBDD
org.springframework.batch.item.ItemStreamException: Failed to initialize the reader
Caused by: org.springframework.jdbc.BadSqlGrammarException: Executing stored procedure; bad SQL grammar [{call PROCEDURE(?)}]; nested exception is java.sql.SQLException: Invalid parameter index 0.
Caused by: java.sql.SQLException: Invalid parameter index 0.
this is java spring code
#Bean
protected ItemReader<AuditKpi> auditKpiRead(DataSource dataSource) throws Exception{
StoredProcedureItemReader<AuditKpi> storedProcedureItemReader = new StoredProcedureItemReader<AuditKpi>();
SqlParameter[] parameter = {new SqlParameter("#INDATE", Types.SQL_DATETIME)};
PreparedStatementSetter stament = new PreparedStatementSetter() {
#Override
public void setValues(PreparedStatement ps) throws SQLException {
ps.setDate(1, new java.sql.Date(new Date().getTime()));
}
};
storedProcedureItemReader.setDataSource(dataSource);
storedProcedureItemReader.setProcedureName("PROCEDURE");
storedProcedureItemReader.setRowMapper(new BeanPropertyRowMapper<AuditKpi>(AuditKpi.class));
storedProcedureItemReader.setParameters(parameter);
storedProcedureItemReader.setPreparedStatementSetter(stament);
storedProcedureItemReader.afterPropertiesSet();
storedProcedureItemReader.setVerifyCursorPosition(false);
System.out.println(storedProcedureItemReader.getSql());
return storedProcedureItemReader;
}
And this is my SQL code
CREATE PROCEDURE PROCEDURE (IN #INDATE DATE)
AS
...
GO
Thranks for your help
Related
I have a code, that when an error returns from a procedure, I need to update a table column in oracle. However, at the time of the update (inside the catch block), the following error occurs:
org.springframework.dao.ConcurrencyFailureException: PreparedStatementCallback; SQL [UPDATE TB_XPTO SET COLUMN_XPTO = XX WHERE ID_XPTO = ?]; ORA-02091: transação repetida
; nested exception is java.sql.SQLTransactionRollbackException: ORA-02091:
My code:
try {
jdbcTemplate.update ("call PROCEDURE_XPTO(?)", ID_XPTO);
} catch (Exception e) {
jdbcTemplate.update("UPDATE TB_XPTO SET COLUMN_XPTO = XX WHERE ID_XPTO = ?", idXpto);
}
My data source Config class
#Bean
public DataSourceBuilder<?> dataSourceBuilder(Environment springEnvironment) {
DataSourceBuilder<?> dataSourceBuilder = DataSourceBuilder.create();
dataSourceBuilder.driverClassName("oracle.jdbc.OracleDriver");
dataSourceBuilder.url("jdbc:oracle:thin:#//server:1521/database.com.br");
dataSourceBuilder.username("user");
dataSourceBuilder.password("pass");
return dataSourceBuilder;
}
#Bean
public DataSource getDataSource(DataSourceBuilder<?> dataSourceBuilder) {
return dataSourceBuilder.build();
}
Any idea ?
thanks for your answer, but worked for me, using #Transactional, in the method that calls the procedure.
I am continuously getting below error , I did enable transaction with #EnableTransactionManagement, but still somehow transaction is not invoked in DefaultTokenServices.
Any help will be much appreciated
Note: it was working with spring-boot 1.5 and recently I upgraded to 2.1
2020-11-19 18:27:12.385 ERROR 49065 [tomcat-exec-2] - o.s.s.o.provider.endpoint.TokenEndpoint : Handling error: TransientDataAccessResourceException, PreparedStatementCallback; SQL [insert into oauth_access_token (token_id, token, authentication_id, user_name, client_id, authentication, refresh_token) values (?, ?, ?, ?, ?, ?, ?)]; Connection is read-only. Queries leading to data modification are not allowed; nested exception is java.sql.SQLException: Connection is read-only. Queries leading to data modification are not allowed
org.springframework.dao.TransientDataAccessResourceException: PreparedStatementCallback; SQL [insert into oauth_access_token (token_id, token, authentication_id, user_name, client_id, authentication, refresh_token) values (?, ?, ?, ?, ?, ?, ?)]; Connection is read-only. Queries leading to data modification are not allowed; nested exception is java.sql.SQLException: Connection is read-only. Queries leading to data modification are not allowed
at org.springframework.jdbc.support.SQLStateSQLExceptionTranslator.doTranslate(SQLStateSQLExceptionTranslator.java:110)
at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:72)
at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:81)
at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:81)
solution
I am able to fix with hack by manually attaching transaction to oauth jdbctokenservice.
private static final String AOP_POINTCUT_EXPRESSION = "execution (* org.springframework.security.oauth2.provider.token.store.JdbcTokenStore.*(..))";
#Autowired
public void txAdvice(TransactionInterceptor txAdvice) throws NoSuchMethodException {
DefaultTransactionAttribute required = new DefaultTransactionAttribute();
MethodMapTransactionAttributeSource source = new MethodMapTransactionAttributeSource();
final Method method = JdbcTokenStore.class.getMethod("storeAccessToken", OAuth2AccessToken.class, OAuth2Authentication.class);
source.addTransactionalMethod(method, required);
txAdvice.setTransactionAttributeSource(source);
}
#Bean
public Advisor txAdviceAdvisor(TransactionInterceptor txAdvice) {
AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
pointcut.setExpression(AOP_POINTCUT_EXPRESSION);
return new DefaultPointcutAdvisor(pointcut, txAdvice);
}
I also created issue with spring-security-oauth but seems it is not supposed to support spring-boot 2.x.
Any Brilliant mind wanna help on why Transaction was not invoked in DefaultTokenServices.
Solution
Create Bean for DefaultTokenServices and pass it to configurer
#Autowired
private DefaultTokenServices tokenServices;
#Bean
#Primary
public DefaultTokenServices defaultTokenServices() {
DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
defaultTokenServices.setTokenStore(tokenStore);
return defaultTokenServices;
}
#Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints)
throws Exception {
endpoints.authorizationCodeServices(authorizationCodeServices())
.tokenStore(tokenStore)
.authenticationManager(auth)
.addInterceptor(handlerInterceptor)
.tokenServices(tokenServices)
.approvalStoreDisabled();
}
link: https://github.com/spring-projects/spring-security-oauth/issues/1900
Using the following code to get the list of data from table but getting invalid column error.
String sql = "select * from employees WHERE emp_status = :statusCode";
Map parameters = new HashMap();
parameters.put("statusCode", "Active");
MapSqlParameterSource parametersSourceMap = new MapSqlParameterSource(parameters );
List<Employee> employees rowSet = jdbcTemplate.queryForList(sql, parametersSourceMap);
Exception
Exception in thread "main" org.springframework.jdbc.UncategorizedSQLException: PreparedStatementCallback; uncategorized SQLException for SQL [select * from employees WHERE emp_status = :statusCode SQL state [null]; error code [17004]; Invalid column type; nested exception is java.sql.SQLException: Invalid column type
at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:83)
at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:80)
at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:80)
at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:603)
at org.springframework.jdbc.core.JdbcTemplate.update(JdbcTemplate.java:812)
at org.springframework.jdbc.core.JdbcTemplate.update(JdbcTemplate.java:868)
at org.springframework.jdbc.core.JdbcTemplate.update(JdbcTemplate.java:876)
at com.spring.EmployeeDAOImpl.addEmployee(EmployeeDAOImpl.java:46)
at com.spring.MainApp.main(MainApp.java:33)
Caused by: java.sql.SQLException: Invalid column type
Table have column as Varchar2
Anyone have idea why we can't get data based on String column?
I recently faced the same issue. In my case, I was using JdbcTemplate instead of NamedParameterJdbcTemplate. I am not sure if the issue is same for you.
You can define a bean of type NamedParameterJdbcTemplate and then autowire it in your repository class.
Configuration class :
#Bean
public NamedParameterJdbcTemplate yourNamedParameterJdbcTemplate(DataSource yourDataSource) {
return new NamedParameterJdbcTemplate(yourDataSource);
}
Repository class :
#Repository
public class YourRepositoryImpl implements YourRepository {
#Autowired
NamedParameterJdbcTemplate jdbcTemplate;
Try to pass parameters like this :
String sql = "SELECT * FROM employees WHERE emp_status = ?";
List<Employee> employees = jdbcTemplate.queryForList(
sql,
new Object[]{"Active"},
new BeanPropertyRowMapper<Employee>(Employee.class)
);
There is an oracle stored procedure:
test_owner.pkg_xyz.daycalculation(p_parameter = >"Tuesday");
My Simple JDBCCall to call Oracle procedure:
public class StoredExecuter {
*fields*
public void ExecuteDailyProced (String dayId) {
try {
String slqPackage = "pkg_xyz";
String procName = "daycalculation";
SimpleJdbcCall jdbcCall = new SimpleJdbcCall(jdbcTemplate)
.withSchemaName("test_owner")
.withCatalogName(sqlPackage)
.withProcedureName(procName)
.declaredParameters(new SqlParameter(dayId,OracleTypes.Varchar));
jdbcCall.setAccessCallParameterMetaData(false);
jdbcCall.execute();
}
catch(Exception e) {
throw new RunTimeException("Cannot perform procedure due to : " +e.getMessage(),e);
}
}
}
Exception:
java.lang.RuntimeException: Cannot perform procedure due to : 0
as tests.StoredExecuter.ExecuteDailyProced......
Caused by: java.lang.ArrayIndexOutOfBoundsException: 0
at org.springframework.jdbc.core.metadata.CallMetaDataContext.matchInParameterValuesWithCallParameters(CallMetaDataContext.java:577)
at org.springframework.jdbc.core.simple.AbstractJdbcCall.matchInParameterValuesWithCallParameters(AbstractJdbcCall.java:442)
at org.springframework.jdbc.core.simple.AbstractJdbcCall.doExecute(AbstractJdbcCall.java:376)
at org.springframework.jdbc.core.simple.SimpleJdbcCall.execute(SimpleJdbcCall.java:188)
Appreciate any help to resolve this problem!
Thank you
I have a stored procedure defined in PostgresSql as below:
CREATE OR REPLACE FUNCTION update_points(accountId bigint, points numeric(19,5)) RETURNS void AS $$
...
...
$$ LANGUAGE plpgsql;
And I call the following method to call the procedure:
public void updatePoints(final Account account, final BigDecimal points) {
SimpleJdbcCall simpleCall = new SimpleJdbcCall(coreJdbcTemplate).withFunctionName("update_points");
SqlParameterSource inputs = new MapSqlParameterSource()
.addValue("accountId", account.getId())
.addValue("points", points);
simpleCall.execute(inputs);
}
When the method is called, I get following spring error:
org.springframework.dao.DataIntegrityViolationException: CallableStatementCallback; SQL [{? = call update_points()}]; No value specified for parameter 1.; nested exception is org.postgresql.util.PSQLException: No value specified for parameter 1.
at org.springframework.jdbc.support.SQLStateSQLExceptionTranslator.doTranslate(SQLStateSQLExceptionTranslator.java:102)
at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:73)
at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:81)
at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:81)
at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:1137)
at org.springframework.jdbc.core.JdbcTemplate.call(JdbcTemplate.java:1173)
at org.springframework.jdbc.core.simple.AbstractJdbcCall.executeCallInternal(AbstractJdbcCall.java:388)
at org.springframework.jdbc.core.simple.AbstractJdbcCall.doExecute(AbstractJdbcCall.java:348)
at org.springframework.jdbc.core.simple.SimpleJdbcCall.execute(SimpleJdbcCall.java:190)
at net.exchangesolutions.veo.dao.AccountTransactionDaoImpl.updateRewardsConsumedAmount(AccountTransactionDaoImpl.java:28)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
I tried another way to call the procedure with CallableStatement in which case the function is not called at all.
Do you know what is the problem with the code or have you any suggestion about how to call the procedure from SpringJPA?
Thanks!
EDIT:
This is how I call with CallableStatement:
public void updatePoints(final Account account, final BigDecimal points) {
Connection connection;
try {
connection = coreJdbcTemplate.getDataSource().getConnection();
CallableStatement callableSt = connection.prepareCall("{call update_points(?, ?)}");
callableSt.setLong(1, account.getId());
callableSt.setBigDecimal(2, points);
callableSt.executeUpdate();
} catch (SQLException e) {
}
}
I resolved this problem by using following method. I could not figure out why the two approaches above did not work. Anyway, following solution is working now.
public void updatePoints(final Account account,
final BigDecimal points) {
coreJdbcTemplate.execute(new CallableStatementCreator() {
public CallableStatement createCallableStatement(Connection con)
throws SQLException {
CallableStatement cs = con
.prepareCall("{call update_points(?, ?)}");
cs.setLong(1, account.getId());
cs.setBigDecimal(2, points);
return cs;
}
}, new CallableStatementCallback() {
public Object doInCallableStatement(CallableStatement cs)
throws SQLException {
cs.execute();
return null;
}
});