I have this mapping at Person entity:
#ManyToMany(fetch = FetchType.LAZY)
#JoinTable(name = "PersonAddress", joinColumns = { #JoinColumn(name = "personId") }, inverseJoinColumns = {
#JoinColumn(name = "addressId") })
private Set<Address> addresses;
And this at Address entity:
#ManyToMany(mappedBy = "addresses")
private Set<Person> owners;
I tried all cascade options available, but everytime when I save a Person entity it removes all relations with addresses. Is it possible to keep addresses when saving Person?
its not recommended to use CascadeType.REMOVE or CascadeType.ALL in to-many associations, you should implement the removal of child entities yourself.
Here the link it explains with details how to do the implementation.
https://thorben-janssen.com/avoid-cascadetype-delete-many-assocations/
Related
There's an Entity Class 'A' (supposed to be a Person),There's another Entity Class 'B' (supposed to be a Contract).
Entity 'A' has a relation #OneToMany to Class 'B' ( a person can sign alot of contracts). Entity 'B' also has a relation #OneToMany to Class 'A' (a contract can have many person signing it).
In this case, there's gonna be 2 JoinTable in database, but actually they both are somehow the same.
Is there anyway that i make them just using One JoinTable?
tnx for any help!
Looks like a #ManyToMany relation to me...
in class Person
#ManyToMany
#JoinTable(name="PERS_CONTRACTS")
public Set<Contract> getContracts() { return contracts; }
in class Contract
#ManyToMany(mappedBy="contracts")
public Set<Person> getSigners() { return signers; }
By using two #OneToMany there is no JoinTable.
you can use #ManyToMany like this
#ManyToMany
#JoinTable(
name="AB",
joinColumns=#JoinColumn(name="A_ID", referencedColumnName="ID"),
inverseJoinColumns=#JoinColumn(name="B_ID", referencedColumnName="ID"))
private List<B> bS;
Its a kind of Many to Many relationships. So it need just one junction table like person_contract in database. It will contains columns like:
Person_id
Contract_id
where both person_id & contract_id will be a composite unique key.
In hibernate it will be:
1. In Person table
#ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
#JoinTable(name = "person_contract ", joinColumns = {
#JoinColumn(name = "person_id", nullable = false, updatable = false) },
inverseJoinColumns = { #JoinColumn(name = "contract_id",
nullable = false, updatable = false) })
public Set<Contract> contracts;
In Contract table
#ManyToMany(fetch = FetchType.LAZY, mappedBy = "contracts")
public Set<Person> persons;
Situation:
You are complicating things here, the appropriate relationship between your Entities would be ManyToMany, because :
A person can sign many contracts.
And a contract can be signed by many persons.
And one JoinTable in this relationship is sufficient to give you all the requested details:
Who signed a given Contract.
Which Contracts have a Person signed.
Mapping:
So your mapping will be like this:
In your Person class:
#ManyToMany(mappedBy = "persons")
private Set<Contract> contracts= new HashSet<Contract>();
And in your Contract class:
#ManyToMany(cascade = CascadeType.ALL)
#JoinTable(
name = "PERSONS_CONTRACTS",
joinColumns = #JoinColumn(name = "CONTRACT_ID"),
inverseJoinColumns = #JoinColumn(name = "PERSON_ID")
)
private Set<Person> persons= new HashSet<Person>();
You can check this Hibernate Many-to-Many Association Annotations Example for further details.
#Entity
public class Conference {
#ManyToOne
#JoinColumn(name = "host_id")
#JsonManagedReference
private User host;
#ManyToMany(fetch = FetchType.EAGER)
#JoinTable(name = "PARTICIPANT_CONFERENCE",
joinColumns = #JoinColumn(name = "CONFERENCE_ID_FRK"),
inverseJoinColumns = #JoinColumn(name = "PARTICIPANT_ID_FRK")
)
#JsonManagedReference
private Set<User> participants;
}
#Entity
public class User {
#ManyToMany(
targetEntity = Conference.class,
fetch = FetchType.EAGER,
cascade = CascadeType.REMOVE,
mappedBy = "participants"
)
#JsonBackReference
private Set<Conference> conferenceSet;
#OneToMany(
targetEntity = Conference.class,
mappedBy = "host",
cascade = CascadeType.REMOVE,
fetch = FetchType.EAGER
)
#JsonBackReference
private Set<Conference> conferenceHostSet;
}
I used JPA and have a problem that OneTOMany field does not update in JPA.
If I added host in Conference, but User's host set did not update.
So, I tried to update User's host set, too.
Set<Conference> conferences = form.getHost().getConferenceHostSet();
conferences.add(conference);
userRepository.save(form.getHost().setConferenceSet(conferences));
It works well, but User's participant set also updated.
How can I update only host?
You have set cascading to only work for "remove" you need to set it up for all of the actions you want.
I am trying to setup and Many to Many relationship between users and roles. I am mostly using JPA Repositories but I also tried using and EntityManger.
I have the following in my main User object.
#ManyToMany(fetch = FetchType.LAZY)
#JoinTable(name = "svcAuthUserRolev2", schema="dbo", joinColumns = {
#JoinColumn(name = "user_id", updatable=false,insertable=false, nullable = false) },
inverseJoinColumns = { #JoinColumn(name = "role_id",
updatable=false,insertable=false, nullable = false) })
private Set<AuthRoleEntity> roles;
And the following in my Roles object
#ManyToMany(fetch = FetchType.LAZY, mappedBy = "roles")
private Set<AuthUserEntity> users;
No matter what I do if I make changes to the roles on a user when saving they are persisted and this is not what I would like. I want roles on the user object to be read only.
I'm not sure why updateable and insertable are not working, I haven't used those attributes much. One possible solution is to make AuthRoleEntity the owning entity of the many-to-many relationship. Just move the #JoinTable annotation to the AuthRoleEntity and put the mappedBy on the AuthUserEntity.
In my DB I have three table USER, PERMISSION and a junction table USER_PERMISSIONS. As you can see I have clear many-to-many relationship.
And here is the question. I'm using a Hibernate. Is it possible to use only two classes, User and Permissions without creating a junction class UserPermissions? I mean can I use some kind of annotations to include my junction table USER_PERMISSIONS?
Yes you can. You need to use the #JoinTable and #JoinColumn annotation. Example below:
#Entity
#Table(name = "USER")
public class User {
#Id
#Column(name = "ID")
private Long id;
#ManyToMany
#JoinTable(name = "USER_PERMISSIONS",
joinColumns = #JoinColumn(name = "USER_ID", referencedColumnName = "ID"),
inverseJoinColumns = #JoinColumn(name = "PERM_ID", referencedColumnName = "ID"))
private Collection<Permissions> permissions;
A full working example with bidirectionaly many to many can be found in here http://en.wikibooks.org/wiki/Java_Persistence/ManyToMany
I am working with JPA and use Hibernate as a provider to my SQL Server database.
I need a many-to-many self referencing relation that has an additional column or even more additional columns.
That is my current code. I am getting exceptions by Hibernate:
#Entity
public class Person {
#OneToMany(cascade = CascadeType.ALL, mappedBy = "person", fetch = FetchType.EAGER)
private Set<Relation> relations;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "relPerson", fetch = FetchType.EAGER)
private Set<Relation> inverseRelations;
}
#Entity
public class Relation implements Serializable {
#Id
#ManyToOne(cascade = CascadeType.ALL, optional = false, fetch = FetchType.EAGER)
#PrimaryKeyJoinColumn(name = "PersonID", referencedColumnName = "id")
private Person person;
#Id
#ManyToOne(cascade = CascadeType.ALL, optional = false, fetch = FetchType.EAGER)
#PrimaryKeyJoinColumn(name = "RelPersonId", referencedColumnName = "id")
private Person relPerson;
}
During runtime i get an exception from hibernate:
org.hibernate.TransientObjectException: object references an unsaved transient instance
Is there any way to implement this a little bit more intelligent and nicely?? Without getting that exception.
Thanks,
ihrigb
If an object not associated with a Hibernate Session, the object will be Transient.
An instance of Relation list may be Transient(Normally, There is no identifier value for that instance) when you save Person.
Here is better way to understand object state.