When using a composite id, the entity is not removed from the persistance context with a delete query written in JPQL
Our Entity and composite id :
{code:java}@Entity @NoArgsConstructor(access = AccessLevel.PRIVATE, force = true) public class SchoolSetting {
@EmbeddedId private final SchoolSettingId id;
@Getter private boolean activated;
public SchoolSetting(@NonNull final String schoolId, @NonNull final String key, final boolean activated) { this.id = new SchoolSettingId(schoolId, key); this.activated = activated; }
public String getKey() { return this.id.getKey(); } }
@Embeddable @NoArgsConstructor(access = AccessLevel.PRIVATE, force = true) @Getter(AccessLevel.PROTECTED) @EqualsAndHashCode public class SchoolSettingId implements Serializable {
private final String schoolId;
private final String key;
public SchoolSettingId(@NonNull final String schoolId, @NonNull final String key) { this.schoolId = schoolId; this.key = key; } }{code}
The repository :
{code:java}interface SpringDataSchoolSettingRepository extends CrudRepository<SchoolSetting, SchoolSettingId> { @Query("delete from SchoolSetting s WHERE s.id.key = :id") @Modifying void deleteById(@Param("id") SchoolSettingId id); }{code}
The following test fail without the testEntityManager.clear() as the entity is still in the persistence context. We we are able to reproduce the same behavior with production code inside the same transaction
{code:java}@DataJpaTest @AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE) @Import(JpaSchoolSettingRepository.class) class JpaSchoolSettingRepositoryIT {
static String SCHOOL_ID = "MY_SCHOOL";
@Autowired TestEntityManager testEntityManager;
@Autowired JpaSchoolSettingRepository jpaSchoolSettingRepository;
@Test void deleteTwiceShouldntThrowAnyException() { testEntityManager.persistAndFlush(createSetting());
assertThat(jpaSchoolSettingRepository.get(new SchoolSettingId(SCHOOL_ID, "ABSENCE_FOR_DAY_OFF"))) .isNotEmpty(); jpaSchoolSettingRepository.delete(new SchoolSettingId(SCHOOL_ID, "ABSENCE_FOR_DAY_OFF"));
//testEntityManager.clear(); assertThat(jpaSchoolSettingRepository.get(new SchoolSettingId(SCHOOL_ID, "ABSENCE_FOR_DAY_OFF"))) .isEmpty(); assertThatCode(() -> jpaSchoolSettingRepository.delete(new SchoolSettingId(SCHOOL_ID, "ABSENCE_FOR_DAY_OFF"))) .doesNotThrowAnyException(); }
private SchoolSetting createSetting() { return new SchoolSetting(SCHOOL_ID, ABSENCE_FOR_DAY_OFF, true); } }{code}
the assertion one line 23 fail without the {{testEntityManager.clear()}} |
|