Stored procedure with Hibernate fails in embedded h2 database - java

Im saving data to myRepository1 and to be able to see the savings via the materialized view, i need to refresh it.
myRepository1.save(myObject);
myRepository2.refreshView();
myRepository2 has:
#Modifying
#Query(value = "BEGIN my_refresh_view(); END;", nativeQuery = true)
void refreshView();
Where my_refresh_view is a simple stored procedure.
This works fine in the real world (Oracle DB) - however, when i run my integration tests for the code above using an embedded h2 database, i get:
BEGIN my_refresh_view(); END; [42000-200]
org.springframework.dao.InvalidDataAccessResourceUsageException could not prepare statement;
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.convertHibernateAccessException(HibernateJpaDialect.java:281)
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:255)
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:528)
at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:61)
Looks like the stored procedure and h2 dont match well together.
Any ideas how to make it work, or maybe there are workarounds?

Hibernate JPA (at least 5.0.0 and below) does not support stored procedures for H2Dialect.H2Dialect inherits Dialect.getCallableStatementSupport() which returns StandardCallableStatementSupport.NO_REF_CURSOR_INSTANCE. The standard callable statement support does not properly handle the H2 "out" parameter which is a Java return value and not a statement parameter
check details here

Related

How to register a function on Dialect from a function with parameters before and after the method?

I'm trying to make a JPQL run using the REGEXP function from MySQL 5.7 database on a H2 memory database. I would like to make a integration test using the same query.
As the REGEXP function does not exists on H2, I'm trying the register a new function to make it work, using the REGEXP_LIKE H2 function instead (just for the tests).
My query is:
String sql = "select o1.id from order o1 where :url REGEXP o1.regex";
But I can't figure out the right syntax to register the function. I'm trying something like this below, but I know that is incorrect anyway, because all examples that I found is mapping "normal" functions with parameters, but the REGEXP use a syntax like :url REGEXP o1.regex and not REGEXP(:url, o1.regex):
public class MyH2Dialect extends H2Dialect {
public MyH2Dialect() {
super();
registerFunction("REGEXP",
new SQLFunctionTemplate(StandardBasicTypes.BOOLEAN, "REGEXP_LIKE(?1, ?2, 'i')"));
}
}
And naturally the JPQL not recognize the function:
Caused by: org.hibernate.hql.internal.ast.QuerySyntaxException: unexpected token: REGEXP
I'm imaginig that I need to do something like this (pseudocode):
registerFunction("?1 REGEXP ?2",
new SQLFunctionTemplate(StandardBasicTypes.BOOLEAN, "REGEXP_LIKE(?1, ?2, 'i')"));
Any ideas?
I'm trying to make a JPQL run using the REGEXP function from MySQL 5.7 database on a H2 memory database.
Well, I couldn't register the function but I was able to run the REGEXP function on H2.
My mistake was trying to use JPQL instead of Native Query to make it run.
em.createNativeQuery(sql);
When I run the same query used on MySQL on the H2 database the SQL works as expected. So, I did not need to register the function. I couldn't understand that this was possible because the H2 documentation does not mention the REGEXP function but another question on SO mentioned that function exists.
Another possibility that I found (before make the above solution works) was upgrade the MySQL to 8.x version, because they create a new function called REGEXP_LIKE that have almost the same signature from the REGEXP_LIKE function from H2.

Fetch result set from a postgres Stored procedure in java

I created a postgres function which returns a set of ref cursors. When I call the stored procedure from java the JDBC statement build is
select * from ga_rpt_movement('CODE','2018-5-10','2018-5-10','2018-5-10','C','STAT1','2018-5-10','2018-5-10','12344','A','T','34',25,50,'M','1','firstname',0,10) as result
When I run the same query on postgres terminal it gives me the four coursors.
Now I am not able to understand how do I fetch this cursor data in java.
Any suggestions, ideas are welcome and appreciated.
Result set when I run this query on postgres terminal look like this :
p_cr_personstatus
p_cr_identification
p_cr_phone
p_cr_count
(4 rows)
I am trying to implement this using spring JPA only.

Change Table names in derby database using entitymanager

I am using an APACHE DERBY database, and basing my database interactions on EntityManager, and I don't want to use JDBC class to build a query to change my tables' names (i just need to put a prefix to each new user to the application, but have the same structure of tables), such as:
//em stands for EntityManager object
Query tableNamesQuery= em.createNamedQuery("RENAME TABLE SCHEMA.EMP_ACT TO EMPLOYEE_ACT");
em.executeUpdate();
// ... rest of the function's work
// The command works from the database command prompt but i don't know how to use it in a program
//Or as i know you can't change system tables data, but here's the code
Query tableNamesQuery= em.createNamedQuery("UPDATE SYS.SYSTABLES SET TABLENAME='NEW_TABLE_NAME' WHERE TABLETYPE='T'");
em.executeUpdate();
// ... rest of the function's work
My questions are :
This syntax is correct?
Will it work?
Is there any other alternative?
Should I just use the SYS.SYSTABLES and find all the tables that has 'T' as tabletype and alter their name their, will it change the access name ?
I think you're looking for the RENAME TABLE statement: http://db.apache.org/derby/docs/10.10/ref/rrefsqljrenametablestatement.html
Don't just issue update statements against the system catalogs, you will corrupt your database.

Using a Local Temp Table and such using SimpleJdbcTemplate (or Spring)

First off, admittedly, I am no DBA...so my SQL-fu is weak.
I was recently working on a project that had a pretty hefty report that did 10 inner joins. When ran against Prod data (SQL Server 2005) using the SQL Studio Management client, the query wasn't a barn-burner, but it returned in just under 20sec. However, when ran through Spring, 31min.
So, we got our DBA ninja on it, and he pointed out that the query plan would be different because the JDBC method would use a prepared statement, passing in the variables as parameters, whereas in the client those were hard-coded. So, he re-worked the query.
The resulting query now sets some declare variables up top, then uses those to create a local temp table, then uses the local temp table as part of the ultimate report query. He said we should be able to send all this as part of the same query string (compound query????). It looks something like this (obfuscated to protect the innocent):
declare #startdate DateTime
declare #enddate DateTime
set #startdate = DATEADD (dd, 0, DATEDIFF (dd, 0, '2013-03-01 00:00:00.000'))
set #enddate = DATEADD (dd, 1, DATEDIFF (dd, 0, '2013-08-08 00:00:00.000'))
CREATE TABLE #LATEST_BLAH_ACTION
(
FK_Blah_Timestamp DATETIME,
FK_Blah_Id VARCHAR(10),
Blah_Other_Thing VARCHAR(10),
[Latest Updated Date/Time] DATETIME
)
INSERT INTO #LATEST_BLAH_ACTION
SELECT FK_Blah_Timestamp, FK_Blah_Id, Blah_Other_Thing,
MAX(Blah_Other_Timestamp) AS [Latest Updated Date/Time]
FROM BlahTable
WHERE Blah_Another_Thing = 'Some value' AND
Blah_Other_Timestamp BETWEEN #startdate and #enddate
GROUP BY FK_Blah_Timestamp, FK_Blah_Id, Blah_Other_Thing
SELECT
-- Bunch of fields
From LATEST_BLAH_ACTION
-- Bunch of crazy Inner Joins and such
However it's not working. If I run this out of SQL Management Studio, I get back results. If I run it out of the Java code using Spring's SimpleJdbcTemplate, no error but no results.
Is it possible to run a (compound???) query like this using Spring, and if so, how? Do I have to do them individually, but as part of a transaction? Maybe use something other than SimpleJdbcTemplate?

Hibernate multiple native SQL statements

I want to run a native SQL from a file using Hibernate. The SQL can contain several statements creating the database structure (i.e. tables, constraints but no insert/update/delete statements).
Example, very simple query is below (which contains the following two SQL statements)
CREATE DATABASE test;
CREATE TABLE test.testtbl( id int(5));
I am using MySQL db, and when I run the above query I am gettng syntax error returned. When I run them one by one, its ok.
Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException:
You have an error in your SQL syntax; check the manual that corresponds to your
MySQL server version for the right syntax to use near
'CREATE TABLE test.testtbl( id int(5))' at line 1
The code to run the query is below (above statement is assigned to 'sql' variable):
session = sf.openSession();
session.beginTransaction();
Query qry = session.createSQLQuery(sql);
qry.executeUpdate();
session.getTransaction().commit();
Any help would be appreciated.
As others have explained
You must run these queries one by one.
The hibernate code gets translated into running one update statement on JDBC.
But you provided two update statements.
In addition,
I personally prefer to have the code that creates tables outside of the Java application, in some DB scripts.
The parameters of the method createSQLQuery is t-sql code;
t-sql code to ensure that in the mysql interface analyzer correctly.
You can try changed the sql :'CREATE TABLE testtbl(id int(5));'
by the way you can use JDBC Connection api (Don't recommend to do so)
Such as:
java.sql.Connection conn=session.connection();

Categories