Delete Not Working in Hibernate/Spring Data

Spring JPA repository delete method doesn't work

The "problem" is your mapping. Your collection is retrieved eagerly. Now why would that be an issue. The deleteById in Spring Data JPA first does a findById which in your case loads the Bar and the Foo and eagerly the collection inside Foo.

Now the Bar is attempted to be deleted but due to it being still attached and referenced by another entity it would be persisted again, hence the delete is cancelled.

To solve you have 3 options

  1. Delete using a query and write your own query method for this
  2. Properly remove the Bar from Foo, set the relation to null and then persist Foo or delete Bar.
  3. Mark either side of the assocation lazy (this still can fail due to 1).

Either of these will work. The first one because it bypasses the JPA caching mechanisms, the second because now the association has been cut. The third can work but if the objects have already been loaded run into the same issue as 1.

Delete not working in Hibernate / Spring Data

What you want is not quite possible. When you call wheelRepository.delete(wheel) you essentially ask to remove the wheel from the database. But this cannot remove an instance wheel from all other places in your running application where this instance is now referenced. Such as car.wheels. So this instance will continue to live. Thus, it cannot be removed from the database. If you want to remove a wheel you have first to remove it from all cars that use that wheel. Exactly like in real life :)

Spring Data problem - derived delete doesn't work

tl;dr

It's all in the reference documentation. That's the way JPA works. (Me rubbing hands washing.)

Details

The two methods do two different things: Long deleteBySystemId(String systemId); loads the entity by the given constraints and ends up issuing EntityManager.delete(…) which the persistence provider is about to delay until transaction commits. I.e. code following that call is not guaranteed that the changes have already been synced to the database. That in turn is due to JPA allowing its implementations to actually do just that. Unfortunately that's nothing Spring Data can fix on top of that. (More rubbing, more washing, plus a bit of soap.)

The reference documentation justifies that behavior with the need for the EntityManager (again a JPA abstraction, not something Spring Data has anything to do with) to trigger lifecycle events like @PreDelete etc. which users expect to fire.

The second method declaring a modifying query manually is declaring a query to be executed in the database, which means that entity lifecycles do not fire as the entities do not get materialized upfront.

However the Spring developers were quick to wash their hands and write it off as a Hibernate problem so no solution or explanation to be found there.

There's detailed explanation why it works the way it works in the comments to the ticket. There are solutions provided even. Workarounds and suggestions to bring this up with the part of the stack that has control over this behavior. (Shuts faucet, reaches for a towel.)

Spring Data delete function not deleting records

If you need to use the given methods provided by CrudRepository, use the JpaRepository.deleteInBatch(). This solves the problem.

orphanremoval doesn't delete if add and remove occur without flush

You expect some transactions being finished or created, but in reality they didn't. That is why you see this behavior.

  1. @DataJpaTest places on every method separate transaction (which will be rolled back anyway by default BTW);
  2. That is why you can use JpaRepository -- it does not create the transaction itself (in the opposite to CrudRepository), but there is underlying one;
  3. If JpaRepository used @Transactional(REQUIRED_NEW), you'd may remove flush;

Answer to your last question. If you put those operations in the separate @Transactional methods, it will work exactly in the same way, because there is underlying transaction in the test created by the @DataJpaTest -- hibernate usually flushes at the very end of the method. You'd have to use @Transactional(REQUIRED_NEW).

Spring data jpa deleteBy query not working

Is the delete not working or not working as how you'd expect? Typically an entity has to be managed before it can be deleted, so a JPA provider (hibernate in your case) will load (the query you see) the entity first, then issue the delete.

If you're only seeing the query, but no corresponding delete, then some possibilities are:

  1. there's nothing to delete, make sure the record is there in the db
  2. the delete needs to be part of a transaction. I believe the Spring data CRUD ops are transactional by default, if not just make sure whatever is calling deleteByEmailAddress is transactional

Note: you can avoid the select when removing an entity using a modifying query delete, example below:

// NOTE: you have return void
@Modifying
@Transactional
@Query(value="delete from Contact c where c.emailAddress = ?1")
void deleteByEmailAddress(String emailAddress)


Related Topics



Leave a reply



Submit