Fully qualify Oracle table name in Hibernate - oracle

My Setup:
I am using Hibernate 5
with the Oracle JDBC driver oracle.jdbc.driver.OracleDriver and dialect org.hibernate.dialect.Oracle9iDialect.
My modelclasses look like this:
#Entity
#Table(name = "MyModel1", catalog = "DB1")
public class MyModel1 {...}
#Entity
#Table(name = "MyModel2", catalog = "DB2")
public class MyModel2 {...}
My Problem:
I have multiple modelclasses that are spread about different DBs on the same DBserver.
I have to use a single DB-connection to query all of my modelclasses so I connect to DB1 for querying.
Everything would be fine, if Hibernate would generate SQL queries like
select * from DB1.MyModel1;
but it does not. For some reason it makes its queries without the catalog ie.
select * from MyModel1;
which is fine for MyModel1 because I connect to DB1 but I need a fully qualified query for MyModel2 otherwise it throws an exception, because the table of MyModel2 cannot be found in DB1.
Do you know any way to trick Hibernate or JPA or the dialect into building queries with fully qualified tablenames?

With Oracle you have to use the schema attribute:
#Entity
#Table(name = "MyModel1", schema= "DB1")
public class MyModel1 {...}
#Entity
#Table(name = "MyModel2", schema= "DB2")
public class MyModel2 {...}

Related

Springboot Joint table from different database

I have a Springboot project with two datasource configured one for each database I'm using. Everything works, but I need to create an Entity in database one that refers to an entity from database 2. The problem is that the entity in the second database is not found.
#Entity
#Table(name = "data", catalog = "data")
public class Data implements Serializable
{
//all stuff related to data here.
#ManyToOne
private User user;
//Entity User is store in the second database
}
Is there anyway to tell spring that the entity User can be found in the second datasource?

How do I use Spring Data JPA(Hibernate) ORM mapping to a Oracle Tables from other Schema?

The oracle db is version 12c. I use ojdbc8 connector.
I was only granted access to an account, let's call it schema "USR". Login with USR, I can see tables of another schema, let's call it schema "ADM". There is a table "TGT_TABLE" that I want to map it with JPA inside schema ADM. And under USR console, I am able to query "select * from ADM.TGT_TABLE" to get correct result. Now I write up the Entity class as:
#Data
#Entity
#Table(name = "ADM.TGT_TABLE") // or #Table(name = "TGT_TABLE") , Neither worked
public class ApiHeaderLogs {
#Id
#Column(name = "id")
String id;
....
and my config:
spring.jpa.hibernate.ddl-auto=none
# Oracle settings
spring.datasource.url=jdbc:oracle:thin:#10.119.125.70:1540:dhtlm4
spring.datasource.username=USR
spring.datasource.password=******
spring.datasource.driver-class-name=oracle.jdbc.OracleDriver
and my test:
Optional<ApiHeaderLogsEntity> ahl = apiHeaderLogsService.findById(id);
I got error:
org.springframework.dao.InvalidDataAccessResourceUsageException: could not extract ResultSet; SQL [n/a]; nested exception is org.hibernate.exception.SQLGrammarException: could not extract ResultSet
....
Caused by: java.sql.SQLSyntaxErrorException: ORA-00942: table or view does not exist
and the SQL query in console is:
select ... from adm_tgt_table where ... //#Table(name = "ADM.TGT_TABLE")
Or
select ... from tgt_table where ... //#Table(name = "TGT_TABLE")
Clearly it does not address the table ADM.TGT_TABLE.
How can I map to ADM.TGT_TABLE?
My experience was mainly on MySQL, which has no account related to schema access, and my colleague already proposed a solution using JDBC directly... which I really want to avoid, please let me know if there is a proper way to handle this, thanks
You must define explicitely the table_name and the schema in the #Table annotation
Example
#Table(name="TGT_TABLE", schema="ADM")
See the documentation in javax.persistence.Table
Ommiting the schema assumes the deafult owner of the connecting session, which leads to an error.
Neither can you pass a qualified name (ADM.TGT_TABLE) as a table name.

Getting aggregate data from table

I want to get aggregate data from a table using spring data.
#Query("SELECT COUNT(*) AS TOTAL_1, MAX(FIELD_1) AS MAX_1 FROM TABLE_NAME WHERE GROUP_ID = :groupId")
Mono<SummaryEntity> getSummary(#Param("groupId" Long groupId));
package com.refinitiv.eit.kv.label.enity.response;
import lombok.AllArgsConstructor;
import lombok.Data;
#Data
#AllArgsConstructor
public class SummaryResponse {
#Column("TOTAL_1")
private Double total_1;
#Column("MAX_1")
private Double max_1;
}
However I get this error : "Could not read property #org.springframework.data.annotation.Id() " ...
There should be no ID, only a single row with the summary data.
Any ideas on getting the summary data?
(the code is more complex but cleared up for this)
First of all, if you need your entity SummaryResponse to be managed by JPA and eventually persist it, you need to annotate it as #Entity and assign it either id or composite id (annotated with #Id).
If you just want to use that DTO for fetching the data, you can use a Spring's interface based projection for that:
public interface SummaryResponseProjection{
getTotal1();
getMax1();
}
and then use it for mapping the results of the query:
#Query("SELECT COUNT(*) AS TOTAL_1, MAX(FIELD_1) AS MAX_1 FROM TABLE_NAME WHERE GROUP_ID = :groupId")
Mono<SummaryResponseProjection> getSummary(#Param("groupId" Long groupId));
Found the reason:
This method was part of a repository defined as ReactiveCrudRepository<RawEntity, Long>, with RawEntity having the id defined.
Moving the method into a new repo defined as ReactiveCrudRepository<SummaryEntity, Void> solves the issue.
Thanks all!

Using reserved keyword in JPA / Hibernate entity

Lets assume that I have to use reserved keyword even if it's incorrect. I'm being forced to rename table to new name, which is reserved keyword.
Now I saw every recommended way, how to escape the name, to fail:
A) Using hibernate config property:
hibernate.globally_quoted_identifiers=true
having entity annotated just like:
#Entity
#Table(name = "LIMIT", schema = "something")
does work, but sadly also escapes schema, meaning it actually does not work, as statements like:
select * from "something"."LIMIT"
won't work.
B) Annotating entity as
#Entity(name = "LIMIT")
#Table(name = "\"LIMIT\"", schema = "something")
or
#Entity
#Table(name = "[LIMIT]", schema = "something")
is unable to see existing table. With it I'll get exception as:
org.hibernate.tool.schema.spi.SchemaManagementException: Schema-validation: missing table [something.limit]
If I turn of hibernate start-up validation, I'll get exceptions with existing queries, like:
QuerySyntaxException: LimitEntity is not mapped
C) annotating entity just:
#Entity
#Table(name = "LIMIT", schema = "something")
will work just OK, but hibernate fails to auto-generate schema out of it in tests
What is the correct escaping of reserved keywords in JPA/hibernate? We need everything to work, not just something, meaning running app, autogenerating table for tests, ...
version:
<artifactId>hibernate-core</artifactId>
<version>5.2.17.Final</version>

Could not execute JDBC batch update

I have a problem with a entity class. When I run my app with hibernate.hbm2ddl.auto = create, then it create all the other entity tables but not this on. Why is that? And when I create the table by myself and after that try to insert something into it, then I get this error: http://pastebin.com/m4gjxqNC
Here's my entity class:
User entity:
http://pastebin.com/YXvzFSgt
Comment entity:
http://pastebin.com/RpZEUPxN
And here's the UserDAO class
http://pastebin.com/LrTCg0GC
You seems to be using PostgreSQL. As per this document, 'User' is a PostgreSQL reserved word. Try adding a #Table("user_tb") annotation for your User entity, to force a new table name.
#Entity
#Table("user_tb")
public class User extends LightEntity implements Serializable {
//..
}

Resources