Have a relation between a sub table and a related table using the primary table. Any thoughts about how to go about the hibernate relation.
A <---> B (One to One relation) B is a sub-table of A.
B <---> C (B has One to Many Relation with C Using A)
It not needed in table B in your case. There is #OneToMany between A and B.
#Entity
#Table(name="A")
public class A {
....
#OneToMany(mappedBy="a")
private B b;
}
#Entity
#Table(name="C")
public class C {
...
#OneToOne
#JoinColume(name="ref_to_a")
private A a;
}
Additional table B is required if #ManyToMany association take place.
Related
I am sorry if the Subject was misleading but here is the scenario that I have.
#Entity
Class A {
#Id
private String id;
#OneToMany
private Set<B> b;
}
#Entity
Class B {
#Id
private String c;
private String d;
}
#Entity
Class C {
#Id
private String e;
private String f;
}
Currently, I am retrieving the entity A with its set of objects from Entity B. The thing is that Entity B and Entity C are not related by foreign key and they need to be joined by their primary keys, so when I retrieve the entity A, in the set of objects, I will get the columns from the entities B and C joined together.
Is there any way to tell Hibernate to join the columns from entities B and C when I try to get the object A ?
In JPA 2.0 for joining related entities join is used. For this FK was needed.
Problem with joining unrelated entities is solved in JPA 2.1 standard, Hibernate 5.1 and above. You can use join on unrelated columns.
I have three classes, with each having a table:
Class A {
long id;
#OneToOne(cascade = CascadeType.ALL, orphanRemoval = true)
B b;
}
Class B {
long id;
#OneToOne(cascade = CascadeType.ALL, orphanRemoval = true)
C c;
}
Class C {
long id;
}
There is an entry in each of tables. The link between table B and C is based on the foreign keys. If I set A.b as null, and then update the table for the class A, it first deletes the entry of table for class B, and then the entry of table for class C, which causes a violation exception:
delete from B_table where id=? [23503-176]];
nested exception is:
org.hibernate.exception.ConstraintViolationException: could not
execute statement
Any ideas?
When having such deep hierarchies you have to "chase the pointers". When you set A.b to null, JPA correctly tries to delete the B entity in the table but you get the constraint violation because it still has a reference on C. You have to also set to null B.c first and according to your setting C will be removed from the table, along with the B.c reference (FK)
The deletion of B is implicitly applied by JPA during flush; you did not call a delete yourself so the cascade.ALL in B is not in effect. If you have a FK with cascade delete in database level then theoretically it might work but the order that the orphan removal is applied is implementation dependent and JPA does not recommend to rely on it.
First of all I've been all the morning seeking for a solution for my problem. I've found similar problems but no one fixed my problem :(
I have a 3 level inheritance on my Java classes model:
A <-- B <-- C
Mapping this into a Relational Data Base I've made
A (1) -- (0..1) B (1) -- (0..1) C, so my annotated Java classes are something like:
#Entity
#Inheritance(strategy=InheritanceType.JOINED)
#DiscriminatorColumn(name="type", discriminatorType=DiscriminatorType.INTEGER)
#XmlRootElement
public class A implements Serializable {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
private Long idA;
private Integer type;
...
}
#Entity
#DiscriminatorValue("2")
#PrimaryKeyJoinColumn(name="idB", referencedColumnName="idA")
#XmlRootElement
public class B extends class A implements Serializable{
private Long idB;
private Integer type;
#OneToOne(cascade={CascadeType.REMOVE}, fetch=FetchType.LAZY)
#JoinColumn(name = "idB")
private A a;
...
}
#Entity
#DiscriminatorValue("8")
#PrimaryKeyJoinColumn(name="idC", referencedColumnName="idB")
#XmlRootElement
public class C extends class B implements Serializable{
private Long idC;
#OneToOne(cascade={CascadeType.REMOVE}, fetch=FetchType.LAZY)
#JoinColumn(name = "idC")
private B b;
...
}
I don't know why, invoking a Query SELECT c FROM C c retrieves me 0 result when I have info on that table. If I do the query SELECT b FROM B b it works fine. It seems to be something wrong with the hierarchy annotations I've used.
Any idea? Thank you in advance :)
Joined table inheritance means that when you have a C entity, there must be a row in the A, B AND C tables. If you have data in C but no corresponding data in A or B that match up, then you will get no C entities back - the data is invisible to JPA because it first queries the A table to see if there are rows with a Type=3, and then joins it to B and C.
So check that your java inheritance model actually matches the data model. You also show that B and C have a reference to their parent - this cause the same id field to be mapped twice, as it is in both the Entity's PrimaryKeyJoinColumn and the mapping's JoinColumn. Since the referenced A (or B) is apart of the B (or C), there is no need to also have an object referenence to it - any of the inherited get methods will return the data from the A table anyway.
I have 2 test classes:
Class A{
B b;
// some other properties
}
Class B{
// some properties
}
every instance of A has only one instance of class B, but an instance of class B can be assigned to more than one instance of class A
like :
B b = new B();
A a1 = new A();
a1.setB(b);
A a2 = new A();
a2.setB(b);
what type of association is this?
At first I was thinking about a one-to-one unidirectional but maybe is a many-to-one? but I don't have any collection of A objects on B.
Can someone explain me what is the correct way to implements this association (using annotation)?
every instance of A has only one instance of class B, but an instance
of class B can be assigned to more than one instance of class A
So , A to B is the many-to-one relationship . B to A is the one-to-many relationship.
The following shows the bi-directional mapping between A and B using annotation:
#Entity
#Table(name="tableA")
Class A{
#ManyToOne
#JoinColumn(name = "B_ID")
B b;
// some other properties
}
#Entity
#Table(name="tableB")
Class B{
#OneToMany(mappedBy = "b")
List Set<A> listOfA= new ArrayList<A>();
// some other properties
}
Important points:
#Entity marks the java class as an hibernate entity. It is mapped to the name of the table specified in the #Table
If no #Table is specified ,by default , it is mapped to the table with the name that is equal to the unqualified class name of the entity.
#ManyToOne defines Class A to Class B 's relationship is many-to-one
In the relational database , one-to-many relationship is expressed by using the following foreign key constraint :
"Many side table" has a FK column which only accepts the PK of the "one side table".
This name of this FK column can be defined explictly by the name attribute of #JoinColumn. If #JoinColumn is not specified , then default value(s) with be used for this FK column , which concatenates with the name of "one side table", _ (underscore), and the name of the PK in the "one side table".
#OneToMany defines Class B to Class A 's relationship is one-to-many.
The relationship is:
B (One) ---to--> A (Many)
i am new to hibernate. currently i am stuck in one problem.
i have no idea how to retrieve the value of relation table column.
senario:
i have three tables.
TableA:
-------
a_id
a_col1
TableB:
-------
b_id
b_col1
TableC
-------
c_id
a_id
b_id
c_col1
i have created model class for TableA and TableB. i have mapped them using #ManyToMany and #JoinTable annotation
TableA
{
...
private Set<TableB> tableB;
#ManyToMany
#JoinTable( name="TableC",
joinColumns={#JoinColumn(name="a_id")},
inverseJoinColumns={#JoinColumn(name="b_id)}
public getTableB()
{
return tableB;
}
public setTableB(...) { ... }
}
now my question is:
===================
how can i retrieve the value of c_col1 from TableA entity
You can't. What you're seeing is that you don't actually have a many-to-many relationship between A and B. You have three objects: A, B, and C, with a one-to-many from C to A and from C to B. Then your c_col1 column will exist on C.