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
Related
I have this repository class:
public interface ShiftRepository extends CrudRepository<Shift, Long> {
#Query("SELECT s FROM Shift s")
public List<Shift> getAllShifts();
}
All I want it to do is grab all shifts.
The Service calling it is just doing this:
public List<Shift> getAllShifts() {
return shiftRepository.getAllShifts();
}
And the Controller is just doing this:
public ResponseEntity<List<Shift>> getAllShifts() {
List<Shift> shifts;
try {
shifts = shiftService.getAllShifts();
} catch (Exception e) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(new ArrayList<>());
}
if (shifts != null) {
System.out.println(shifts.size());
return ResponseEntity.status(HttpStatus.OK).body(shifts);
} else {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(new ArrayList<>());
}
}
On the frontend I am getting this response.
Empty array of shifts
succesful 200 response
So I don't know what the issue is, I just want all the records. Using Spring boot and Heroku Postgres
application.yml:
spring:
jpa:
properties:
hibernate.default_schema: dev_env
hibernate:
ddl-auto: create-drop
database-platform: org.hibernate.dialect.PostgreSQLDialect
datasource:
hikari:
schema: dev_env
driverClassName: org.postgresql.Driver
type: org.apache.tomcat.jdbc.pool.DataSource
Your problem seems like in that Query annotation. You have to define value tag before your query. As:
#Query(value = "SELECT s FROM Shift s")
Sorry for wasting time. It's late was very enthralled in Spring boot and React debugging my application. Did not realize I had not populated database with test data XD
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 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 creating a quick project using R2DBC and H2 to familiarize myself with this new reactive stuff. Made a repository that extends ReactiveCrudRepository and all is well with the world, as long as i use the DatabaseClient to issue a CREATE TABLE statement that matches my entity first...
I understand spring data R2DBC is not as fully featured as spring data JPA (yet?) but is there currently a way to generate the schema from the entity classes?
Thanks
No, there is currently no way to generate schema from entities with Spring Data R2DBC.
I'm using it in a project with Postgres DB and it's complicated to manage database migrations, but I managed to wire in Flyway with synchronous Postgre driver (Flyway doesn't work with reactive drivers yet) at startup to handle schema migrations.
Even though you still have to write your own CREATE TABLE statements which shouldn't be that hard and you could even modify your entities in some simple project to create JPA entities and let Hibernate create schema then copy-paste it into a migration file in your R2DBC project.
It is possible for tests and for production.
I production make sure your user has no access to change schema otherwise you may delete tables by mistake!!! or use a migration tool like flyway.
You need to put your schema.sql in the main resources and add the relevant properties
spring.r2dbc.initialization-mode=always
h2 for test and postgres for prod
I use gradle and the versions of driver are:
implementation 'org.springframework.boot.experimental:spring-boot-actuator-autoconfigure-r2dbc'
runtimeOnly 'com.h2database:h2'
runtimeOnly 'io.r2dbc:r2dbc-h2'
runtimeOnly 'io.r2dbc:r2dbc-postgresql'
runtimeOnly 'org.postgresql:postgresql'
testImplementation 'org.springframework.boot.experimental:spring-boot-test-autoconfigure-r2dbc'
The BOM version is
dependencyManagement {
imports {
mavenBom 'org.springframework.boot.experimental:spring-boot-bom-r2dbc:0.1.0.M3'
}
}
That's how I solved this problem:
Controller:
#PostMapping(MAP + PATH_DDL_PROC_DB) //PATH_DDL_PROC_DB = "/database/{db}/{schema}/{table}"
public Flux<Object> createDbByDb(
#PathVariable("db") String db,
#PathVariable("schema") String schema,
#PathVariable("table") String table) {
return ddlProcService.createDbByDb(db,schema,table);
Service:
public Flux<Object> createDbByDb(String db,String schema,String table) {
return ddl.createDbByDb(db,schema,table);
}
Repository:
#Autowired
PostgresqlConnectionConfiguration.Builder connConfig;
public Flux<Object> createDbByDb(String db,String schema,String table) {
return createDb(db).thenMany(
Mono.from(connFactory(connConfig.database(db)).create())
.flatMapMany(
connection ->
Flux.from(connection
.createBatch()
.add(sqlCreateSchema(db))
.add(sqlCreateTable(db,table))
.add(sqlPopulateTable(db,table))
.execute()
)));
}
private Mono<Void> createDb(String db) {
PostgresqlConnectionFactory
connectionFactory = connFactory(connConfig);
DatabaseClient ddl = DatabaseClient.create(connectionFactory);
return ddl
.execute(sqlCreateDb(db))
.then();
}
Connection Class:
#Slf4j
#Configuration
#EnableR2dbcRepositories
public class Connection extends AbstractR2dbcConfiguration {
/*
**********************************************
* Spring Data JDBC:
* DDL: does not support JPA.
*
* R2DBC
* DDL:
* -does no support JPA
* -To achieve DDL, uses R2dbc.DataBaseClient
*
* DML:
* -it uses R2dbcREpositories
* -R2dbcRepositories is different than
* R2dbc.DataBaseClient
* ********************************************
*/
#Bean
public PostgresqlConnectionConfiguration.Builder connectionConfig() {
return PostgresqlConnectionConfiguration
.builder()
.host("db-r2dbc")
.port(5432)
.username("root")
.password("root");
}
#Bean
public PostgresqlConnectionFactory connectionFactory() {
return
new PostgresqlConnectionFactory(
connectionConfig().build()
);
}
}
DDL Scripts:
#Getter
#NoArgsConstructor(access = AccessLevel.PRIVATE)
public final class DDLScripts {
public static final String SQL_GET_TASK = "select * from tasks";
public static String sqlCreateDb(String db) {
String sql = "create database %1$s;";
String[] sql1OrderedParams = quotify(new String[]{db});
String finalSql = format(sql,(Object[]) sql1OrderedParams);
return finalSql;
}
public static String sqlCreateSchema(String schema) {
String sql = "create schema if not exists %1$s;";
String[] sql1OrderedParams = quotify(new String[]{schema});
return format(sql,(Object[]) sql1OrderedParams);
}
public static String sqlCreateTable(String schema,String table) {
String sql1 = "create table %1$s.%2$s " +
"(id serial not null constraint tasks_pk primary key, " +
"lastname varchar not null); ";
String[] sql1OrderedParams = quotify(new String[]{schema,table});
String sql1Final = format(sql1,(Object[]) sql1OrderedParams);
String sql2 = "alter table %1$s.%2$s owner to root; ";
String[] sql2OrderedParams = quotify(new String[]{schema,table});
String sql2Final = format(sql2,(Object[]) sql2OrderedParams);
return sql1Final + sql2Final;
}
public static String sqlPopulateTable(String schema,String table) {
String sql = "insert into %1$s.%2$s values (1, 'schema-table-%3$s');";
String[] sql1OrderedParams = quotify(new String[]{schema,table,schema});
return format(sql,(Object[]) sql1OrderedParams);
}
private static String[] quotify(String[] stringArray) {
String[] returnArray = new String[stringArray.length];
for (int i = 0; i < stringArray.length; i++) {
returnArray[i] = "\"" + stringArray[i] + "\"";
}
return returnArray;
}
}
It is actually possible to load a schema by defining a specific class in this way:
import io.r2dbc.spi.ConnectionFactory
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.core.io.ClassPathResource
import org.springframework.data.r2dbc.repository.config.EnableR2dbcRepositories
import org.springframework.r2dbc.connection.init.ConnectionFactoryInitializer
import org.springframework.r2dbc.connection.init.ResourceDatabasePopulator
#Configuration
#EnableR2dbcRepositories
class DbConfig {
#Bean
fun initializer(connectionFactory: ConnectionFactory): ConnectionFactoryInitializer {
val initializer = ConnectionFactoryInitializer()
initializer.setConnectionFactory(connectionFactory)
initializer.setDatabasePopulator(
ResourceDatabasePopulator(
ClassPathResource("schema.sql")
)
)
return initializer
}
}
Pay attention that IntelliJ gives an error "Could not autowire. No beans of 'ConnectionFactory' type found" but it is actually a false positive. So ignore it and build again your project.
The schema.sql file has to be put in resources folder.
I want to insert data into a table using the following code
public User registerUser(String usr, String pwd) {
u=em.find(User.class,usr);
if(u!=null)
{
return null;
}
String query1 = "insert into users values('" + usr + "','" + pwd +"')";
Query q = em.createQuery(query1);
u=em.find(User.class,usr);
return u;
}
here 'u' is the object of User class and em is EntityManager.
I get this following exception:
Servlet.service() for servlet action threw exception
org.hibernate.hql.ast.QuerySyntaxException: expecting OPEN, found 'values' near line 1, column 19 [insert into users values('pawan','am')]
Try
public User registerUser(String usr, String pwd) {
u=em.find(User.class,usr);
if(u!=null)
{
return null;
}
//Now saving...
em.getTransaction().begin();
em.persist(u); //em.merge(u); for updates
em.getTransaction().commit();
em.close();
return u;
}
If the PK is Identity, it will be set automatically in your persisted class, if you are using auto generation strategy (thanks to David Victor).
Edit to #aman_novice comment:
set it in your class
//Do this BEFORE getTransaction/persist/commit
//Set names are just a example, change it to your class setters
u.setUsr(usr);
u.setPwd(pwd);
//Now you can persist or merge it, as i said in the first example
em.getTransaction().begin();
(...)
About #David Victor, sorry I forgot about that.
You're not using SQL but JPAQL, there is no field-based insert. You persist object rather than inserting rows.
You should do something like this:
public User registerUser(String usr, String pwd) {
u=em.find(User.class,usr);
if(u!=null)
{
return u;
}
u = new User(usr, pwd);
em.persist(u);
return u;
}
This isn't really the way to go. You are trying to insert a row in a table but have no associated attached entity. If you're using the JPA entity manager - then create a new instance - set the properties & persist the entity.
E.g.
User u = new User();
u.setXXX(xx);
em.persist(u);
// em.flush() <<-- Not required, useful for seeing what is happening
// etc..
If you enable SQL loggging in Hibernate & flush the entity then you'll see what is sent to the database.
E.g. in persistence.xml:
<property name="hibernate.format_sql" value="true" />