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:
- there's nothing to delete, make sure the record is there in the db
- 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)
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 JPA expression using deleteBy
This article show how to return deleted records: Spring Data JPA – Derived Delete Methods
And try maybe this code:
List<Student> deleteAllByStudentNameIsNullOrStudentNameAndStudentIdIn(String studentName, List<Integer> studentIds);
But can't be sure that will be work because I don't know your Student's model structure.
Spring Data JPA : Repository DeleteById method not working
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 associated entities eagerly.
Now entity is attempting to be deleted but due to it being still attached and referenced by another entity it would be persisted again, hence the delete is canceled.
Possible solutions:
- Delete using a query and write your own query method for this
- Mark either side of the association lazy
Example:
@Entity
public class Ability {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
private String name;
private String color;
private String image;
@ManyToOne(
fetch = FetchType.LAZY
)
private Subject subject;
@OneToMany(
mappedBy = "ability",
cascade = CascadeType.ALL,
orphanRemoval = true,
fetch = FetchType.LAZY
)
private Set<Technology> technologies;
}
@Repository
public interface AbilityRepository extends CrudRepository<Ability, Integer> {
}
Controller:
abilityRepository.deleteById(abilityId);
Spring Data: "delete by" is supported?
Deprecated answer (Spring Data JPA <=1.6.x):
@Modifying
annotation to the rescue. You will need to provide your custom SQL behaviour though.
public interface UserRepository extends JpaRepository<User, Long> {
@Modifying
@Query("delete from User u where u.firstName = ?1")
void deleteUsersByFirstName(String firstName);
}
Update:
In modern versions of Spring Data JPA (>=1.7.x) query derivation for delete
, remove
and count
operations is accessible.
public interface UserRepository extends CrudRepository<User, Long> {
Long countByFirstName(String firstName);
Long deleteByFirstName(String firstName);
List<User> removeByFirstName(String firstName);
}
Spring Data JPA: deleteById does not delete record from database but derived delete method does
I found the root cause. There was another entity having a reference to Inbox
like this:
@OneToMany(mappedBy = "inbox", cascade = ALL, fetch = FetchType.EAGER)
private Set<Inbox> inbox = new HashSet<>();
The FetchType.EAGER
in combination with the cascade caused the problem, i.e. as soon as the Inbox
was deleted, this reference caused the Inbox
to get "re-persisted". Setting FetchType.LAZY
resolved the problem.
Related Topics
Could Not Reserve Enough Space for Object Heap to Start Jvm
Rjava Install Error "Java_Home Cannot Be Determined from the Registry"
How to Support Both Ipv4 & Ipv6 on Java
How to Create Native Binaries for Your Java App
Connect to SQL Server from Linux via Jdbc Using Integratedsecurity (Windows Authentication)
Arval SQLexception: Fatal: Sorry, Too Many Clients Already in Postgres
Cross-Platform Way to Open a File Using Java 1.5
Java Is Installed, in Listing, But Execution Produces "./Java: No Such File or Directory"
Java Jsch Changing User on Remote MAChine and Execute Command
Tomcat 7: How to Set Initial Heap Size Correctly
Difference Between Using Java.Library.Path and Ld_Library_Path
How to Get the Ip of the Computer on Linux Through Java
How to Kill a Linux Process in Java with Sigkill Process.Destroy() Does Sigterm
Java: How to Get a Class Literal from a Generic Type
Ssl Handshake Alert: Unrecognized_Name Error Since Upgrade to Java 1.7.0
Line-Breaking Widget Layout for Android