I'm developing a Spring Boot application using an embedded HSQLDB for local deployment. I defined the bean as follows
#Bean
public DataSource ds() {
return new EmbeddedDatabaseBuilder()
.setType(EmbeddedDatabaseType.HSQL)
.addScript("classpath:db/schema.sql")
.addScript("classpath:db/data.sql")
.build();
}
However, when I try to fetch all the entities from the database with JPA, I get an empty result.
I would like to execute query against the embedded database at runtime to see the actual data. What port/protocol the HSQLDB listens to, and what client I need to connect and execute query?
The solution was to add following properties to application.properties
spring.jpa.generate-ddl=false
spring.jpa.hibernate.ddl-auto=validate
This is because the default strategy for hibernate is to drop and re-create the the database schema for the entities it manages, which negated my database scripts.
Related
I have created an specific schema(example myschema) in aws postgre service and I am trying to connect with my spring boot application. But It is not working. I am successfully able to connect to public schema for aws postgre, but not able to connect with new schema created.
I have tried using below two method:
Appending schema in jdbc url: jdbc:postgresql://xxxxxxxxxx/mydatabase?currentSchema=myschema
But in here my application is performing CRUD in public schema.
I tried to add below two properties in application.properties ,
spring.datasource.hikari.schema=myschema AND
spring.jpa.properties.hibernate.default_schema=myschema
since I am using spring.jpa.hibernate.ddl-auto=validate, property, while starting spring application it is getting failed and showing error like "org.hibernate.tool.schema.spi.SchemaManagementException: Schema-validation: missing table"
but the table and required objects created.
Kindly suggest me related to this issue.
You have two options:
using of default_schema in application properties
spring.jpa.properties.hibernate.default_schema: my_custom_schema
explicitly specifying schema for each entity
#Entity
#Table(name = "my_table", schema = "my_custom_schema")
You don't need to patch jdbc url in any way.
I use hikari but I've never specified spring.datasource.hikari.schema. It looks redundant
My spring-boot app has following properties set,
spring.jpa.hibernate.ddl-auto=none
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/my-schema
spring.datasource.username=root
spring.datasource.password=*****
spring.flyway.check-location=false
spring.flyway.createSchemas=true
spring.flyway.schemas=my-schema
The schema 'my-schema' does not pre-exist and I would want for it to be created by flyway and then be used by spring-boot app to sping up HikarCP datasource.
If I run the application with the above configurations I get the following error upon startup:
Caused by: org.flywaydb.core.internal.exception.FlywaySqlException:
Unable to obtain connection from database: Unknown database 'my-schema'
Now, if I change,
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/
The application starts up perfectly and creates the schema. However, when it tries to query any table the thrown exception is:
java.sql.SQLException: No database selected
You can configure Flyway with a URL that's used purely for migrations and then configure your app to use a different URL. Something like this:
spring.flyway.url=jdbc:mysql://127.0.0.1:3306
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/my-schema
You'll also need to provide credentials for the Flyway-specific connection to the database using spring.flyway.user and spring.flyway.password.
I have developed spring-boot microservice and for Database interaction I am using jdbcTemplate. Currently I am placing all my queries in application.properties as below:
sql.select.query=update SCHEMA.TABLE_NAME set COL_NAME='ABC' where COL2_NAME='XYZ'
and in Dao Layer, Iam using this variable for query.
#Value{sql.select.query}
private query;
The above piece of code is fine and running as expected but now the requirement came up that Schema name should be segregated from query so that in future it can be changed.
I'm trying to write tests for a Spring Boot (Spring 4) Application.
My Junit test class is configured like this to allow autowired.
#RunWith(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(classes = SpringApp.class)
public class MyServiceTest {
...
My src/main/resources/application.properties is like this
spring.jpa.database=POSTGRESQL
spring.jpa.show-sql=false
spring.jpa.hibernate.ddl-auto=update
spring.datasource.driverClassName=org.postgresql.Driver
spring.datasource.url=jdbc:postgresql://localhost/mydb
spring.datasource.username=BNF0016779
spring.datasource.password=
In test context, src/test/resources/application.properties is just empty.
In can query the db as usual, creating objects...
But I'd like to create a data init sql.
To begin with a strange behavior, It seems that Spring loads any "schema.sql" in classpath.
Something like the following is not required ?
//This is not required to execute schema.sql
#Configuration
public class DatabaseTestConfig {
#Bean
public DataSource dataSource() {
return new EmbeddedDatabaseBuilder()
.setType(EmbeddedDatabaseType.H2)
.addScript("classpath:schema.sql")
.build();
}
}
Then, I can't create any Table from this SQL.
Always receive org.h2.jdbc.JdbcSQLException: Table "MY_TABLE" already exists; SQL statement:
H2 is supposed to be a in-memory DB, no keeping data between two startup !
Why do I receive these errors ?
Any ideas ?
Thanks
Spring Boot will in fact execute a file named schema.sql in the root of the classpath by default. Furthermore, Spring Boot will also automatically create an embedded database for your application unless you instruct it otherwise. Consult the "Initialize a database using Spring JDBC" section of the Spring Boot reference manual for details.
H2 is supposed to be a in-memory DB, no keeping data between two
startup !
Yes and no.
If Spring Boot creates an embedded H2 database for you, yes it will be in-memory.
However, the database is actually a bean in the ApplicationContext (just like any other Spring-managed component). Thus it lives as long as the ApplicationContext lives, and the Spring TestContext Framework caches contexts between tests: that's one of its main features. In other words, the embedded database will not be recreated between tests (unless you annotate your test classes or test methods with #DirtiesContext). Consult the Context caching section of the Spring Framework reference manual for details.
Regards,
Sam (author of the Spring TestContext Framework)
H2 can be in memory. But I'm assuming the default DataSource it uses is not.
You can set the DataSourceFactory on the EmbeddedDatabaseBuilder to generate a DataSource that connects with a url such as jdbc:h2:mem:test.
H2 has a range of compatibility modes for various other databases such as MS SQL Server, MySQL, Oracle, etc that support different SQL dialects. However, when setting up an embedded database in Spring I do not find any corresponding setting. Does this imply that I have to use "plain" SQL without any dialect specific features if I for example use Oracle in production and H2 during test? Have I overlooked something?
which version of H2 database? per the documentation, you can set compatible mode by SQL statement (http://www.h2database.com/html/features.html#compatibility)
SET MODE PostgreSQL
just add this statement into your first sql script file loaded by Spring jdbc embedded-database
According to the H2 doc, the Oracle compatibility mode is quite limited.
For instance, you can not use PL/SQL procedures.
If you use Spring's EmbeddedDatabase, you cannot set the compatibility mode as-is; you have to implement you own EmbeddedDatabaseConfigurer and specify the compatibility mode through the JDBC URL (see below).
But also, to use the compatibility mode with H2 and Spring, you just have to set the mode in your JDBC URL (so it is not Spring related) in a classic way, using a DataSource:
jdbc:h2:~/test;MODE=Oracle
And if you use Hibernate, you have to specify the Oracle dialect instead of the H2 one.
You have 2 options:
use spring to start the H2 database as follows (check setName() to see how to pass H2 specific URL parameters to spring builder):
Spring code generates the URL as follows:
String.format("jdbc:h2:mem:%s;DB_CLOSE_DELAY=-1", databaseName)
So, in setName() you can all any H2 specific parameter in the URL.
private DataSource dataSource() {
EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder();
EmbeddedDatabase db = builder
.setType(EmbeddedDatabaseType.H2)
.setName("testdb;DATABASE_TO_UPPER=false;MODE=Oracle")
.addScript("schema.sql")
.addScript("data.sql")
.build();
return db;
}
configure directly the DB URL, sth like:
org.h2.jdbcx.JdbcDataSource dataSource = new org.h2.jdbcx.JdbcDataSource();
dataSource.setURL("jdbc:h2:testdb;MODE=MySQL;DATABASE_TO_UPPER=false;INIT=runscript from 'src/test/resources/schema.sql'\;runscript from 'src/test/resources/data.sql'");
The main different is that (2) is executing scripts defined at INIT for every database connection creation and not once per DB creation! This causes various issues, like INSERTs failing due to duplicate keys etc..