i want to join 4 tables with hibernate. i write following code for fetch name , teacher detail and schedules of course:
public Student getStudentDetail(int studentId) {
Criteria criteria = createEntityCriteria();
criteria.add(Restrictions.eq("id", studentId));
criteria.setFetchMode("attends", FetchMode.JOIN);
Criteria attendCriteria = criteria.createCriteria("attends", "attend")
.setFetchMode("course", FetchMode.JOIN);
Criteria courseCriteria = attendCriteria.createCriteria("course", "course")
.setFetchMode("scheduleList", FetchMode.JOIN);
Criteria scheduleCriteria = courseCriteria.createCriteria("scheduleList", "schedule");
return (Student) scheduleCriteria.uniqueResult();
}
the query created by hibernate is to get detail is:
select
this_.id as id1_4_4_,
this_.code_melli as code_mel2_4_4_,
this_.email as email3_4_4_,
this_.mobile as mobile4_4_4_,
this_.name as name5_4_4_,
this_.phone as phone6_4_4_,
this_.register_date as register7_4_4_,
attend1_.course_id as course_i1_1_0_,
attend1_.student_id as student_2_1_0_,
attend1_.score as score3_1_0_,
course2_.id as id1_2_1_,
course2_.cluster as cluster2_2_1_,
course2_.code as code3_2_1_,
course2_.end_date as end_date4_2_1_,
course2_.name as name5_2_1_,
course2_.salary as salary6_2_1_,
course2_.start_date as start_da7_2_1_,
course2_.students as students8_2_1_,
course2_.teacher_id as teacher10_2_1_,
course2_.tuition as tuition9_2_1_,
schedule3_.course_id as course_i1_2_6_,
schedule3_.course_id as course_i1_3_6_,
schedule3_.day as day2_3_6_,
schedule3_.course_id as course_i1_3_2_,
schedule3_.day as day2_3_2_,
schedule3_.endt as endt3_3_2_,
schedule3_.start as start4_3_2_,
teacher8_.id as id1_5_3_,
teacher8_.code_melli as code_mel2_5_3_,
teacher8_.email as email3_5_3_,
teacher8_.mobile as mobile4_5_3_,
teacher8_.name as name5_5_3_,
teacher8_.phone as phone6_5_3_,
teacher8_.register_date as register7_5_3_
from
public.students this_
inner join
public.attend attend1_
on this_.id=attend1_.student_id
inner join
public.courses course2_
on attend1_.course_id=course2_.id
left outer join
public.schedule schedule3_
on course2_.id=schedule3_.course_id
left outer join
public.teachers teacher8_
on course2_.teacher_id=teacher8_.id
where
this_.id=?
but it has problem:
setFetchMode method dont work. beacuse program throw following exception:
threw 'org.hibernate.LazyInitializationException' exception.
Related
I have this diagram:
table diagram
and I want to filter by the employees that have a project.
In normal SQL I will go like this
select * from employees e
join employee_projects ep on ep.employee_id = e.id
How can I achieve the same with Hibernate?
I tried using criteria builder and specifications but I can't get the data from the join table.
You can select all employees that have a project like this
em.createQuery(
"SELECT e FROM Employee e JOIN e.projects p WHERE p IS NOT NULL", Employee.class).getResultList()
You can join tables using join method of root object.
try something like this below
I have used it for one to many relation
Join<Post, Tag> join = root.join("tags", JoinType.INNER);
Predicate tagPredicate = criteriaBuilder.like(join.get("name"), "%" + search + "%");
for many to many relation,
Join<Post, Tag> postTagsTable = root.join("tags", JoinType.INNER);
return postTagsTable.<String>get("name").in(tagNames);
here I have tags field in Post entity, which is used inside join
I want to reduce the amount of querys run by spring. When getting an object with #ElementCollection via SQL I want to get the data for the ElementCollections directly via a JOIN within the quers.
The attribute with the ElementCollection
#ElementCollection(fetch = FetchType.EAGER)
#JoinTable(name = "song_genre_list")
#org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
private List<String> genre;
The Method that uses a custom string:
#Query(
value = "select distinct s.*, g.* from musicdb.songs s left join musicdb.song_genre_list g on s.id = g.song_id where s.name like ?1 or s.artist like ?1",
nativeQuery = true)
List<Song> searchSong(String title);
How I would imagine defining a query that also loads this element collection:
SELECT DISTINCT s.*, g.* FROM musicdb.songs s LEFT JOIN musicdb.song_genre_list g ON s.id = g.song_id WHERE s.name LIKE ?1 OR s.artist LIKE ?1
What Spring currently does (loading the genres for 3 songs with more querys):
Hibernate: select distinct s.*, g.* from musicdb.songs s left join musicdb.song_genre_list g on s.id = g.song_id where s.name like ?1 or s.artist like ?1
Hibernate: select genre0_.song_id as song_id1_4_0_, genre0_.genre as genre2_4_0_ from musicdb.song_genre_list genre0_ where genre0_.song_id=?
Hibernate: select genre0_.song_id as song_id1_4_0_, genre0_.genre as genre2_4_0_ from musicdb.song_genre_list genre0_ where genre0_.song_id=?
Hibernate: select genre0_.song_id as song_id1_4_0_, genre0_.genre as genre2_4_0_ from musicdb.song_genre_list genre0_ where genre0_.song_id=?
What I want Spring to do:
Hibernate: select distinct s.*, g.* from musicdb.songs s left join musicdb.song_genre_list g on s.id = g.song_id where s.name like ?1 or s.artist like ?1
The required Data for the ElementCollection is already included with the join. How can I tell spring to import that Data?
FetchType.EAGER will already load the genres for you, so you dont need to write a join in your original query. But for that hibernate hibernate uses separate queries by default. To change this add the annotation '#Fetch(FetchMode.JOIN)' on the genre field
I have these following Classes:
class Person(){
#OneToMany(mappedBy="person")
private List<PersonRoles> roles;
}
class PersonRoles(){
#ManyToOne
#JoinColumn(name = "person_id", nullable = false)
private Person person;
#ManyToOne
#JoinColumn(name = "request_id")
private Request request;
}
class Request(){
#OneToMany(mappedBy="request")
private List<PersonRoles> roles;
}
Now I am going to fetch all person based on a given request id and his roles by using hibernate and inner join but my log is telling me that my table doesn't exist. This is my query so far:
sql = "SELECT p.* FROM person AS p INNER JOIN p.roles ON p.roles.personId = p.id
INNER JOIN request AS r ON p.roles.requestId = r.id AND p.roles.role like :item
AND r.id = :id";
query = session.createSQLQuery(sql);
query.addEntity(Person.class);
query.setParameter("item", "Members");
query.setParameter("id", id);
person = (Person) query.uniqueResult();
and this is what i received on the log:
Table 'p.roles' doesn't exist
Did i forget some hibernate annotation? or My query has something wrong?
Brief reason
your syntax of SQL is wrong
Detailed explanation
here is the syntax of inner join example
SELECT column_name(s)
FROM table1
INNER JOIN table2
ON table1.column_name = table2.column_name;
for multiple inner join
SELECT *
FROM table1
INNER JOIN table2
ON table1.primaryKey=table2.table1Id
INNER JOIN table3
ON table1.primaryKey=table3.table1Id
but you have used INNER JOIN p.roles there should be a table name after the INNER JOIN, not a column name.
that's why you got an error, moreover, use HQL instead of SQL in hibernate it is a good practice.
happy coding!
I am new to JPA and I have a Left Join scenario.
I have my native sql query as below and I am using left join to fetch the complete records from V_MONITORING table for st.id = 10001.
I have some null values for id_legislature which also needs to be selected and hence using a left join
select distinct
mv.id_set, mv.id_travel, mv.id_legislature
from
V_MONITORING mv
left join v_set st on mv.id_set = st.id
left join v_travel fg on mv.id_travel = fg.id
left join v_legislature gg on mv.id_legislature = gg.id;
The same thing I am implementing using the JPA criteria query, I am unable to fetch the null records
Below is the code
Predicate predicate = cb.conjunction();
Root<MonitoringBE> mvRoot = criteriaQuery.from(MonitoringBE.class);
mvRoot.fetch(MonitoringBE.id_set, JoinType.LEFT);
mvRoot.fetch(MonitoringBE.id_travel, JoinType.LEFT);
mvRoot.fetch(MonitoringBE.id_legislature, JoinType.LEFT);
final Path<Object> serieneinsatzterminPath= mvRoot.get(MonitoringBE.id_set);
predicate = cb.and(predicate, cb.EqualTo(serieneinsatzterminPath.get(SetBE.GUELTIG_VON_DATUM), startSetDate));
criteriaQuery.multiselect(
mvRoot.get(MonitoringBE.id_travel).alias("id_travel"),
mvRoot.get(MonitoringBE.id_set).alias("id_set"),
mvRoot.get(MonitoringBE.id_legislature).alias("id_legislature"))
.distinct(true).where(predicate);
Can some one guide me.
You have to replace the mvRoot.get(MonitoringBE.id_travel) and others in the multiselect-statement with mvRoot.join(MonitoringBE.id_travel, JoinType.LEFT). Otherwise they will end up in a inner join.
I need to create subquery using the Criteria API
the current Criteria query which i have created is
Criteria propCriteria = session.createCriteria(PropertyDetail.class);
propCriteria.createAlias("property","prop");
propCriteria.createAlias("country", "country");
propCriteria.add(Restrictions.eq("prop.propertyId",promotionFormBean.getPropertyId()));
The SQL produced by Hibernate is
select * from PROPERTY_DETAILS this_, COUNTRY_MASTER country2_,
PROPERTY_MASTER prop1_, USER_MASTER user6_, ROLE_MASTER role7_,
USER_MASTER user8_ where this_.country_id=country2_.country_Id and
this_.property_id=prop1_.PROPERTY_ID and
prop1_.archive_user_id=user6_.id(+) and
user6_.role_id=role7_.ROLE_ID(+) and
prop1_.create_user_id=user8_.id(+) and prop1_.PROPERTY_ID=?.
What i need to do is to produce the below SQL using criteria
Required:
select * from PROPERTY_DETAILS this_, COUNTRY_MASTER country2_,
PROPERTY_MASTER prop1_, USER_MASTER user6_, ROLE_MASTER role7_,
USER_MASTER user8_ where (this_.country_id=country2_.country_Id or
country2_.controller_order in (select zone_id from
property_zone_mapping where property_id=?)) and
this_.property_id=prop1_.PROPERTY_ID and
prop1_.archive_user_id=user6_.id(+) and
user6_.role_id=role7_.ROLE_ID(+) and
prop1_.create_user_id=user8_.id(+) and prop1_.PROPERTY_ID=?
The bold part of Required section.Property_zone_mapping is one another table which not associated with PropertyDetail.class.
I want somehow to use this table using subquery .
Thanks in advance.
I find criteria queries so much harder to read than HQL. Have you considered a NamedQuery?
#NamedQueries({
#NamedQuery(
name="PropertyDetail.findByPropertyId",
query="from PropertyDetail join property p join country c where p.propertyId = :propertyId"
)
})
public class PropertyDetail {
...
}
public class PropertyDetailDao {
public List<PropertyDetail> findByPropertyId(long propertyId) {
Query query = getSession().getNamedQuery("PropertyDetail.findByPropertyId");
query.setParameter("propertyId", propertyId);
return query.list();
}
}