I'm using hibernate to manage DB operations and MySQL in my application - use org.hibernate.dialect.MySQLInnoDBDialect as the hibernate dialect. But for testing purposes I'm using HSQLDB 1.8.0.10.
I have problem with query like this (working good on mysql not on hsql):
SELECT DISTINCT(id) FROM table ORDER BY name;
I know that the problem is with distinct and order by (http://weblogs.sqlteam.com/jeffs/archive/2007/12/13/select-distinct-order-by-error.aspx ) and solution of this could be for example:
SELECT DISTINCT(id) FROM table GROUP BY id ORDER BY MAX(name);
But my question is, if there is any possibility to using MySQL dialect in HSQLDB and not have to using this solution?
HSQLDB implements the SQL Standard correctly and does not allow the ambiguous query. It is not possible to change its behaviour.
It is better to modify your MySQL queries to be standard compliant. This allows you to port your application to another database more easily.
Related
In my current project, I am doing migration from Oracle to Azure SQL Server. Right now, we need to integrate both database working with same queries. Depending on what I have on my configuration, project will connect with Oracle or Azure SQL.
Problem is, there are some queries that are not compatible for both database types. For instance, nextval works for Oracle, but not with Azure SQL:
In Oracle:
... values(unique_id_seq.nextval ...
In Azure SQL:
... values(NEXT VALUE FOR unique_id_seq, ...
Therefore, I think I will need to create two different queries and my project should know which database I am loading and it should map to correct query. Is this possible to achieve in springboot? I am pretty new to springboot..
(One of my co-worker said If possible try to convert query into HQL or add the mapping entity, instead of creating separate queries., but I am not sure what this means.)
Try using Spring Boot with Hibernate.
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
I am new to Hibernate. While reading Hibernate, I came across the Dialect property. Whatever database we will use in our application, we need to set dialect related to that database and Hibernate will generate appropriate query related to that database.
Just want to know if it is the mandatory property to be set? If it is not and not specified in the hibernate.cfg.xml file, then how will Hibernate generate the SQL queries i.e. which database compliant SQL query will be generated?
No it is not mandatory as per documentation
http://docs.jboss.org/hibernate/orm/3.3/reference/en/html/session-configuration.html#configuration-optional-dialects
, I had not try with the same. While your answer of others points I will also like to get answer from some good experienced here. :)
I think it's not mandatory but it's a good practice to set it in your hibernate.cfg.xml as
<property name="dialect">your dialect</property>
posible values:
DB2 org.hibernate.dialect.DB2Dialect
DB2 AS/400 org.hibernate.dialect.DB2400Dialect
DB2 OS390 org.hibernate.dialect.DB2390Dialect
PostgreSQL org.hibernate.dialect.PostgreSQLDialect
MySQL org.hibernate.dialect.MySQLDialect
MySQL with InnoDB org.hibernate.dialect.MySQLInnoDBDialect
MySQL with MyISAM org.hibernate.dialect.MySQLMyISAMDialect
Oracle (any version) org.hibernate.dialect.OracleDialect
Oracle 9i org.hibernate.dialect.Oracle9iDialect
Oracle 10g org.hibernate.dialect.Oracle10gDialect
Sybase org.hibernate.dialect.SybaseDialect
Sybase Anywhere org.hibernate.dialect.SybaseAnywhereDialect
Microsoft SQL Server org.hibernate.dialect.SQLServerDialect
SAP DB org.hibernate.dialect.SAPDBDialect
Informix org.hibernate.dialect.InformixDialect
HypersonicSQL org.hibernate.dialect.HSQLDialect
Ingres org.hibernate.dialect.IngresDialect
Progress org.hibernate.dialect.ProgressDialect
Mckoi SQL org.hibernate.dialect.MckoiDialect
Interbase org.hibernate.dialect.InterbaseDialect
Pointbase org.hibernate.dialect.PointbaseDialect
FrontBase org.hibernate.dialect.FrontbaseDialect
Firebird org.hibernate.dialect.FirebirdDialect
This is why...
You do not need the dialect property if you set up your database connection with hibernate configuration because hibernate does it for you:
hibernate.connection.driver
hibernate.connection.url
user configs and etc...
However, if you set up the connection with regular data source code and use hibernate you need to specify the hibernate.dialect property, because then the connection will not know what hibernate dialect.
dataSource.setdriverClassName
datasource.setUrl...
password configs and etc...
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