Fetch relation of fetched relation in hibernate HQL query - java

I have entity Customer, Car:
#Entity
public class Customer{
List<Car> cars;
...
}
#Entity
public class Car{
List<Customer> previousOwners;
...
}
Basicly Customer can have multiple cars rented, and Cars remember previous owners.
Both entities have more relations, and i am omiting them.
Now want to retrieve all cars of Customer:
public List<Car> getCars(int customerId) {
List<Car> cars= new ArrayList<>();
Transaction tx = null;
try (Session session = HibernateUtil.getSessionFactory().openSession()) {
tx = session.beginTransaction();
cars= (List<Car>) session.createQuery("SELECT cars FROM Customer u JOIN u.cars cars WHERE u.id IN :ids ").setParameter("ids", customerId).list();
} catch (HibernateException e) {
if (tx != null) tx.rollback();
e.printStackTrace();
}
return cars;
}
This will return list of Cars, i need to use JOIN cuz lazyinitialization is set to FALSE.
Now i want to fetch Cars and their previos owners. But i am unable to think of any query, i tried using:
"SELECT cars FROM Customer u JOIN u.cars cars JOIN u.cars.previousOwners previousOwners WHERE u.id IN :ids " but this did nothing.
What i am aming for is to return object Car, with list inside, when i tried using
"SELECT cars, cars.previousOwner FROM Customer u JOIN u.cars cars JOIN u.cars.previousOwner previosOwner WHERE u.id IN :ids "
it returned the list of previousOwners, but not inside Car object, but as second element in returned list...
How can i create such query? Thanks fo help!

You probably want a (LEFT) JOIN FETCH query:
SELECT cars FROM Customer u
JOIN u.cars cars
JOIN FETCH cars.previousOwners
WHERE u.id IN :ids
This instructs Hibernate to join the cars.previousOwners relation even when it's declared to use lazy-fetching by default. Use a left join fetch if you also want to return cars with no previousOwners.
See the docs for more info.

Related

How to select from multi tables (many to many)?

Database:
I want to get a list User, who have the same Monhoc (it has maMH= MH1).
My code :
private final SessionFactory sf = HibernateUtil.getSessionFactory();
Public List<User> listUserMonHoc() {
try {
sf.getCurrentSession().beginTransaction();
Query query = sf.getCurrentSession().createSQLQuery("select a.username, a.name from Monhoc b join b.User a where b.mamh = :id");
query.setString("id", "MH1");
List<User> list = query.list();
sf.getCurrentSession().getTransaction().commit();
return list;
} catch (Exception e) {
System.out.println("sai");
System.out.println(e.toString());
//return null;
e.printStackTrace();
return null;
}
}
ERROR message: ERROR: Table 'b.user' doesn't exist.
Thank you!
As i can see you have problems with your query. First you must join your third table and then search by id from the monhoc table.
Second there is a problem here
Query query = sf.getCurrentSession().createSQLQuery("select a.username, a.name from Monhoc b join b.User a where b.mamh = :id");
you must change b.User to User, cause b is allias of your Monhoc table.
So as a native query in MySql will look something like this :
SELECT u.username, u.name
FROM user AS u
INNER JOIN user_monhoc AS um
ON u.username = um.user_id
INNER JOIN monhoc AS m
ON um.mh_id = m.mamh
WHERE ....
I am using inner join (it can be different depents on your needs).

Hibernate data fetching

Here is how I fetch data:
public static List<SubjectSubjectUsersUsers> getAllSubjectUsers()
{
List<SubjectSubjectUsersUsers> theList = null;
Session session = ServiceLocator.getSessionFactory().openSession();
try{
theList = session.createSQLQuery("SELECT s.name as subject_name, u.name as user_name, u.surname as user_surname, su.id as id from subjects s "
+ "join subject_users su on s.id = su.subject_id join users u on su.user_id = u.id")
.addScalar("subject_name", StandardBasicTypes.STRING)
.addScalar("user_name", StandardBasicTypes.STRING)
.addScalar("user_surname", StandardBasicTypes.STRING)
.addScalar("id", StandardBasicTypes.LONG)
.setResultTransformer(Transformers.aliasToBean(SubjectSubjectUsersUsers.class)).list();
}catch(Exception e){
e.printStackTrace();
}finally{
session.flush();
session.close();
}
return theList;
}
The problem is when I update data manually in the DB, the fetched data is not changed. But when I reload the server and IDE it works. What could be the cause of the problem? I guess I used the session object in the incorrect way. Thank you.
you need to set CacheMode to refresh
query.setCacheMode(CacheMode.REFRESH);
Your query will look like -
theList = session.createSQLQuery("SELECT s.name as subject_name, u.name as user_name, u.surname as user_surname, su.id as id from subjects s "
+ "join subject_users su on s.id = su.subject_id join users u on su.user_id = u.id")
.setCacheMode(CacheMode.REFRESH)
.addScalar("subject_name", StandardBasicTypes.STRING)
.addScalar("user_name", StandardBasicTypes.STRING)
.addScalar("user_surname", StandardBasicTypes.STRING)
.addScalar("id", StandardBasicTypes.LONG)
.setResultTransformer(Transformers.aliasToBean(SubjectSubjectUsersUsers.class)).list();
However it's a bad idea to update DB from outsite while using hibernate, otherwise you won't get benefits of hibernate cache.

Is there any spring jpa equivalent to following query

Query :
#Query("Select p.name,t.points from Player p,Tournament t where t.id=?1 And p.id=t.player_id")
I have my player and tournament entity and their corresponding JPA repositories. But the problem is we can get only entities from our query, but i want to do above query, please help me with this i am new to it.
this is my sql query i want to add but where to add i am not getting:
Select p.name, t.points_rewarded from player p, participant t where t.tournament_id="1" and t.player_id=p.id;
This is how you can do it with JPQL for JPA:
String queryString = "select p.name, t.points from Tournament t," +
" Player p where t.player_id=p.id " +
"and t.id= :id_tournament";
Query query = this.entityManager.createQuery(queryString);
query.setParameter("id_tournament", 1);
List results = query.getResultList();
You can take a look at this JPA Query Structure (JPQL / Criteria) for further information about JPQL queries.
And this is ho you can do it using HQL for Hibernate, these are two ways of doing it:
String hql = "SELECT p.name, t.points from Player p,Tournament t WHERE t.id= '1' And p.id=t.player_id";
Query query = session.createQuery(hql);
List results = query.list();
Or using query.setParameter() method like this:
String hql = "SELECT p.name, t.points from Player p,Tournament t WHERE t.id= :tournament_id And p.id=t.player_id";
Query query = session.createQuery(hql);
query.setParameter("tournament_id",1);
List results = query.list();
You can take a look at this HQL Tutorial for further information about HQL queries.
Note:
In both cases you will get a list of Object's array List<Object[]> where element one array[0] is the p.name and the second one is t.points.
TypedQuery instead of normal Query in JPA
this is what i was looking for, thanks chsdk for help, i have to create pojos class, and in above link answer is working fine foe me,
Here is my code sample
String querystring = "SELECT new example.restDTO.ResultDTO(p.name,t.pointsRewarded) FROM Player p, Participant t where t.tournamentId=?1 AND t.playerId = p.id ORDER by t.pointsRewarded DESC";
EntityManager em = this.emf.createEntityManager();
try {
Query queryresults = em.createQuery(querystring).setParameter(1, tournamentId);
List<ResultDTO> result =queryresults.getResultList();
return new ResponseEntity<>(result, HttpStatus.OK);
} catch (Exception e) {
e.printStackTrace();
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
} finally {
if (em != null) {
em.close();
}}

Get multiple entities from hibernate sql join

I have 4 table:
Orders(orderID, orderDate, orderItem (OneToMany))
OrderItem(id, order(manyToOne), book (manyToOne), quantity)
Book (id, title, cost)
User(id, username, password)
Here is my query in SQL:
String sql = "SELECT orders.id, book.title, orderitem.quantity
FROM orderitem INNER JOIN book ON book.id = orderitem.book_id INNER JOIN orders ON orders.id = orderitem.orders_id WHERE user_id = 1;
(user_id is the foreign key of User in Orders table)
(orders_id is the foreign key of Orders in OrderItem table)
List<OrderItem> orderBookInfo = (List<OrderItem>) session.createSQLQuery(sql); // returns List<Object[]> why?!
This query result comes from joining of 3 tables (Book, Order, OderItem)
And this is the result in table:
Question is how can i assign each result's column to it's corresponding properties?
For example:
orderBookInfo.order.id = (first location of orderBookInfo)
orderBookInfo.book.title = (second location of orderBookInfo)
You need to execute an Entity query instead. Assuming you already mapped the entities properly, this is how the HQL query would look like:
SELECT o
FROM orderitem oi
JOIN FETCH oi.book
JOIN FETCH oi.orders
JOIN FETCH oi.user u
WHERE u.id = 1;

Joining multiple table using hibernate criteria

I am trying to join multiple table to join using criteria but getting some problem , please help me:
I have a sql query like :
SELECT a.type, a.time, c.code AS exchangeCode
FROM CutOffTime AS a INNER JOIN
Country AS b ON a.country_fk = b.id INNER JOIN
Exchange AS c ON c.country_fk = b.id
These three table : CutOffTime (has country), Country, Exchange (has country) are 3 entity classes.
How can i join like this using hibernate criteria,my code below still not complete :
List<Map<String, Object>> aa= ( List<Map<String, Object>>) getHibernateTemplate().executeFind(new HibernateCallback() {
#Override
public Object doInHibernate(final Session session) throws HibernateException, SQLException {
final Criteria c = session.createCriteria(CutOffTime.class,"cutofftime");
c.createAlias("cutofftime.country", "country");
final Criteria c2= session.createCriteria(Exchange.class,"exchange");
c2.createAlias("exchange.country", "country");
// c.add(Restrictions.eqProperty("cutofftime.country.id","exchange.country.id"));
return c.list();
}
});
I think you can't get it done from hibernate using a single join as you don't have a bidirectional relationship from Country to anywhere.So I think you have to have 2 seperate joins and then filter the results in second join such that the countrrID in (country ids in first join)

Categories