Hibernate #ManyToMany with extra columns - java

So I've been trying the solutions out there to map a ManyToMany relationship with extra columns but none of them is working for me and I don't know what am I doing wrong.
The Many to Many relationship is between Patient and Disease (a Patient can have multiple diseases and a Disease can be suffered by many Patients). The time attribute means "the type of the disease" (acute, chronic...)
My classes are:
#Entity
#Table(name="patient")
public class Patient{
#Id
#NotNull
#Column(name="nss")
private String NSS;
//Some attributes
#OneToMany(mappedBy = "patient")
private Set<PatientDisease> diseases = new HashSet<PatientDisease>();
//Empty constructor and constructor using fields omitted
//Getters and setters ommited
}
,
#Entity
#Table(name="disease")
public class Disease{
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name="id")
private Integer id;
#OneToMany(mappedBy = "disease")
private Set<PatientDisease> patients = new HashSet<PatientDisease>();
//Constructors and getters and setters ommited for brevity
}
Associated class
#Entity
#Table(name = "Patient_Disease")
#IdClass(PatientDiseaseID.class)
public class PatientDisease{
#Id
#ManyToOne(fetch = FetchType.LAZY,
cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH, CascadeType.DETACH})
#JoinColumn(name = "nssPatient", referencedColumnName = "id")
private Patient patient;
#Id
#ManyToOne(fetch = FetchType.LAZY,
cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH, CascadeType.DETACH})
#JoinColumn(name = "diseaseID", referencedColumnName = "id")
private Disease disease;
#Column(name="time")
private String time;
//GETTERS AND SETTERS OMMITED FOR BREVETY. Constructor NOT Needed following the example
}
The id class:
#Embeddable
public class PatientDiseaseId implements Serializable {
private static final long serialVersionUID = 1L;
#Column(name = "nssPatient")
private String patient;
#Column(name = "diseaseID")
private Integer disease;
//getters and setters
//hashCode and equals
}
My main app:
...
List<Diseases> diseases = sesion.createQuery("from Disease").getResultList();
System.out.println("Diseases: ");
for(Disease d: diseases) {
System.out.println(d.getName());
for(PatientDisease pd: e.getPatientDisease()) {
System.out.println(pd.getPatient().toString());
}
}
...
When running the main App I get the exception on line 5 (2nd for loop):
Exception in thread "main" org.hibernate.PropertyAccessException: Could not set field value [1] value by reflection : [class entities.PatientDisease.diseases] setter of entities.PatientDisease.diseases
I have tried some solutions here in Stack Overflow an some others that I found on the Internet, but I can't get them to work and I don't know why

Because you are using #IdClass you don't need to annotate PatientDiseaseId with #Embedded and #Column. And you have to refer to the entities.
This is what it should look like:
public class PatientDiseaseId implements Serializable {
private static final long serialVersionUID = 1L;
private Patient patient;
private Disease disease;
//getters and setters
//hashCode and equals
}

Related

JPA : reference to a generated JoinTable

I have two entities : Product and Aisle.
A product can be in one or many aisles and an aisle can have one or more products.
#Entity
public class Product{
#Id
private Long id;
private String name;
#ManyToMany
#JoinTable(name = "product_aisle",
joinColumns = { #JoinColumn(name = "product_id") },
inverseJoinColumns = { #JoinColumn(name = "aisle_id") })
private Set<Aisle> aisles = new HashSet<>();
/* getters, setters, equals and hashcode */
}
#Entity
public class Aisle{
#Id
private Long id;
private String row;
private String shelf;
#ManyToMany(mappedBy="aisles")
private Set<Product> products = new HashSet<>();
/* getters, setters, equals and hashcode */
}
And I have a last entity : Salesman.
A salesman is responsible for a product in an aisle:
#Entity
public class Salesman{
#Id
private Long id;
private String name;
/* ManyToOne to ProductAisle ?*/
}
Question : How can I reference a Salesman to the auto-created join table (ProductAisle) with a "#ManyToOne" annotation ?
Regards
To represent a Product that is in a specific Aisle you need another entity. This is an example:
#Entity
public class Product{
#Id
private Long id;
private String name;
#OneToMany(mappedBy = "product")
private Set<ProductAisle> productAisle = new HashSet<>;
/* getters, setters, equals and hashcode */
}
#Entity
public class Aisle{
#Id
private Long id;
private String row;
private String shelf;
#OneToMany(mappedBy = "aisle")
private Set<ProductAisle> productAisle = new HashSet<>();
/* getters, setters, equals and hashcode */
}
#Entity
public class ProductAisle{
#Id
private Long id;
#ManyToOne(fetch = FetchType.LAZY)
private Product product;
#ManyToOne(fetch = FetchType.LAZY)
private Aisle aisle;
/* getters, setters, equals and hashcode */
}
And then your Salesman would point to a collection of ProductAisle instances, which maps a product with an aisle:
#Entity
public class Salesman{
#Id
private Long id;
private String name;
#ManyToOne(fetch = FetchType.LAZY)
private Set<ProductAisle> productAisle;
}
Since both Aisle and Product have bi-directional mappings to each other, you can join any of them (or even both of them) to Salesman class, and you do not need to join service table at all.

Hibernate not finding map property

So I am getting the exception:
org.hibernate.AnnotationException: mappedBy reference an unknown target entity property: se.mulander.cosmos.movies.model.Cast.starredIn in se.mulander.cosmos.movies.model.ExtendedMovie.cast
But I can't really figure out why.
The two objects that I am going to map are:
#Entity
#Table(name = "cast")
#ApiModel(description = "A cast member that has been part of making the movie")
public class Cast
{
#JsonIgnore
#ManyToOne(fetch = FetchType.EAGER, cascade = {CascadeType.ALL})
#JoinColumn(name = "movie_id")
public ExtendedMovie starredIn;
}
and
#Entity
#Table(name = "extended_movie")
public class ExtendedMovie
{
#OneToMany(cascade = {CascadeType.ALL}, mappedBy = "starredIn", orphanRemoval = true)
#LazyCollection(LazyCollectionOption.FALSE)
public List<Cast> cast = new ArrayList<>();
}
I have stripped them of some other properties, but in essence this is the relationship that is not working.
So what I don't get is why it says that it is an unknown property, as the property is public and hibernate shouldn't have any problems mapping it.
what is it that I am missing here?
Try something like:
ExtendedMovie :
#Entity
public class ExtendedMovie implements Serializable {
private static final long serialVersionUID = 6771189878622264738L;
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private Long id;
#OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, orphanRemoval = true)
#JoinColumn(name = "cast_id", referencedColumnName = "id")
private Set<Cast> cast;
public Set<Cast> getCast() {
return cast;
}
public void setCast(Set<Cast> cast) {
this.cast= cast;
}
}
Cast:
#Entity
#ApiModel(description = "A cast member that has been part of making the movie")
public class Cast implements Serializable {
private static final long serialVersionUID = 6771189878622265738L;
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private Long id;
//Remove extendedmovie from here
//other property getter and setters here
}
This will establish a one-to-many relationship between ExtendedMovie and Cast.

Unable to find column with logical name hibernate

I have table where to 2 columns join another relations. I was tried join this with #JoinColumns but i getting error Invocation of init method failed; nested exception is org.hibernate.MappingException: Unable to find column with logical name CLASS_ID in table item_sub_class
I looked in h2-console and in table item_sub_class i see column class_id. Look screenshot
This is my relations code from Item class
#Entity
#JsonIgnoreProperties(ignoreUnknown = true)
public class Item implements Serializable {
#Id
private Long id;
private String description;
private String name;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "class_id")
private ItemClass itemClass;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumns({
#JoinColumn(name= "subclass_id",referencedColumnName = "subclass"),
#JoinColumn(name= "class_id",referencedColumnName = "class_id")
})
private ItemSubClass itemSubClass;
private Long sellPrice;
//getter and setters
}
And ItemSubClass
#Entity
public class ItemSubClass implements Serializable {
#Id
#GeneratedValue
private Long id;
#JsonProperty("subclass")
#Column(name = "subclass")
private Long subclass;
private String name;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "class_id")
private ItemClass itemClass;
//getters and setters
}
Some one can explain what is bad and why this relation throwing me error? This is possible to fix this?

Hibernate many to many mapping, join table with PK and extra columns

I've done the necessary changes to my models outlined here. However, I don't know what to put on my join table entity.
Note that my join table has a surrogate key , and two extra columns (date and varchar).
What I've got so far is:
User.java
#Entity
#Table (name = "tbl_bo_gui_user")
#DynamicInsert
#DynamicUpdate
public class User implements Serializable {
private String id;
private String ntName;
private String email;
private Set<GroupUser> groupUsers = new HashSet<GroupUser>(0);
// Constructors and some getters setters omitted
#OneToMany(fetch = FetchType.LAZY, mappedBy = "pk.user", cascade=CascadeType.ALL)
public Set<GroupUser> getGroupUsers() {
return groupUsers;
}
public void setGroupUsers(Set<GroupUser> groupUsers) {
this.groupUsers = groupUsers;
}
}
Group.java
#Entity
#Table (name = "tbl_bo_gui_group")
#DynamicInsert
#DynamicUpdate
public class Group implements Serializable {
private String id;
private String groupName;
private String groupDesc;
private Set<GroupUser> groupUsers = new HashSet<GroupUser>(0);
// Constructors and some getters setters omitted
#OneToMany(fetch = FetchType.LAZY, mappedBy = "pk.group", cascade=CascadeType.ALL)
public Set<GroupUser> getGroupUsers() {
return groupUsers;
}
public void setGroupUsers(Set<GroupUser> groupUsers) {
this.groupUsers = groupUsers;
}
}
The problem is that I don't know what to put on my join table entity. Here it is.
GroupUser.java
#Entity
#Table (name = "tbl_bo_gui_group_user")
#DynamicInsert
#DynamicUpdate
#AssociationOverrides({
#AssociationOverride(name = "pk.user",
joinColumns = #JoinColumn(name = "id")),
#AssociationOverride(name = "pk.group",
joinColumns = #JoinColumn(name = "id")) })
public class GroupUser implements Serializable {
private String id;
private User userId;
private Group groupId;
private Date dateCreated;
private String createdBy;
// constructors and getters and setters for each property
// What now? ? No idea
}
user to group would be a Many-To-Many relation. Now, you are splitting that up into Two One-To-Many Relations. Therefore your Mapping Entity simple needs to complete the Many-To-Many relation, by using Many-To-One:
public class GroupUser implements Serializable {
private String id;
#ManyToOne
private User userId;
#ManyToOne
private Group groupId;
private Date dateCreated;
private String createdBy;
}
See also this example: Mapping many-to-many association table with extra column(s) (The Answer with 38 upvotes)

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