Mapping a bidirectional One-to-Many Hibernate Entity with JPA - java

I am trying to map a bidirectional One-to-Many relationship in Hibernate. In the build logs I receive the error "repeated column in mapping for entity."
What is generating the error?
The entity source code is below. One has a compound primary key. I am using Lombok to generate getters and setters.
The relationship: Award (One) --> AwardReceived (Many)
Award Entity
#Entity
#Table(name = "awards")
#JsonInclude(JsonInclude.Include.NON_NULL)
#Data
public class Award implements Serializable {
#Id
#Column(name = "award_id")
private Long awardId;
#OneToMany(cascade=CascadeType.ALL, mappedBy = "award")
private Set<AwardReceived> awardsReceived;
#Column(name = "award_type")
private String awardType;
#Column(name = "award")
private String award;
#Column(name = "description")
private String description;
}
AwardReceived Entity
#Entity
#Table(name = "awards_received")
#JsonInclude(JsonInclude.Include.NON_NULL)
#Data
public class AwardReceived implements Serializable{
#EmbeddedId
#JsonUnwrapped
private AwardReceivedPk awardReceivedPk;
#ManyToOne(cascade=CascadeType.ALL)
#JoinColumn(name = "award_id")
private Award award;
#Column(name = "award_name")
private String awardName;
#Column(name = "citation")
private String citation;
}
AwardReceivedPk
#Embeddable
#JsonInclude(JsonInclude.Include.NON_NULL)
#Data
public class AwardReceivedPk implements Serializable{
#JsonIgnore
#Column(name = "client_no")
private String clientNo;
#Column(name = "award_id")
private Long awardId;
#Column(name = "year")
private Long year;
}

Please try
#ManyToOne(cascade=CascadeType.ALL)
private Award award;
instead of
#ManyToOne(cascade=CascadeType.ALL)
#JoinColumn(name = "award_id")
private Award award;

Related

How to use multiple #Onetoone & #OnetoMany annotation

I'm newbie in Spring boot and making first time an experimental app. This app consist on 3 classes / tables:
Account:
has an account numbers that can be call by JournalEntryDetail, so I get #onetoone relation
JournalEntryMaster:
can have many JournalEntryDetail
I use here #OnetoMany annotation
JournalEntryDetail:
can have one JournalEntryMaster
Foreign key to Account, as Account number should be equal b/w JournalEntDetail & Account table
I get an error:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name
'entityManagerFactory' defined in class path resource
[org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Invocation
of init method failed; nested exception is org.hibernate.AnnotationException: #Column(s) not
allowed on a #OneToOne property: com.accounts.entity.JournalEntryMaster.jvNumber
I can understand what does error means but unfortunately I did not find solution, so I came here. Any one could advise will be appreciated.
I copy entities hereunder:
accountnumber
public class Account {
#Id
#GeneratedValue
#Column(name="account_id")
private Long id;
#Column(name="account_number")
private Long accountNumber;
#Column(name="account_name")
private String accountName;
#Enumerated(EnumType.STRING)
#Column(name="dr_or_credit")
private DrOrCrSide drOrCrSide;
#Enumerated(EnumType.STRING)
#Column(name="account_type")
private AccountType accountType;
#ManyToOne(cascade = CascadeType.ALL)
private JournalEntryDetail journalEntryDetail;
JournalEntryMaster
#Entity
#Getter
#Setter
#AllArgsConstructor
#NoArgsConstructor
#EqualsAndHashCode
#ToString
public class JournalEntryMaster {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name="id")
private Long id;
#OneToOne
#Column(name="jv_number")
private Long jvNumber;
#Column(name="jv_master_date")
private Date Date;
#Column(name="jv_reference_no")
private String ReferenceNo;
#Column(name="memo")
private String Memo;
#Column(name="posted")
private boolean Posted;
#OneToMany(targetEntity = JournalEntryDetail.class, cascade = CascadeType.ALL)
private Set<JournalEntryDetail> journalEntryDetail = new HashSet<>();
}
JourEntryDetail
#Entity
#Getter
#Setter
#AllArgsConstructor
#NoArgsConstructor
#EqualsAndHashCode
#ToString
public class JournalEntryDetail {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(name="account_number")
private Long accountNumber;
#Enumerated(EnumType.STRING)
#Column(name="jv_detail_drcr")
private DrOrCrSide DrCr;
#Column(name="amount")
private Double Amount;
#Column(name="memo")
private String Memo;
#ManyToOne
#JoinColumn(name = "jv", referencedColumnName = "id")
private JournalEntryMaster jv;
#JoinColumn(name = "account_fk_jv", referencedColumnName = "account_number")
#OneToOne(targetEntity = Account.class, cascade = CascadeType.ALL)
private Account account_number;
#JoinColumn(name = "jvnumber_fk", referencedColumnName = "jv_number")
#OneToOne(targetEntity = JournalEntryMaster.class, cascade = CascadeType.ALL)
private JournalEntryMaster jvNumber;
In
public class JournalEntryMaster {
...
#OneToOne <-- remove this annotation
#Column(name="jv_number")
private Long jvNumber;
You use Long for the jvNumber. If this is just a database column and its not related to an entity, don't use #OneToOne. You can remove the annotation and your error #Column(s) not allowed on a #OneToOne property: com.accounts.entity.JournalEntryMaster.jvNumber will disappear.
On the other hand, if it is related to an entity, you have to use JoinColumn instead of Column and use your EntityClass instead of Long.
Remove #OneToOne from JournalEntryMaster above #Column(name="jv_number") private Long jvNumber and relation of JournalEntryDetail with JournalEntryMaster
is #ManyToOne not #OneToOne. you give two relation together for one table in JournalEntryDetail
remove:
#JoinColumn(name = "jvnumber_fk", referencedColumnName = "jv_number")
#OneToOne(targetEntity = JournalEntryMaster.class, cascade = CascadeType.ALL)
private JournalEntryMaster jvNumber;
Here down modified code:
JournalEntryMaster
#Entity
#Getter
#Setter
#AllArgsConstructor
#NoArgsConstructor
#EqualsAndHashCode
#ToString
public class JournalEntryMaster {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name="id")
private Long id;
#Column(name="jv_number")
private Long jvNumber;
#Column(name="jv_master_date")
private Date Date;
#Column(name="jv_reference_no")
private String ReferenceNo;
#Column(name="memo")
private String Memo;
#Column(name="posted")
private boolean Posted;
#OneToMany(targetEntity = JournalEntryDetail.class, cascade = CascadeType.ALL)
private Set<JournalEntryDetail> journalEntryDetail = new HashSet<>();
}
JourEntryDetail
#Entity
#Getter
#Setter
#AllArgsConstructor
#NoArgsConstructor
#EqualsAndHashCode
#ToString
public class JournalEntryDetail {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(name="account_number")
private Long accountNumber;
#Enumerated(EnumType.STRING)
#Column(name="jv_detail_drcr")
private DrOrCrSide DrCr;
#Column(name="amount")
private Double Amount;
#Column(name="memo")
private String Memo;
#ManyToOne
#JoinColumn(name = "jv", referencedColumnName = "id")
private JournalEntryMaster jv;
#JoinColumn(name = "account_fk_jv", referencedColumnName = "account_number")
#OneToOne(targetEntity = Account.class, cascade = CascadeType.ALL)
private Account account_number;

Hibernate AnnotationException: Use of #OneToMany or #ManyToMany targeting an unmapped class

I know this question has been raised many times before, but I am still confused where the mistake might be in my case:
AnnotationException: Use of #OneToMany or #ManyToMany targeting an unmapped class: com.collab.collabplatform.persistance.entities.CategoryModel.category2projectRel[com.collab.collabplatform.persistance.keys.Category2ProjectRelKey]
CREATE TABLE IF NOT EXISTS `category2projectRel`
(
`project_id` bigint(20) NOT NULL,
`category_id` bigint(20) NOT NULL,
PRIMARY KEY (`project_id`, `category_id`),
CONSTRAINT `FK_category2project_project_id` FOREIGN KEY (`project_id`) REFERENCES `project` (`id`),
CONSTRAINT `FK_category2project_category_id` FOREIGN KEY (`category_id`) REFERENCES `category` (`id`)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4;
and the entities and key classes:
#Entity
#Table(name = "\"category2projectRel\"")
#NoArgsConstructor
#Getter
#Setter
public class Category2ProjectRelModel {
#EmbeddedId
private Category2ProjectRelKey id;
#ManyToOne
#MapsId("project_id")
#JoinColumn(name = "project_id")
private ProjectModel project;
#ManyToOne
#MapsId("category_id")
#JoinColumn(name = "category_id")
private CategoryModel category;
}
&
#Getter
#Setter
#NoArgsConstructor
#Embeddable
public class Category2ProjectRelKey implements Serializable {
#Column(name = "project_id")
Long projectId;
#Column(name = "category_id")
Long categoryId;
}
&
#Entity
#Table(name = "\"category\"")
#NoArgsConstructor
#Getter
#Setter
public class CategoryModel extends BaseEntity {
#Column
#NotNull
private String title;
#Column
private String color;
#OneToMany(mappedBy = "category")
List<Category2ProjectRelKey> category2projectRel;
}
&
#Entity
#Table(name = "\"project\"")
#NoArgsConstructor
#Getter
#Setter
public class ProjectModel extends BaseEntity {
#ManyToOne
#JoinColumn(name="location_id")
private LocationModel location;
#NotNull
#Column
private String title;
#NotNull
#Column(name = "creation_date")
private OffsetDateTime creationDate;
#NotNull
#Column
private String status;
#Column(name = "termination_date")
private OffsetDateTime terminationDate;
#Column
private String description;
#Column
private Boolean virtual;
#OneToMany(mappedBy = "project")
List<Category2ProjectRelKey> category2projectRel;
#OneToMany(mappedBy = "project")
List<Project2TagRelKey> project2tagRel;
}
#ManyToOne #OneToMany #OneToOne #ManyToMany annotations should be used with Entity classes (classes annotated with #Entity)
So, in CategoryModel class, you use #OneToMany with class Category2ProjectRelKey, which is not an entity.
#OneToMany(mappedBy = "category") // this annotation should target an entity class
List<Category2ProjectRelKey> category2projectRel;
#Embeddable annotation on a class, does not mean it's an entity, but means that it represents a set of a column of more that could be included in other entities.

StackOverflow Exception while using Hibernate and Jackson on bi-directional objects

I am trying some hibernate.The following is the pojo I am using,
#Entity
#Table(name = "person")
public class Person {
#Id
#GeneratedValue
#Column(name = "person_id")
private long person_id;
#Column(name = "name")
private String name;
#Column(name = "Address")
private String Address;
#OneToMany(fetch = FetchType.EAGER, mappedBy = "person" )
private Set<Phone> phone;
//Getters ande Setters
}
#Entity
#Table(name = "phone")
public class Phone{
#Id
#GeneratedValue
#Column(name = "phone_id")
private long phone_id;
#Column(name = "name")
private String name;
#ManyToOne(cascade = CascadeType.MERGE,fetch = FetchType.EAGER)
#JoinColumn(name = "person_id")
private Person person ;
//Getters ande Setters
}
What I want is when I fetch a record from person and need corresponding all phone details. (Like Select * from person) I have around 1360 data in person and nearly double in phone. But for some reason error is thrown. I am not able to see full error stack . Below is the error I am getting.
at
com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:505)
~[jackson-databind-2.4.6.jar:2.4.6] at
com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:639)
~[jackson-databind-2.4.6.jar:2.4.6] at
com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:152)
~[jackson-databind-2.4.6.jar:2.4.6] at
com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:505)
~[jackson-databind-2.4.6.jar:2.4.6] at
com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:639)
~[jackson-databind-2.4.6.jar:2.4.6] at
com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:152)
~[jackson-databind-2.4.6.jar:2.4.6] at
com.fasterxml.jackson.databind.ser.std.CollectionSerializer.serializeContents(CollectionSerializer.java:117)
~[jackson-databind-2.4.6.jar:2.4.6] at
com.fasterxml.jackson.databind.ser.std.CollectionSerializer.serializeContents(CollectionSerializer.java:23)
~[jackson-databind-2.4.6.jar:2.4.6] at
.....
I was not able to post all error that I got
Using JsonManagedReference and JsonBackReference annotations may solve your problem.
While jackson trying to convert objects to json, visits objects and
their attributes. So if objects have bi-directional relations, for
jackson we need to think about cyclic dependencies. Jackson starts
serialize person and see the phone list and take a phone from list and
start serialize phone and sees person in phone and take person from
phone and start serilize it bla bla bla so this is an endless loop. If
jackson sees these annotations, stops and breaks the loop.
Give it a try as below code;
#Entity
#Table(name = "person")
public class Person {
#Id
#GeneratedValue
#Column(name = "person_id")
private long person_id;
#Column(name = "name")
private String name;
#Column(name = "Address")
private String Address;
#JsonManagedReference
#OneToMany(fetch = FetchType.EAGER, mappedBy = "person" )
private Set<Phone> phone;
// Getters and Setters
}
#Entity
#Table(name = "phone")
public class Phone{
#Id
#GeneratedValue
#Column(name = "phone_id")
private long phone_id;
#Column(name = "name")
private String name;
#ManyToOne(cascade = CascadeType.MERGE,fetch = FetchType.EAGER)
#JoinColumn(name = "person_id")
#JsonBackReference
private Person person;
// Getters and Setters
}
You can alternatively use #JsonIdentityInfo on classes
#Entity
#JsonIdentityInfo(generator=ObjectIdGenerators.IntSequenceGenerator.class, property="#id")
#Table(name = "phone")
public class Phone {
}
#Entity
#JsonIdentityInfo(generator=ObjectIdGenerators.IntSequenceGenerator.class, property="#id")
#Table(name = "person")
public class Person {
}
I was also getting the same error.
Using #JsonBackReference and #JsonManagedReference was still giving me error so I used #JsonIdentityInfo and it worked like a charm.
Below are my classes :-
BookModel :
#Data
#Entity
#Table(name = "book")
#JsonIdentityInfo(generator=ObjectIdGenerators.IntSequenceGenerator.class, property="bookId")
public class BookModel implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "book_id")
private int bookId;
#Column(name="book_name")
private String bookName;
#Column(name="book_author")
private String bookAuthor;
#Column(name="book_publish_date")
private Date bookPublishDate;
#Column(name="book_price")
private double bookPrice;
#OneToMany(mappedBy = "book_model")
List<BookImagesModel> bookImagesModels;
//getters and setters
//default constructor
}
BookImagesModel :
#Data
#Entity
#Table(name = "book_images")
#JsonIdentityInfo(generator=ObjectIdGenerators.IntSequenceGenerator.class, property="imageId")
public class BookImagesModel implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "image_id")
private long imageId;
#ManyToOne
#JoinColumn(name = "book_id")
private BookModel book_model;
#Column(name = "image_path")
private String imagePath;
//getters and setters
//default constructor
}
I used Mysql8 database with spring boot.

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.

hibernate annotations and joins

I am trying to use hibernate to retrieve data from my database...I have a query that joins two tables (all fields being one to one) using a left join. I need to know how to handle this with hibernate and annotations. I have created two classes that map to tables and I am trying to figure out how to use the joins...Hibernate docs are confusing...
//one class
#Entity
#Table(name = "Class1")
public class Class1{
#Id
#Column(name = "INITIAL")
private String initial;
#Column(name = "NUMBER")
private Integer number;
...
//twoclass
#Entity
#Table(name = "Class2")
public class Class2{
#Column(name = "STATE")
private String state;
#Id
#Column(name = "NUMBER")
private Integer number
...
#Entity
#Table(name = "Class1")
public class Class1 {
#Id
#Column(name = "INITIAL")
private String initial;
#Column(name = "NUMBER")
private Integer number;
}
#Entity
#Table(name = "Class2")
public class Class2 {
#Id
#Column(name = "STATE")
private String state;
#Column(name = "NUMBER")
private Integer number
#OneToOne
#JoinColumn(name = "columnWithClass1id")
private Class1 class1;
}

Categories