For testing the @Version annotation, I am using the following setup to manage persistence:
- Spring Boot Starter 1.5.3.RELEASE
- Hibernate 5.2.10.Final
- Spring Data Envers 1.1.3.RELEASE -> Spring Data JPA 1.11.3.RELEASE
Databases tested:
- H2
- PostgreSQL
- MariaDB
- Oracle
The entities are utilizing an @Version annotated field which will be incremented on update. One example entity looks like this:
import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.Table; import javax.persistence.Version; @Entity @Table(name = "\"users\"") public class User { @Id private Long id; private boolean active; @Version @Column(nullable = false) private long version = 0L; // getters/setters (not shown) } The Spring Data JPA based UserRepository provides custom modifying queries besides the CRUD ones:
import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.CrudRepository; public interface UserRepository extends CrudRepository<User, Long> { @Modifying @Query("UPDATE User u SET u.active = false WHERE u.id = ?1") void deactivate(Long id); @Modifying @Query("UPDATE User u SET u.active = false WHERE u.id IN :ids") void deactivateAll(@Param("ids") Long... ids); @Modifying @Query("UPDATE User u SET u.active = false WHERE u.id IN :ids") void deactivateAll(@Param("ids") Iterable<Long> ids); } As the version field is not automatically increased for JPQL/HQL queries, this must be done manually by adjusting the custom queries accordingly.
When trying to use the Hibernate specific (non-JPA conforming) VERSIONED keyword (HQL only) to extend the query
@Modifying @Query("UPDATE VERSIONED User u SET u.active = false WHERE u.id = ?1") void deactivate(Long id); the generated SQL is not valid indepentently of the database tested, resulting in an error looking something like this (schema name is TEST):
Table "USER0_" not found; SQL statement: update "TEST"."users" set user0_."version"=user0_."version"+1, "active"=0 where ("id") IN (select "id" from "HT_users") [42102-194]
So, how can I update the JPA/Hibernate @Version field in a Spring Data JPA @Modifying @Query query?