Mock JOINED inheritance strategy without actual inheritance - java

I want to use mixed #Inheritance strategy, but Hibernate doesn't support it.
Is there any way to implement JOINED inheritance without actual class inheritance.
For example:
#Entity
#Table(name="A")
#Inheritance(strategy=InheritanceType.JOINED)
public class A {
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "ID_SEQ")
private Long id;
//getters
//setters
}
#Entity
#Table(name="B")
#Inheritance(strategy=InheritanceType.SINGLE_TABLE)
public class B {
#Id
private Long id;
//getters
//setters
}
So, basically in B I just want to refer to #Id generated in A without extending from A.

I found the solution. JPA doesn't allow you to combine #Id and #OneToOne. However, #MapsId annotation does the trick:
#Entity
public class A {
#Id
private Long id;
//getters
//setters
}
#Entity
public class B {
#Id
private Long id;
#MapsId
#OneToOne(optional=false, fetch=FetchType.EAGER)
#JoinColumn(nullable=false, name="id")
private A a;
//getters
//setters
}

I think you can accomplish this by making a #OneToOne relationship or a #OneToMany and point the table name like this
#Id #OneToOne
#JoinColumn(name = "id")
private A a;

Related

JPA StackOverflow -- Many to Many and one to one mapping

I am trying to save a JPA entity which has ManytoMany Relationship (Consumer and Product table) and OnetoOne relation with ConsumerDetailstable.Below are my entities
#JsonInclude(JsonInclude.Include.NON_NULL)
#JsonIgnoreProperties(ignoreUnknown = true)
#JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class)
#Entity
public class Consumer {
#Id
#GeneratedValue
private Long id;
private String firstName;
private String lastName;
#JsonManagedReference
#OnToMany(mappedBy = "consumer")
private Set<ConsumerProduct> consumerProducts;
#OneToOne
private CustomerDetails consumerDetails;
}
#Entity
public class Product {
#Id
#GeneratedValue
private Long productId;
private String productCode;
#OneToMany(mappedBy = "product")
private Set<ConsumerProduct> consumerProducts;
}
#JsonInclude(JsonInclude.Include.NON_NULL)
#JsonIgnoreProperties(ignoreUnknown = true)
#JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class)
#Entity(the join table)
public class ConsumerProduct {
#EmbeddedId
ConsumerProductKey id;
#JsonBackReference
#ManyToOne
#MapsId("id")
#JoinColumn(name = "id")
private Consumer consumer;
#ManyToOne
#MapsId("productId")
#JoinColumn(name = "product_id")
private Product product;
}
#Embeddable (forgein keys combined as embeded id)
public class ConsumerProductKey implements Serializable {
#Column(name="id")
private Long id;
#Column(name = "product_id")
private Long productId;
}
#Enitity (one to one relation table)
public class CustomerDetails {
#Id
#GeneratedValue
private Long consumerDtlId;
#OneToOne
private Consumer consumer;
private String city;
private String state;
private String country;
}
To save the entity am have just extended JPARepository and called save method
public class ConsumerRepository<Consumer> Implements JPARepository<Consumer, Long> {
#Override
public Consumer S save(Consumer entity) {
return save(entity);
};
}
I get java.lang.StackOverFlowError at save method.
Anything wrong with my Mappings ?
Question: Since this will be save operation and since Consumer Id is yet to be generated how do I assign to below Entities
ConsumerProduct.ConsumerProductKey (how do i assign Id of consumer table once it is inserted to join table ? will JPA take care of it)
CustomerDetails (how do i assign Id of consumer table once it is inserted to join table ? will JPA take care of it)
EDIT: I have updated the entity with JsonManagedReference and JsonBackedReference but still i have am facing stackoverflow error
It is due to Consumer trying to access ConsumerProduct and ConsumerProduct trying to access consumer entity and end up with StackOverflow error.
You should use #JsonManagedReference and #JsonBackReference annotation in consumer and ConsumerProduct respectivly.

#OneToOne with #Id: Composite-id class must implement Serializable

I have two simple entities:
#Entity
public class User {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
Long id;
}
#Entity
public class Address {
#Id
#OneToOne
#JoinColumn(name = "FK")
User user;
}
When I run my Spring Boot application I get the following error:
org.hibernate.MappingException: Composite-id class must implement Serializable: Address
But the entities are almost identical to those in JPA Spec (Section 2.4.1, Example 4). For some reason Hibernate thinks that the user attribute is a composite id.
What am I doing wrong?
I would suggest you to correct your mapping in this way:
#Entity
public class User {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
Long id;
}
#Entity
public class Address {
#Id
Long id;
#MapsId
#OneToOne
#JoinColumn(name = "FK")
User user;
}
See also this section of hibernate documentation.
it seems you are using #Id two times in one Entity class

How to store amount of objects in Spring data

Description
I have a system where I can add Component and save it to DB(Mysql). After that a can create Product which contains Components in different amount.
As I understand table should be like component_id|product_id|amount_of_component
Component class:
#Entity
#Table(name = "component")
public class Component {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String name;
}
Product class:
#Entity
#Table(name = "product")
public class Product {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String name;
//something should be here
private Component component;
}
Question
Which annotation or Collection I should use to create such relations between that entities ?
You must use OneToMany with either Set or List. Here is an example:
#OneToMany
#JoinColumn("product_id")
private Set<Component> component;
Please read the Hibernate documentation about Collection mapping: https://docs.jboss.org/hibernate/orm/5.4/userguide/html_single/Hibernate_User_Guide.html#collections

Map an abstract collection with generics in JPA

I have an abstract and generic class:
#MappedSuperclass
public abstract class Field<T> {
#Id #GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "field_id")
private int id;
#ManyToMany
#JoinTable(name = "FIELD_SECTION")
private List<Section> sections;
}
with a couple of classes extending it, such as:
#Entity
#Inheritance
public class StringField extends Field<String> {
}
or
#Entity
#Inheritance
public class DateField extends Field<Date> {
}
I also have a Section class, which contains an abstract collection of Field
#Entity
public class Section {
#Id #GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "section_id")
private int id;
#ManyToMany(mappedBy = "sections")
private List<Field<?>> fields;
}
However, the JPA cannot properly map the List<Field<?>> fields collection which results in the following error:
Caused by: org.hibernate.AnnotationException: Use of #OneToMany or #ManyToMany targeting an unmapped class: com.model.Section.fields[com.model.field.Field]
Basicly, it should be doable, since the FIELD_SECTION table would hold a pair of (section_id, field_id). Each type of field would have a separate table, but all of the field_id's would be unique in all of the field tables, allowing the JPA to determine the type of each field.
Is there a way to achieve the above?

Hibernate delete row and foreign key row ManyToOne

I have the following two classes, one ReqCandAssociation can have many Comments and it is mapped like so. I need to figure out a way that when I delete a ReqCandAssociation it deletes all of its associated comments. Thanks
#Entity
#Table(name = "candidate_jobReq")
public class ReqCandAssociation implements Serializable {
#Id
private Integer candidateId;
#Id
private Integer jobId;
#Column(name = "reqStatus")
private String reqStatus;
#ManyToOne
#PrimaryKeyJoinColumn(name="candidateId", referencedColumnName="id")
private Candidate candidate;
#ManyToOne
#PrimaryKeyJoinColumn(name="jobId", referencedColumnName="id")
private JobReq jobReq;
public ReqCandAssociation(){
}
Second class
#Entity
#Table(name="comment")
public class Comment {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
private Integer id;
#Column(name="commentText")
private String commentText;
#Column(name="commentDate")
private Date commentDate;
#ManyToOne
#PrimaryKeyJoinColumn(name="reqCandAssociationId", referencedColumnName="id")
private ReqCandAssociation reqCandAssociation;
#ManyToOne
#PrimaryKeyJoinColumn(name="userId", referencedColumnName="id")
private User user;
Change this to the following, i'm making it bidirectional mapping.
#Entity
#Table(name = "candidate_jobReq")
public class ReqCandAssociation implements Serializable {
#Id
private Integer candidateId;
#Id
private Integer jobId;
#Column(name = "reqStatus")
private String reqStatus;
#OneToMany(cascade = { CascadeType.ALL }) //this is added here.
#JoinColumn(name ="reqCandAssociationId")
private Set<Comment> comments;
-----
Readup more on the cascade options. All cascade types are all|none|save-update|delete|all-delete-orphan|delete-orphan
The cascade all will delete all the comments associated to this class.

Categories