Hibernate mapping a map without a join table - java

I'm trying to use hibernate to map an object like this:
#Entity
public class ParentClass {
#Id
#GeneratedValue
int Id;
#OneToMany
Map<String, ChildClass> map;
}
#Entity
public class ChildClass {
#Id
#GeneratedValue
int Id;
String text;
}
I don't want Hibernate to create a join table. I want it to add a column to the table for ChildClass. I'd also prefer not to add a field for the key in ChildClass. Ideally, when saving the object Hibernate would automatically take the key in the map and save it in the corresponding table, and do the reverse when querying. Is this possible?
If I do have to add a field to ChildClass for the key, can hibernate populate this field automatically with the key from the map? The reason I ask is because I'm getting my data from a JSON web service and using Jackson to parse it and I don't know of a way to make Jackson copy the keys to the fields in the value objects. I could write code to do that manually, but I`d rather avoid that.

Unidirectional relation without jointable:
#Entity
public class Customer implements Serializable {
#OneToMany(cascade=CascadeType.ALL, fetch=FetchType.EAGER)
#JoinColumn(name="CUST_ID")
public Set<Ticket> getTickets() {
...
}
#Entity
public class Ticket implements Serializable {
... //no bidir
}
Bidirectional without jointable:
#Entity
public class Troop {
#OneToMany(mappedBy="troop")
public Set<Soldier> getSoldiers() {
...
}
#Entity
public class Soldier {
#ManyToOne
#JoinColumn(name="troop_fk")
public Troop getTroop() {
...
}
It's from documentation: http://docs.jboss.org/hibernate/annotations/3.5/reference/en/html_single/
Apply these samples to your case.

Related

Hibernate extending entity for read with additional joins

I have an entity that corresponds to some table in DB
#Entity
#Table
public class MyEntity {
#Id
private Long id;
#Column
private String description;
#OneToMany
private List<Foo> foos;
...
//getters setters
...
}
And I would like to extend that entity for read-only and have additional joins to another table. I need this joins only in one case for specific read user-case:
#Entity
public class ExtendedEntity extends MyEntity {
#ManyToMany(fetch = FetchType.EAGER)
private List<Bar> bars;
}
Just using extensions will create a discriminator column in DB, which I don't need since I'm using the ExtendedEntity only for the read. I found I hack with using #DiscriminatorFormula that will be resolved to the same Integer value like this:
#DiscriminatorFormula("0")
#DiscriminatorValue("0")
public class MyEntity
#DiscriminatorValue("00")
public class ExtendedEntity extends MyEntity
But this really looks like a hack. With using #MappedSuperclass I cannot have associations, but this is the main reason I need to extend my entity.
What other options do I have and what are the best practices for this use-case?

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

How do I keep the last reference of #ManyToOne in JPA?

I want to create two class which has #OneToMany and #ManyToOne relationship. Below is a sample code.
#Entity
public class ClassA {
#Id
public Long id;
#ManyToOne
public ClassB classB;
public String something;
}
#Entity
public class ClassB {
#Id
public Long id;
#OneToMany(mappedby = "classB")
public List<ClassA> classAList = new ArrayList<>();
public String somet;
}
That code works just fine but, I want to have the last reference of class A in class B. I can do that by adding #OneToOne public ClassA lastClassA; in ClassB (just like here). Below is the code:
#Entity
public class ClassA {
#Id
public Long id;
#ManyToOne
public ClassB classB;
public String something;
}
#Entity
public class ClassB {
#Id
public Long id;
#OneToMany(mappedby = "classB")
public List<ClassA> classAList = new ArrayList<>();
#OneToOne
public ClassA lastClassA;
public String somet;
}
That code is working. The problem occurs when I insert data to either of it, I got the following error: foreign key constraint fails. That happened because I don't have a reference in another table.
It is not clear exactly what you want to do however if you want a reference to the final item in the collection there are some options that could work.
Mark the collections as 'extra-lazy' which will allow you to access the last item in the list without loading the whole collection. If you do require to load the other items in the collection this may be problematic however.
https://docs.jboss.org/hibernate/orm/3.3/reference/en/html/performance.html
"Extra-lazy" collection fetching: individual elements of the
collection are accessed from the database as needed. Hibernate tries
not to fetch the whole collection into memory unless absolutely
needed. It is suitable for large collections.
If you only require the last item then use a Hibernate #Where clause to filter the collection
https://docs.jboss.org/hibernate/stable/annotations/reference/en/html_single/
Create a database view to filter the most recent items and map an additional entity to that.

Primary Key Column Name with Spring Data JPA and Hibernate

I have the following setup with Spring Data JPA and Hibernate as the persistence provider. All of my entities inherit from a base class
#MappedSuperclass
public class BaseEntity {
#Id
private id;
#Version
private String version;
//more common fields
}
For example:
#Entity
public class Foo extends BaseEntity {
}
This leads to a primary key column with name "ID" to be generated on the "FOO" table. I would like to change the naming of the primary key column. It should reflect the name of class or table. So it should be "FOO_ID" instead of just "ID".
I know that I could do this statically by using #Column(name = "FOO_ID"). But that would mean I have to do this for every Entity. Is there a more dynamic way to achieve this?
I know this is an old question, but stumbled across this looking for an answer... Eventually found this solution elsewhere:
#Entity
#AttributeOverride(name="id", column=#Column(name="FOO_ID"))
public class Foo extends BaseEntity {
}
All your subClasses will have the same ID column name because of the inheritance, you can specify a common id colum name for all subClasses in the Base entity Class
Why use inheritance then? Just do it without inheritance.
You could use getters/setters to rename your fields
Ex:
class Foo {
private Long id;
public Long getFooId() {
return this.id;
}
public void setFooId(Long fooId) {
this.id = fooId;
}
}

Categories

Resources