How to call oracle function from spring boot application? - java

My requirement is i need to call oracle function from spring boot application without using NATIVE query.
below is my oracle function which is taking Date as input
create or replace FUNCTION todate(src_dt IN date)
RETURN date
is
BEGIN
RETURN(to_date(src_dt));
END;
i was searching solution on internet but so far did't find. people are saying some custom dialect need to create but not found any perfect step by step link.
below is my java code :-
Query query1 = entityManager.createQuery("select todate(ActSubT.createdDt) from ActSubT ActSubT");
List<Object> result=query1.getResultList();
this code should run , as of now its giving error as todate is oracle function and i haven't configured anything in application.yml file.
below error i am getting
java.lang.IllegalArgumentException: org.hibernate.QueryException:
No data type for node:
org.hibernate.hql.internal.ast.tree.MethodNode
\-[METHOD_CALL] MethodNode: '('
+-[METHOD_NAME] IdentNode: 'todate' {originalText=todate}
Please help

I am able to solve my issue .
step 1 :- i created custom dialect, below is my code..
public class CustomDialect extends Oracle12cDialect {
public CustomDialect() {
super();
// CustomFunction implements SqlFunction
// registerFunction("custom_function", new CustomFunction());
// or use StandardSQLFunction; useful for coalesce
registerFunction("todate", new StandardSQLFunction("todate", StandardBasicTypes.DATE));
}
}
Step 2 :- now i am calling todate function , below is the Java code
Query query1 = entityManager.createQuery("select function('todate',ActSubT.createdDt) from ActSubT ActSubT where ActSubT.id=1105619");
Object resulth=query1.getSingleResult();
Step 3 :- this entry we need to put in application.poperties / application.yml
# Allows Hibernate to generate SQL optimized for a particular DBMS
spring.jpa.properties.hibernate.dialect = com.sbill.app.config.CustomDialect
That's all now i can call db function with java code.

Related

How to use a 'Hibernate Types' library type in a single native query that selects Postgres arrays?

I have a query that returns a Postgres array of UUIDs:
SELECT e.id, e.date,
ARRAY
(
SELECT cs.api_id FROM event_condition_set ecs
JOIN condition_set cs on cs.id = ecs.condition_set_id
WHERE ecs.event_id = e.id
) AS condition_set_ids,
...
And then create and run this query as a native query: Query query = entityManager.createNativeQuery(queryString);
Since Hibernate can normally not deal with these Postgres arrays, I use Vlad's Hibernate Types library.
However, currently I need to register this UUIDArrayType globally in my application:
public class PostgreSQL95CustomDialect extends PostgreSQL95Dialect {
public PostgreSQL95CustomDialect() {
super();
this.registerHibernateType(Types.ARRAY, UUIDArrayType.class.getName());
}
}
Aside from the fact this is a bit ugly, it also leaves no room for other types of arrays.
(Note I also tried registering a generic ListArrayType but this throws a NullPointerException during execution of the query.)
I have also tried registering it as a scalar type:
query.unwrap(org.hibernate.query.NativeQuery.class)
.addScalar("condition_set_ids", UUIDArrayType.INSTANCE);
But this makes the entire query only return a single UUID, which is very strange and seems bugged.
Is there a way to ONLY use this UUIDArrayType specifically in this query?
(Please don't suggest using array_agg because the performance is terrible for this case)
you can call native queries using custom Hibernate types as follows:
String myJsonbData = ...;
String[] myStringArr = ...;
final String queryStr = "select your_function(?, ?, ...)"; // ? for each param
entityManager
.createNativeQuery(queryStr)
.setParameter(1, new TypedParameterValue(JsonBinaryType.INSTANCE, myJsonbData))
.setParameter(2, new TypedParameterValue(StringArrayType.INSTANCE, myStringArr));
This is just an example, but as a rule of thumb, you need to instantiate a new TypedParameterValue.
Answering my own question here. After waiting for a while and updating to the most recent library version (I'm on 2.19.2 right now) I don't have any issues anymore with the scalar types registration as I mentioned in my question, i.e.:
query.unwrap(org.hibernate.query.NativeQuery.class)
.addScalar("condition_set_ids", UUIDArrayType.INSTANCE);
So it appears to just have been a bug and I can now avoid the global registration in favor of using scalars.

How to call custom oracle function in spring boot application?

I need to call custom oracle function from spring boot application without using native query.
below is my oracle function which is taking Date as input
create or replace FUNCTION todate(src_dt IN date)
RETURN date
is
BEGIN
RETURN(to_date(src_dt));
END;
i was searching solution on internet but so far did't find. people are saying some custom dialect need to create but not found any perfect step by step link.
below is my java code :-
Query query1 = entityManager.createQuery("select todate(ActSubT.createdDt) from ActSubT ActSubT");
List<Object> result=query1.getResultList();
this code should run , as of now its giving error as todate is oracle function and i haven't configured anything in application.yml file.
Please help

mysql with jdbc returning fully qualified column names

I have a java web application and mysql 5.7 as database, and using jooq 3.8.2 to execute JDBC code.
Executing the following select:
Result<Record> result = dsl.select(TABLE1.fields())
.select(TABLE2.fields())
.from(TABLE1)
.join(TABLE2).ON(TABLE1.FK.eq(TABLE2.ID))
.fetch();
for(Record rec : result) {
Table1Record tb1Rec = rec.into(TABLE1);
Table2Record tb2Rec = rec.into(TABLE2);
}
After updating jooq to version 3.8.2, my logs shows the following message:
INFO org.jooq.impl.Fields - Ambiguous match found for ....
To me, it's clear that the problem is that both tables have some columns with same names. So I tried (as example):
Field tb1Field = TABLE1.FIELD1;
dsl.select(tb1Field.as("TABLE1_" + tb1Field.getName())
But then
Table1Record tb1Rec = rec.get(TABLE1);
returns null.
My preferred solution is, in same way, force mysql return fully qualified column names, but I can't found any option to do that.
Any help?

Too many parameters error on the following $in query

I'm using jongo API - org.jongo.MongoCollection is the class.
I have list of object ids and converted the same as ObjectId[] and trying to query as follows
collection.find("{_id:{$in:#}}", ids).as(Employee.class);
The query throws the exception - "java.lang.IllegalArgumentException: Too
many parameters passed to query: {"_id":{"$in":#}}"
The query doesn't work as specified in the URL In Jongo, how to find multiple documents from Mongodb by a list of IDs
Any suggestion on how to resolve?
Thanks.
Try it with a List as shown on the docs:
List<String> ages = Lists.newArrayList(22, 63);
friends.find("{age: {$in:#}}", ages); //→ will produce {age: {$in:[22,63]}}
For example the following snippet I crafted quick & dirty right now worked for me (I use older verbose syntax as I am currently on such a system ...)
List<ObjectId> ids = new ArrayList<ObjectId>();
ids.add(new ObjectId("57bc7ec7b8283b457ae4ef01"));
ids.add(new ObjectId("57bc7ec7b8283b457ae4ef02"));
ids.add(new ObjectId("57bc7ec7b8283b457ae4ef03"));
int count = friends.find("{ _id: { $in: # } }", ids).as(Friend.class).count();

DB2 sql error code -245 for a date

I am reading several sql queries from database inside a loop as below:
{ // start of loop
Map<String, Object> queryRS = this.jdbcTemplate.queryForMap(this.querySql,queryParam);
String query = (String) queryRS.get("QUERY");
// code here as explained below
} // end of loop
The query returned could have any number of parameters. However, in all of them I have to set same date as the parameter.
For this I am counting the number of occurrence of character ? in the query and creating an Object array with same date repeated as below.
String date = '2010-12-31';
int numArgs = StringUtils.countMatches(query, "?");
String[] paramArgs = new String[numArgs];
for (int i = 0; i < numArgs; i++) {
paramArgs[i] = date;
}
After which I am executing the query as below:
SqlRowSet myRowSet = this.jdbcTemplate.queryForRowSet(query,(Object[]) paramArgs);
However, this is giving error when the query has a Date(?) function.
com.ibm.db2.jcc.am.SqlSyntaxErrorException: DB2 SQL Error: SQLCODE=-245, SQLSTATE=428F5, SQLERRMC=DATE;1, DRIVER=3.64.96
The description of above error is:
An untyped parameter marker is passed to a function and there are two or more possible candidate functions to resolve to during function resolution.
What is the solution to this?
Thanks for reading!
I suppose you are using String jdbcTemplate.
I had not the same but a similar problem: the function was char(?) and I was
passing an integer argument to it.
I was using a Old framework Ibatis 2.x (now I use MyBatis 3.x).
The framework was not the error cause.
On Ibatis I pass the argument so: char(#value:INTEGER#)
On my develop server all was work well but on remote production server I get your same error.
The problem was caused by the JDBC driver version 4.x on develop end 1.x on production.
To solve my problem I have two ways:
change the production driver (but I cannot)
use a different call: char('$value:INTEGER$') (I do this)
In IBATIS/MYBATIS framework, if value is 123, char('$value:INTEGER$') is translate to sql char('123') so solve my problem and when production change driver I can put back to char(#value:INTEGER#).
You have a similar problem. Try to:
look at the driver version
use type like in spring reference, sql type, spring manual
I do not use direct access to jdbcTemplate but I think that you have not to put args in string, you have to create a Date variable end put it in an Object array.
I hope that this can help you.

Categories

Resources