I'm getting this exception:
org.h2.jdbc.JdbcSQLException:
Table "CUSTOMERS" not found; SQL statement:
SELECT * FROM CUSTOMERS
This is the H2 Console. I have created a table there:
I have the application.yml file. I have tried to add DB_CLOSE_DELAY=-1 and DATABASE_TO_UPPER=false as well:
spring:
database:
url: jdbc:h2:mem:testdb
h2:
console.enabled: true
Also, I have a configuration class, where I have created the H2 Embedded Database:
#Bean
public DataSource dataSource() {
return new EmbeddedDatabaseBuilder().setType(EmbeddedDatabaseType.H2).build();
}
Finally, the query. The table is named CUSTOMERS:
public List<Customer> getAll() {
return jdbcTemplate.query("SELECT * FROM CUSTOMERS", (resultSet, rowNum) -> {
Customer customer = new Customer();
customer.setId(resultSet.getLong("id"));
customer.setName(resultSet.getString("name"));
customer.setAge(resultSet.getInt("age"));
return customer;
});
}
What should I do?
I had the same concern as you for a few days.
I solved it by adding this:
;TRACE_LEVEL_FILE=3;TRACE_LEVEL_SYSTEM_OUT=3
ie : jdbc:h2:mem:testdb;TRACE_LEVEL_FILE=3;TRACE_LEVEL_SYSTEM_OUT=3
It helps to know why H2 has a problem.
Usually it is a keyword problem.
You can ignore it by using NON_KEYWORDS : https://www.h2database.com/html/commands.html#set_non_keywords
I use social login in a spring boot container. This works fine, but when I keep the browser open over night, the next morning I cannot login any more. I need to restart the container and refresh the website, after this it works again.
I hope to get this work by storing the authentication token also in the database by adding JdbcOAuth2AuthorizedClientService. Now, and this is the actual problem, the token is NOT PERSITED although I get these lines in the log:
o.s.jdbc.core.JdbcTemplate : Executing prepared SQL query
o.s.jdbc.core.JdbcTemplate : Executing prepared SQL statement [SELECT client_registration_id, principal_name, access_token_type, access_token_value, access_token_issued_at, access_token_expires_at, access_token_scopes, refresh_token_value, refresh_token_issued_at FROM oauth2_authorized_client WHERE client_registration_id = ? AND principal_name = ?]
o.s.jdbc.datasource.DataSourceUtils : Fetching JDBC Connection from DataSource
o.s.jdbc.core.StatementCreatorUtils : Setting SQL statement parameter value: column index 1, parameter value [google], value class [java.lang.String], SQL type 12
o.s.jdbc.core.StatementCreatorUtils : Setting SQL statement parameter value: column index 2, parameter value [XXXXXX], value class [java.lang.String], SQL type 12
o.s.jdbc.core.JdbcTemplate : Executing prepared SQL update
o.s.jdbc.core.JdbcTemplate : Executing prepared SQL statement [INSERT INTO oauth2_authorized_client (client_registration_id, principal_name, access_token_type, access_token_value, access_token_issued_at, access_token_expires_at, access_token_scopes, refresh_token_value, refresh_token_issued_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)]
o.s.jdbc.datasource.DataSourceUtils : Fetching JDBC Connection from DataSource
o.s.jdbc.core.StatementCreatorUtils : Setting SQL statement parameter value: column index 1, parameter value [google], value class [java.lang.String], SQL type 12
o.s.jdbc.core.StatementCreatorUtils : Setting SQL statement parameter value: column index 2, parameter value [XXXXXX], value class [java.lang.String], SQL type 12
o.s.jdbc.core.StatementCreatorUtils : Setting SQL statement parameter value: column index 3, parameter value [Bearer], value class [java.lang.String], SQL type 12
o.s.jdbc.support.lob.DefaultLobHandler : Set bytes for BLOB with length 165
o.s.jdbc.core.StatementCreatorUtils : Setting SQL statement parameter value: column index 5, parameter value [2022-04-25 09:56:57.137607903], value class [java.sql.Timestamp], SQL type 93
o.s.jdbc.core.StatementCreatorUtils : Setting SQL statement parameter value: column index 6, parameter value [2022-04-25 10:56:56.137607903], value class [java.sql.Timestamp], SQL type 93
o.s.jdbc.core.StatementCreatorUtils : Setting SQL statement parameter value: column index 7, parameter value [https://www.googleapis.com/auth/userinfo.profile,https://www.googleapis.com/auth/userinfo.email,openid], value class [java.lang.String], SQL type 12
o.s.jdbc.support.lob.DefaultLobHandler : Set BLOB to null
o.s.jdbc.core.StatementCreatorUtils : Setting SQL statement parameter value: column index 9, parameter value [null], value class [null], SQL type 93
o.s.jdbc.core.JdbcTemplate : SQL update affected 1 rows
The table keeps empty. I tried with H2 and also PostgreSQL but no difference. The application itself is able to write records to tables using Spring data. No problem at all.
Has anyone an idea? I appriciate for every hint :-)
Thx,
SteveP
This is my security configuration:
#Configuration
#EnableWebSecurity
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
#Autowired final MyAppMemberService memberService;
#Autowired private MyAppProperties properties;
#Resource private ClientRegistrationRepository repo;
#Resource private DataSource dataSource;
#Override
protected void configure(final HttpSecurity http) throws Exception {
final RequestMatcher[] unprotectedGuiApi = new RequestMatcher[] {
new AntPathRequestMatcher("/api/v*/gui/currentUser"),
new AntPathRequestMatcher("/api/v*/gui/oauth2-clients"),
};
final RequestMatcher[] administrationApi = new RequestMatcher[] {
new AntPathRequestMatcher("/api/v*/administration/**")
};
final RequestMatcher[] guiApi = new RequestMatcher[] {
new AntPathRequestMatcher("/api/v*/**"),
new AntPathRequestMatcher("/logout"),
new AntPathRequestMatcher("/**/oauth2/**"),
};
http
.requestMatchers()
.requestMatchers(guiApi)
.and()
.csrf()
.disable()
.cors()
.configurationSource(httpRequest -> properties.getCors())
.and()
.headers()
.contentTypeOptions().disable()
.frameOptions().disable()
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
.and()
.authorizeRequests()
.antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
.antMatchers("**/websocket/**").permitAll()
.requestMatchers(unprotectedGuiApi).permitAll()
.requestMatchers(administrationApi).hasRole(Role.ADMIN.name())
.anyRequest().authenticated()
.and()
.logout()
.permitAll()
.logoutSuccessUrl(properties.getGatewayUrl()) // SPA endpoint
.and()
.oauth2Login()
.loginPage(properties.getGatewayUrl() + "/login")
.authorizedClientService(oAuth2AuthorizedClientService())
.userInfoEndpoint()
.userService(oauth2UserService())
.and()
.successHandler(authenticationSuccessHandler());
}
#Bean
public AuthenticationSuccessHandler authenticationSuccessHandler() {
// just registers new users on successful auth
return new MyAppAuthenticationSuccessHandler(properties, memberService);
}
#Bean
public OAuth2UserService oauth2UserService() {
// load member and roles from database
return new MyAppOAuth2UserService(memberService);
}
#Bean
public OAuth2AuthorizedClientService oAuth2AuthorizedClientService() {
return new JdbcOAuth2AuthorizedClientService(new JdbcTemplate(dataSource), repo);
}
}
This post brought me the idea that it might not be committed into DB:
When sharing a Jdbc connection pool between spring-data-jpa and spring-security-oauth's JdbcTokenStore, how to handle transactions?
Using this logging technique I could see the INSERT-statement was sent to DB
https://vladmihalcea.com/the-best-way-to-log-jdbc-statements/
but no final log statement
o.s.jdbc.core.JdbcTemplate : SQL update affected 1 rows
I adopted my WebSecurityConfiguration like this:
#Bean
public OAuth2AuthorizedClientService oAuth2AuthorizedClientService() {
return new TransactionalJdbcOAuth2AuthorizedClientService(jdbcTemplate, repo);
}
and added:
#Transactional(propagation = Propagation.REQUIRES_NEW)
public class TransactionalJdbcOAuth2AuthorizedClientService extends JdbcOAuth2AuthorizedClientService {
public TransactionalJdbcOAuth2AuthorizedClientService(final JdbcOperations jdbcOperations, final ClientRegistrationRepository clientRegistrationRepository) {
super(jdbcOperations, clientRegistrationRepository);
}
#Override
public <T extends OAuth2AuthorizedClient> T loadAuthorizedClient(final String clientRegistrationId, final String principalName) {
return super.loadAuthorizedClient(clientRegistrationId, principalName);
}
#Override
public void saveAuthorizedClient(final OAuth2AuthorizedClient authorizedClient, final Authentication principal) {
super.saveAuthorizedClient(authorizedClient, principal);
}
#Override
public void removeAuthorizedClient( final String clientRegistrationId, final String principalName) {
super.removeAuthorizedClient(clientRegistrationId, principalName);
}
}
Now it is persisted! I asked myself: Am I the first person using Spring's JdbcOAuth2AuthorizedClientService? No hint in the JavaDoc or in any Spring documentation. Anyway, hopefully this hint will help someone else.
I am getting a bad SQL grammer error when trying to run this.
public List<UserTemp> findByID(Integer PatientNumber) {
String sql = "SELECT PatientNumber,FirstName,Surname from paitents WHERE 'PatientNumber' = ?,PatientNumber";
return jdbcTemplate.query(sql,
(rs, rowNum) ->
new UserTemp(
rs.getInt("PatientNumber"),
rs.getString("FirstName"),
rs.getString("Surname")
));
}
I am trying to select a patient based on the PatientNumber
Is your table called paitents or patients?
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
I'm trying to use ResultSetExtractor to send a SQL statement to the database, but the method is getting stuck at the line l.setId(resultSet.getInt("Id"));.
This is my error message:
"message": "PreparedStatementCallback; uncategorized SQLException for
SQL [SELECT Cities.Name FROM cities INNER JOIN Notes on Cities.Id = Notes.CitiesId WHERE Notes.CitiesId = ? AND Notes.id = ?]; SQL state [S0022]; error code [0]; Column 'Id' not
found.; nested exception is java.sql.SQLException: Column 'Id' not
found.",
The Cities table has 3 columns named Id, Name, and Code. I checked my SQL statement in Workbench and it is correct. What's wrong with my code?
public List<Cities> GetCity(String CityId, String NoteId) {
final String sql = "SELECT Cities.Name FROM cities INNER JOIN Notes on Cities.Id = Notes.CitiesId WHERE Notes.CitiesId = ? AND Notes.id = ?";
final List<Cities> cityList = jdbcTemplate.query(sql, new ResultSetExtractor<List<Cities>>() {
#Override
public List<Cities> extractData(ResultSet resultSet) throws SQLException, DataAccessException {
List<Cities> list = new ArrayList<Cities>();
while (resultSet.next()) {
Cities l = new Cities();
l.setId(resultSet.getInt("Id"));
l.setName(resultSet.getString("Name"));
l.setCode(resultSet.getString("Code"));
list.add(l);
}
System.out.println(list);
return list;
}
}, CityId, NoteId);
return cityList;
}