From SQL to HQL - java

I'm having problems with the following query from SQL to Hibernate HQL:
select
(lot of things from table 1)
from
table1
inner join
table2 on table1.investigationEvent = table2.id_investigationEvent
inner join
table3 on table2.eventSection = table3.sectionEventsCod
inner join
table4 on table3.sectionEventsCod = table4.investigationSectionEvent
In HQL I wrote this:
Select blabla
+ "FROM table1 t1 "
+ "INNER JOIN t1.investigationEvent t2 "
+ "INNER JOIN t2.eventSection t3 , "
+ "table4 t4
INNER JOIN t4.investigationSectionEvent t3 "
+ "WHERE iset.typology.idTypology = :idTypology "
+ "WHERE ast.typology.idTypology = :idTypology ";
The problem is that with this syntax i can make joins from:
table 1 - > table 2
table 2 - > table 3
but i can't make the join
table 3 -> table 4
since the table 3 bean doesen't have any attribute to go to table 4 bean. However, is possibile make the contrary:
table 4 - > table 3 (since table 4 contains an attribute table 3 bean)
The problem is: using this syntax i have to call a second FROM (table4, as you can see from my hql query). Can you solve my problem? I have to make the query calling only the first table with FROM then using all JOIN(s).
This is Some Beans:
Table 1 {
...
Table 2 investigationEvent; }
Table 2 {
...
Table 3 eventSection
and then
Table 4{
...
Table3 investigationSectionEvent; }
The problem is that Table 3 doesen't contain Table 4.

Related

Unable to form a single query to join multiple tables

I have to write a single select query to fetch all details from seven tables. Earlier I had separate queries but now I am working on optimizing the queries.
The following is my table structure :
Main Table (SN, model , regId) -- 1 row
Table1(col1,col2....SN) - SN is forienKey -- 1 row
Table2(col1,col2,....SN) - SN is forienKey -- 1 row
Table3(col1,col2,.....regId) - regId is forienKey -- 1 row
Table4(col1,col2,.....regId) - regId is forienKey - 2 rows
Table5(col1,col2,.....regId) - regId is forienKey - 2 rows
Table6(col1,col2,.....regId) - regId is forienKey - 1 row
There is a one to many mapping between the main table and table 4 and table 5.
I have tried using inner join to fetch the rows but I am getting duplicate values. Below is the query that I have written. Is there anything I am missing?
select * from MainTable
inner join Table1 on MainTable.SN = Table1.SN
inner join Table2 on MainTable.SN = Table2.SN
inner join Table3 on MainTable.regId = TABLE3.regId
inner join TABLE4 on MainTable.regId = Table4.regId
inner join TABLE5 on MainTable.regId = Table5.regId
inner join TABLE6 on MainTable.regId = Table6.regId
try joining tables like below to join all of them together
select * from (select * from MainTable
inner join Table1 on MainTable.SN = Table1.SN
inner join Table2 on Table1.SN = Table2.SN ) tempMain
inner join Table3 on tempMain.regId = TABLE3.regId
inner join TABLE4 on TABLE3.regId = Table4.regId
inner join TABLE5 on Table4.regId = Table5.regId
inner join TABLE6 on Table5.regId = Table6.regId
though from your example i don't know if table2 & table 3 are related. anyways you can try to find similar.

How to select different data of the same table that depends on variable

I need to select some data from a join table. The thing is that this table changes its data depending on a variable x (if x=1 the data is A and if x=2 the data is B)
I am trying something like this:
"SELECT new nameDTO(joinTableA.dataA, joinTableB.dataB, table.something, table....) "
+ "FROM Table table "
+ "JOIN joinTable joinTableA"
+ "JOIN joinTable joinTableB "
+ "WHERE joinTableA.x = 1 AND joinTableA.x = 2"
+ "AND ..... "
However this WHERE does not work because the query returns nothing instead of de data of both cases.
I hope the question in understandable, it's a bit tricky.
There's a bit of information missing in your question, so I've made some up and hoping this is close enough to what you are trying to do.
I start with two tables. I'm only showing the content of the tables, not the definition.
table1
id content
-------------
1 Hello
2 World
table2
table1_id x content_a content_b
--------------------------------------
1 1 Content 1 Content 2
1 2 Content 3 Content 4
2 1 Content 5 Content 6
2 2 Content 7 Content 8
With the following SQL statement
SELECT
t1.content `greeting`,
CASE
WHEN t2.x = 1 THEN t2.content_a
WHEN t2.x = 2 THEN t2.content_b
ELSE "Unknown x value"
END `content`
FROM
table1 `t1`
INNER JOIN table2 `t2` ON t2.table1_id = t1.id
;
the result would be
greeting content
----------------------
Hello Content 1
Hello Content 4
World Content 5
World Content 8
This should be possible to convert to a JPQL query or a Criteria query.

How to join three tables in SQLite?

How to join three tables in SQLite? I have three tables, one is Info, second is workForce and third is workDetails.
Table Info:id(PK),name,status,date,weather
Table WorkForce: id1(PK), subContractors,noOfPeople,noOfHours
Table WorkDetails:id2(PK),project,workDescription,TableInfo_id(FK) //contains multiple row
Table Info
ID NAME Weather Date Status
---------- ---------- ---------- ---------- ----------
1 Paul Sunny 15/10 MC
2 Allen Rainy 15/10 Working
Table WorkForce
ID1 SubContractors NoOfPeople NoOfHours
---------- -------------- ---------- ----------
1 AAA 2 2
2 BBB 3 1
Table WorkDetails
ID2 Project WorkDescription TableInfo_id
---------- ---------- -------------- ----------
1 A B 1
2 1
3 1
4 1
5 C D 2
6 2
7 2
8 2
Assume the name is Paul, so all the row with ID 1 and TableInfo_id 1 will be retrieved.
Here is what I tried so far
public Cursor readEntry(String name) {
String selectQuery = ("SELECT Weather,Date,Status,SubContractors,NumberOfPeople,NumberOfHours,TimeIn,TimeOut FROM "+TABLE_INFO+TABLE_WORKFORCE+TABLE_WORKDETAILS+ "WHERE Name= ? AND"+ID=ID1+ "AND"+ID=TableInfo_id);
Cursor c = database.query(TABLE_INFO,TABLE_WORKFORCE,TABLE_WORKDETAILS,new String[]{id,name,weather,date,status,iD1,subcontractors,numberOfPerson,numberOfHours,id2project,workDescription,TableInfo_id},MyDatabaseHelper.Name+"=?",
new String[] { String.valueOf(name)}, null, null, null, null,null,null,null,null,null,null,null,null);
if (c != null) {
c.moveToFirst();
}
return c;
}
My code seems like not working..how can I achieve this? Thanks!
Fist thing you need to do is to add foreign key of Table Info into Table WorkForce and foreign key of Table WorkForce into Table WorkDetails
Then write modify your query like this
Select * from Table Info tf
LEFT JOIN Table WorkForce twf ON twf.tf_id = tf.id
LEFT JOIN Table WorkDetails twd ON twd.tw_id = twf.id
Modify your query based on requirement after joining the three tables.
Check out the tutorials for adding a foreign key.
Add a foreign key to the workforce table the point to ID within the info table
select * from Info inner join Workforce inner join Workdetails ON Info.ID = Wordforce.SOME_FOREIGN_KEY AND Info.ID = Workdetails.TableInfo_id Where NAME = 'Paul'
Think that should work have not tried it tho

How to join two unrelated entities using JPA and Hibernate

I have two tables - one containing Address and another containing Photographs. The only common field between them is the PersonID. These were mapped to two POJO Classes Address and Photo. I was able to fetch details in these tables by creating criteria and adding restrictions on the fields . How should we write a join on the two tables. Is it possible to get the result as two objects -Address and Photo.
I want to do a left join so that i can get records of persons without photos as well.
I have read that this is possible only using hql but Can this be done using criterias as well?
You can easily write HQL query that will return result as two objects using Theta Join (as Adrian noted). Here is an example:
String queryText = "select address, photo from Address address, Photo photo "
+ " where address.personID=photo.personId";
List<Object[]> rows = session.createQuery(queryText).list();
for (Object[] row: rows) {
System.out.println(" ------- ");
System.out.println("Address object: " + row[0]);
System.out.println("Photo object: " + row[1]);
}
As you can see query returns list of Object[] arrays that represents each fetched row. First element of this array will contain one obejct and second element - another.
EDIT:
In case of left join I think you need to use native SQL query (not HQL query). Here how you can do this:
String queryText = "select address.*, photo.* from ADDRESS address
left join PHOTO photo on (address.person_id=photo.person_id)";
List<Object[]> rows = sess.createSQLQuery(queryText)
.addEntity("address", Address.class)
.addEntity("photo", Photo.class)
.list();
This should work for your case.
Basically, you have two options:
Since Hibernate 5.1, you can use ad-hoc joins for unrelated entities.
Tuple postViewCount = entityManager.createQuery(
"select p as post, count(pv) as page_views " +
"from Post p " +
"left join PageView pv on p.slug = pv.slug " +
"where p.title = :title " +
"group by p", Tuple.class)
.setParameter("title", "High-Performance Java Persistence")
.getSingleResult();
Prior to Hibernate 5.1, you could only use theta-style joins. However, a theta-style join is equivalent to an equijoin, hence you can only emulate INNER JOINs not OUTER JOINs.
List<Tuple> postViewCount = entityManager.createQuery(
"select p as post, count(pv) as page_views " +
"from Post p, PageView pv " +
"where p.title = :title and " +
" ( p.slug = pv.slug ) " +
"group by p", Tuple.class)
.setParameter("title", "Presentations")
.getResultList();
Finally after 12 years the Hibernate team has implemented such a feature
From Hibernate docs:
The FROM clause can also contain explicit relationship joins using the join keyword. These joins can be either inner or left outer style joins.
List<Person> persons = entityManager.createQuery(
"select distinct pr " +
"from Person pr " +
"join pr.phones ph " +
"where ph.type = :phoneType", Person.class )
.setParameter( "phoneType", PhoneType.MOBILE )
.getResultList();
List<Person> persons = entityManager.createQuery(
"select distinct pr " +
"from Person pr " +
"left join pr.phones ph " +
"where ph is null " +
" or ph.type = :phoneType", Person.class )
.setParameter( "phoneType", PhoneType.LAND_LINE )
.getResultList();
Or you can use WITH and ON keywords. A remark on those
The important distinction is that in the generated SQL the conditions
of the WITH/ON clause are made part of the ON clause in the generated
SQL, as opposed to the other queries in this section where the
HQL/JPQL conditions are made part of the WHERE clause in the generated
SQL.
Example
List<Object[]> personsAndPhones = session.createQuery(
"select pr.name, ph.number " +
"from Person pr " +
"left join pr.phones ph with ph.type = :phoneType " )
.setParameter( "phoneType", PhoneType.LAND_LINE )
.list();
I am currently eager to try the new feature.
Joining two unrelated entities are possible in Hibernate 5.1.
Eg :
select objA from ObjectA objA
JOIN ObjectB objB on objB.variable = objA.variable
where objA.id = 1
It's best to have a class containing those classes you want to join to have them all together.
But if you are joining these tables just for some occasional purposes, you can use criteria and manually load data from each table and put them together. (and yes, you can have these tables' data separately if for Address and Photo there are two separate classes and tables)
What you are looking for is
HQL
Join on fields that you haven't modeled as relationships
Left Join
(During the time the question was first asked and this answer was given) Hibernate supports Theta Join which allows you to do 1 & 2. However, only inner join is available for theta join style.
Personally I would recommend you to model proper relationships, so you just need 1 & 3 which is well-supported in HQL.
(Another answer actually provided an update on new Hibernate feature that provides such feature, that you may simply refer to)

Can I convert this Mysql query to JPA?

I'm fairly familiar with SQL but very new to the Java Persistence API. I'm using JPA through the Play Framework.
I have the following MySql query that I'd like to convert to pure JPA code if I can:
SELECT a.id, b.id
FROM Rankable a
INNER JOIN Rankable b on a.id < b.id
WHERE
a.category_id = ? AND b.category_id = ?
AND NOT EXISTS (
SELECT *
FROM Comparison c
WHERE c.lower in (a.id, b.id))
AND NOT EXISTS (
SELECT *
FROM Comparison c
WHERE c.higher IN (a.id, b.id))
ORDER BY a.id * rand()
LIMIT 1;
The purpose of this query is to select two rows from the Rankable table, but ensure that this specific pair is not present in the Comparison table.
What would be the best way to call a somewhat complicated query like this from Play/JPA?
It is possible to do a self join in JPA.
Take a look at this example
from the example
#NamedQuery(name="siblings", query="select distinct sibling1 "
+ "from Deity sibling1, Deity sibling2 where "
+ "sibling1.father = sibling2.father "
+ "and sibling1.mother = sibling2.mother "
+ "and sibling2 = ?1 and sibling1 <> ?1"),

Categories