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

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.

Related

How to Map a ManyToOne relationship from 2 sides with shared primary key

I have 3 tables : Employee, Imputation and Task.
each employee may have many imputations and an imputatino can belong
to only one employee at a time ( ManyToOne relationship )
List each task may have multiple imputations and an imputation can only belong to one task at a time (ManyToOne relationship
I want the imputation table to have TASK_ID as its PRIMARY_KEY
here are my 3 entities :
#Entity
#Data
#NoArgsConstructor
#AllArgsConstructor
#Table(name="employee")
public class AppUser {
#Id #GeneratedValue(strategy = IDENTITY)
private Integer id;
private String first_name;
private String last_name;
#OneToMany(mappedBy="employee")
private List<Imputation> imputations;
}
#Entity
#Data
#NoArgsConstructor
#AllArgsConstructor
public class Imputation {
#Id
private String id; //something needs to be done here to have the id = task_id
private LocalDate day;
private Double workload;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name= "employee_id")
private AppUser employee;
}
#Data
#Entity
#NoArgsConstructor
#AllArgsConstructor
public class Task {
#Id
#GeneratedValue(strategy = SEQUENCE)
private Long id;
private String name;
private String description;
#OneToMany(mappedBy = "task")
private List<Imputation> imputations;
}
this is how i want my table Imputation to look like (as i said, task_id is a PRIMARY KEY AND a FOREIGN KEY ) :
task_id | day | workload |employee_id
Try:
#Entity
public class Imputation {
#Id
#OneToOne
#JoinColumn(name= "task_id")
private Task task;
private LocalDate day;
private Double workload;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name= "employee_id")
private AppUser employee;
}
Or if you want to keep a string property in the entity:
#Entity
public class Imputation {
#Id
private String id;
#MapsId
#OneToOne
#JoinColumn(name= "task_id")
private Task task;
private LocalDate day;
private Double workload;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name= "employee_id")
private AppUser employee;
}

Hibernate One To One mapping, Foreign Key is NULL

This is my first attempt to map with One to One relation. I have the following entities:
#Entity
#Data
#NoArgsConstructor
#AllArgsConstructor
public class Client {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Size(max = 100)
private String name;
#Email(message = "Email should be valid")
private String email;
#OneToOne
#PrimaryKeyJoinColumn
private Key key;
}
AND
#Entity
#Data
#NoArgsConstructor
#AllArgsConstructor
public class Key {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(unique = true)
private UUID number;
#OneToOne
private Client client;
public Key(UUID number) {
this.number = number;
}
}
They do not see each other, I get NULL in the foreign key section. There is a solution when using the EntityManager class in the following post:
JPA / Hibernate OneToOne Null in foreign key
Unfortunately, that method doesn't work for me.
Database snapshot:
Thank you for the answers!
We don't need to mention the #PrimaryKeyJoinColumn annotation. When we are mapping the tables it will create primary key and foreign key. We just need to map properly.
In the Client model class you have to create the mapping like below
#OneToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "key_id", referencedColumnName = "id")
private Key key;
and in the Key model class like this
#OneToOne(mappedBy = "key")
private Client client;

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;

JPA #ManyToOne joining on part of composite primary key

I have two tables that I want to join.
Lets say TableA and TableB.
TableA
#Entity
#Table(name = "TableA")
#Data
#Builder
#AllArgsConstructor
#NoArgsConstructor
public class TableA {
#Id
#EmbeddedId
private TableA.PrimaryId id = new TableA.PrimaryId();
#Column(name = "COL1")
private Integer col1;
#ManyToOne
#JoinColumn(name = "ID1")
private TableB tableB;
#Data
#Embeddable
#Builder
#AllArgsConstructor
#NoArgsConstructor
public static class PrimaryId implements Serializable {
#Column(name = "ID1")
private Integer id1;
#Column(name = "ID2")
private Integer id2;
}
}
TableB
#Entity
#Table(name = "TableB")
#Data
#Builder
#AllArgsConstructor
#NoArgsConstructor
public class TableB {
#Id
#EmbeddedId
private PrimaryId id = new PrimaryId();
#Column(name = "COLUMN1")
private String column1;
#Data
#Embeddable
#Builder
#AllArgsConstructor
#NoArgsConstructor
public static class PrimaryId implements Serializable {
#Column(name = "ID1")
private Integer id1;
#Column(name = "KEY2")
private Integer key2;
#Column(name = "KEY3")
private Integer key3;
#Column(name = "KEY4")
private Long key4;
}
}
The problem is that TableB has composite primary key (4 columns), but I need to do join only on 1 column (ID1).
It isnt a standart join, it is a partial primary key join.
So it causes an error:
nested exception is org.hibernate.AnnotationException: A Foreign key refering TableB from TableA has the wrong number of column. should be 4
If I try this
#ManyToOne
#JoinColumn(name = "ID1", referencedColumnName = "ID1", updatable=false, insertable=false)
I get another error
nested exception is org.hibernate.AnnotationException: referencedColumnNames(ID1) of TableA.TableB referencing TableB not mapped to a single property
I've looked for an answer in similar posts but found nothing useful :(
So I appreciate any help...

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

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;

Categories