Spring : Join entity with one row table without join column - java

I want to join table A with table B in Spring Boot.
Table A has multiple rows but table B has only one row (with general parameters, by the way)
There is no joining columns between these two tables
I just want to use a column from table B in entity class of table A
Table A
#Getter
#Setter
#Entity
#Table(name="tableA")
public class tableA {
#Id
#Column(name = "id")
private Long id;
#Column(name = "code")
private String code;
}
TableB has only one row with one column "codeformatt"
| codeformat |
|------------|
| AAAAA-AAAA |
this is the format for the code of tableA. I want to use it yo display code with the proper format.
There are no foreign keys or joining columns
If I had to write it in SQL I would write it like this:
select A.code , B.codeformat
from tableA A inner join tableB B on (1=1)
Does anyone has any clue how to do it?
Thanks a lot
Kostas

You will have to go with a custom query using #Query annotation.
#Query("SELECT column1, column2 FROM A tb1, B tb2 WHERE ...")
Like this.

Related

Spring Data JPA retrieve entities where root field or list entity field matches criteria

The following entity relationship exists: A 1 <-> * B (edited down for brevity)
#Entity
public class EntityA {
#Id
UUID id;
#Column
String searchText;
#OneToMany(mappedBy = "entity_a", fetch = FetchType.LAZY)
List<EntityB> listOfB;
}
#Entity
public class EntityB {
#Id
UUID id;
#Column
String searchText;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "entity_a_id")
EntityA entityA;
}
I would like to retrieve all entities (EntityA) where a specific field (searchText) matches a criteria - easy enough. Now I want to go through all linked entities (EntityB) with a field (searchText) matching the criteria as well, only returning the matching entities. This result can be in any format for eg:
Map<EntityA, List<EntityB>> (The parent EntityA, possibly matching, with matching children EntityB)
List<EntityA_EntityBSearchResult> (some custom domain model)
List<EntityA> (bad: don't use entities with not conforming to expected relationship)
There are two main constrains complicating this
The outer entity (EntityA) should stay pageable
The resulting list (of EntityB) is limited to a maximum of 10 items
What I've tried:
Building the SQL before converting to JPA Query
For simplicity the criteria is a simple like '%textToFind%' on field searchText
1. Retrieve all of EntityB where EntityA or EntityB matches criteria.
select a.*, b.* from entity_a a
inner join entity_b b on b.entity_a_id = a.id
where a.search_text like '%textToFind%' or b.search_text like '%textToFind%'
Good: Pageable on EntityA
Bad: EntityB not limited to max of 10 items. Grouping will have to be done afterwards to Map<EntityA, List<EntityB>>.
2. Retrieve all of EntityB where EntityA or EntityB matches criteria - limited to 10 of EntityB.
select * from entity_b where id in (
select limitedB.id from (
select ROW_NUMBER() OVER(PARTITION BY a.id ORDER BY b.created_date_time DESC) AS RowNumber, b.* from entity_a a
inner join entity_b b on b.entity_a_id = a.id
where a.search_text like '%textToFind%' or b.search_text like '%textToFind%') limitedB
WHERE RowNumber <= 10)
Good: EntityB limited to 10
Bad: Not pageable on EntityA
3. Retrieve all of EntityA first (where EntityA or EntityB matches criteria). Followed by retrieval of EntityB (where EntityA or EntityB matches criteria) with parent EntityA id in previous list.
select DISTINCT a.* from entity_a a
inner join entity_b b on b.entity_a_id = a.id
where a.search_text like '%textToFind%' or b.search_text like '%textToFind%'
use the result to create an EntityA id list (List<UUID> EntityA_Ids). Send this list to the next query:
select * from entity_b where id in (
select limitedB.id from (
select ROW_NUMBER() OVER(PARTITION BY a.id ORDER BY b.created_date_time DESC) AS RowNumber, b.* from entity_a a
inner join entity_b b on b.entity_a_id = a.id
where a.search_text like '%textToFind%' or b.search_text like '%textToFind%') limitedB
WHERE RowNumber <= 10) and entity_a_id in EntityA_Ids
From this result a map (Map<EntityA, List<EntityB>>) can easily be created with Collectors.groupingBy.
Good: EntityA is pageable and EntityB is limited to 10
Bad: Multiple queries

Jpa select with relations

I have 4 tables in relations. A,B,C,D.
So I wrote select bellow:
select NEW org.example.ExtendsA(a,b.name,c.name,d.name)
from A a LEFT JOIN a.bItems b LEFT JOIN a.cItems c LEFT JOIN b.dItems d
order by b.name ASC;
A is unique but the relations are incomplette.
and I tried this:
select NEW org.example.ExtendsA(a,b.name,c.name,d.name)
from A a LEFT JOIN FETCH a.bItems b LEFT JOIN FETCH a.cItems c
LEFT JOIN FETCH b.dItems d order by b.name ASC;
A is not unique.
A object definition is:
#Entity
public class A implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "ID")
private Long id;
#NotNull
#Size(min = 1, max = 100)
#Column(name = "NAME")
private String name;
#OneToMany(mappedBy = "aId")
private List<B> bItems;
#OneToMany(mappedBy = "aId")
private List<C> cItems;
}
Some relations are empty but need A object with null relations.
Some A object has more than one relations between B and C and I want to select with all in one A object (distinct A).
Would you help me how to solve this issue? Maybe the approach is bad?
I use EclipeLink data provider.
This is a typical problem with loading OneToMany relathionships.
This is because of the nature of SQL result sets. Imagine a SQL result of a join of entity with it's other entities linked to it. On the left side, fields of this entity will be duplicated as many times as many related entities it has.
Unforunately, EclipseLink doesn't filter them out and you get many items of the same entity in your result. Although, EclipseLink is smart enough and each item will actually be the same Java object instance.
It's also the reason why you can't use setMaxResults in such queries.
You need to use distinct keyword that in this particular keys will not be mapped to a real SQL distinct, but will filter duplicated entities. Or, you can filter them manually.

Hibernate unidirectional One-to-many with multiple constraints

Suppose I have some generic tables apple, orange etc and a table note which contains notes about a row in one of my generic table. The note is stored by saving the entity_type (e.g. the table name) and entity_id (e.g. the id of the row).
I'm trying to make a unidirectional One-to-Many mapping from apple to note. Effectively creating this relationship:
SELECT *
FROM apple f
INNER JOIN note n
ON f.id = n.entity_id
AND n.entity_type = 'apple'
I've been trying something like:
#Entity
public class Apple {
...
#OneToMany
#JoinColumn(name = "entity_id", referencedColumnName = "id")
#WhereJoinTable(clause = "entity_type = 'apple'")
private Set<Note> changeNotes = new HashSet<>();
Which isn't working (error is #WhereJoinTable on an association without join table). Any ideas?
Update:
I think this is the sort of thing I"m trying to do https://docs.oracle.com/html/E13946_02/ref_guide_mapping_notes_nonstdjoins.html
However hibernate is looking for a column instead of just using the string...

How to map native sql results to oneToMany field with SqlResultSetMapping in JPA

For example, say I have the following database tables
Building
-----------
id
name
and
Room
-----------
id
roomNo
buildingId
the Building Java class will look something like
#Entity
public class Building {
private int id;
#OneToMany private List<Room> rooms;
...
I have the following SQL to fetch Building
SELECT b.id,
b.name,
r.id AS rid,
r.roomNo
FROM Building b
LEFT JOIN Room r ON
b.id = r.buildingId
the result will be
id, name, rid, roomNo
---------------------
1, 'b1', 10, 'r100'
1, 'b1', 11, 'r101'
2, 'b2', 12, 'r10'
Note that there are duplicate Building due to one-to-many relationship.
I know that I can get the Building entity simply by using JPQL but I want to do this with native SQL. So how would I map the result above back to the Building class using JPA's #SqlResultSetMapping?
You can use this code if you want to keep the Join statement:
SELECT DISTINCT
b.id,
b.name,
0 AS rid,
'' AS roomNo
FROM Building b
LEFT JOIN Room r ON
b.id = r.buildingId

Pulling a field from another table in Hibernate

I have two tables, which have a one-to-one relationship and look something like this:
OrderItem
ID data1 data2 data3
1 a b c
2 d e f
3 g h i
DisputedItem
ID data4
1 q
3 r
Is there a way to pull data4 into my Hibernate model for OrderItem without having a separate DisputedItemModel? Preferably using annotations.
You can use Hibernate #Formula annotation, if you have annotation based mappings or <formula> tag if you are mapping by XML.
What formula can do is help you extract a value by a query and map it to a field in your OrderItem domain model. This field can be from any table but the query thats used to map the property should return the indented field type.
You can use following URL for reference Hibernate Formula
Yes, here is an example:
#Table(name = "table")
public class c
{
#Id
#Column(name = "ID")
private int Id;
#Formula("(select t.data from table t where t.ID = ID))")
private String data;
}

Categories