How to fetch many-to-many relationship entity - java

I have following table structure
TABLE1
T1_ID
T1_Col1
TABLE2
T1_ID
T3_ID
TABLE3
T3_ID
T3_COL1
Table1 and Table3 are joined by a middle table which is Table2. Now I have only T1_ID and I want to fetch all the rows from Table3 which are associated with T1_ID. A simple SQL query would be
select T1.*, T3.*
from TABLE1 T1, TABLE T2, TABLE3 T3
where T1.T1_ID = T2.T1_ID
and T2.T3_ID = T3.T3_ID
So how can i do this in hibernate/jpa ... I have yet to write my entity classes for Table1, Table2, Table3. I want to execute this query as part of Table1, so that i can write a method say entity.fetchAssociatedTable3(). The easiest approach i can think of is in fetchAssociatedTable3 i can put custom queries like the one i mentioned above. But since i am using hibernate/jpa I want to know if there is a better way to do this.
UPDATE
Apparently, my question isn't clear enough. I want to do something as user Dragan Bozanovic mentioned. However, What i want to know that
How would i write Table1 entity ? I mean what annotations i would put on the columns etc which will make hibernate/jpa understand that this column is related to Table3 column via Table2
I guess if question 1 is answered, then it would be difficult to write getEntity3s() method. But if (for a noob) there is something that I need to know, I would appreciate.

Assuming that you will have a many-to-many association between Entity1 (mapped to TABLE1) and Entity3 (mapped to TABLE3), you can either:
1) read the Entity1 by id and get all of the Entity3s from it:
Entity1 entity1 = entityManager.find(Entity1.class, entity1Id);
Collection<Entity3> entity3s = entity1.getEntity3s();
2) or, execute the JPQL query to get Entity3s without loading the Entity1 instance:
select distinct e3 from Entity3 e3 join Entity1 e1 where e1.id = :entity1Id

First thing you would need do is to stop thinking in terms of tables when using ORM tool (Hibernate/JPA). You model your classes and their relations and let the ORM tool help with the mappings declaratively. Your join table just is serving here for creating relation many to many relation between two entities. So in terms of classes you would have only Entity1 and Entity3. You would not be creating a class representing join table (unless of course you want it to have other attributes other than foreign keys in which case it would qualify to be a Entity class in it's own right). And then you can use either method suggested by #Dragan i.e., loading by primary key or using explicit HQL/JPQL.

Related

How can I make sql generated by Hibernate use in operators over equality operators

What I want is a way for Hibernate to generate 1 statement to delete all children, instead of 1 statement per child.
If I have a relationship between Entity A and B , where A is the parent and B can be many children.
If I use annotations such as OrphanRemoval or OnCascade delete on the entity relationship, when I delete the parent the sql that gets automatically generated says
delete from table where id=? - per child
What I want Hibernate to do is generate sql like
delete from table where id in (child1,child1)
Is there an annotation or setting I can use to do this easily?
I feel I'm not the first person to run into this issue, but I cant find any way to solve it other then writing my own sql and removing the annotations.
You can't do that with entityManager.remove() but you can use executeUpdate():
Query q = entitiyManager.createQuery("delete from MyEntity m where m.id in :ids)");
q.setParameter("id", <list of ids>);
q.executeUpdate();
Read more in the documentation: https://docs.jboss.org/hibernate/orm/current/userguide/html_single/Hibernate_User_Guide.html#batch-bulk-hql-update-delete

having an Hibernate entity with a count children column - without scalar subquery

I have an entity and I want it to have an attribute of the count of the children.
Let's say I have these two tables:
create table father
(
id int,
name
);
create table child
(
id int,
father_id int
);
I want the father entity in Hibernate to have an attribute like this:
private int countChildren;
From SQL perspective, it is easy:
SELECT f.id, f.name, count(father_id) as count_children
FROM father f JOIN child c ON f.id = c.father_id
GROUP BY f.id, f.name;
Easy and efficient. But, since I want to have it as an Hibernate attribute of the entity, the closest I found is:
#Formula("(select count(*) from child c where c.father_id = id)")
private int countChildren;
However, behind the scenes it is performed as a Scalar sub-query, where the access to the child table is per every father record - highly inefficient (some databases like Oracle do some optimization for these kind queries, but I don't want to rely on that, and it is still not optimal compared to the SQL version with GROUP BY).
Is there an Hibernate way to solve this one? One that behind the scenes is performed in a similar way to the above GROUP BY example?
#Formula("(SELECT COUNT(*) FROM father f JOIN child c ON f.id = c.father_id WHERE f.id = id)")
Where last id is your entity field name.

Join Entity with table that has no entity assosiated in JPQL

I have a table that has no associated Entity. I need to write JPQL query which will filter by that table's fields. Is it possible?
I know that I can do one of the following:
Create an Entity for that table( but it's basically a join table, so it will look strange to create an Entity class for it)
Write a native query( I don't like this approach either. If I use JPA, I must use JPQL only).
Create fully functional ManyToMany mapping( I just don't need it).
Could there be another approach?
Unfortunately you cannot do that with JPQL.
You should use SQL.
But a native query can also return Entities. Either if the returned values matches the entity or using #SqlResultSetMapping as described here:
http://javaee.support/sample/jpa-native-sql-resultset-mapping/
If you only need to join to entities on a relationship that is not mapped JPA 2.1 is able to JOIN on any table columns.
The problem was that I did not need a real many-to-many object mapping but only collection of id's in my only entity. So I came to following solution:
#ElementCollection
#CollectionTable(
name="user_to_feed",
joinColumns = #JoinColumn(name = "feed_id",referencedColumnName = "id")
)
#Column(name="user_id")
private List<Integer> userIds = new ArrayList<>();
This allows me to make following query:
select f.url from Feed f join f.userIds u where :id in u

SELECT query for multiple column with multiple table

I attach one image of my problem:
In Testing jFrame jTextField I will insert customer id then after pressing ok button query will select and collect information related to that customer.Then it will show in the jTableModel.
I attach my database image.
Error is "SQL code cannot be executed".
You can do like this (without Join):
SELECT papers.paper_list,papers_rate.monday,papers_rate.tuesday,
papers_rate.wednesday,papers_rate.thrsday,papers_rate.friday,
papers_rate.saturday,papers_rate.sunday,magzines.magzine_name,magzines_rate.rate
FROM papers,papers_rate,magzines,magzines_rate
WHERE example_table.customer_id = ? AND other conditions"
This syntax is, in effect, a simple INNER JOIN. Some databases treat it exactly the same as an explicit JOIN. The WHERE clause tells the database which fields to correlate, and it returns results as if the tables listed were combined into a single table based on the provided conditions.(http://www.techrepublic.com/article/sql-basics-query-multiple-tables/)
You need to join the tables properly.
Like this:
SELECT
paper_list,monday,tuesday,wednesday,thrsday,friday,saturday,sunday,magzine_name,rate
FROM papers
LEFT JOIN papers_rate
ON papers_rate.paperId = papers.id
LEFT JOIN magzines
ON magzines.paperId = papers.id
LEFT JOIN magzines_rate
ON magzines_rate.magazineId = magzines.id
WHERE customer_id = ?"
If you do an inner join, all your results will vanish if you don't have a magazine_rate for example...
And check your spelling.
You're writing thrsday instead of thursday and magzine instead of magazine...
PS: And where does customer_id come from ?
Use joins to select multiple column from multiple tables. Refer this to get an understanding about the join and for join examples.
Note: There should be a common field between two tables to perform join operation
If the tables are related you must use JOIN: let's see an example (I don't know your tables fields, so I'll invent a custom example). Think about person and pet tables; the person tables could contain these fields:
Person (personID, first_name, last_name, age)
the pet table could contain these other fields:
Pet (petID, name, age, personID)
The personID field in the pet table identifies the owner of the pet. It is a simple 1:N relation. To select some values from these two tables you must do something like:
SELECT Person.first_name, Person.last_name, Pet.name
FROM Person INNER JOIN Pet ON
Person.personID = Pet.personID
WHERE Person.age > 30
This is just an example, clearly. And the INNER JOIN is just a join type (there are several join methods). Here you can find some documentation concerning these issues.
You need to either use a Join clause (... FROM papers JOIN papers_rate ON papers.[id_column] = papers_rate.[foreign_key]) or use an equi-join (replace JOIN...ON clause with a condition in the WHERE clause) (... FROM papers,papers_rate WHERE papers.[id] == papers_rate.[foreign_key])
Could you please post the schema of your tables?

Hibernate inheritance query

I have 4 entities:
User, Teacher, Student, Course
and 4 tables:
t_user, t_teacher_course, t_student_course, t_course
Teacher and Student extends User (with descriminators) and have #ManyToMany relationship with Course (User do NOT have)
Teacher's relations stored in t_teacher_course and Student's relations stored in t_student_course.
Now i want to select all users with courses (if they exists) in one query
select u from User u left join fetch u.courses c (notice that User do not have courses)
This select generated something like this:
select
...
from
T_USER user0_
left outer join
T_TEACHER_COURSE course1_
on user0_.USERID_=courses1_.TEACHER_
left outer join
T_COURSE course2_
on courses1_.LANE_=course2_.COURSENAME_
where
user0_.GROUP_=?
As you can see clearly Hibernate did NOT join with t_student_course table
I am using Hibernate 4.1Final
Question:
Does Hibernate support such queries
a) if supports then why it didn't fetched courses for Student entity?
b) if do not support than how can i select all users with their courses using JPQL?
Since u.courses could be student.courses or teacher.courses, Hibernate resolves the ambiguity by choosing the first (or last) association with this name in its metadata.
It might work if the name of the courses collection is not the same in both subclasses. For example, you could define Student.attendedCourses and Teacher.teachedCourses.
Otherwise, you'll have to issue two queries (one for teachers and one for students), and join the result lists. Or you'll have to pull up the association in the User entity.

Categories

Resources