h2 database Junit test case failing on executing 'INSERT IGNORE INTO ..' query? - java

I have this Spring Boot Application, where I have used h2 database to cover Junit test case. Everything is working fine until I have this new scenario where I need to execute a MySql query using jdbcTemplate.
The jdbcTemplate is to execute below query
'INSERT IGNORE INTO someTableName ......'
It is working fine when running the service and from postman getting successful response but jUnit test cases are started failing after this change.
I have used #DataJdbcTest annotation to support h2 database based jUnit test case.
I am pretty much sure the issue is due to IGNORE keyword in sql query, but I need to know if there is simple solution for this issue.

You could try h2's MySQL Compatibility Mode.
From their docs:
INSERT IGNORE is partially supported and may be used to skip rows with duplicate keys if ON DUPLICATE KEY UPDATE is not specified.

Related

HSQLDB SET DATABASE SQL SYNTAX: Table Data is Read Only

I am using HSQLDB for JUnit Tests, the test data is provided by XML Files with dbUnit. Our application uses an Oracle DB in production.
In order to suppert Oracle-specific queries I have added the property sql.syntax_ora=true to the url like this:
db.url=jdbc:hsqldb:mem:unitdb;sql.syntax_ora=true
When I run my JUnit test I get the exception
org.hsqldb.HsqlException: The table data is read only
I have also tried to execute the query SET DATABASE SQL SYNTAX ORA TRUE;
but this gives me the same exception.
Please help me with this problem. Thanks!

H2 Database doesn’t support schema.package.function structure

In my project we are using oracle database as the main application db and H2 as in memory database to run only the integration test cases. Oracle db has many functions which are of the structure "schema.package.function()". The problem is, i'm not able to recreate the same function in H2 for integration test cases as H2 treats it in the form of "dbname.schemaname.functionname()".
for example : When code runs with oracle db , "SELECT MDM.NEXT_KEYS.NEXT_REF_SOURCE_KEY from dual" works. During integration test case on H2, it throws error "DB MDM not found". So i set the db name as MDM and schema name as NEXT_KEYS in h2 setup.It worked. But my next function PAYERS.KEY_TRANSLATIONS.CORE_ENHANCED_DESC_4_KEY fails now saying "DB PAYERS not found".
Changing the oracle functions is out of the equation as they are used by multiple teams.
If this is not possible with H2 , can you suggest a good alternate in-memory db for spring boot
Appreciate your help !
I was able to fix the issue. Adding the solution link here so that it might help someone
Setting this flag IGNORE_CATALOGS=TRUE fixed the issue. When it is enabled, name of catalog (database) is ignored.
spring.datasource.url = jdbc:h2:mem:testdb;MODE=Oracle;IGNORE_CATALOGS=TRUE
Refer the below link https://github.com/h2database/h2database/issues/2893

How to map different queries for different database in one project in springboot?

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.

Run test insert scripts in before and after Junit testing Hibernate

I have a Junit test case for testing a method which require some initial data. The data required is not part of the current schema used by my hibernate project. So I cannot use model object to create that insert data. Is there any way to run sql scripts before and after running junit test ?
The Non Hibernate way is the following
Process p = Runtime.getRuntime().exec("psql -U user -d db -h host -f file.sql");
How to handle this using hibernate ?
I solved this by running native sql query using the hibernate api
Query persistableQuery = entityManager.createNativeQuery("QUERY");
persistableQuery.executeUpdate();
The #Sql annotation is my first option.
Haven't tried it, but since you are using Spring, you can also use ScriptUtils in your #Before method:
Connection connection = dataSource.getConnection();
ScriptUtils.executeSqlScript(connection, new ClassPathResource("test_db.sql"));
There's also nice library called dbunit that allows to set database to known state before and after junit tests.

Liquibase issue while running spring boot integration test

I am trying to run the integration test in spring boot which creates liqubase bean and run all the changesets. I get an error while running below change set in yaml file.
spring boot integration test run exception
- changeSet:
id: 2
author: XXX
changes:
- sql:
splitStatements: true
sql: CREATE ROLE dba_user LOGIN PASSWORD 'dba_user';
stripComments: true
Exception is
Caused by: org.h2.jdbc.JdbcSQLException: Syntax error in SQL statement "CREATE ROLE DBA_USER LOGIN[*] PASSWORD 'dba_user' "; SQL statement:
CREATE ROLE dba_user LOGIN PASSWORD 'dba_user' [42000-196]
Why does it add [*] or is there some other issue? The same exception I get while running changeset to create a view.
Your test is running against H2 database, which doesn't have CREATE ROLE feature.
BTW, I don't think it is good idea to create role via Liquibase. Liquibase is meant to be used for DB schema/data migrations, not for creating DB instance (where DB role creation falls as well). I would suggest to create role when DB instance is being created (doesn't matter if it is automated or manual).
If you have SQL queries that not compatible with H2, you can use testcontainers to use PostgreSQL with your integration tests. It runs docker containers under the hood for your database needs in tests and you can query the containerized PostgreSQL.
preConditions:
- onFail: MARK_RAN
- not:
- dbms:
type: h2
I found a way to skip database specific script with this. So it won't run if it's h2.

Categories

Resources