I am trying to select an entity A that has a B that contains a list of C where the value C.d must match a parameter.
My entities look like this:
#Entity
class A {
#GeneratedValue
#Id
private Long id;
#Column(name="B")
#OneToOne(cascade=CascadeType.ALL)
#MapsId
private B b1;
}
#Entity
class B {
#GeneratedValue
#Id
private Long id;
#OneToMany(mappedBy="b2", cascade=CascadeType.ALL)
private List<C> cs;
}
#Entity
class C {
#GeneratedValue
#Id
private Long id;
#ManyToOne
#JoinColumn(name="B")
private B b2;
private String d;
}
My naive approach on selecting my entity look like this:
SELECT entity FROM A entity WHERE entity.b1.cs.d = :d
How should the query be structured?
Should be:
SELECT entity FROM A entity INNER JOIN entity.b1.cs CSList WHERE CSList.d = :d
Read about INNER JOIN in JPA.
http://www.thejavageek.com/2014/03/24/jpa-inner-joins/
try this
TypedQuery<A> query = em.createQuery("select b.a from B b inner join C c where c.d = :d",A.class);
List<A> a = query.getResultList();
Related
Here is my code:
class A {
Integer id
String name
Set<B> bs;
//Getters and setters
}
class B {
Integer id;
A a;
//Getters and setters
}
I need do a consult to get all rows of A, and for each row need know how many B reference to A.
I have a SQL query, but I don't know how do it with hibernate in Java
Simplified query:
select
a.ID as y0_,
(select count(*)
from B b
where b.c47 = a.ID
and b.FDL = 'N') as count,
from
A a
inner join
C c on a.operario = c.ID
where
a.DID = 2
and a.FDL = 'N'
Thanks in advance
#Entity
#Table(name = "a_table")
class A
{
#Id
#GeneratedValue
Integer id;
#Column
String name;
#OneToMany(mappedBy = "a")
Set<B> bs;
//Getters and setters
}
#Entity
#Table(name = "b_table")
class B
{
#Id
#GeneratedValue
Integer id;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "a_id")
A a;
//Getters and setters
}
The HQL:
select a.id, count(bs)
from A a
left join a.bs bs
inner join a.c c
where
a.id = 2
and a.FDL='N'
and bs.FDL='N'
i try to write a JPQL query, which deletes all entities which are within a collection of another entity.
(Example code, without getter/setter and annotations)
class Aa implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String value;
}
#Entity
class A implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#JoinColumn(nullable = false)
#OneToOne
private Aa aa;
#OneToMany(fetch = FetchType.EAGER, cascade = {CascadeType.ALL})
private List<B> data;
}
#Entity
class B implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String value;
}
I have tried the following:
DELETE FROM B b WHERE b.id IN(SELECT k.id FROM A a JOIN a.data k WHERE a.id = :id)
But its end in a foreign key violation exception.
Another approach was
DELETE FROM B b WHERE EXISTS(SELECT a FROM A a WHERE a.id = :id)
but its end in a foreign key violation too.
However if i execute a sql query on the database directly, like
DELETE FROM B WHERE id = <a id number here>
then no error occurs...
EntityManager.remove() is not an option because i want to delete a huge amout of data.
I'm thankfully for every answer and help.
Can't add comments since I don't have enough reputation.
You skipped the annotations, which are kind of important, because it would help to know which side, parent, child or maybe something in between them, is in control of the relationship. For example, if parent side is controlling, in some cases it is enough to empty the List on parent side and persist to remove its children. So more code would be helpful.
EDIT 1:
If you are using JPA 2.0 you could add orphanRemoval="true" to your #OneToMany. Then just get the parent from persistence, do parent.getData().clear(), and then do EntityManager.merge(parent) OR make children aware of relationship. You are trying to remove children that aren't aware of their parent so I suggest doing so through parent, or making them aware.
Okay, with the help of Syfors' suggestions i have change the relationship between A and B:
class Aa implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String value;
}
#Entity
class A implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#JoinColumn(nullable = false)
#OneToOne
private Aa aa;
#OneToMany(fetch = FetchType.EAGER, cascade = {CascadeType.ALL}, mappedBy = "owner")
private List<B> data;
}
#Entity
class B implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#OneToOne
private A owner;
private String value;
}
I have also found:
[...]Normally it is best to define the ManyToOne back reference in Java[...]
Source: http://en.wikibooks.org/wiki/Java_Persistence/OneToMany
Now JPA doesn't generate a thrid table for the m:1 relationship and now my JPQL query works fine:
DELETE FROM B b WHERE b.id IN(SELECT k.id FROM A a JOIN a.data k WHERE a.id = :id)
This is a related question to another question:
Hibernate exception PropertyNotFoundException when using Transformer
I have several tables joining hql. The tables are like this:
A
- A_ID
- NAME
B
- B_ID
- A_ID
C
- C_ID
- B_ID
- LENGTH
- UNIT
Classes:
#Entity
#Table(name="A")
class A
{
#Id
#Column(name="A_ID", updatable=false)
private Long id;
#Column(name="NAME", nullable=false, length=10, updatable=false)
private String name;
#OneToMany(mappedBy="a", fetch=FetchType.LAZY, cascade={CascadeType.ALL})
#JoinColumn(name="A_ID", nullable=false)
private Set<B> bs;
// Setters and getters
...
}
#Entity
#Table(name="B")
class B
{
#Id
#Column(name="B_ID", updatable=false)
private Long id;
#ManyToOne
#JoinColumn(name="A_ID", nullable=false, insertable=true, updatable=false)
private A a;
#OneToMany(mappedBy="b", fetch=FetchType.LAZY, cascade={CascadeType.ALL})
#JoinColumn(name="B_ID", nullable=false)
private Set<C> cs;
#Transient
private Double length;
#Transient
private String unit;
// Setters and getters
...
}
#Entity
#Table(name="C")
class C
{
#Id
#Column(name="C_ID", updatable=false)
private Long id;
#ManyToOne
#JoinColumn(name="B_ID", nullable=false, insertable=true, updatable=false)
private B b;
#Column(name="LENGTH", nullable=false, updatable=false)
private Double length;
#Column(name="UNIT", nullable=false, length=10, updatable=false)
private String unit;
// Setters and getters
...
}
After solving that issue, it is like this now:
select b.id as id, sum(c.length) as length, min(c.unit) as unit
from B b
left outer join b.c as c
group by b.id
Now the problem is:
I don't know how to set the alias of A in the returned B object in the HQL. This is causing a NPE when I'm doing this:
b.getA().getName();
Because I don't know how to set the related object "A" with "B" since there is only an ID in the B table.
Please help. Thank you very much.
b.getA().getName(); This will throw a NPE because select b.id as id, sum(c.length) as length, min(c.unit) as unit from B b does not include A. When you use the select clause in a HQL query it will only return the fields mentioned.
Please refer to http://docs.jboss.org/hibernate/orm/3.3/reference/en/html/queryhql.html for more information.
EDIT:
If you read through the documentation provided you would have see select cat.mate from Cat cat. This can be incorporated to your query. Add b.A in your select clause and it should work.
EDIT:
If select b.id as id, sum(c.length) as length, min(c.unit) as unit
from B b
left outer join b.c as c
group by b.id
work then
select b.id as id, sum(c.length) as length, min(c.unit) as unit, b.A
from B b
left outer join b.c as c
group by b.id, b.A
should as well.
How do I join two tables in hibernate and Spring. below is my suto java code and I need to do a join on objectA where the name field is equal to the name field in objectB but I am going to be searching on ObjectA ID field but I need returned. ObjectA ID, ObjectA Name, ObjectA Regin, ObjectB Address.
//
// CLASS OBJECT A
//
#Entity
#Table(name = "tableA")
public class ObjectA {
#Id
#Column(name = "id")
private String id;
#Column(name = "name")
private String name;
#Column(name = "region")
private String region;
}
//
// CLASS OBJECT B
//
#Entity
#Table(name = "tableB")
public class ObjectB {
#Id
#Column(name = "id")
private String id;
#Column(name = "name")
private String name;
#Column(name = "address")
private String address;
}
can someone please tell me how to do this within the java code.
Add this to your A class:
#OneToOne
#JoinColumn(name="name")
private ObjectB objectB;
So that when you retrieve for A, you'll get inside corresponding B by name.
Use a cross join with a condition in the where clause to limit the join. This is the only good way (other than native sql) that i know of, to join two objects when there is no mapped relationship between them.
You can do this easily with an hql query
select a.id, a.name, a.region, b. address
from ObjectA a, ObjectB b
where a.id = b.id
You can also use inner join
select A.ID,A.Name,A.Regin,B.Address
from ObjectA as A inner join ObjectB as B
I have a SQL query
SELECT * FROM Thing AS a JOIN Thing_Property AS b ON a.id=b.Thing_ID
JOIN Property AS c ON b.properties_ID = c.id
JOIN Item AS d ON c.item_ID = d.id
ORDER BY a.name, d.name
and I Eclipselink to create my object model with it.
Here is the model:
#SuppressWarnings("serial")
#Entity
public class Thing implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.TABLE)
private int id;
private String name;
#OneToMany(cascade=CascadeType.ALL)
#PrivateOwned
private List<Property> properties = new ArrayList<Property>();
...
// getter and setter following here
}
public class Property implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.TABLE)
private int id;
#OneToOne
private Item item;
private String value;
...
// getter and setter following here
}
public class Item implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.TABLE)
private int id;
private String name;
....
// getter and setter following here
}
// Code end
but I can not figure out, how to make Eclipselink create the model from that query. Can you help?
You will need to use the API EntityManager.createNativeQuery(String sqlString, Class resultClass);
entityManager.createNativeQuery("SELECT * FROM Thing AS a JOIN Thing_Property AS b ON a.id=b.Thing_ID JOIN Property AS c ON b.properties_ID = c.id JOIN Item AS d ON c.item_ID = d.id ORDER BY a.name, d.name ", Thing.class);