ORA-02292 when using Hibernate - java

I am trying to implement a delete function but all I get is this ORA-02292 ERROR:
Caused by: java.sql.SQLIntegrityConstraintViolationException: ORA-02292: Integritäts-Constraint (VDMA.FK892DE8B473F40868) verletzt - untergeordneter Datensatz gefunden
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:447)
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:396)
at oracle.jdbc.driver.T4C8Oall.processError(T4C8Oall.java:951)
I have an Entity (MainEntity) that has an n:m relationship with its child entity.
For example: A User can have multiple cars, each car can be driven by different users.
When a User is deleted, I want the associations between the User and the Car to be deleted as well. That´s why I thought I could do the following :
User Entity
#ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
#JoinTable(name = "user_car", joinColumns = {#JoinColumn(name = DATABASE_COLUMN_ID, nullable = false, updatable = false) }, inverseJoinColumns = {#JoinColumn(name = DATABASE_COLUMN_TYPE_ID,
nullable = true, updatable = false) })
private Set<UserCar> userCars;
Car Entity
#ManyToMany(fetch = FetchType.LAZY, mappedBy = "userCars")
private Set<User> users;
The result is :
The tables get created, the data gets persisted - everything works fine.
EXCEPT deleting entries: As soon as I try to delete a User and the User has a car (and therefore a user : car relationship) I do get the errors shown above.
If the user doesn´t have any cars I can delete him without any issues. So the problem must be the constraint in the USER_CAR table.

Clear userCars as well:
user.getUserCars().clear()
This will break the association between user and associated cars (it will delete the corresponding records from the junction table).
Also, you don't want CascadeType.ALL on many-to-many associations, because it implicitly contains CascadeType.REMOVE. Using it means that removal will be cascaded to cars as well, although there are other users who are associated with those cars.

Pls make sure you delete the child records, adding the orphanRemoval will help
#ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL,orphanRemoval=true)
#JoinTable(name = "user_car", joinColumns = {#JoinColumn(name = DATABASE_COLUMN_ID, nullable = false, updatable = false) }, inverseJoinColumns = {#JoinColumn(name = DATABASE_COLUMN_TYPE_ID,
nullable = true, updatable = false) })
private Set userCars;
This will delete all cars assoicated with a user.

Related

How to remove entities from many-to-many hibernate?

I am new to Hibernate and now trying to understand cascade types. I know there mey be a lot of similiar questions, but let's say I have a many-to-many relationship between two tables: state and capital , which creates state_capital which stores two foreign keys of capital and state. If I were to remove a state entity or capital entity, it should remove only either state entity from state table or capital entity from capital table plus the corresponding records in state_capital. Currently If I try to remove a capital entity, it automatically removes the linked state and vice versa. Here's the relationship:
#ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.MERGE)
#JoinTable(name = "state_capital",
joinColumns = {
#JoinColumn(name = "id_state", referencedColumnName = "id_state",
nullable = false, updatable = false)},
inverseJoinColumns = {
#JoinColumn(name = "id_capital", referencedColumnName = "id_capital",
nullable = false, updatable = false)})
private Set<Capital> capitals = new HashSet<>();
#ManyToMany(mappedBy = "capitals", fetch = FetchType.LAZY, cascade = CascadeType.MERGE)
private Set<State> states = new HashSet<>();
What should I do?

How to create a separate table with two mapped fields?

I have a user entity. The user will have a list of friends. I have a problem with creating a batch to this mapped list. I want the board to look like this https://zapodaj.net/41cd4553308d3.png.html The first column is the user ID, and the second column is the friend's ID. I was thinking about doing it
#ElementCollection
#CollectionTable(
name = "users_friends",
joinColumns = #JoinColumn(name = "user_id", nullable = false, updatable = false)
)
#Column(name = "user_friend_id")
private Set<UserEntity> friends;
But ElementCollection does not map the entity and this way goes away.
How can I create such a special table for mapping the user with a list of friends?
This is a many-to-many relationship. JPA supports them no problem https://en.wikibooks.org/wiki/Java_Persistence/ManyToMany
In your case doing
#ManyToMany
#JoinTable(
name="users_friends",
joinColumns=#JoinColumn(name="user_id", referencedColumnName="id"),
inverseJoinColumns=#JoinColumn(name="user_friend_id", referencedColumnName="id"))
private List<UserEntity> friends;
Should do the trick

Hibernate many to many cascade type issue

I am currently using Hibernate in a project and I am having trouble setting up a Many to Many relationship. I think my issue is related to the Cascade types.
The scenario is we have an advert and each advert can have many tags but each tag can be related to many adverts. The ManyToMany annotation of the advert entity is:
#ManyToMany(fetch = FetchType.LAZY, cascade = { CascadeType.MERGE, CascadeType.DETACH, CascadeType.REFRESH })
#JoinTable(name = "adMediaAdvertiserTag",
joinColumns = { #JoinColumn(name = "adMediaId") },
inverseJoinColumns = { #JoinColumn(name = "advertiserTagId") })
And the ManyToMany mapping on the tag entity is:
#ManyToMany(mappedBy = "advertiserTags", fetch = FetchType.LAZY, cascade = { CascadeType.PERSIST, CascadeType.MERGE })
I am seeing two different errors depending on the configuration of the cascade types and if the tag already exists in the database.
If the cascade type on the advert doesn't include PERSIST and the tag doesn't already exist then we get this exception:
TransientObjectException: object references an unsaved transient instance
And if the cascade type on the advert does include PERSIST and the tag does already exist we get:
PersistentObjectException: detached entity passed to persist
The only way I can get this working is not have PERSIST as a cascade type but loop through each tag and save them to the session.
Is this the correct approach? Is there a way that hibernate could automatically handle this for me?
Let me know if this isn't clear or you need any more information.
UPDATE
I am saving the objects using a service that uses the save method the CrudRepository object of the springframework. There is a lot of code so I can't really post it all.
I am currently not calling any merge or persist method for any object I am trying to save. I was under the impression Hibernate would handle that sort of thing for me.
Can you please add the code you are using to persist your Advert and Tag objects. I tested with the following code (which I believe similar to yours) and it works:
User user = new User();
Role role = new Role();
role.setId("TEST_ROLE");
user.getRoles().add(role);
entityManager.persist(user);
User user2 = new User();
user2.getRoles().add(role);
entityManager.persist(user2);
System.out.println(user2.getId());
in User I have:
#ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.PERSIST)
#JoinTable(name = "user_roles",
joinColumns = {#JoinColumn(name = "user_id", nullable = false, updatable = true)},
inverseJoinColumns = {#JoinColumn(name = "role_id", nullable = false, updatable = true)})
protected List<Role> roles = new ArrayList<>();
and in Role I have:
#ManyToMany(mappedBy="roles")
protected List<User> users;

ManyToMany Hibernate annotation

I have this relationship in my database:
And I want to be able to create an order, that contains more products (as well more instances of the same product). Nevertheless I am able to have just one row in the order_has_product table for every single order_id. Moreover, I tried to load the data via lazyloading, but it won't work and it makes the whole app to run really slowly. Here are definitions of the relationship in my entities:
OrderEntity:
#ManyToMany(fetch = FetchType.LAZY)
#Cascade({org.hibernate.annotations.CascadeType.ALL})
#JoinTable(name = "order_has_product",
joinColumns = {#JoinColumn(name = "order_id", nullable = false, updatable = false)},
inverseJoinColumns = {#JoinColumn(name = "product_id", nullable = false, updatable = false)})
private List<ProductEntity> products;
ProductEntity:
#ManyToMany(fetch = FetchType.EAGER, mappedBy = "products")
private List<OrderEntity> orders;
Any idea how to fix lazyloading and to make it possible to have more products in order?

How to enforce orphan deletion on a ManyToOne relationship

#ManyToOne(fetch = LAZY)
#JoinColumn(name = COL_GROUP_ID, nullable = false, insertable = false, updatable = false, referencedColumnName = COL_ID)
#OnDelete(action = CASCADE)
#Cascade(value = DELETE_ORPHAN)
private Group group;
How to enforce orphan deletion on a ManyToOne relationship, the above code snippet worked for us in Hibernate 3.3.x, but post migration to 3.6.5.Final it shows up as a WARNING in the code. is there a equivalent flag like orphanRemoval = true which is applied on a #OneToMany notation?
You can not apply ORPHAN_REMOVAL to MANY_TO_ONE side.
Suppose you have an entity City which has #OneToMany Citizen and on the other side you have #ManyToOne City in Citizen entity. In your scenario removing one citizen will lead to removing the whole city, thus ORPHAN_REMOVAL is only applicable to XXX_TO_Many side

Categories