I'm using Spring Boot and JDBC for my database connection. I placed schema.sql at the classpath to initialize a schema and tables.
Because the schema doesn't exist yet while connecting to the datasource, I have to configure the datasource in application.properties like so:
spring.datasource.url=jdbc:mysql://localhost:3306/
schema.sql:
CREATE DATABASE IF NOT EXISTS <schema_name>
USE <schema.name>;
CREATE TABLE...
So I select the schema after creating it. This obviously doesn't persist for too long.
How do I configure this properly? Is there a way to select a default schema after the create script or maybe change the datasource url?
With JDBC you need to use Connection.setCatalog to switch between databases. You should not use USE <databasename> as the JDBC driver itself needs to be aware of which database it is operating on.
Based on your code from the schema.sql
USE <schema.name>;
This will not work for your java environment. The schema.sql will be executed and finished, which will not cater your requirement to set the default schema.
The General approach will be to use JDBC URL as;
jdbc:mysql://localhost:3306/DB_NAME
This will set the default db as DB_NAME.
Assumptions: I am assuming that you want to connect to single node DB without any loadbalancer or failover mechanism to be used. URL may change based on these features to be configured.
If you are not specifying the DB_NAME in the URL, it means their is no default schema.
You have 2 options to access the DB in that case.
1) Always use the Connection.setCatalog() method to specify the desired database in JDBC applications, rather than the USE database statement.
2) fully specify table names using the database name (that is, SELECT dbname.tablename.colname FROM dbname.tablename...) in your SQL. Opening a connection without specifying the database to use is generally only useful when building tools that work with multiple databases, such as GUI database managers.
For more details refer to the below mysql portal for reference.
https://dev.mysql.com/doc/connector-j/en/connector-j-reference-configuration-properties.html
Related
What is the difference between spring.jpa.hibernate.hbm2ddl and spring.jpa.hibernate.ddl?
I have found in this question: What are the possible values of spring.datasource.initialization-mode? that OP is using both in properties, however it seems like the origin of hbm2ddl is hibernate directly not Spring Data Jpa.
Nevertheless, reading the answer from another OP, it looks like pass-through only.
However in our commercial project with mariadb, when we do not close our spring boot application gracefully with spring.jpa.hibernate.hbm2ddl.auto=create, when the application is run again, it deletes old data and creates everything from scratch. On the other hand with spring.jpa.hibernate.ddl.auto=create every second run (after no graceful application shutdown) causes key constraint exceptions (DB is not being dropper before creation)
From this Link
By default, JPA databases are automatically created only if you use an embedded database (H2, HSQL, or Derby).
You can explicitly configure JPA settings by using spring.jpa.* properties. For example, to create and drop tables you can add the following line to your application.properties:
spring.jpa.hibernate.ddl-auto=create-drop
Hibernate’s own internal property name for this (if you happen to remember it better) is hibernate.hbm2ddl.auto.
From this Link
spring.jpa.hibernate.ddl-auto This is actually a shortcut for the "hibernate.hbm2ddl.auto" property.
Defaults to "create-drop" when using an embedded database and no schema manager was detected. Otherwise, defaults to "none".
From this Link
Spring Boot can automatically create the schema (DDL scripts) of your DataSource and initialize it (DML scripts).
It loads SQL from the standard root classpath locations: schema.sql and data.sql, respectively.
In addition, Spring Boot processes the schema-${platform}.sql and data-${platform}.sql files (if present), where platform is the value of spring.datasource.platform.
This allows you to switch to database-specific scripts if necessary. For example, you might choose to set it to the vendor name of the database (hsqldb, h2, oracle, mysql, postgresql, and so on).
as the title says, I have an application (Spring Boot) which must execute some queries on specified objects on a SQL Server database. Such database having a single catalog and multiple schemas, which must be selected based on a previous query and some command line parameters.
I cannot seem to implement a strategy which involves Hibernate multi-tenancy, as most of the tutorials and answers on this site deal with schema names coming from a web request or an external parameter, while I need a database connection before creating the main multi-tenant EntityManager. So, I switched to a custom DataSource which tries to change the connection's default schema (using ALTER USER... WITH DEFAULT_SCHEMA = ...). But this also fails because the logged-in user does not have permission to alter his own default schema.
So I'm at a loss of what to do. Any suggestions?
Just create an EntityManager(Factory) per schema and put them in a map to choose from.
If you don't know the schemas before hand you can create EntityManager(Factory)s as soon as you learn about a schema.
that you can configure an EntityManagerFactory programatically.
do someone of you know a way to have 2 Databases running parallel?
We are using Hibernate 4 and as a main database Postgres 9.3 - this db is hosted on another machine then the application - if the database is down we still have to save some stuff.
So first intention was to write it into a csv, but I'm not a friend of writing stuff into an unordered file. So I want just to use a fallback Database (thinking of H2 Database). Does someone has experience with such a construct?
We are also using Spring 4 - I would just set up another datasource + sessionfactory + transactionmanager - and add the name at the #Transactional method to use the right manager. any other ideas?
Thank you!!
You can extend the Spring AbstractRoutingDataSource and configure two actual data sources:
a primary PostgreSQL data source
a secondary H2 data source
The application logic will see only one data source, which is the router which will decide which data source is going to switch to on demand.
When the primary data source is down you need to instruct the router to pick the fall-back H2 one.
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..
I used to run my Java code with Hibernate to mysql.
Some logical changes led me to decide that I don't need to save the data in the database, but in java class that will handle it as a database (The data is delete in every startup of the application).
How can I do in Hibernate? is there a way to create an in memory database?
Consider H2 (recommended) or HSQLDB. You can certainly use Hibernate with them. In fact, HSQLDB was the database used by default in Hibernate for their test suite (I think they just changed to H2).
Take a look at Apache Derby.
You could also use SqlLite, which is an in-memory database. I'm just about to start using it with NHibernate for the same purpose in unit tests.
You just need to:
add the driver for the database you want to use and change the hibernate settings for this driver,
change the setting hibernate database dialect,
change the jdbc connection String
(add the jars for the database)
For example for Hypersonic H2 Database:
driverClassName = org.h2.Driver
dialect = org.hibernate.dialect.H2Dialect
connection string = jdbc:h2:mem:test