i'm using a library which have some entity and relations
like this :
public class BaseEntity1{
private Long id;
private List<BaseEntity2> baseEntity2List;
}
public class BaseEntity2{
private Long id;
private String title;
}
Entities have no jpa annotation's
i need to persist them into database
so i extend them and Override getter's to add jpa annotations
like this :
#Entity
#Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public abstract class ChildEntity1 extends BaseEntity1{
#Override
#Id
public Long getId(){
..
}
#Override
#OneToMany
public List<BaseEntity2> getBaseEntity2List(){
..
}
}
#Entity
#Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public abstract class ChildEntity2 extends BaseEntity2{
#Override
#Id
public Long getId(){
..
}
#Override
#Column
public String getName(){
..
}
}
my problem is that OneToMany relation , i have no idea to replace BaseEntity2 to ChildEntity2
Does anyone have any idea ?
Related
I have somewhat big object model in my app, and want to decouple model definition from persistence layer. This is an example of class that I want to generate entity class from:
#Setter
#Getter
public abstract class AbstractAccount {
protected Long id;
protected AbstractProfile profile;
protected AbstractAuthorization<AbstractRole> authorization;
protected AbstractWallet wallet;
protected AbstractActivityHistory<AbstractGameSessionRecord, AbstractOperationRecord> history;
// Constructors and stuff...
}
Simply marking every class with #Entity, manipulating field annotations as well would be enough, but I really need to decouple them. I want to get entities like this:
#Data
#Entity
#SuperBuilder
#Inheritance(strategy = InheritanceType.JOINED)
#JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id")
public abstract class AccountEntity {
public AccountEntity(AccountType accountType) {
this.accountType = accountType;
}
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
public Long id;
#Embedded
public AbstractWalletEntity walletEntity;
#Embedded
public AbstractProfileEntity profileEntity;
#Embedded
AbstractAuthorizationEntity authorizationEntity;
#Column(nullable = false)
#Enumerated(EnumType.STRING)
public AccountType accountType;
}
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.
I created abstract generic #MappedSuperclass. This is working fine with select, insert queries. But hibernate don't generate update queries. I don't understand what's wrong with generic class.
#MappedSuperclass
#Cacheable
public abstract class Category<T extends Category> {
private Integer id;
private String name;
private T parent;
private List<T> children;
#Id #GeneratedValue(strategy = GenerationType.IDENTITY)
public Integer getId() {
return id;
}
//omitted
}
#Entity
#Table(name = "staticPageCategory")
public class StaticPageCategory extends Category<StaticPageCategory> implements Serializable {
#ManyToOne
#Override
public StaticPageCategory getParent() {
return super.getParent();
}
#OrderBy("ordering asc, name asc")
#OneToMany(mappedBy = "parent")
#Override
public List<StaticPageCategory> getChildren() {
return super.getChildren();
}
}
Question is why hibernate ignoring getCurrentSession().update(myCategory);
I want to create a primary composite key and use an #Id field from a parent class. But it does not work. Why?
#MappedSuperclass
static abstract class SuperEntity {
#Id
private Long id;
}
#Entity
#IdClass(SuperPK.class)
public static class ChildEntity extends SuperEntity {
#Id
private String lang;
}
public class SuperPK {
public SuperPK(Long id, String lang) {
//...
}
}
Result: Property of #IdClass not found in entity ChildEntity: id
I found an open issue regarding this bug.
One of the comments states to override the getters for the ID properties as a workaround.
#Entity
#IdClass(SuperPK.class)
public static class ChildEntity extends SuperEntity {
#Id
private String lang;
#Override #Id
public Long getId() {
return super.getId();
}
}
I'm working with Hibernate Annotations and the issue that I'm trying to solve goes as follows:
I need to have 2 different #Entity classes with the same columns mapping but with a different Identifier.
The first one should use id as identifier.
The second should use name as identifier.
So, I have an abstract class, annotated with #MappedSuperclass that have all of the columns including id and name, and in addition 2 #Entity classes that extends the super class and overriding the getters of the id and name.
#MappedSuperclass
public class MappingBase {
protected Integer id;
protected String name;
#Column (name = "ID")
public void getId() {
return this.id;
}
#Column (name = "NAME")
public void getName() {
return this.name;
}
}
#Entity
#Table (name = "TABLE")
public class Entity1 extends MappingBase {
#Id
#Column (name = "ID")
public void getId() {
return this.id;
}
}
#Entity
#Table (name = "TABLE")
public class Entity2 extends MappingBase {
#Id
#Column (name = "NAME")
public void getName() {
return this.name;
}
}
Note: I must have the members (id,name) in the super class.
I know that i can add #Transient to the id and name getters but this means that i must add both of them in each class and it's not a good design :(
In addition, the following insertable="false, updateable=false can help but i don't understand what is the meaning of this...
Please help me!
Hibernate/JPA allows us to annotate either properties or accessors. If we have #Id annotation on a property, JPA will lookup all the properties of the class. Similarly, if we have #id annotation on a getter method, JPA will lookup all the getters.
We can solve the above problem by annotating properties instead. The superclass and the two subclasses will be as follows-
#MappedSuperclass
public abstract class AbstractMappingBase {
//properties other than id and name
public abstract Integer getId();
public abstract String getName();
//other getters and setters
}
#Entity
public class Entity1 extends AbstractMappingBase {
#Id
private Integer id;
private String name;
#Override
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
#Override
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
#Entity
public class Entity2 extends AbstractMappingBase {
private Integer id;
#Id
private String name;
#Override
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
#Override
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Here JPA will look for properties instead of getters. There are no duplicate properties between superclass and its subclasses. So it will work fine.
You are much better off defining your base class as #Embeddable and using #Embedded in your implementation classes with the use of #AttributeOverride.
If i remember correctly, I simply defined 2 #Entity classes with the same table that inherits from one abstract #MappedSuperclass class. The super class contains the id member and each Entity class define it's own #Id #Column definition. It should work!