I have User class and Country class with respective tables. Country table data is fixed.
I make a mapping table User_Country(userid, countryid) and following mapping in User class
#OneToMany(fetch=FetchType.EAGER)
#JoinTable(name = "User_Country", joinColumns ={
#JoinColumn(name = "userid")
}, inverseJoinColumns = {
#JoinColumn(name = "COUNTRYID")
})
private Set<Country> country;
When i persist User class it successfully persist user data and insert data in mapping table(user_country). This is exactly i want but when i find User by using hql('from user where userid=?') and then try to get country maaping (which is stored in mapping tableuser_country). I didn't get any data from user_country. How can i write annotation so that it gets data from user_country. If i put cascade then it update country table(which is fixed) which i don't want.
I am not too sure but, try with inverse="false", as that might help.
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 tables Tags, Blog and BlogTags.
With using many-to-many I would like a blog to have many tags (as objects with id, name).
In front end, when I add tags, they are created with name only and id of null so when I save the blog, new tag gets created every time as it auto increments Tag, what I would like is for the Tag to be merged with blog if said tag already exists. The idea is so that I can click on any give tag and get the all the blogs associated with it.
So object sent to backend would be:
{id: null,
name: 'name'
,.....
tags: [{id: null, name: 'name},{id: null, name: 'name}]}
Any help is appreciated.
#Data
#Entity
public class Tag {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
#ManyToMany(mappedBy = "tags", fetch = FetchType.LAZY, cascade = CascadeType.MERGE)
private List<BlogPost> blogPosts;
}
public class BlogPost {
//other data
#ManyToMany(fetch = FetchType.LAZY, cascade = {CascadeType.MERGE, CascadeType.PERSIST})
#JoinTable(
name = "blog_post_tag",
joinColumns = {#JoinColumn(name = "blog_post_id")},
inverseJoinColumns = {#JoinColumn(name = "tag_id")})
private List<Tag> tags;
}
I went with #ElementCollection without many-to-many annotations and it works.
Not having the TAG ID is the normal behavior to register.
You can try, which for me is the best option, to load a master table from which you get the id if it already exists and with a find (depending on the technology used) at the moment the user inserts the check if tag. exists to load the id, get the DB entity and set the relationship of the tag entity to the post
Or before saving the entity, post iterate over all the tags making a query by tag to see if it exists and assign it.
In essence it is the same but with the first option we only make a query to DB
I have a Hibernate ManyToMany mapping between data table and user table linked by data_user table. Now I want to update the data table to add one more user to the data. How to update link table(data_user) to add one more entry for the new user?
I, first updated the user collection: data.getUsers().add(user), and then in the DAO layer tried session.saveOrUpdate(data). But it deleted everything in the link table.
Update1: data_user(iddata_user,iddataroom,iduser) was manually created in the db.
Update2 : implemented Hashcode and equals for Data and User.
Update 3: I changed to CascadeType.MERGE. This updates my link table. Also, I am never going to update User table from Data which hibernate was trying when CascadeType was ALL.
org.hibernate.NonUniqueObjectException: a different object with the
same identifier value was already associated with the session.
PS: I am very new to hibernate.
public class Data {
private int dataId;
private Data parentData;
private Set<User> users;
#ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
#JoinTable(name = "data_user", joinColumns = { #JoinColumn(name = "iddata") },
inverseJoinColumns = { #JoinColumn(name = "iduser") })
public Set<User> getUsers() {
return users;
}
...
}
You need to override equals() and hashCode() in your entities or you are going to run into issues sooner or latter see this for more details.
If your problem still exists after overriding equals() and hashCode() you may add a mappedBy on the other side of the relation see this for more details.
I am having following problem. I have a user entity that has a many to many relationship with other user entities. Hence I want to make a self-join with manytomany annotation. This relation is based on already existing table that is used across the system so I cannot make changes to the DB at all. So we have 2 tables User(Id, ShortName) and UserLink(ParentId, ChildId).
The annotation of ID is assigned to ShortName, but the actual keys in both User and UserLink are ID from User and ParentId and ChildId from UserLink.
I am trying to handle this the following way from the User entity:
#Id
#Column(name = "ShortName")
private String shortName;
#Column(name = "Id")
private long id;
#ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
#JoinTable(name = "UserLink",
joinColumns = { #JoinColumn(name = "ParentId", referencedColumnName = "Id") },
inverseJoinColumns = { #JoinColumn(name = "ChildId", referencedColumnName = "Id") })
private Collection<UserEntity> children;
Since the key in the User entity is on the ShortName field, I have to specify the "Id" as referenced column name param. If I don't do that, it takes the ShortName as the key and doesn't fetch any data.
When I try to do this the way I showed above, I get the following exception:
Caused by: org.hibernate.MappingException: Duplicate property mapping of **_entity_UserEntity_children found in **.entity.UserEntity
at org.hibernate.mapping.PersistentClass.checkPropertyDuplication(PersistentClass.java:486)
at org.hibernate.mapping.PersistentClass.validate(PersistentClass.java:476)
at org.hibernate.mapping.RootClass.validate(RootClass.java:268)
at org.hibernate.cfg.Configuration.validate(Configuration.java:1287)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1729)
at org.hibernate.ejb.EntityManagerFactoryImpl.<init>(EntityManagerFactoryImpl.java:84)
at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:904)
... 81 more
Do you have any idea how this could be fixed? One idea is that I could change the #Id in the entity and move it to the Id property that is used for joins, but this would need a lot of effort to rewrite bad existing code.
Anyway, is it possible to make a self-join manytomany on columns that are not keys?
Cheers
Adam
I'm trying to save an item in the database which has manytoone relation with the Librarian(which is a subclass of user). The code below creates a table *librarian_item* which has librarian_id and item_id as attributes. When I try to save the data, the program prints no *librarian_id*. The librarian is set on the item but still it throws error.
#ManyToOne(cascade=CascadeType.PERSIST, fetch = FetchType.LAZY)
#JoinTable(name = "librarian_item",
joinColumns = #JoinColumn(name = "item_id"),
inverseJoinColumns = #JoinColumn(name = "librarian_id"))
#NotNull
#Valid
private User librarian;
The Item class has following code for Hibernate:
#OneToMany(cascade=CascadeType.PERSIST)
#JoinTable(name = "librarian_item",
joinColumns = #JoinColumn(name="librarian_id"),
inverseJoinColumns = #JoinColumn(name="item_id"))
#Valid
public Collection<Item> getItemList() {
return itemList;
}
As Librarian is a subclass of User and I have used discriminator to identify each type of User in the user table, *librarian_id* is necessarily a *user_id*.
I changed my code as it is discussed here. Apparently, the new approach doesn't create a new table. A new column is created in the table which references to another table to establish a relationship.