Joining multiple table using hibernate criteria - java

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)

Related

JPQL Extract pk of an relation entity without a second query

I have these entities (is an example because i cant share real name entities):
#Entity
public class User { #Id private BigDecimal id; private String name, private Color favouriteColor }
#Entity
public class Color { #Id private Long colorId; private String colorName;}
In the table I have this data:
USER
ID|NAME|FavColor
1 |John| 1
2 |Sarah| 2
3 |Mike| 1
COLOR
1|Red
2|Blue
Now I want make a query that recover all my user data without select Color entity, only its ids.
#Query("new myDto(u.iduser,u.username,u.favcolor) from user u where favcolor in :listcolors")
This makes me an query of the two tables, I want a unique query because i dont need color entities, only the ids.
--
Other option that I am testing is making a implementation of a nativequery like this:
final List<MyDTO> result = new ArrayList<>();
Query q = entityManager.createNativeQuery("SELECT " +
" USER_ID, " +
" USER_NAME, " +
" FAV_COLOR " + +
"FROM USER " +
"WHERE FAV_COLOR IN (?)");
q.setParameter(1, colors.toString().replace("[","").replace("]",""));
Long TRUE = new Long(1L);
final List<Object[]> resultList = q.getResultList();
for (Object[] objects : resultList) {
MyDTOdto = new MyDTO();
dto.userId(((((BigDecimal) objects[0]) != null) ? ((BigDecimal) objects[0]).longValue() : null));
dto.userName(((((String) objects[0]) != null) ? ((String) objects[0]).longValue() : null));
dto.favColor(((((BigDecimal) objects[0]) != null) ? ((BigDecimal) objects[0]).longValue() : null));
result.add(dto);
}
return result;
In this case, I am getting error code (ORA-1722 - Number Not valid). I don't know what I can test now. Some ideas? Thanks
I am guessing you have issues with the SQL generated and your use of the inner join: when you call "u.favcolor" in the select clause, you are telling JPA to perform an inner join from User to Color based on the favcolor relationship. As favcolor is a Color reference, you are going to get the full color row, where as your native query implies you just want the foreign key value. If all you want is the fk/ID value from Color, the query should be:
"SELECT new myDto(u.iduser, u.username, color.id) FROM user u join u.favcolor color WHERE color.id in :listcolors"
This still might perform an inner join from user to color, but it should be in a single statement.
If you want to ensure you avoid the join:
Use EclipseLink's COLUMN JPQL extension to access the foreign key column directly. Something like:
"SELECT new myDto(u.iduser, u.username, COLUMN('FAV_COLOR', u) FROM user u WHERE COLUMN('FAV_COLOR', u) in :listcolors"
Use EclipseLink native query key functionality to access the "FAV_COLOR" foreign key column in the USER table directly for your JPQL queries. This requires a descriptor customizer to access, but allows you to use the foreign key value in JPQL queries directly without having to map it, and without the COLUMN mechanism tying your JPQL queries to a particular database table detail. This would allow a query of the form:
"SELECT new myDto(u.iduser, u.username, u.favColorVal FROM user u join u.favcolor color WHERE u.favColorVal in :listcolors"
Just map the FAV_COLOR as a basic mapping, in addition to the existing favColor reference mapping (or replacing it if you want):
#Basic
#Column(name="FAV_COLOR", updatable=false, insertable=false)
BigDecimal favColorId
This then allows you to use query "SELECT new myDto(u.iduser, u.username, u.favColorId FROM user u join u.favColorId color WHERE u.favColorId in :listcolors" to the same effect, but you can also just return the User instance (marking favColor as lazy and not serializable) as it will have the same data anyway.

Pageable not work spring data MySQL Hibernate

I create dao layer using spring data as follow
#Query(value="SELECT p FROM Products p INNER JOIN FETCH p.categoriesProducts cp INNER JOIN FETCH cp.categoryId c INNER JOIN FETCH p.mediasList ml ")
public List<Products> getAllProduct(Pageable pageable);
and I call it as follow
PageRequest pr = new PageRequest(0,100) ;
List<Products> ls = this.repo.getProductRepo().getAllProduct(pr) ;
my issue is I dont see the limit key word in the printed SQL in the log which is shown as follow
select products0_.id as id1_8_0_, categories1_.product_id as product_1_2_1_, categories2_.id as id1_1_2_, mediaslist3_.id as id1_4_3_, products0_.description as descript2_8_0_, products0_.discount_price as discount3_8_0_, products0_.price as price4_8_0_, products0_.prod_condition as prod_con5_8_0_, products0_.prod_number as prod_num6_8_0_, products0_.qty as qty7_8_0_, products0_.title as title8_8_0_, categories1_.category_id as category2_2_1_, categories2_.cat_name as cat_name2_1_2_, categories2_.description as descript3_1_2_, categories2_.keywords as keywords4_1_2_, categories2_.parent_id as parent_i5_1_2_, mediaslist3_.big_image_file as big_imag2_4_3_, mediaslist3_.media_type as media_ty3_4_3_, mediaslist3_.product_id as product_6_4_3_, mediaslist3_.thumb_image_file as thumb_im4_4_3_, mediaslist3_.video_file as video_fi5_4_3_, mediaslist3_.product_id as product_6_8_0__, mediaslist3_.id as id1_4_0__ from products products0_ inner join categories_products categories1_ on products0_.id=categories1_.product_id inner join categories categories2_ on categories1_.category_id=categories2_.id inner join medias mediaslist3_ on products0_.id=mediaslist3_.product_id
I am not sure what I do wrong the previous query is return 1000 rows from mysql and then it get the first 100 with the spring data but I need it to append limit 0,100 in the end of query, not sure how to do that

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;

HQL right join empty list

I am using hql with hibernate. I've tried to write a query over three tables. The tables are Medientyp, RaumMedientyp and Raum. I wanna read all Medientyp's from the whole table and all RaumMedientyp's from a specific raumId.
The realtions between the tables are:
Medientyp 1 <--> mc RaumMedientyp mc <--> 1 Raum
I need all as RaumMedientyp Entity.
The query i tried is:
String hql = "from RaumMedientyp rm right join rm.medientyp m inner join rm.raum r where r.id = :raumId";
Query query = getSession().createQuery(hql);
query.setInteger(":raumId", raumId);
But if i'm executing
query.list();
i've got a empty list as return.

Hibernate detached queries as a part of the criteria query

java experts can you please help me write detached queries as a part of the criteria query for the following SQL statement.
select A.*
FROM AETABLE A
where not exists
(
select entryid
FROM AETABLE B
where B.classpk = A.classpk
and B.userid = A.userid
and B.modifiedDate > A.modifiedDate
)
and userid = 10146
You need to write a correlated subquery. Assuming property / class names match column / table names above:
DetachedCriteria subquery = DetachedCriteria.forClass(AETable.class, "b")
.add(Property.forName("b.classpk").eqProperty("a.classpk"))
.add(Property.forName("b.userid").eqProperty("a.userid"))
.add(Property.forName("b.modifiedDate").gtProperty("a.modifiedDate"));
Criteria criteria = session.createCriteria(AETable.class, "a")
.add(Property.forName("userid").eq(new Integer(10146)))
.add(Subqueries.notExists(subquery);
Just one addition to the above query. If the entryid is not the primary key, then you'll need to add projection.
DetachedCriteria subquery = DetachedCriteria.forClass(AETable.class, "b")
.add(Property.forName("b.classpk").eqProperty("a.classpk"))
.add(Property.forName("b.userid").eqProperty("a.userid"))
.add(Property.forName("b.modifiedDate").gtProperty("a.modifiedDate"))
.add(setProjection(Projections.property("entryId")); // Additional projection property
Criteria criteria = session.createCriteria(AETable.class, "a")
.add(Property.forName("userid").eq(new Integer(10146)))
.add(Subqueries.notExists(subquery);

Categories