We're using Spring Data Jpa, Spring boot for our application. The problem arises when we're trying to introduce concurrency solution into our project using @Version annotation on @Entity class.
@Annotation is working, because log shows that update is executed with version = ? clause , but still it does not throw any exception and target entity goes updated. Where can be the problem?
It seems like somehow entity's version is cached in hibernate?
According question identification as possible duplicate, I would like to address next explanation for the review. I don't want to do manual version management. I want spring to manage them. In my case I suppose that some of application configuration misbehave. As I mentioned in comment my suspicious eye directed on Hibernate, which caches object with old version (v1) number. Then when someone update entity in db (making v2), on select entity version is old (v1), so no exception is thrown.
Is there any special config for version control in case when app uses manual config for spring beans? I mean there is no autoConfig annotation.
Some code snippets as example:
@Entity
@Table(name="some_object")
@SequenceGenerator(name="seq_some_object", sequenceName="seq_survey")
@Getter
@Setter
@ToString
@NoArgConstructor
@EqualsAndHashCode
public class SomeObject implements Serializable{
@Id
@GeneratedValue(strategy = GenerationType.AUTO, generator = "seq_some_object")
private Long id;
@Version
private Long version = -1L;
private Long testValue = -1L;
}
@Service
public class SomeObjectServiceImpl implements SomeObjectService{
@Autowired
private SomeObjectRepository someObjectRepository;
@Override
@Transactional
public void update(SomeObject someObject) {
Long version = someObjectRepository.getVersion(someObject.getId());
if(version != someObject.getVersion())
throw new SomeObjectOldVersionException();
someObject.setVersion(someObject.getVersion() + 1);
someObjectRepositoryRepository.saveAndFlush(someObject);
}
}
TEST QUERY:
public interface SomeObjectRepository extends jpaRepository<SomeObject, Long>{
@Lock(LockModeType.READ)
@Query("SELECT s.version FROM SomeObject s WHERE s.id = :id")
Long getVersion(@Param("id") Long id);
}
Further explanation: In example above if I operate with version field. Lets assume that version is same as defined. When I featch object with 2 different users and then one of them updates entity, version value increments in database (equal to 0 right now). Then when second one trying to do same thing version value is wrong, meaning that getVersion(Long id) method from repository return value is -1L;
Let's assume now that I do everything exactly same way, but with testValue field. In that case I'm getting correct version of object and everything looks fine.
I suppose that current issue somehow connected with this one. Pls take a look at Spring 4 MVC updates entity before modifying post request
SOLUTION
Description of the problem background and solution is in this topic. Spring 4 MVC updates entity before modifying post request