Reputation: 1906
I'm writing some hql queries using the @Query
annotation in a spring data jpa repository. I know that I can use the methods from the repository interface, but for learning purpose, I'm writing them explicitly.
Here is my Main class
@SpringBootApplication
public class Main implements CommandLineRunner {
@Autowired
PersonRepository personRepository;
public static void main( String[] args ) {
SpringApplication.run(Main.class, args);
}
/**
* if we delete the transactional annotation-> we get an exception
*/
@Override
@Transactional
public void run( String... args ) throws Exception {
saveOperation();
deleteOperationUsingHql();
}
private void saveOperation() {
Person p = new Person("jean", LocalDate.of(1977,12,12));
personRepository.save(p);
}
private void deleteOperationUsingHql() {
personRepository.deleteUsingHql(1L);
personRepository.flush();
Optional<Person> p = personRepository.findById(1L);
if (p.isPresent()){
System.out.println("still present");
}
}
}
My personRepository interface
public interface PersonRepository extends JpaRepository<Person, Long> {
@Query(value = "select p from Person p where p.id=?1")
List<Person> getById( Long id);
@Modifying
@Query(value = "delete from Person p where p.id=:id")
void deleteUsingHql( Long id );
}
The person class
@Entity
@Table(name = "Person")
public class Person {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private LocalDate date;
// constructors,getters...omitted for brievety
}
everything is running well, but for the deleteOperationUsingHql()
, even If I deleted the person from the database and even if I flush the modification to the database, the person with id=1
is still returned by the findById(1L)
method. What should I do for making the findById(1L)
returning an empty Optional.
My second question is about the @Transactional
annotation, I know how it works in details, but I don't know why if we delete it, We get the following exception
Caused by: javax.persistence.TransactionRequiredException: Executing an update/delete query
Could someone explains why I'm getting this exception when @Transactional
is removed.
Upvotes: 1
Views: 2622
Reputation: 691933
even If I deleted the person from the database and even if I flush the modification to the database, the person with id=1 is still returned by the findById(1L) method
That's normal, because you use a query to delete the person, instead of actually using the repository (and thus the EntityManager) delete method. Queries bypass the session cache completely, so Hibernate has no idea that this person has been deleted, and returns the instance in its cache. Solution: don't use a query. Alternate solution, clear the cache after deleting (for example by setting the clearAutomatically
flag of the Modifying
annotation to true).
Could someone explains why I'm getting this exception when @Transactional is removed.
Because when @Transactional
is removed, there is no transaction being started by SPring before executing the method, and as you can see from the error message, delete queries must be executed inside a transaction.
Upvotes: 3