Spring Data JPA join 2 tables - java

I have 2 tables in MySQL database: user and user_additional_details with columns described below.
User
id (auto increment)
userId (unique)
first name
last name
phone
email
User Additional Details
id (auto increment)
userId (matches userId in User)
personalPhone
personalEmail
Table user_additional_details contains 0 or 1 row for each userId in user table.
However, database does not have a foreign key constraint defined. Ideally, columns from user_additional_details should have been added as nullable columns in user table, but that was not done for some unknown reason. Now I need to define the entity for following query.
select user.userId, user.phone, user_a_d.personalPhone
from user
join user_additional_details as user_a_d
on user.userId = user_additional_details.userId
I tried defining JPA entities for the tables, but not able to figure out how to create an entity that uses columns from different tables.

It seems like the SecondaryTable annotation is what you are looking for
Specifies a secondary table for the annotated entity class. Specifying
one or more secondary tables indicates that the data for the entity
class is stored across multiple tables.
Here you find a detailed example of how to use it - http://www.thejavageek.com/2014/09/18/jpa-secondarytable-annotation-example/

Create UserEntity (with all the columns from User table) and UserAdditionalDetailsEntity(with all the columns from user_additional_details table). I assume you are aware how to create JPA entities and map them to database table.
I hope you would have create entity manager factory object in your spring configuration file. With the help of that create entity manager object .
Once EntutyManager Object is created:
Query q= em.createQuery("select user.userId, user.phone, userDetails.personalPhone
from UserEntity user
join UserAdditionalDetailsEntity as userDetails
on user.userId = userDetails.userId");
List<Object[]> resultList= q.getResultList();
Once you get resultList you can iterate over the list of object array and get data.
Each index of the resultList will contain the object array representing one row
Keep in mind that field name mentioned in query should be same as the one mentioned in your JPA Entites.

Related

Mapping multiple hibernate Entities inside non-entity java bean

Hi I am using a spring boot app with Hibernate using Oracle as DB.
I have 5 classes named
1.Reqest -> Mapped with Request Table
2.Team -> Mapped with Team Table
3.Partner -Mapped with Partner Table
4.Customer -> Mapped with Customer Table
Now I want to Display a Summary of Request on summary screen of the app where all the information from above-mentioned tables is needed.
Suppose I create a bean class as follows.
public class SummaryBean{
Request req;
Team team;
Customer cust;
Partner part;
//Getter setters;
}
Now since I have all the tables mapped with Java classes I can use hql join query to fetch data.
I don't want use plain SQL query with join and then iterate the resulting Object[] list from hibernate query and stub data into SummaryBean manually.
All the above-mentioned tables have REQ_ID as joining column
My question is How can I make hibernate map the result of that query to SummaryBean object?
Is it possible at all?
You can use constructor query.
Something like
"select new SummaryBean(req, team, cust, part) from (here you join your tables)"
You need to provide a constructor for the SummaryBean with those 4 types.
Note that the SummaryBean class doesn't have to be mapped, but you might have to use fully qualified name in the query (packageName.className).

VO and DAO, How to design classes and execute query

I have a 3 tables:
Item: item_id (pk), short_description, ...
SupplierItem: item_id (fk), supplier_id (fk), vendor_product_number, ...
Supplier: item_supplier (pk), name, ...
Relation between Item and Supplier is many to many. SupplierItem is
intermediate table.
I want use VO and DAO.
How to design this in VO (Java)?
After, How can I do the following query in java code.
select i.item_id, i.short_description, s.vendor_product_number as FONUA_PRODUCT_CODE
from item i
left join supplier_item s
on i.item_id=s.item_id
where ((i.item_id=:item_id) OR :item_id IS NULL)
and i.parent_item_id is null
order by vendor_product_number DESC"
I still do not understand the concept in use VO and DAO.
Thanks
DAO would be the java file where you define your query and get the results of the query call on the database.
The results from the query will be saved by setting them as values to the properties of a particular VO.
For Example:
Your query returns ,
item_id, short_description, vendor_product_number
So let us say that you will have to create another java file say ItemVO.java and declare the particular properties of the ItemVO object,
For Ex:
private String itemId;
private String shortDescription;
private String vendorShortNum;
/*Define your getters and setters*/
In the DAO file you will have to map the query results to the VO file's objects.
ItemVO itemVO= new ItemVO();
itemVO.setItemId(/*the particular column value from the query result*/);
itemVO.setShortDescription(/*the particular column value from the query result*/);
itemVO.setVendorShortNum(/*the particular column value from the query result*/);

Spring framework data JPA Inner Join on multiple columns

I would like to do the following query using spring jpa. I am able to build the where clause for my statement with Predicate.toPredicate. However, I don't know how to join on more than one column. On a single column it can be done in the repository using #Query and #Param
SELECT a.name, a.column_x, b.column_y
FROM table_a a
INNER JOIN table_b b
ON b.name = a.name
AND b.pk_2 = a.pk_2
AND b.pk_3 = a.pk_3
WHERE ...;
Another question I have is, is an intermediate tableA_tableB association beneficial if I have something like this, oneToMany relations.
Table 1: thing
thing_name
type
tenant
other1
other2
Table 2: thing_sub_prop
prop_name
value
Association table: thing_thing_sub_prop
type
thing_name
tenant
prop_name
value
Or is it better to just have two tables, thing and thing_sub_prop with the primary key columns of thing repeated in thing_sub_prop as a foreign key?

Hibernate Envers: Initializing ListProxy of related objects

I've two entities: User and UserGroup. Relation between them is #ManyToMany and I'm using envers for auditing these entities, class level #Audited annotation is placed on both of them. However, when I try to execute this query:
AuditReader reader = AuditReaderFactory.get(em);
AuditQuery query = reader.createQuery().forRevisionsOfEntity(User.class, false, true);
Returnted user entities have "org.hibernate.envers.entities.mapper.relation.lazy.proxy.ListProxy" collections of user groups with size equal to zero. Calling size() method on these list proxies doesn't initialize them. Any help will be appreciated.
The problem was the following: I started auditing of entities when there already were users and usergroups in the database. Let's say I was modifying some user's groups. This modification caused in addition of corresponding rows in User_AUD and User_UserGroup_AUD tables, but UserGroup_AUD table was still empty. Later when I was querying for revisions of User entity, it wasn't able to find related UserGroup entities since there was no record in UserGroup_AUD table about those user groups.

EJB - How to search by non-indexed fields?

I'm trying to create "search engine" on my DB.
I have a table with Id, Name and Description.
When I have an Id I can get the record with this Id by find().
But if I want to get records by Name or Description how can I do that? Did I've to set the Name as index?
Thanks.
As a general rule, if you have to frequently query a table by one of its fields and the table contains many records, it might be a good idea to create an index for that field in the database.
About the other question: if you need to get records by name, by description or by some other field and you're using JPA, then use the JPQL query language. For example, assuming that the entity is of type MyEntity (with fields id, name, description) the following query will return a list of entities with name aName:
EntityManager em = ... // get the entity manager
Query q = em.createQuery("SELECT me FROM MyEntity me WHERE me.name = :name");
q.setParameter("name", aName); // aName is the name you're looking for
List<MyEntity> results = (List<MyEntity>) q.getResultList();
Read more about the Java Persistence API in the tutorial.

Categories