I want to run the following SQL in hibernate:
SELECT c.id, c.name, ipc.total
FROM Category c,
(
SELECT comm.category.id as id, count(*) as total
FROM Commerce as comm
GROUP BY comm.category.id
) ipc
WHERE c.id = ipc.id
This is my attempt to write that one in JQL but I get an error. It doesn't seem to like my join against a query result.
Request processing failed; nested exception is java.lang.IllegalArgumentException: org.hibernate.hql.internal.ast.QuerySyntaxException: unexpected token: ( near line 1, column 86 [SELECT c.id, c.name, ipc.total FROM com.brujulasolutions.directorio.model.Category c,( SELECT comm.category.id as id, count(*) as total FROM com.brujulasolutions.directorio.model.Commerce as comm GROUP BY comm.category.id ) ipc WHERE c.id = ipc.id]
SELECT c.id, c.name, ipc.total
FROM Category c,
(
SELECT comm.category.id as id, count(*) as total
FROM Commerce as comm
GROUP BY comm.category.id
) ipc
WHERE c.id = ipc.id
Hibernate query language does not directly support this type of update join. Instead, we can use a correlated subquery in the select clause:
SELECT c.id, c.name,
(SELECT COUNT(*)
FROM Commerce AS comm
WHERE comm.category.id = c.id) AS total
FROM Category c
I am working on a requirement where I need to populate a unique constant identifier on a row which is the manager row and unique in each department. My table structure is
CREATE
TABLE TEST_ORGANIZATION
(
EMPLOYEE_ID NUMBER NOT NULL,
MANAGER_ID NUMBER,
FIRST_NAME VARCHAR2(256),
DEPARTMENT_ID VARCHAR2(28) NOT NULL,
UUID VARCHAR2(28) ,
PRIMARY KEY(UUID)
);
This table contains information as.
UUID
DEPARTMENT_ID
EMPLOYEE_ID
MANAGER_ID
FIRST_NAME
radmon1
finance
employee1
John B
radmon2
finance
employee2
employee1
Michal
radmon3
finance
employee3
employee1
Ronaldo
radmon4
finance
employee4
employee1
Thomas
radmon5
finance
employee5
Percey
radmon6
account
employee6
Stacy
radmon7
account
employee7
Jordan
radmon8
account
employee8
employee6
Micky
radmon9
account
employee9
employee6
Author
radmon10
account
employee10
employee6
Gordan
I would like to add another column to the table to provide a sequence to managers only (where Manager_ID is null). But, the sequence should be grouped with DEPARTMENT_ID
ALTER TABLE TEST_ORGANIZATION ADD SEQUENCE_ID NUMBER
UUID
DEPARTMENT_ID
EMPLOYEE_ID
MANAGER_ID
FIRST_NAME
SEQUENCE_ID
radmon1
finance
employee1
John B
1
radmon2
finance
employee2
employee1
Michal
radmon3
finance
employee3
employee1
Ronaldo
radmon4
finance
employee4
employee1
Thomas
radmon5
finance
employee5
Percey
2
radmon6
account
employee6
Stacy
1
radmon7
account
employee7
Jordan
2
radmon8
account
employee8
employee6
Micky
radmon9
account
employee9
employee6
Author
radmon10
account
employee10
employee6
Gordan
I tried using sequence and identity columns added after oracle 12/19c.
I could it programmatically from backend service and update SEQUENCE_ID using
Select NVL(MAX(SEQUENCE_ID), 0) + 1 FROM TEST_ORGANIZATION WHERE MANAGER_ID is NULL AND DEPARTMENT_ID = ? query. But, I would like to know if there is any function in Oracle 19c to handle this behaviour on the Database side itself.
Try This:
SELECT d1.*,
1 AS f,
CASE WHEN manager_id is null then
RANK() OVER (partition by department_ID order by manager_id nulls first,employee_id)
end as sequenc
FROM (
SELECT 'radmon1' AS UUID,'finance' AS DEPARTMENT_ID,'employee1' AS EMPLOYEE_ID,'' AS MANAGER_ID,'John B' AS FIRST_NAME from dual UNION ALL
SELECT 'radmon2','finance','employee2','employee1','Michal' from dual UNION ALL
SELECT 'radmon3','finance','employee3','employee1','Ronaldo' from dual UNION ALL
SELECT 'radmon4','finance','employee4','employee1','Thomas' from dual UNION ALL
SELECT 'radmon5','finance','employee5','','Percey' from dual UNION ALL
SELECT 'radmon6','account','employee6','','Stacy' from dual UNION ALL
SELECT 'radmon7','account','employee7','','Jordan' from dual UNION ALL
SELECT 'radmon8','account','employee8','employee6','Micky' from dual UNION ALL
SELECT 'radmon9','account','employee9','employee6','Author' from dual UNION ALL
SELECT 'radmon10','account','employee10','employee6','Gordan' from dual
)d1;
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;
My database looks like this
tickets table
-------------
ticket_id
title
description
department_id
status_id
priority_id
assignee_id
creator_id
departments table
------------------
dep_id
dep_name
status table
------------
status_id
status_name
priority table
---------------
pr_id
pr_name
users table
-----------
u_id
username
password
salt
email
firstName
lastName
department_id
userlevel_id
userlevels table
-----------------
ul_id
ul_name
I need to load all tickets given the asignee id. My query looks like this
SQLQuery q = q.createSQLQuery("SELECT t.*,d.*,s.*,p.*,u.*,a.* FROM tickets t, departments d, status s, priority p, users u, attachments a WHERE t.department_id=d.dep_id AND t.status_id=s.stat_id AND t.priority_id=p.pr_id AND t.assignee_id=u.u_id AND t.creator_id=u.u_id AND t.tick_id=a.ticket_id AND assignee_id=?");
q.setInt(0, some_valid_assignee_id);
List<Object> result = q.list();
But it's returning an empty object list. Can anyone point me in the right direction, thanks!!
In your query you have AND t.assignee_id = u.u_idand also AND t.creator_id = u.u_id. The only way that would return any records is if the assignee_id and creator_id were the same. I think what you really need to do is link to the users table twice like so:
SELECT t.*, d.*, s.*, p.*, u1.*, u2.*, a.*
FROM tickets t
INNER JOIN departments d ON t.department_id = d.dep_id
INNER JOIN status s ON t.status_id = s.stat_id
INNER JOIN priority p ON t.priority_id = p.pr_id
INNER JOIN users u1 ON t.assignee_id = u.u_id
INNER JOIN users u2 ON t.creator_id = u.u_id
INNER JOIN attachments a ON t.tick_id = a.ticket_id
WHERE assignee_id = ?
You should use proper join syntax . . . makes the query easier to read and to write.
However, I'm guessing that the problem is:
t.assignee_id = u.u_id AND t.creator_id = u.u_id
That would assume that
t.assignee_id = t.creator_id
Perhaps this never happens in your data.
Right now, In a short example, if i have two entities Person and Applicant and i want to write a query that gets all applicants in my database, i end up getting referenced queries with the following set up. I am using Single_Table_Inheritance strategy (fyi)
public class Person {
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "schoolID")
private School school;
}
The Teacher object with a reference to another entity.
public class Applicant extends Person {
#OneToMany(targetEntity = ApplicantSchool.class, cascade = { javax.persistence.CascadeType.PERSIST, javax.persistence.CascadeType.REMOVE }, mappedBy = "applicant")
private Set<ApplicantSchool> schools = new HashSet<ApplicantSchool>();
}
Query attempt that jumps and attempts to query for the school relationship in Person
public List<Applicant> getAllApplicants(){
EntityManager entityManager = factory.createEntityManager();
#SuppressWarnings("unchecked")
List<Applicant> applicants = entityManager.createQuery("Select a from Applicant a LEFT JOIN FETCH a.schools WHERE a.active = :active ")
.setParameter("active", true).setHint("eclipselink.refresh", "true")
.getResultList();
//List<Applicant> applicants = Applicant.findAllApplicants();
System.out.println("The long query getting applicants");
entityManager.close();
return applicants;
}
If i try to change my query to use nested joining, i get an error saying relationship not recognized. I tried to query like so:
entityManager.createQuery("Select a from Applicant a LEFT JOIN FETCH a.schools WHERE LEFT JOIN FETCH a.person.school a.active = :active ")
UPDATED
After removing the keyword "left join fetch" my new query:
List<Applicant> applicants = entityManager.createQuery("Select a from Applicant a WHERE a.active = :active ")
.setParameter("active", true)
.getResultList();
The only query i agree with that it first creates is this one
SELECT personID, TYPE, DATEADDED, FIRSTNAME, LASTNAME, MIDDLENAME, ACTIVE, BIRTHDAY, EMAILADDRESS, ETHNICITY, GENDER, HISPANIC, IMAGEPATH, MARITAL, NATIVELANGUAGE, PRIMARYTELEPHONE, RELIGIOUSAFFILIATION, SECONDARYTELEPHONE, version, addressID, schoolID, MAJOR FROM PERSON WHERE ((ACTIVE = ?) AND (TYPE = ?))
bind => [true, AP]
Returns this stack trace and the following sql's selects are created:
[EL Fine]: sql: 2012-07-13 17:25:52.297--ServerSession(1529073996)--Connection(726700617)--Thread(Thread["http-bio-8080"-exec-18,5,main])--SELECT schoolID, ACTIVE, ADMISSIONSEMAILADDRESS, ADMISSIONSPHONE, CODE, description, HELPGENERALEMAILADDRESS, NAME, PRIMARYPHONE, version, addressID FROM SCHOOL WHERE (schoolID = ?)
bind => [1]
[EL Fine]: sql: 2012-07-13 17:25:52.305--ServerSession(1529073996)--Connection(1615948530)--Thread(Thread["http-bio-8080"-exec-18,5,main])--SELECT id, ACTIVE, CODE, DESCRIPTION, NAME, version, SCHOOLDEPARTMENT_schoolID FROM DEPARTMENT WHERE (SCHOOLDEPARTMENT_schoolID = ?)
bind => [1]
[EL Fine]: sql: 2012-07-13 17:25:52.308--ServerSession(1529073996)--Connection(893810654)--Thread(Thread["http-bio-8080"-exec-18,5,main])--SELECT programID, ACTIVE, CODE, description, NAME, PROGRAMTYPE, REQUIREDCREDITS, version, SCHOOL_schoolID FROM PROGRAM WHERE (SCHOOL_schoolID = ?)
bind => [1]
[EL Fine]: sql: 2012-07-13 17:25:52.31--ServerSession(1529073996)--Connection(399107363)--Thread(Thread["http-bio-8080"-exec-18,5,main])--SELECT personID, TYPE, DATEADDED, FIRSTNAME, LASTNAME, MIDDLENAME, ACTIVE, BIRTHDAY, EMAILADDRESS, ETHNICITY, GENDER, HISPANIC, IMAGEPATH, MARITAL, NATIVELANGUAGE, PRIMARYTELEPHONE, RELIGIOUSAFFILIATION, SECONDARYTELEPHONE, version, addressID, schoolID, MAJOR, studentId FROM PERSON WHERE (schoolID = ?)
bind => [1]
[EL Fine]: sql: 2012-07-13 17:25:52.314--ServerSession(1529073996)--Connection(464642021)--Thread(Thread["http-bio-8080"-exec-18,5,main])--SELECT registrationId, SEMESTERTYPE, version, YEAR, semesterCourseId, personID FROM REGISTRATION WHERE (personID = ?)
bind => [501]
[EL Fine]: sql: 2012-07-13 17:25:52.322--ServerSession(1529073996)--Connection(395757277)--Thread(Thread["http-bio-8080"-exec-18,5,main])--SELECT registrationId, SEMESTERTYPE, version, YEAR, semesterCourseId, personID FROM REGISTRATION WHERE (personID = ?)
bind => [552]
[EL Fine]: sql: 2012-07-13 17:25:52.327--ServerSession(1529073996)--Connection(328677993)--Thread(Thread["http-bio-8080"-exec-18,5,main])--SELECT registrationId, SEMESTERTYPE, version, YEAR, semesterCourseId, personID FROM REGISTRATION WHERE (personID = ?)
bind => [602]
[EL Fine]: sql: 2012-07-13 17:25:52.358--ServerSession(1529073996)--Connection(873312397)--Thread(Thread["http-bio-8080"-exec-18,5,main])--SELECT addressID, CITY, COUNTRY, STATE_US, STREETADDRESS, STREETADDRESS2, version, ZIPCODE FROM ADDRESS WHERE (addressID = ?)
bind => [2]
[EL Fine]: sql: 2012-07-13 17:25:52.365--ServerSession(1529073996)--Connection(509650638)--Thread(Thread["http-bio-8080"-exec-18,5,main])--SELECT applicantSchoolID, CREDITSCOMPLETED, FROMMONTH, FROMYEAR, GPA, NAME, SCHOOLTYPE, TOMONTH, TOYEAR, version, APPLICANT_personID FROM APPLICANTSCHOOL WHERE (APPLICANT_personID = ?)
bind => [151]
[EL Fine]: sql: 2012-07-13 17:25:52.385--ServerSession(1529073996)--Connection(17334753)--Thread(Thread["http-bio-8080"-exec-18,5,main])--SELECT applicantSchoolID, CREDITSCOMPLETED, FROMMONTH, FROMYEAR, GPA, NAME, SCHOOLTYPE, TOMONTH, TOYEAR, version, APPLICANT_personID FROM APPLICANTSCHOOL WHERE (APPLICANT_personID = ?)
bind => [51]
You cannot nest join in JPA, but you shouldn't need to when querying on Applicant.
JPQL "Select a from Applicant a LEFT JOIN FETCH a.schools LEFT JOIN FETCH a.school where a.active = :active " should work, since Appliant IS a Person and so has the school relationship. Nesting is only if Applicant has a relation to person and you needed to fetch join both person and school.
If that is the case, EclipseLink allows batch reading or joins through query hints described here:
http://wiki.eclipse.org/EclipseLink/Examples/JPA/QueryOptimization
You can also specify batching/fetch joins at the mapping level using EclipseLink annotations described here:
http://www.eclipse.org/eclipselink/documentation/2.4/jpa/extensions/a_batchfetch.htm#CHDCCIDA
and
http://www.eclipse.org/eclipselink/documentation/2.4/jpa/extensions/a_joinfetch.htm#CEGFFHHA
Batch reading will result in 2 queries, while fetch joins in 1.
For the query described above, you could also use:
em.createQuery("Select a from Applicant a WHERE a.active = :active ")
.setParameter("active", true)
.setQueryHint("eclipselink.left-join-fetch", "a.schools");
.setQueryHint("eclipselink.left-join-fetch", "a.school");
.getResultList();