I'm working on JPA and I got stuck with syntax or right approach to write JPQL, I have entities: department and employee,
#Entity
Department
#OneToMany
Employee
-----------------------------------------
#Entity
Employee
#ManyToOne
Department
Now I have DOA where I am just adding condition dynamically to the JPQL query for where condition
I need to pull the employee who belong to XYZ department
So my JPQL looks like this
select * from employee where department='PK_OF_DEPT'
NOTE : PK_OF_DEPT is the PK (some sequence)
The error which I am getting is syntax error unknown column department, I tried giving department.id = still not working invalid path error,
NOTE : Id is the attribute name in java object
Can someone help me to get the right syntax, NOTE : I can't use FIND method since it need to be in that DOA which Is used dynamically for listing
There's not much information here, but try this
from employee left join fetch employee.department where department.id='PK_OF_DEPT'
Try this one :
#Query("select d.dname,d.deptno,e.ename,e.eno from Department d join d.employees e where d.id = ?1")
List<Object[]> getDepartmentAndEmployeeDetailsCustomQuery(int departId);
Related
I know there are many topics around this, but I can't find a solution to my problem. I know if I use "distinct" and "order by" with hibernate, the column from the order by has to be in the select clause. The other articles just say that the column must be in select, but I haven't found an example how this is possible to achieve.
This is my Class:
#Entity
#Table(name = "DANCE")
public class Dance implements Serializable {
#Id
private int tanzid;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "SID")
private School school;
#Basic
#Column(name = "titel")
private String titel;
(getter setter...)
My (not working) query:
SELECT distinct d FROM Dance d order by d.school.schoolname
If I do order by title for example it is working.
I have tried to set the schoolname in the select clause:
SELECT distinct d, d.school.schoolname FROM Dance d order by d.school.schoolname
but then hibernate is complaining that the return type of the query isn't from type "Dance.class"
How can I achieve an order by schoolname.
Thank you
You would have to select distinct rows with regard to one column. This is unfortunately not the part of sql standard, so in jpql or hql this cannot be done. You would have to use vendor - specific syntax and native query to achieve this. Here is an example in postgres.
I have trouble with JPA/Hibernate, no matter what I set fetch = FetchType.Lazy or fetch = FetchType.Eager.
My custom method not working (when debug, I see answers collection is PersistentBag and whenever I call getter, the answer is actually created and some condition with WITH in my custom was not applied).
That's what I dont want, I want it will be set at my custom method.
Question is :
1, Am I doing right, disable fetch type and set association at hql query ?
2, If I am doing right, why it's not working, association only when call getter ?
3, If I am wrong, Please tell me how to implement this.
Thanks for reading .
My Parent class :
#Entity
#NamedQuery(name="Question.findAll", query="SELECT q FROM Question q")
public class Question implements Serializable {
//bi-directional many-to-one association to Answer
#OneToMany(mappedBy="question",fetch=FetchType.LAZY)
#JsonManagedReference
private List<Answer> answers;
...
}
And Child class :
#Entity
#NamedQuery(name="Answer.findAll", query="SELECT a FROM Answer a")
public class Answer implements Serializable {
//bi-directional many-to-one association to Question
#ManyToOne
#JoinColumn(name="question_id")
#JsonBackReference
private Question question;
...
}
In My custom method , I'm using HQL as :
public List<Question> search() {
String sql = "SELECT distinct(question)"
+ " FROM Question as question "
+ " LEFT JOIN question.answers as answer with answer.isDeleted = true";
List<Question> result = query.getResultList();
return result;
}
PS. I found I have very similar issue with this post https://stackoverflow.com/a/1372725
but I dont know how to follow his instruction.
JPA doesn't provide any specification on mapping annotations to select fetch strategy. In general, related entities can be fetched in any one of the ways given below
SELECT => one query for root entities + one query for related mapped entity/collection of each root entity = (n+1) queries
SUBSELECT => one query for root entities + second query for related mapped entity/collection of all root entities retrieved in first query = 2 queries
JOIN => one query to fetch both root entities and all of their mapped entity/collection = 1 query
Set your #OneToMany with fetch=FetchType.LAZY and add #Fetch(FetchMode.SELECT)
Then your query will working fine.
This query
SELECT distinct(question)
FROM Question as question
LEFT JOIN question.answers as answer with answer.isDeleted = true
means the same as
SELECT distinct(question)
FROM Question
This query
SELECT distinct(question)
FROM Question as question
INNER JOIN question.answers as answer with answer.isDeleted = true
means get questions that have at least one answer with isDeleted = true.
To fetch a lazy association join fetch can be used
SELECT distinct(question)
FROM Question as question
LEFT JOIN FETCH question.answers
But, I think, it is impossible to fetch an association with a condition.
There is an example using EclipseLink:
http://java-persistence-performance.blogspot.com.by/2012/04/objects-vs-data-and-filtering-join.html#Filtering
You can try something similar with Hibernate. I think, it will not work.
Other option is use #Where
#OneToMany(mappedBy="question",fetch=FetchType.LAZY)
#Where(clause = "is_deleted = 0")
private List<Answer> answers;
But, probably, it doesn't suitable to you, because of it is impossible to disable #Where clause. You will never have all answers with fetching.
So better to load answers with condition with a separate query.
I am using Spring JPA and in order to ad a List of String to my Entity I am using #ElementCollection as below.
#ElementCollection
private Map<Integer, String> categories;
When I use this it generates a table called subscription_categories this contains the following columns subscription(varchar), catergories(varchar) and caterogies_key (int)
If I use my SQL tool on my desktop I can query this table fine with the following
select `subscription_categories`.`subscription` from `subscription_categories` where `subscription_categories`.`categories`='TESTING';
However, when I attempt to use this in Spring Data it fails with a "... not mapped" error
Here are a few attempts below:
#Query("select s.subscription from subscription_categories s where s.categories = ?1")
List<Subscription> findUsernameByCategory(String category);
#Query("select s.subscription from categories s where s.categories = ?1")
List<Subscription> findUsernameByCategory(String category);
Both return the same error.
Caused by: org.hibernate.hql.internal.ast.QuerySyntaxException:
categories is not mapped
My question is this:
How can I query the table created by the #ElementCollection?
You can't directly query from #ElementCollection. You should query base entity (I assume its name is Subscription).
#Query("select s from Subscription s where s.categories = ?1")
List<Subscription> findUsernameByCategory(String category);
If you want query by key, then use
#Query("select s from Subscription s where index(s.categories) = ?1")
List<Subscription> findUsernameByCategoryKey(Integer key);
I'd also side with #talex on this and argue that you need to base your query on the parent/container/base object of the #ElementCollection.
In my experience following query should suffice:
#Query("select category from Subscription subscription inner join subscription.categories category")
Side-note: Querying subscription_categories seems to be the wrong path, since this table is part of a different layer (the database layer in Sql/Jpql), while the query should be formed on the Hibernate layer (hql), which uses your entity/class-names as references.
I have used Upper-case class names, instead of lower-case table names.
Let's say I have the following tables:
Locations
================
LocationKey, LocationName
Employees
================
EmployeeKey, FirstName, LastName
EmployeeLocationXRef
================
EmployeeLocationXRefKey, LocationKey, EmployeeKey
TimeSheets
=================
TimeSheetKey, EmployeeLocationXRefKey, Minutes
OK, so as you can see, in order for me to get all of the TimeSheets for a Location and Employee, I can do the following in SQL
select
*
from TimeSheets ts
join EmployeeLocationXRef ex on (ex.EmployeeLocationXRefKey = ts.EmployeeLocationXRefKey)
join Locations l on (l.LocationKey = ex.LocationKey)
join Employees e on (e.EmployeeKey = ex.EmployeeKey)
where
l.LocationKey = 'xxxx'
and e.EmployeeKey = 'yyyy'
But I have tried every way I can think of to map with (with annotations) in JPA using #JoinTable, etc.
Any ideas how this could be done? Unfortunately, this is a legacy system and the schema cannot be changed.
EDIT
Forgot to mention the EmployeeLocationXRef entity has not been directly mapped. Which could be the real problem. I will see about creating that entity mapping and see if it makes it easier.
I don't see anything particularly difficult or strange about this schema. There should simply be one entity per table and (unless there are unique constraints):
a ManyToOne between EmployeeLocationXRef and Location, using a JoinColumn
a ManyToOne between EmployeeLocationXRef and Employee, using a JoinColumn
a ManyToOne between Timesheet and EmployeeLocationXRef, using a JoinColumn
(these associations can of course be made bidirectional, or be in the other direction if you prefer so).
The JPQL query would simply be
select ts from Timesheet ts
join ts.employeeXRef ex
join ex.location l
join ex.employee e
where
l.locationKey = 'xxxx'
and e.employeeKey = 'yyyy'
which is a straightforward translation of the SQL query.
Imagine a table emp:
CREATE TABLE emp
( id NUMBER
, name VARCHAR
, dept_code VARCHAR
)
and a table dept:
CREATE TABLE dept
( code VARCHAR
, name VARCHAR
)
emp.dept_code references dept.code as a ForeignKey.
These tables are mapped to JPA Entities, and the ForeignKey is modeled as an association:
#ManyToOne
#JoinColumn(name = "dept_code")
private Department department;
Given following data:
emp dept
---------------- ------------------
1 John SALS SALS Sales
2 Louis SALS SUPT Support
3 Jack SUPT
4 Lucy SUPT
I would like to write a JPA query that returns all Emloyees in the Support Department. Assume I know the PrimaryKey of the Support Department (SUPT)
I guess that would be:
SELECT emp
FROM Employee emp JOIN emp.department dept
WHERE dept.code = 'SUPT'
Question:
As the Department key SUPT code is available in the emp table, is there a way to rewrite the JPA query by avoiding the JOIN to the Department Entity?
Would this result in a performance improvement? Or is a JPA implementation (like Hibernate) smart enough to avoid the database join to the dept table?
You would usually write the query as
select emp
from employee emp
where emp.department.code = 'SUPT'
and let your provider figure out the best way to come up with the result. In the case of hibernate, yes, it is smart enough to realize it can just look at the join column.
edit : It is worth noting, that you haven't set up lazy loading in your annotations, so it's going to join the table in to create the department entity anyway :)