JPA direction of entity relationships - java

I am new to JPA and am having some difficulty understanding the "Direction in Entity Relationships" concepts as described here:
http://docs.oracle.com/javaee/7/tutorial/doc/persistence-intro001.htm#BNBQI
Is uni- or bidirectionality something that you choose when designing your entities or is it given by the database schema? Like in the order application (http://docs.oracle.com/javaee/7/tutorial/doc/persistence-basicexamples001.htm), could you for example design it so that the lineitem knows about which orders it belongs to, but an order wouldn't know which lineitems it has?

You decide whether a relationship is uni-directional or bi-directional by the fields and annotations you include on the entities.
Uni-directional
#Entity
public class Parent(){
#OneToMany
private List<Child> children;
}
#Entity
public class Child(){
}
Bi-directional
#Entity
public class Parent(){
#OneToMany
private List<Child> children;
}
#Entity
public class Child(){
#ManyToOne
#JoinColumn
private Parent parent;
}
As you can see the uni-directional relationship does not allow the child to access the parent, while the bi-directional does allow parent access. This link is created by adding an annotated field to the child of the parent's type and is completely optional. It boils down to a design decision.
Of course the database must support the relationship, meaning the proper primary/foreign keys are established to link the tables, but nothing special is required in your database.
One important concept to be aware of when modeling these relationships is the owning entity. I have written this article about the topic which may be helpful.

That depend upon your requirement
Unidirectional
#Entity
#AutoProperty
public class OneToOneUnidirectionalA implements Serializable {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private long id;
#OneToOne
private OneToOneUnidirectionalB b;
private String s;
// Setters, Getters, Constructors, Pojomatic...
}
#Entity
#AutoProperty
public class OneToOneUnidirectionalB implements Serializable {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private long id;
// No reference to OneToOneUnidirectionalA
// since this is a unidirectional relationship
private String s;
// Setters, Getters, Constructors, Pojomatic...
}
Bidirectional
A owns the relationship. We need to avoid Pojomatic circular reference issues too:
#Entity
#AutoProperty
public class OneToOneBidirectionalA implements Serializable {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private long id;
#Property(policy=PojomaticPolicy.NONE)
#OneToOne
private OneToOneBidirectionalB b;
// Setters, Getters, Constructors, Pojomatic...
}
#Entity
#AutoProperty
public class OneToOneBidirectionalB implements Serializable {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private long id;
#Property(policy=PojomaticPolicy.NONE)
#OneToOne(mappedBy="b")
private OneToOneBidirectionalA a;
// Setters, Getters, Constructors, Pojomatic...
}

Related

Does JPA allow mapping over multiple target entity in #OneToMany relationship?

I have two child entity, both share the same parent class:
#MappedSuperclass
abstract class Parent {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
}
#Entity
class Child1 extends Parent {
private Integer child1Attr;
}
#Entity
class Child2 extends Parent {
private String child2Attr;
}
And the Parent is supposed to be the "many side" of the #OneToMany relationship, something like this:
#Entity
class MyClass {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
#OneToMany
private Set<Parent> allChildSet; // <- hibernate throws exception
}
Is there a way to allow allChildSet accept either child1 or child2 class, since they share the same parent class? Something like this:
#OneToMany(targetEntity = {Child1.class, Child2.class}) // <- not allowed, it only accept one single class
private Set<Parent> allChildSet;
I'm not sure if such feature is possible from the database or ORM's point of view. If not possible, creating a #Transient field, I assume, is the best way to workaround. Any comment or answers are appreciated.

How to expose fields of and #EmbeddedId

I have an #Entity with three fields A, B, C out of which A and B act as composite primary key. I created an #EmbeddedId class holding A and B. To ease the burden of defining getters and setters i used lombok #Data annotation.
#Entity
#Data
public class MyClass {
#EmbeddedId
private PrimaryKey id;
}
#Embeddable
#Data
public class PrimareyKey implements Serializable {
private String A;
private String B;
}
I would not like to expose that A and B are the primary key and access A and access all fields in the same way.
//Exposes primary key
myObject.getid().getA();
myObject.getid().getB();
myObject.getC();
//Hides primary key
myObject.getA();
myObject.getB();
myObject.getC();
Currently one could use #IdClass tagging each filed as #Id as suggested in this answer but if I still need to use #EmbeddedId (or any #Embedded actually) the only way (I know) to achieve this is to write ad hoc getters and setters bypassing the id variable such as
#Entity
#Data
public class MyClass {
#EmbeddedId
private PrimaryKey id;
public String A getA(){
return id.getA()
}
public String A setA(String a){
id.setA(a);
}
//same for B and any other fiels in PrimaryKey
}
This looks like a lot of boilerplate code to write and maintain.
Is there an annotation to expose #EmbeddedId getters and setters?
In MyClass, add Lombok #Delegate annotation to your PrimaryKey. It should look like:
#Entity
#Data
public class MyClass {
#Delegate
#EmbeddedId
private PrimaryKey id;
}
Then you can set/get PrimaryKey fields directly from MyClass. Here is a link for you to read more about it.
You can use the AccessLevel with #Getter and #Setter as follows:
#Getter(AccessLevel.NONE)
#Setter(AccessLevel.NONE)
private PrimaryKey id;
When using #Data, you have the public access to accessors by default, and using AccessLevel.NONE will overwrite the default behaviour and will not allow to access the accessors.

Store Dependent JPA Entity as JSON Column In Parent Entity

I have a parent entity like so:
#Entity
public class Parent implements Serializable {
#Id
private String id;
#Convert(converter = ChildConverter.class)
private Collection<Child> children;
...
}
And the child entity is defined like so:
#Entity
public class Child implements Serializable {
#Id
private String id;
...
}
However, I want my Child entity to be saved not in its own table but as a (JSON) column in the Parent table. The reason I want to do this is because the Child entity contains little data and I feel as if it does not warrant its own table. Is this possible for JPA?
Update:
In the end, I've decided to simply not annotate the Child class with #Entity. But the trouble this brings is that I have to enforce entity constraints without JPA's help.
You still need a table to store the children of parents, because you use a Collection in the Parent class.
You may use #Embeddable annotation on Child class and #ElementCollection and #CollectionTable on children Collection in the Parent class.
#Embeddable
public class Child implements Serializable {
#Id
private String id;
...
}
#Entity
public class Parent implements Serializable {
#Id
private String id;
#Convert(converter = ChildConverter.class)
#ElementCollection
#CollectionTable(
name="CHILD",
joinColumns=#JoinColumn(name="PARENT_ID")
private Collection<Child> children;
...
}

JPA Annotations with inheritance

I am working on JPA project and I need your help.
I have two classes, “Person” and “Leader” which inherits from Person.
#Entity
#Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public class Person implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#Column(unique = true)
private String personId;
}
And
#Entity
public class Leader extends Person implements Serializable {
private List < Person > listTeam;
public void addPersonInTeam(Person e) {
listTeam.add(e);
}
}
My question Is, do I need to have JPA annotations #OneToMany or something else before private List listTeam in class Leader?
Thank you very much
You need to specify a mapping between the two classes because for Hibernate the association is not relevant here, you have to use annotations in both sides and I guess you will need a OneToMany mapping here :
Here's the mapping that you are seraching for:
In Person class:
#Entity
#Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public class Person implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#Column(unique = true)
private String personId;
#ManyToOne
#JoinColumn(name="leader_id")
private Leader leader;
//getter and setter
}
In Leader class:
#Entity
public class Leader extends Person implements Serializable {
#OneToMany(mappedBy = "leader")
private List <Person> listTeam;
//getter and setter
public void addPersonInTeam(Person e) {
listTeam.add(e);
}
}
For further information you can see these links:
Hibernate – One-to-Many example (Annotation).
Hibernate One To Many Annotation tutorial.
Note:
I don't see the use of the field personId in the Person class, there's no need to use two differents ids.
EDIT:
To answer your questions:
The #JoinColumn(name="leader_id") is not mandatory, but it's used to specify the foreign key name.
If the relation is ManyToMany the mappedBy property is used to specify the owner of the relationship, you can see this answer for more details.

jpa inheritance - reuse an entity in several others

I am new to jpa and wonder how I have to realize this. I want to use an Entity called Address in several other Entities.
Car entity:
#Entity
public class Car
#Id
private String id;
private String licensePlate;
#ManyToOne
private Address address;
public Car() {
}
/* Getter and setters */
....
..
Person entity:
#Entity
public class Person {
#Id
private String id;
private String name;
#OneToMany(mappedBy = "address", cascade = CascadeType.ALL)
private Set<Address> addresses;
public Person() {
}
/* Getter and setters */
....
..
Address entity:
#Entity
public class Address {
#Id
private String id
private String streetAndNumber;
/* Now what?????? */
private Car car; // would fit for car
private Person person; // would fit for person
// But what would be fitted both?
I searched the internet to find a solution. But, most likely to my lack of knowledge. I couldn't find something understandable.
There is actually no need to make all relations bidirectional, it's a best practice to prefer unidirectional relationships in a model whenever possible, see Domain Driven Design Quickly.
In this case Address does not need to know of all the entities that it's associated with. Also consider making the address a Value Object (see DDD quickly) using the #Embeddable annotation.

Categories

Resources