Hibernate embed a mapped superclass - java

I am trying to use #ElementCollection with a set of classes which are all inherited from a #MappedSuperclass but when persisting to the database there is no column to identify which subclass was created and therefore will fail when trying to retrieve it from the database. If I change the class to make it an entity instead it will then work but I need it to be #Embeddable to work with #ElementCollection
Below is the code:
#Entity
public class A {
private String attr1;
private String attr2;
....
#ElementCollection
private List<B> list;
....
}
Superclass:
#Embeddable
#MappedSuperclass
#Inheritance(strategy = InheritanceType.SINGLE_TABLE)
public class B {
private String attr3
private String attr4
....
}
Subclass1:
#Embeddable
#DiscriminatorValue("B1")
public class B1 extends B {
private String attr5
....
}
Subclass2:
#Embeddable
#DiscriminatorValue("B2")
public class B2 extends B {
private String attr6
....
}
Thanks in advance

#ElementCollection is for basic or embeddable values which both have no concept of inheritance. If you want inheritance, you need to model the value as entity and then use #OneToMany. From a relational mapping perspective, the two mappings are almost the same:
#Entity
public class A {
private String attr1;
private String attr2;
....
#OneToMany(mappedBy = "a")
private List<B> list;
....
}
#Entity
#Inheritance(strategy = InheritanceType.SINGLE_TABLE)
public abstract class B {
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "a_id")
private A a;
private String attr3
private String attr4
....
}

Related

Store Custom Object Attributes as Columns in Hibernate

how can we generate table using custom object attribute as table column
private class CustomObject {
String attr1;
String attr2;
}
#Entity
#Table(name = "result")
public class Result {
#Column
private String id;
#Column
public CustomObject cobject;
}
RESULT table generate as follow
id
attr1
attr2
From Hibernate_User_Guide documentation:
PA defines two terms for working with an embeddable type: #Embeddable
and #Embedded. #Embeddable is used to describe the mapping type itself
(e.g. Publisher).#Embedded is for referencing a given embeddable type
(e.g. book.publisher).
So you can annotate your classes like below:
#Embeddable
private class CustomObject {
String attr1;
String attr2;
}
#Entity
#Table(name = "result")
public class Result {
#Column
private String id;
#Embedded
public CustomObject cobject;
}

is there a #MappedSuperclass equivalent annotation for mongoDB in spring?

In my project, we are moving from SQL to NoSQL to a certain extent.
I wanted to know, how can we inherit BaseClass properties into child classes in spring data mongo.
I know how to do it in Spring JPA for SQL.
Example,
Below is BaseEntity parent class which is annotated with #MappedSuperClass
It has id and version as its fields.
#MappedSuperclass
public class BaseEntity {
#Id
#GeneratedValue
private Long id;
#Version
private Integer version;
//Getters and setters omitted for brevity
}
entities can extend the BaseEntity class and skip declaring the #Id or #Version properties since they are inherited from the base class.
#Entity(name = "Post")
#Table(name = "post")
public class Post extends BaseEntity {
private String title;
#OneToMany
private List comments = new ArrayList();
#OneToOne
private PostDetails details;
#ManyToMany
#JoinTable(//Some join table)
private Set tags = new HashSet();
//Getters and setters omitted for brevity
public void addComment(PostComment comment) {
comments.add(comment);
comment.setPost(this);
}
public void addDetails(PostDetails details) {
this.details = details;
details.setPost(this);
}
public void removeDetails() {
this.details.setPost(null);
this.details = null;
}
}
#Entity(name = "PostComment")
#Table(name = "post_comment")
public class PostComment extends BaseEntity {
#ManyToOne(fetch = FetchType.LAZY)
private Post post;
private String review;
//Getters and setters omitted for brevity
}
How can I implement same thing in Mongo? For example
#MappedSuperclass
public class BaseEntity {
#Id
#GeneratedValue
private Long id;
#Version
private Integer version;
//Getters and setters omitted for brevity
}
#Document(collection = "Post")
public class Post extends BaseEntity {
private String title;
//Rest of the code
}
#Document(collection = "PostComment")
public class PostComment extends BaseEntity {
#ManyToOne(fetch = FetchType.LAZY)
private Post post;
private String review;
//Getters and setters omitted for brevity
}
You do not need any annotation to do that in Mongo. Mongo itself will take care of superclass for you.
Just extend BaseEntity class in all your entities, all entities will have fields from BaseEntity class when you read and write entities to database. This also works at multilevel hierarchy. i.e. Post extends BaseEntity, BaseEntity extends Entity, in this case Post will have fields from both BaseEntity and Entity class.

Java and Hibernate - How to make OneToOne relation with SuperMappedClass and not an Entity

I have tree Entities: Client, ClientConfigurationA and ClientConfigurationB.
I try to make something like:
#Entity
#Table(name = "CLIENT")
public class Client {
#Id
private int id;
#OneToOne(mappedBy = "client")
private ClientConfiguration configuration
// some getter and setter
}
#MappedSuperClass
public class ClientConfiguration {
#Id
private int id;
#OneToOne
#MapsId
protected Client client;
// getters and setters
}
#Entity(name = "CLIENT_CONF_A")
public class ClientConfigurationA extends ClientConfiguration { ... }
#Entity(name = "CLIENT_CONF_B")
public class ClientConfigurationB extends ClientConfiguration { ... }
But actually I can't define a OneToOne related to MappedSuperClass and not an Entity.
So what's the best way to implement this case ?
I already tried this solution without succes.
Thanks for reading.
It's impossible and here's why:
When hibernate processes entities it needs to know what table to join with when resolving one to one relations.
The problem arise with #MappedSuperClass is that it doesn't define table, so multiple entities could be inherited from this class, each one having different table. Hibernate just couldn't know what table to join then.
If you want to have common super class, I suggest using an abstract #Entity class.
After many attempts i finally succeeded.
#Entity
#Table(name = "CLIENT")
public class Client {
#Id
private int id;
#OneToOne(mappedBy = "client")
private ClientConfiguration configuration
// some getter and setter
}
#Entity
#Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
#DiscriminatorColumn(name = "TYPE")
public abstract class ClientConfiguration {
#Id
private int id;
#Column(name = "TYPE")
private String type;
#OneToOne
#MapsId
protected Client client;
// getters and setters
}
#Entity(name = "CLIENT_CONF_A")
public class ClientConfigurationA extends ClientConfiguration { ... }
#Entity(name = "CLIENT_CONF_B")
public class ClientConfigurationB extends ClientConfiguration { ... }

Search JPA complex object for nested object based on its value

Lets assume we have a complex JPA relation, a fraction of which looks like this:
#MappedSuperclass
public class DiffEntity {
private String diffId;
public DiffEntity() {
this.diffId = UUID.randomUUID().toString();
}
//...
}
#Entity
#Inheritance(strategy = InheritanceType.JOINED)
public class ParentEntity extends DiffEntity {
#Id
#GeneratedValue
private long id;
#Column
private String name;
//...
}
#Entity
public class Construct extends ParentEntity {
#Column
private String variable;
#OneToMany(mappedBy = "construct", cascade = CascadeType.ALL)
private List<Partconstruct> partconstructs;
//...
}
#Entity
public class Partconstruct extends ParentEntity {
#OneToMany(mappedBy = "partconstruct", cascade = CascadeType.ALL)
private List<Field> fields;
#OneToMany(mappedBy = "partconstruct", cascade = CascadeType.ALL)
private List<Hardparameter> hardparameters;
#ManyToOne
#JoinColumn(name = "construct_id")
private Construct construct;
//...
}
#Entity
public class Field extends ParentEntity {
#Column
private int fieldSize;
#ManyToOne
#JoinColumn(name = "partconstruct_id")
private Partconstruct partconstruct;
//...
}
#Entity
public class Hardparameter extends ParentEntity {
#Column
private String value;
#ManyToOne
#JoinColumn(name = "partConstruct_Id")
private Partconstruct partConstruct;
//...
}
We are concerned with Construct type objects. Construct is deeply cloned and persisted, having all its nested objects on the object graph being cloned too and getting a new Id (primary key). On every clone the diffId (from DiffEntity entity) stays the same (it serves the purpose of correlating objects for a diffing feature).
How would it be possible to search and get a reference for a specific DiffEntity given we have the below:
a reference to the Construnct instance
type of the nested object
diffId we are after.
I have tried different versions of object graph traversers with reflection, which will work for a small in size Construct object, but once it becomes too big performance is very slow.
Is there any magic on the entity manager itself to achieve that ?

JPA OrderBy in #OneToMany by external field

I have entities:
#Entity
public class C {
#Column
private String name;
}
#Entity
public class B {
#Column
private Integer id;
#ManyToOne
#JoinColumn(name = "id_c")
private C c;
}
#Entity
public class A {
#OneToMany(mappedBy = "a")
#OrderBy("id")
private Set<B> itemsB;
}
Now when i access to A.itemsB() - items ordered by B.id
I need to get A.itemsB() ordered by C.name. Is this possible?
I tried to write something like #OrderBy("c.name") but it not work.
just check wich Order is imported : org.hibernate.annotations.OrderBy or javax.persistence.OrderBy.. you should use the second.
You should not use a 'Set<B>', but a 'List<B>'.Sets are always unordered.

Categories