简体   繁体   中英

Hibernate criteria left our join

I have the following entities:

Machines {
   id,
   name
}

Favorites {
  userId,
  objectId,
  objectType
}

Now I want to return list of machines ordered by favorites, name.

Favorites does not have any relation with Machines entities, its a generic entity which can hold various favoritable objects.

I got the sorting to work by the following raw sql. Is there any way to get this working using hibernate criterias. Basically ability to add alias for Favorites though Machines doesn't have any reference to it.

select m.* from Machines m left outer join Favorites f on m.id=f.objectId and f.userId =@userId order by f.userId desc, m.name asc

There are two ways to do this:

  1. Use an SQL query or an SQL restriction for a criteria query.
  2. Map the relation between Favorites and Machines as an Any type association .

Since you already have the query, executing it as a native SQL query through hibernate is the simplest solution:

sess
  .createSQLQuery("SELECT ... ")
  .addEntity(Machine.class)
  .list();

The Any type association however, will probably benefit you in other situations where you want to query favoritables.

As said by @Maarten Winkels, you can use native SQL query that you have. You can do that but, if you want change your database then syntax may differs. So, it is recommended not to use native SQL query.

You cannot perform outer join using Hibernate criteria without any association between tables. If you change your mind & want to add an association between these tables, then You can do something like below using criteria

List machines = session.createCriteria( Machines.class )
                    .createAlias("Machines", "m")
                    .createAlias("Favorites", "f", Criteria.LEFT_JOIN, 
                                Restrictions.and(Restrictions.eq("m.id", "f.objectId"),
                                Restrictions.eq("f.userId", "@userId")))
                    .addOrder(Order.desc("f.userId"))
                    .addOrder(Order.asc("m.name"))
                    .list();

If for some reason you don't want to add any relationship between these tables, then you can use INNER JOIN or CROSS JOIN to get all machines with whatever criteria you want.

from Machines m, Favorites f where m.id = f.objectId and f.userId = @userId order by f.userId desc, m.name asc; 

With inner joins there is one problem, if there is outer join relation in database then it doesn't work.

You can also write subqueries or separate queries & perform manual conditional checks between the results returned by those queries.

And one thing I want to ask you, What is the meaning of @userId in your SQL query ? I keep it as it is in my answer but, I didn't understand for what purpose @ is there ?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM