I am using Spring JPA + Hibernate and on one of my entities I have added a version column to ensure multiuser update support. The entity have is a Long
with the @Version
annotation.
Now in my service where I inject a standard JpaRepository
I need to annotate the service class with @Transactional
to for another usecase, but just adding the transactional annotation on my service breaks the version handling. Now I can give any value to the version field, and JPA will automatically set the correct value before saving, and therefore not showing the conflict error when trying to update with the wrong version value from the client.
I can't find any doc on this - and why just adding @Transactional to the service class should change the @Version logic?
@Entity
@Table(name="tbl")
public class SomeEntity {
@Id
private Long id;
@Version
private Long rowVersion;
private String value;
}
@Repository
public interface SomeEntityRepository extends JpaRepository<SomeEntity, Long> {}
@Service
@Transactional
public class SomeService {
private final SomeEntityRepository rep;
public void update(Long id, Long rowVersion, String value) {
var entity = rep.findById(id).get();
entity.setValue(value);
entity.setRowVersion(rowVersion);
rep.save(entity);
}
}
You should not have to manually update the version field for such simple scenarios. See here on proper usage of the version-column: https://vladmihalcea.com/jpa-entity-version-property-hibernate/
Completely drop the line entity.setRowVersion(rowVersion);
. If you want to check if a user has the most recent version of a row, you can check if the version number from the database matches expectations, but you should not set it since hibernate appends incrementing the version number to the update-statements it generates.