I have problem with hibernate and #ManyToMany annotation. Please look at two entities classes:
Company entity:
#ManyToMany
#JoinTable(name="company_user_tab",
joinColumns={#JoinColumn(name="company_id")},
inverseJoinColumns={#JoinColumn(name="user_id")})
private Set<User> users = new HashSet<User>();
... getters and setters
User entity:
#ManyToMany(mappedBy="users")
private Set<Company> companies = new HashSet<Company>();
... getters and setters
Scenario:
I created first user and first company and connect them correctly.
Problem occured when I create new user and try update existing company with new user. I receive database error on company_user_tab: "duplicate key value violates unique constraint"
It's look like hibernate insert again to join table first user witch is correctly associated with company.
How I update object?
entityManager.merge(object);
Of course I add before user to company and company to user for example:
user.getCompanies().add(company);
company.getUsers().add(user);
Thanks for advice.
try this code:
#ManyToMany(cascade= {CaseCadeType.ALL})
#JoinTable(
name = "company_user_tab",
joinColumns = { #JoinColumn(name="company_id") },
inverseJoinColumns = { #JoinColumn(name="user_id") }
)
private Set<User> users = new HashSet<User>();
// setters and getters
Related
Hi I am new to Hibernate and trying to build a Rest APP.
I have 3 tables in the database as shown in the above image.
USERS table has ManyToMany relation with GROUPS table and USER_GROUP is an association table.
I am using ORM, Hibernate and CurdRepository.
I am able to insert into users table and group table with save() method of CurdRepository.
Now I am trying to add a row in GROUPS table and USER_GROUP table only. Can anyone lead me to the right direction?
For example:
I want to add an groupid to GROUPS table and then associate it with an user id
Let's say I want to insert (10) groupid in GROUPS and (14,10) in USER_GROUP table.
Is it doable with ORM, if yes how?
Thanks in advance
To use existing connecting table, USE_GROUP, User entity will be like following .
#Entity
public class Users {
#Id
private Integer userid;
private String password;
#ManyToMany(cascade = { CascadeType.MERGE, CascadeType.PERSIST })
#JoinTable(name = "USER_GROUP", joinColumns = { #JoinColumn(name = "USERID") },
inverseJoinColumns = { #JoinColumn(name = "GROUPID") })
private Set<Groups> groups;
// Getter, Setter
}
And then client code, add new User and Group, will be something like below.
User user = new User()
// set password , etc
Set<Groups> groups = new HashSet<>();
Group group = new Group();
// set
groups.add(group);
user.setGroups(groups);
userRepository.save(user);
There are many articles online about exactly this model to showcase how to use Hibernate. Here is one article I quickly found by googling for "hibernate user group example": https://www.codejava.net/frameworks/hibernate/hibernate-many-to-many-association-annotations-example
I have a many to many relationship with Users and Roles. The user is the owner of the relationship and has CascadeType.ALL. When i'm seeding the database, I first create users, create roles and assign the roles to the users. Afterwards I save all users with the repository.
I would imagine since I'm saving users, the roles also get saved in the database because of the cascadetype but the error I'm getting is the one mentioned in the title.
User:
#Entity
public class User {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private Long id;
#ManyToMany(cascade = CascadeType.ALL)
#JoinTable(
name = "users_roles",
joinColumns = #JoinColumn(
name = "user_id", referencedColumnName = "id"),
inverseJoinColumns = #JoinColumn(
name = "role_id", referencedColumnName = "id"))
private List<Role> roles;
Role:
#Entity
public class Role {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#JsonIgnore
#ManyToMany
private List<User> users;
The code used for seeding the database:
User user1= new User();
User user2= new User();
Role role1 = new Role();
Role role2 = new Role();
user1.addRole(role1);
user2.addRole(role1);
user2.addRole(role2);
role1.addUser(user1);
role1.addUser(user2);
role2.addUser(user2);
userRepository.save(user1);
userRepository.save(user2);
Any help is appreciated!
EDIT: I found that the problem only occurs when I add multiple roles to the same user and have updated the code.
Your Cascading here is wrong. Having Cascade.ALL on a many to many collection does not make sense exactly because you can have Roles that are shared across users.
What hibernate is trying to tell you is that you already have a role that has associated ID and the you are trying to invoke persist on the same role.
You need to figure out how to manage your roles. You have two options:
Remove the cascading.
Reasign the managed roles to your user2, so that you are not using the detached one.
Personaly I would remove the Cascade.ALL. IMO it is wrong.
This example works for me, no exception there. Please share more info: hibernate version, database and the actual code that you're running.
I have table Animal with OneToMany mapping to table EventAnimal:
#OneToMany(mappedBy = "animal")
public Set<EventAnimal> getEventAnimals() {
return eventAnimals;
}
Table EventAnimal looks like this
#Entity
#Table(name = "eventAnimal")
public class EventAnimal {
#Id
int id;
#ManyToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "userEvent_id")
UserEvent userEvent;
#ManyToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "animal_id", nullable=false)
Animal animal;
#ManyToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "eventAnimalClass_id")
EventAnimalClass eventAnimalClass;
}
When I add Event animal to animal and save animal, database is not being updated:
//Create EventAnimal object, set properties
eventAnimal.setUserEvent(newEvent);
eventAnimal.setAnimal(animal);
animal.getEventAnimals().add(eventAnimal);
animalPersistenceService.saveAnimal(animal);
What am I doing wrong?
When I try inserting Event animal, like eventAnimalDao.insert(eventAnimal);
instead of
animalPersistenceService.saveAnimal(animal);
I get exception that "animal_id" does not have default value even though I set it.
What is your ID generation strategy? Are you generating the ids by yourself or you will leave this to the DB? If it will be database put:
#GeneratedValue(strategy=GenerationType.AUTO)
You may want to update the key to Integer instead of int too but don`t think this is the problem.
Also if you want to add event in animal and expect to persist it update your mapping to:
#OneToMany(mappedBy = "animal", cascade = CascadeType.ALL)
I have table Company with OneToMany mapping to table Customer:
//bi-directional many-to-one association to Customer
#OneToMany(mappedBy="company")
private Set<Customer> customer;
I have mapped from tis format:
//bi-directional many-to-one association to Company
#ManyToOne
#JoinColumn(name="company_id")
private Company company;
I have use this code, Sucessfully add,edit and delete function is working.
Add function :
Customer customer = new Customer();
Company company = new Company();
company.setCompanyId(intCompanyId);
customer.setCompany(company);
I resolved the problem. It was rather silly mistake - script didn't remove one foreign key from table and I didn't care to look into SQL table.
I have two entities, User and Event. Each event can have multiple users associated with it, so its a one to many between Event and User.
The way its being stored in the database, is that I have 3 tables, user, event, and event_user. event_user contains 3 fields, id, eventId, userId. So I can do a query like select userId from event_user where eventId = ? to get all the users which are associated with the event.
My question is, how can I map this relationship between the events and users in Hibernate, to get it to auto save/load the users associated with the event? I want to have the following field in the Event class:
Set<User> users = new HashSet<>();
and have hibernate auto load / save the users to this set.
How can I map this (using annotations)?
Use the #ManyToMany annotation.
class Event{
#ManyToMany(cascade=CascadeType.ALL)
#JoinTable(name = "EVENT_USER",
joinColumns = { #JoinColumn(name = "EVENT_ID") },
inverseJoinColumns = { #JoinColumn(name = "USER_ID") })
private Set<Users> users = new HashSet<Users>();
}
For more information on many to many associations in JPA check out this video tutorial at my blog.
Hibernate doc on the Bidirectional mapping using annotations should help
Basically you need to do something like this
#Entity
public class User implements Serializable {
#ManyToMany(
targetEntity=org.hibernate.test.metadata.manytomany.Event.class,
cascade={CascadeType.ALL}
)
#JoinTable(
name="USER_EVENT",
joinColumns=#JoinColumn(name="USER_ID"),
inverseJoinColumns=#JoinColumn(name="EVENT_ID")
)
public Set<Event> getEvents() {
return events;
}
...
}
#Entity
public class Event implements Serializable {
#ManyToMany(
cascade = {CascadeType.ALL},
mappedBy = "events",
targetEntity = User.class
)
public Set<User> getUsers() {
return users;
}
}
I have two persistence entity: User and UserDetail. They have one-to-one relationship. I use hibernate annotations. But I am getting in my database several objects of user information for one same user. Apparently my knowledge of Hibernate annotations are not so good to solve this problem.
User class:
#Entity
#Table(name = "USER")
public class User {
#Id
#GeneratedValue
#Column(name = "ID")
private Long id;
#Column(name = "NAME")
private String name;
#Column(name = "PASSWORD")
private String password;
#OneToOne(mappedBy = "user", cascade = CascadeType.ALL)
private UserDetail userDetail;
// setters and getters
}
UserDetail class:
#Entity
#Table(name = "USER_DETAIL")
public class UserDetail {
#OneToOne
#JoinColumn(name = "USER_ID")
private User user;
// other fields
}
I use this in my code as follows:
UserDetail userDetail = new UserDetail();
userDetail.setInfo(info);
userDetail.setUser(seventhUser);
hibernateTemplate.saveOrUpdate(userDetail);
And everything works properly. Here's what my table USER_DETAIL:
But when I try to change user information, I get an incorrect behavior. I get following table after I again set user information:
UserDetail newUserDetail = new UserDetail();
newUserDetail.setInfo(newInfo);
newUserDetail.setUser(seventhUser);
hibernateTemplate.saveOrUpdate(newUserDetail);
Why the same two objects of information correspond to one user?? I have One-To-One relationship. How can I avoid this? What am I doing wrong?
If you want to modify an existing UserDetail, then you must set its ID, or get it from the session and modify it. Else, Hibernate thinks it's a new one that must be saved, since it doesn't have any ID.
UserDetail existingUserDetail = session.get(UserDetail.class, theUserDetailId);
existingUserDetail.setInfo(newInfo);
To make sure you don't save two UserDetail instances for the same user, you should add a unique constraint on the USER_ID column of the UserDetail database table.