I am new to Hibernate. I am working on two entities as follows:
Entity 1 is as follows:
#Entity
#Table(name = "vm_user")
public class VmUser implements Serializable {
private static final long serialVersionUID = 1L;
#Column(name = "created_by")
private String createdBy;
#Column(name = "last_modified_by")
private String lastModifiedBy;
#Column(name = "created_date")
private Instant createdDate;
#Column(name = "last_modified_date")
private Instant lastModifiedDate;
#OneToOne
#JoinColumn(unique = true)
private User user; <--- HOW WILL I DENOTE THIS PRIMARY KEY OF VMUSER ENTITY ?
In the associated table in mysql i.e. vm_user, user_id is both primary key as well as foreign key which refers to id of user table associated with User entity.
Entity 2 is as follows:
#Entity
#Table(name = "my_entity")
public class MyEntity implements Serializable {
private static final long serialVersionUID = 1L;
#Column(name = "created_by")
private String createdBy;
#Column(name = "last_modified_by")
private String lastModifiedBy;
#Column(name = "created_date")
private Instant createdDate;
#Column(name = "last_modified_date")
private Instant lastModifiedDate;
#ManyToOne
private A a;
#OneToOne
#JoinColumn(unique = true)
private B b;
In the associated table in mysql i.e. my_entity, primary key is a combination of id of a and id of b. I am not getting how to denote this in Hibernate entity MyEntity.
Regarding the same, I have gone through a few posts: Hibernate foreign key as part of primary key and JPA & Hibernate - Composite primary key with foreign key, but no getting idea how to do these two ?
The solution is #MapsId
For example
#Entity
#Table(name = "vm_user")
public class VmUser implements Serializable {
#Id
#Column(name = "user_id")
private Integer id;
#MapsId
#OneToOne
private User user;
You can also remove the #JoinColumn(unique = true) because #Id makes it unique already.
public class MyEntityPk implements Serializable {
private Integer aId;
private Integer bId;
// IMPORTANT: Override equals() and hashCode()
}
#IdClass(MyEntityPk.class)
#Entity
#Table(name = "my_entity")
public class MyEntity implements Serializable {
#Id
private Integer aId;
#Id
private Integer bId;
#MapsId("aId")
#ManyToOne
private A a;
#MapsId("bId")
#OneToOne
private B b;
Please find more information in the Hibernate documentation https://docs.jboss.org/hibernate/orm/5.4/userguide/html_single/Hibernate_User_Guide.html#identifiers-derived
You need to use #EmbeddedId and #MapsId ,
#Entity
#Table(name = "vm_user")
public class VmUser implements Serializable {
#Id
#Column(name = "user_id")
private Integer id;
#MapsId("user_id")
#OneToOne
private User user;
}
You can do the same thing for MyEntity as below,
#Embeddable
class BKey {
private int aId;
private int bId;
}
#Entity
#Table(name = "my_entity")
public class MyEntity implements Serializable {
#EmbeddedId
private BKey primaryKey;
#MapsId("aId")
#ManyToOne
private A a;
#MapsId("bId")
#OneToOne
#JoinColumn(unique = true)
private B b;
}
VM Users class
public class VmUser implements Serializable {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private long id;
#OneToOne
#JoinColumn(name="ID")
private Users user;
Users class
public class Users implements Serializable {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private long id;
#OneToOne(mappedBy="user")
private VmUser vmUser;
A class
#Entity
public class A implements Serializable {
#Id
private long id;
#OneToMany(mappedBy="a")
private List<MyEntity> myEntitys;
B Class
#Entity
public class B implements Serializable {
#Id
private long id;
#OneToMany(mappedBy="b")
private List<MyEntity> myEntitys;
MyEntity class
#Entity
public class MyEntity implements Serializable {
private static final long serialVersionUID = 1L;
#EmbeddedId
private MyEntityPK id;
#ManyToOne
#JoinColumn(name="ID1")
private A a;
#ManyToOne
#JoinColumn(name="ID2")
private B b;
MyEntityPK class
#Embeddable
public class MyEntityPK implements Serializable {
#Column(insertable=false, updatable=false)
private long id1;
#Column(insertable=false, updatable=false)
private long id2;
I have a scenerio where one staff can belong to multiple organisation and for each organisation he can have different role. How can i map this in jpa?
Staff.java
public class Staff {
#ManyToMany
#JoinTable(name="STAFF_ORGANIZATION",joinColumns=#JoinColumn(name="staff_id"),inverseJoinColumns=#JoinColumn(name="organization_id"))
private Set<Organization> organizations;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
}
Organization.java
public class Organization {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
#Column
private String OrganizationName;
#ManyToMany(mappedBy="organizations")
private Set<Staff> staff;
}
StaffRoles.java
public class StaffRoles {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
#Column
#Enumerated(EnumType.ORDINAL)
private Roles roles;
public enum Roles {
USER(100), ADMIN(200);
private int values;
Roles(int values) {
this.values = values;
}
public int getValues() {
return values;
}
}
Can anyone please help me in mapping the roles to the staff. So many staff can belong to many organisation and for each organisation he can have different role.
Any help will be highly appreciated!
Im learning JPA and I have an entity class named User that has two lists of another entity, Car, but i cant get it to work with jpa.
The classes have all the getters, setters and constructors needed.
This is my User class:
#Entity
#Table(name = "Users")
public class User implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#Column(unique = true)
private String userName;
#OneToMany(i dont know what goes here as well)
private List<Car> owned;
#OneToMany( ?? )
private List<Car> rented;
This is my Car class:
#Entity
#Table(name = "Cars")
public class Car implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#ManyToOne ( ?? )
private User owner;
My two questions would be:
What annotations go to each #Something to make this work?
After i have all set up, how would i add a new car to an existing user and persist it as well?
Thank you!
I have those two entities :
#Entity
#Table(name = "commande")
public class Commande implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#Column(name = "name")
private String name;
#OneToMany(mappedBy = "commande")
#JsonIgnore
private Set<Piece> pieces = new HashSet<>();
#Entity
#Table(name = "piece")
public class Piece implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#Column(name = "ref")
private String ref;
#ManyToOne
private Commande commande;
When I load the entity Commande, I would like its property pieces not to be empty if there are pieces linked to this commande.
How can I achieve that?
Thank you.
I have below 1-m relationship on entities which Mentor to Students. The mentor has composite primary key which i use as foreign key in student
#Entity
public class Mentor implements Serializable {
private static final long serialVersionUID = 1L;
#Id
private MentorPK id;
private String email;
#OneToMany(mappedBy="mentor")
private Set<Student> students;
public MentorPK getId() {
return id;
}
//getters and setters
}
#Embeddable
public class MentorPK implements Serializable {
private static final long serialVersionUID = 1L;
private String name;
private String add;
//getters and setters
//override equals and hashcode
}
#Entity
public class Student implements Serializable{
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private int id;
private String name;
#ManyToOne
#MapsId("id")
#JoinColumns({
#JoinColumn(name="name_fk", referencedColumnName="name"),
#JoinColumn(name="address_fk", referencedColumnName="address")
})
private Mentor mentor;
//Getters and setters
}
I then persist the above as below but only the mentor is persisted where student table is empty.
How can I persist the mentor with students?
Set<Student> students = new HashSet<Student>();
Student s1 = new Student();
s1.setName("Student 1");
Student s2 = new Student();
s2.setName("Student 2");
students.add(s1);
students.add(s2);
MentorPK mpk = new MentorPK();
mpk.setAddress("C");
mpk.setName("D");
Mentor m = new Mentor();
m.setId(mpk);
m.setEmail("emaill");
m.setStudents(students);
studentManager.saveMentor(m);
Try changing annotation of students field to
#OneToMany(mappedBy="mentor", cascade = CascadeType.PERSIST)
When you use a composite-key, mapped as an Embeddable you need to use #EmbeddedId:
#Entity
public class Mentor {
#EmbeddedId
private MentorPK id;
private String email;
#OneToMany(mappedBy="mentor")
private Set<Student> students;
public MentorPK getId() {
return id;
}
//getters and setters
}
and the Student becomes:
#Entity
public class Student {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private int id;
private String name;
#ManyToOne
#JoinColumns({
#JoinColumn(name="name_fk", referencedColumnName="name"),
#JoinColumn(name="address_fk", referencedColumnName="address")
})
private Mentor mentor;
//Getters and setters
}
The #MapsId is used when both the #Id and the #ManyToOne share the same database columns, which is not your case, since you have a numeric identifier and a composite foreign-key.
You may need to create the reference from Student to Mentor in each Student.
So in your code, after you create m you need to:
s1.setMentor(m);
s2.setMentor(m);
Otherwise Hibernate may not know what to populate columns name_fk and address_fk with.
How about changing:
#OneToMany(mappedBy="mentor")
private Set<Student> students;
to:
#OneToMany(mappedBy="mentor")
private Set<Student> students = new HashSet();
or
#OneToMany(cascade=CascadeType.ALL)
#JoinColumn(name="student_id")
#org.hibernate.annotations.IndexColumn(name="idx")
private Set<Student> students = new HashSet();
also try not to skip
= new HashSet();
part
As I understand your request, you would like to have the Mentor be the owner of the relationship. You do not obtain this with the line #OneToMany(mappedBy="mentor"). This actually puts the Student as the owner of the relation.
I have tested this domain model and did a few modifications to the annotations in order to have the test code work as you expect.
Student
public class Student implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy= GenerationType.AUTO)
private int id;
private String name;
#ManyToOne
#JoinColumns({
#JoinColumn(name="name_fk", referencedColumnName="name", insertable = false, updatable = false),
#JoinColumn(name="address_fk", referencedColumnName="address", insertable = false, updatable = false )
})
private Mentor mentor;
//setters and getters
}
Mentor
public class Mentor implements Serializable {
private static final long serialVersionUID = 1L;
#Id
private MentorPK id;
private String email;
#OneToMany(cascade = CascadeType.ALL)
#JoinColumns({
#JoinColumn(name="name_fk", referencedColumnName="name"),
#JoinColumn(name="address_fk", referencedColumnName="address")
})
private Set<Student> students;
//setters and getters
}
It even works without doing:s1.setMentor(m);s2.setMentor(m);. I did not expect it but it seems that hibernate is dealing with this.
A related article is here.
Attention: drop the database tables after you change the annotations in order to allow hibernate to recreate the tables.