Skip to content

Commit 7abb5e7

Browse files
committed
Test deleting dirty detached and managed versioned entity
1 parent a3cf247 commit 7abb5e7

File tree

2 files changed

+72
-0
lines changed

2 files changed

+72
-0
lines changed

spring-data-jpa/src/test/java/org/springframework/data/jpa/domain/sample/VersionedUser.java

+11
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222

2323
/**
2424
* @author Oliver Gierke
25+
* @author Yanming Zhou
2526
*/
2627
@Entity
2728
public class VersionedUser {
@@ -33,6 +34,8 @@ public class VersionedUser {
3334
@Version
3435
private Long version;
3536

37+
private String name;
38+
3639
public Long getId() {
3740
return id;
3841
}
@@ -48,4 +51,12 @@ public Long getVersion() {
4851
public void setVersion(Long version) {
4952
this.version = version;
5053
}
54+
55+
public String getName() {
56+
return name;
57+
}
58+
59+
public void setName(String name) {
60+
this.name = name;
61+
}
5162
}

spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/support/JpaRepositoryTests.java

+61
Original file line numberDiff line numberDiff line change
@@ -18,22 +18,30 @@
1818
import static org.assertj.core.api.Assertions.*;
1919

2020
import jakarta.persistence.EntityManager;
21+
import jakarta.persistence.OptimisticLockException;
2122
import jakarta.persistence.PersistenceContext;
2223

2324
import java.util.Arrays;
2425
import java.util.Iterator;
2526
import java.util.List;
27+
import java.util.Map;
28+
29+
import javax.sql.DataSource;
2630

2731
import org.jetbrains.annotations.NotNull;
2832
import org.junit.jupiter.api.BeforeEach;
2933
import org.junit.jupiter.api.Test;
3034
import org.junit.jupiter.api.extension.ExtendWith;
35+
import org.springframework.beans.factory.annotation.Autowired;
3136
import org.springframework.data.jpa.domain.sample.PersistableWithIdClass;
3237
import org.springframework.data.jpa.domain.sample.PersistableWithIdClassPK;
3338
import org.springframework.data.jpa.domain.sample.SampleEntity;
3439
import org.springframework.data.jpa.domain.sample.SampleEntityPK;
40+
import org.springframework.data.jpa.domain.sample.VersionedUser;
3541
import org.springframework.data.jpa.repository.JpaRepository;
3642
import org.springframework.data.repository.CrudRepository;
43+
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations;
44+
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
3745
import org.springframework.test.context.ContextConfiguration;
3846
import org.springframework.test.context.junit.jupiter.SpringExtension;
3947
import org.springframework.transaction.annotation.Transactional;
@@ -46,21 +54,28 @@
4654
* @author Jens Schauder
4755
* @author Greg Turnquist
4856
* @author Krzysztof Krason
57+
* @author Yanming Zhou
4958
*/
5059
@ExtendWith(SpringExtension.class)
5160
@ContextConfiguration({ "classpath:infrastructure.xml" })
5261
@Transactional
5362
class JpaRepositoryTests {
5463

64+
@Autowired DataSource dataSource;
65+
5566
@PersistenceContext EntityManager em;
5667

5768
private JpaRepository<SampleEntity, SampleEntityPK> repository;
5869
private CrudRepository<PersistableWithIdClass, PersistableWithIdClassPK> idClassRepository;
70+
private JpaRepository<VersionedUser, Long> versionedUserRepository;
71+
private NamedParameterJdbcOperations jdbcOperations;
5972

6073
@BeforeEach
6174
void setUp() {
6275
repository = new JpaRepositoryFactory(em).getRepository(SampleEntityRepository.class);
6376
idClassRepository = new JpaRepositoryFactory(em).getRepository(SampleWithIdClassRepository.class);
77+
versionedUserRepository = new JpaRepositoryFactory(em).getRepository(VersionedUserRepository.class);
78+
jdbcOperations = new NamedParameterJdbcTemplate(dataSource);
6479
}
6580

6681
@Test
@@ -162,6 +177,48 @@ public Iterator<SampleEntityPK> iterator() {
162177
assertThat(repository.findAll()).containsExactly(two);
163178
}
164179

180+
@Test
181+
void deleteDirtyDetachedVersionedEntityShouldRaiseOptimisticLockException() {
182+
183+
VersionedUser entity = new VersionedUser();
184+
entity.setName("name");
185+
versionedUserRepository.save(entity);
186+
versionedUserRepository.flush();
187+
em.detach(entity);
188+
189+
versionedUserRepository.findById(entity.getId()).ifPresent(u -> {
190+
u.setName("new name");
191+
versionedUserRepository.flush();
192+
});
193+
194+
assertThatExceptionOfType(OptimisticLockException.class).isThrownBy(() -> {
195+
versionedUserRepository.delete(entity);
196+
versionedUserRepository.flush();
197+
});
198+
199+
jdbcOperations.update("delete from VersionedUser", Map.of());
200+
}
201+
202+
@Test
203+
void deleteDirtyManagedVersionedEntityShouldRaiseOptimisticLockException() {
204+
205+
VersionedUser entity = new VersionedUser();
206+
entity.setName("name");
207+
versionedUserRepository.save(entity);
208+
versionedUserRepository.flush();
209+
210+
211+
assertThat(jdbcOperations.update("update VersionedUser set version=version+1 where id=:id",
212+
Map.of("id", entity.getId()))).isEqualTo(1);
213+
214+
assertThatExceptionOfType(OptimisticLockException.class).isThrownBy(() -> {
215+
versionedUserRepository.delete(entity);
216+
versionedUserRepository.flush();
217+
});
218+
219+
jdbcOperations.update("delete from VersionedUser", Map.of());
220+
}
221+
165222
private interface SampleEntityRepository extends JpaRepository<SampleEntity, SampleEntityPK> {
166223

167224
}
@@ -170,4 +227,8 @@ private interface SampleWithIdClassRepository
170227
extends CrudRepository<PersistableWithIdClass, PersistableWithIdClassPK> {
171228

172229
}
230+
231+
private interface VersionedUserRepository extends JpaRepository<VersionedUser, Long> {
232+
233+
}
173234
}

0 commit comments

Comments
 (0)