Store Dependent JPA Entity as JSON Column In Parent Entity - java

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;
...
}

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.

Hibernate annotation mapping to joined table with composite key

I have an entity, that i'd like to join OneToOne with a table with a composite key (Omitting getters/setters):
#Entity
#Table(name = "parent")
public class Parent {
#Id
private String parentId;
#Column(name = "data")
private String data;
#OneToOne
private Child child;
}
And:
#Entity
#IdClass(ChildKey.class)
#Table(name = "child")
public class Child{
#Id
private String parentId;
#Id
private String username;
#Column(name = "data")
private String childData;
}
public class ChildKey implements Serializable {
private String parentId;
private String username;
}
Parent does not have a notion of the 'username' field in the Child entity. I need to pass this in as criteria. In the DB, the primary key of child is on parentId and username.
If I don't specify a JoinColumn, hibernate attempts to map using fields child_username and child_parentId. If I specify only one Joincolumn, I get a broken mapping. If I specify both JoinColumns, I have no column on parent to specify.
How can I map this class and pass in the username as criteria? (it is coming from authentication data) Or how can I do this in a different way if I'm off track.
You might be able to use a Derived Identity.
The Parent class would remain the same; but you would specify a #OneToOne mapping back to the child's parent and the Child and ChildKey classes would look like this:
#Entity
#IdClass(ChildKey.class)
#Table(name = "child")
public class Child{
#Id
#OneToOne(mappedBy="child")
private Parent parent;
#Id
private String username;
#Column(name = "data")
private String childData;
}
public class ChildKey implements Serializable {
private String parent; // name matches name of the #Id field and type matches type of Parent #Id field
private String username; // name and type match those of the #Id field
}
Derived identity is discussed in JPA 2.1 spec, section 2.4.1.
What I ended up doing was defining a #Filter on the Child class, like so:
#Entity
#IdClass(ChildKey.class)
#Table(name = "child")
#FilterDef(name = "usernameFilter", parameters = {
#ParamDef( name = "username", type="string")
})
public class Child { ... }
On the Parent class, I annotated the collection with a reference to the filter:
#OneToMany(fetch = FetchType.EAGER)
#JoinColumn(name = "parentId")
#Filter(name="usernameFilter", condition = "username = :username")
private List<Child> children;
Finally, in my DAO, I parameterized the filter by name like so:
Filter filter = currentSession().enableFilter("usernameFilter");
filter.setParameter("username", user.getUsername());
Doing this resulted in the exact SQL I had in mind, which is an additional clause in the JOIN criteria with a variable:
SELECT
...
FROM
parent this_
LEFT OUTER JOIN
child child_ ON this_.parentId = child_.parentId
AND child_.username = ?
I might not have been clear about what end result I was looking for in my original question. Posting this answer in case it helps someone else.

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.

Hibernate/JPA one-to-many relationship if parent reference is defined as an ID with no parent reference

Standard way to define one-to-many relationship in Hibernate/JPA is to have a reference in a Child object to its Parent object.
#Entity
#Table(name="PARENT")
public class Parent {
// ...
#OneToMany(mappedBy="department")
private Set<Child> children;
// ...
}
#Entity
#Table(name="CHILD")
public class Child {
// ...
#ManyToOne
#JoinColumn(name="parent_id")
private Parent parent;
// ...
}
The problem with this method is that Child becomes a heavyweight class, which is harder to send across the wire, etc.
Is it possible to define a one-to-many relationship with no Parent object referenced from Child and with no additional reference/join table? In that case Child class defined as follows:
#Entity
#Table(name="CHILD")
public class Child {
// ...
#Column(name="DEPARTMENT_ID")
private Long departmentId;
// ...
}
If you are using JPA 2.0, it is possible OneToMany uni-direction with no parent entity at child entity.
Parent.java
#Entity
#Table(name="PARENT")
public class Parent {
#OneToMany
#JoinColumn(name = "PARENT_ID", referencedColumnName = "ID")
private Set<Child> children;
}
Child.java
#Entity
#Table(name="CHILD")
public class Child {
// No need to hold parent entity
//#ManyToOne
//#JoinColumn(name="parent_id")
//private Parent parent;
}
More Reference

JPA direction of entity relationships

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...
}

Categories

Resources