I have a JPA 2 query that is driving me nuts. A SurveyQuestion may have an Organization. Here's the mapping within SurveyQuestion
#ManyToOne( optional=true )
#JoinColumn( name="organization_key" )
private Organization organization;
Organization has a field named key. I create a TypedNamedQuery with the following jpql
SELECT q from SurveyQuestion q
where q.organization IS NULL
or q.organization.key = :organizationKey
with that query I only get the questions that have the given key. If I remove the q.organization.key = :organizationKey from the query, then I get all those that have no organization, but I can't for the life of me get it to return the combination of those that have no organization or have the given organization.
JPA2 with EclipseLink provider.
This is JPA standard.
q.organization.key
resolves to an inner join on q.organization, not to a left join!
You have to do this:
SELECT q
from SurveyQuestion q
left join q.organization o
where o is null OR o.key = :organizationKey
Related
I want to write this query using Hibernate Criteria language. I am pretty new to Hibernate and not able to convert this query into Criteria form. I referred lots of answers available on SO but in my case I am using inner join on different columns rather than primary key/ foreign key column. I referred this but still can't make it right.
select TableA.columnA1, TableA.columnA2, TableA.columnA3, TableB.columnB1, TableC.columnC2 from TableA inner join TableB
on
cast(TableA.columnA3 as Integer) = TableB.columnB2
inner join
TableC
on
TableB.columnB3 = TableC.columnC1
To handle the joining logic, you are going to want to use from for each of the tables and include all of your conditions from the on-clauses in the where predicate.
Here is a JPA example that handles a parent-child relationship without having a foreign-key relationship:
EntityManager em = getDb().getEntityManager();
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Child> criteria = cb.createQuery(Child.class);
Root<Parent> p = criteria.from(Parent.class);
Root<Child> c = criteria.from(Child.class);
Predicate condition = cb.and(
cb.equal(c.get(Child_.parentId), p.get(Parent_.id)),
...
);
criteria.where(condition);
criteria.select(c);
criteria.orderBy(cb.asc(c.get(Child_.createDate)));
TypedQuery<Child> q = em.createQuery(criteria).setMaxResults(limit);
A JPA example is provided here, because the Hibernate criteria API is deprecated in favor of the JPA criteria API (see Legacy Hibernate Criteria Queries).
I am using JPA repository to access Mysql.
I have this query :
#Query("Select s.productName, s.stock from Sell s");
I am getting an execution error because stock is sometime null.
The generated sql translation of this query is :
select sell0_.productName, sell0_.stock_id from T_SELL sell0_ inner join T_STOCK stock0_ on sell0_.stock_id=stock0_.id
Is there a way to make this JPA query work even if stock_id is null?
Should be able to coalesce
#Query("Select s.productName, coalesce(s.stock,'xxx') from Sell s");
Full man is https://docs.jboss.org/hibernate/orm/4.3/devguide/en-US/html/ch11.html
Hope this helps.
Try to change relation definition, using optional = true:
#OneToOne(optional = true)
private Stock stock;
You can even change how this data should be fetched, using a join, a subselect or with a different select. More info here: JPA eager fetch does not join
How do I get JPA & JPQL to pass a complete join query to the RDBMS? For example,
SELECT e
FROM Employee e
WHERE a.runkey = e.runkey
AND e.middle = 'M'
AND a.state = 'MA'
With the following Employee class
#Entity
public class Employee implements Serializable {
blah ... blah
#OneToOne
#JoinColumn(
name = "runkey",
referencedColumnName = "runkey",
insertable=false, updatable=false)
private Address address;
}
and the JPQL,
SELECT e
FROM Employee e
INNER JOIN FETCH e.address AS a
WHERE a.state = :state
AND e.middle = :middle
I am able to get Hibernate JPA to pull the data as expected.
However, eclipselink croaks that it cannot traverse associated field "address".
If so, how then should I design the Employee entity and how should I phrase the JPQL in order to get eclipselink to execute a table join with WHERE filters on both tables?
(Rant: Otherwise Eclipselink JPA is no better than JDO!!!)
~
Further edit: Does this post mean anything to my case ....
https://forums.oracle.com/forums/thread.jspa?threadID=1568659
The problem is that you are trying to alias a join fetch which is not allowed according to the JPQL specs. Hibernate allows this anyway.
You can still obtain the desired behavior with EclipseLink using query hints.
Take a look at the following posts:
jpa fetch join query
EclipseLink JPQL (Glassfish v3): join fetch syntax problem?
The following link can also be useful:
http://wiki.eclipse.org/EclipseLink/Examples/JPA/QueryOptimization
I have 3 tables, Role[roleId, roleName], Token[tokenID, tokenName] & ROLETOKENASSOCIATION[roleId, tokenID]. The 3rd one was created automatically by hibernate. Now if i simply write a Query to get all the objects from Role class means, it gives the all role objects along with the associated tokenID & tokenName.
I just wanted the association as unidirectional. i.e: Roles--->Tokens
So the annotation in the Role class looks like,
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private int roleId;
private String roleName;
#ManyToMany
#JoinTable(name="ROLE_TOKEN_ASSOCIATION",
joinColumns={#JoinColumn(name="roleId")},
inverseJoinColumns={#JoinColumn(name="tokenID")})
private List<Token> tkns;
//Getters & Setters
Now i want the tokenNames for the specific roleId.
First i made a query like this SELECT tkns.tokenName FROM Role WHERE Role.roleId=:roleId
But, i ended up with some dereference error.
Then i changed the query to SELECT tkns FROM Role r WHERE r.roleId=:roleId
Now i have got what i wanted. But it comes with roleId too.
How shall i get tokenName itself?
Actually my problem is solved, but i would like to know how to do it.
It ll be helpful to me, if anyone explains the Query Construction.
Any suggestions!!
Have you tried
SELECT t.tokenName FROM Role r JOIN r.tkns t WHERE r.roleId = :roleId
EDIT: This query almost directly maps to the corresponding SQL query where Role r JOIN r.tkns t is a shorthand syntax for the SQL join via the link table Role r JOIN ROLETOKENASSOCIATION rt ON r.roleId = rt.roleId JOIN Token ON rt.tokenId = t.tokenId. Affe's answer is another syntax for the same query.
See also:
Chapter 14. HQL: The Hibernate Query Language
You want a scalar list of just the name field? You should be able to get that like this
select t.name from Roles r, IN(r.tkns) t where r.roleId = :id
I'm piggy-backing off of How to join tables in unidirectional many-to-one condition?.
If you have two classes:
class A {
#Id
public Long id;
}
class B {
#Id
public Long id;
#ManyToOne
#JoinColumn(name = "parent_id", referencedColumnName = "id")
public A parent;
}
B -> A is a many to one relationship. I understand that I could add a Collection of Bs to A however I do not want that association.
So my actual question is, Is there an HQL or Criteria way of creating the SQL query:
select * from A left join B on (b.parent_id = a.id)
This will retrieve all A records with a Cartesian product of each B record that references A and will include A records that have no B referencing them.
If you use:
from A a, B b where b.a = a
then it is an inner join and you do not receive the A records that do not have a B referencing them.
I have not found a good way of doing this without two queries so anything less than that would be great.
Thanks.
I've made an example with what you posted and I think this may work:
select a,b from B as b left outer join b.parent as a in HQL.
I have to find a "criteria" way of doing that though.
You may do so by specifying the fetch attribute.
(10) fetch (optional) Choose between outer-join fetching and fetching by sequential select.
You find it at: Chapter 6. Collection Mapping, scroll down to: 6.2. Mapping a Collection
EDIT
I read in your question's comment that you wanted a way to perform a raw SQL query? Here a reference that might possibly be of interest:
Chapter 13 - Native SQL Queries
and if you want a way to make it possible through HQL:
Chapter 11. HQL: The Hibernate Query Language
In chapter 11, you want to scroll down to 11.3. Associations and joins.
IQuery q = session.CreateQuery(#"from A as ClassA left join B as ClassB");
I guess however that ClassB needs to be a member of ClassA. Further reasdings shall help.
Another thing that might proove to be useful to you are named queries:
<query name="PeopleByName">
from Person p
where p.Name like :name
</query>
And calling this query from within code like so:
using (var session = sessionFactory.OpenSession())
using (var tx = session.BeginTransaction()) {
session.GetNamedQuery("PeopleByName")
.SetParameter("name", "ayende")
.List();
tx.Commit();
}
Please take a look at the referenced link by Ayende who explains it more in depth.