I need to join 3 tables where A.id == B.id and B.id == C.id using JPA #SecondaryTables where I need to map these tables to a single entity. what is the way I should I should try?
Since A.ID = B.ID = C.ID, you can just have 2 secondary tables, with the relationship A.ID = B.ID, and A.ID = C.ID. Your "main" table will be A, and B and C are your secondary tables. You can reference the table as follows in your column declaration. (many other parameters in the annotations left out for brevity)
#Entity
#Table(name = "A")
#SecondaryTables({
#SecondaryTable(name="B", #PrimaryKeyJoinColumn(name="ID", referencedColumnName="ID")),
#SecondaryTable(name="C", #PrimaryKeyJoinColumn(name="ID", referencedColumnName="ID"))
})
public Claass Blah {
#ID
private int id;
#Column(table = "B")
private String someColumn;
#Column(table = "C")
private String someOtherColumn;
etc...
}
Related
This is a JPA Query question. I have successfully used "LEFT JOIN" and "IN:" in EntityManager.CreateQuery in separate situations, but when i combine the two e.g.
SELECT a.id
FROM TableA a
LEFT JOIN TableB b on a.myAField = b.id and b.myBField in :Ids
LEFT JOIN TableC c on b.myBOtherField = c.id
where Ids is List<Long> it starts giving me this error "The left parenthesis is missing from the IN expression."
The sql works fine when pasted directly into postGres pgAdmin explicitly writing out the parameters. Have I made a mistake with the syntax here or is this a jpa limitation and i need an alternative?
List<Long> myBFieldTypes = new ArrayList<>();
myBFieldTypes.add(5L);
myBFieldTypes.add(10L);
try {
List<Long> resultArray = em.createQuery("SELECT a.id FROM TableA a LEFT JOIN TableB b on a.myAField = b.id and b.myBField in :Ids LEFT JOIN TableC c on b.myBOtherField = c.id")
.setParameter("Ids", myBFieldTypes)
.getResultList();
return resultArray;
} catch (Exception ex) {
throw ex;
} finally {
em.close();
}
I have the following 3 entities: Item, Warehouse and ItemWarehouse which has item_id and warehouse_id. I've set up the #OneToMany and #ManyToOne relationships on the 3 tables. In addition, I use soft-deletes, so each Entity has #Where(clause = "deleted_flag = 0").
I wrote a query to fetch all items that goes like this:
SELECT i FROM Item i
JOIN FETCH i.itemWarehouses iw
JOIN FETCH iw.warehouse
The JPQL converts to this statement on the console:
select
// fields
from item item0_
inner join item_warehouse itemwareho1_ on item0_.id=itemwareho1_.item_id and ( itemwareho1_.deleted_flag = 0)
inner join warehouse warehouse2_ on itemwareho1_.warehouse_id=warehouse2_.id
where ( item0_.deleted_flag = 0)
It is visible that the first inner join and the last where clause contain deleted_flag = 0 but the 2nd inner join doesn't. Why is that?
My Entities are defined like this
#Entity
#Table(name = "item")
#Where(clause = "deleted_flag = 0")
class Item
#Entity
#Table(name = "item_warehouse",)
#Where(clause = "deleted_flag = 0")
class ItemWarehouse
#Entity
#Table(name = "warehouse")
#Where(clause = "deleted_flag = 0")
class Warehouse
I have Pojo mapped with JPA annotations like this
#Entity
#Table(name = "record")
public class SearchRecord {
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE)
private int id;
private String vidName;
#ElementCollection
private List<String> videoLabels = new ArrayList<String>();
and would like to run a Hibernate query that filters out all SearchRecords that match/contain 1..n videoLabels. (only objects that match all of the videoLabels)
I was able to search for SearchRecords that match a single label by running the following query:
String labelCar = "Car";
String labelPerson = "Person";
TypedQuery<SearchRecord> query = em.createQuery("SELECT b FROM SearchRecord b JOIN b.videoLabels l WHERE l = :param1",SearchRecord.class);
query.setParameter("param1", labelCar);
List<SearchRecord> results = query.getResultList();
But how can I execute a query filtering out all SearchResults matching Car and Person?
Thanks for your support
I was able to solve the problem with the following query
SELECT DISTINCT a FROM SearchRecord a JOIN a.labels b JOIN a.labels c WHERE b.name = 'Car' and c.name = 'Person'
I have 2 tables:
course: id, name
student: id, course_id, age
Tables are tied with oneToMany annotation
I am trying to write a hibernate query against course that will return courses and students that are x years 0ld. That's my attempt:
SELECT c from Course c RIGHT JOIN c.student p ON p.age = 20
It returns a course that has at least one student that is 20. when there are more students that are not 20, they are included in the result set as well. Is there a way to restrict the joined table values?
Edit:
These are my entities:
public class Course implements Serializable {
private static final long serialVersionUID = 646349111982187812L;
#Id
#Column(name = "id", unique=true, nullable=false)
private String id;
#Column(name = "name", unique=false, nullable=false)
private String name;
#OneToMany(cascade={CascadeType.ALL, CascadeType.REMOVE},
fetch=FetchType.LAZY, mappedBy = "Course")
#OrderBy("age")
#JsonManagedReference
private Set<Student> students;
getters and setters ...
}
public class Student implements Serializable {
private static final long serialVersionUID = 646349221337813L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#Column(name = "age", unique=false, nullable=true)
private String age;
#ManyToOne()
#JsonBackReference
private Course course;
}
I am trying to use this method from my crudrepository to get the expected result:
#Query(?????)
public List<Course> findCoursesWithAdults(#Param("age")int age)
it sounds like you want an inner join instead of a right join
SQL
SELECT distinct c.* from Course c inner join Student p on (c.id=p.course_id and p.age=20)
or with hql
select distinct c from Course c inner join c.student p with p.age=20
in order to get the information you are requesting, you will either have to limit the Set in Course using #Where ("age = 20" ) or simply deal with a list of students instead of courses.
select p from Course c inner join c.student p with p.age=20
you can reference the attached course object through any one of the getCourse methods on the student objects. You could also use "group by" here to help you order things.
or you can use a filter within the hibernate Entity...
#Transient
public List<Students> getStudents(Integer age){
List<Students> tmp = new ArrayList<>();
for(Student s: getStudents())
if(s.getAge().equals(age))tmp.add(s);
return tmp;
}
one more edit and im done... there is another way to do this that i didnt mention..
a select wrapper query.
create a wrapper object for your course and student
public class CourseWrapper(){
private Course c;
private List<Students> p = new ArrayList<>();
....constructor ... getters ...setters
}
select new CourseWrapper(c, students)
from Course c
left outer join c.students p with p.age=20'
more info here
SELECT c.name, s.id
FROM course c
INNER JOIN student s ON c.id = s.course_id
WHERE s.age = 20
I have a following working SQL query:
SELECT count(*)
FROM A a
LEFT OUTER JOIN B b
ON a.id = b.aid
AND a.x = 700 AND b.y = 800
WHERE a.type = 1 AND b.type = 2;
I want to use an HQL equivalent.
I've tried the following but it doesn't work (compilation):
SELECT count(*)
FROM A AS a
LEFT JOIN B AS b
AND a.x = 700 AND b.y = 800
WHERE a.type = 1 AND b.type = 2;
W/o the "and a.x = 700 and b.y = 800" part it works fine.
Can you please advise?
p.s.
I need the "and a.x = 700 and b.y = 800" part before the "where" cause it's indexed and partitiouned, and I need the indexes and partitions to be used during join.
thanx,
Pavel.
Hi,
It seems that my problem is more complex than the usual case, so I"ll just post the exact code:
#Entity
#AttributeOverride(name = "id", column = #Column(name = HFrEvent.COL_EVENT_ID))
#Table(name = HFrEvent.TBL_HFREVENT)
public class HFrEvent extends HOrgEntity {
..
#OneToMany(fetch = FetchType.EAGER)
#Cascade({ org.hibernate.annotations.CascadeType.ALL, org.hibernate.annotations.CascadeType.DELETE_ORPHAN })
#JoinColumn(name = COL_EVENT_ID)
public List<HFrEventKeys> getEventKeys() {
return eventKeys;
}
..
}
#Entity
#Table(name = "HFREVENTKEYS")
public class HFrEventKeys extends HOrgEntity {
..
}
The following query works, although there is no explicit "on" statement:
select count(event) from HFrEvent as event left join event.eventKeys as key where event.orgFields.customerId = 110 AND event.orgFields.institutionId = 121 and key.orgFields.customerId = 110 AND key.orgFields.institutionId = 121 and key.name=:name and key.value=:value and event.eventType = 1113;
I want to move some the customerid and institutionid into the join part.
the following not compiles:
SELECT count(event)
FROM HFrEvent AS event
LEFT JOIN event.eventKeys AS key
ON event.orgFields.customerId = 110
AND event.orgFields.institutionId = 121
AND key.orgFields.customerId = 110
AND key.orgFields.institutionId = 121
WHERE key.name=:name
AND key.value=:value
AND event.eventType = 1113;
thank you,
Pavel.