문제 상황

@EntityListeners(AuditingEntityListener.class)
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Entity
public class Room {

		@OneToMany(mappedBy = "room")
    private final List<Session> sessions = new ArrayList<>();

		//...
}
@EntityListeners(AuditingEntityListener.class)
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Entity
public class Session {

		@Column(nullable = false)
    private boolean deleted = false;

		//...

		public void delete() {
        if (user.isLinkedSession(this)) {
            user.unLinkSession(this);
        }
        if (room.containsSession(this)) {
            room.exitSession(this);
        }
        deleted = true;
    }
}

Session은 논리적 삭제를 사용하고 있는데, Roomsessions필드가 지연로딩 될 때, 논리적 삭제를 사용하고 있는 것을 모르기 때문에 모든 session을 가지고 오는 문제가 있었다.

해결

Hibernate에서 제공해주는 어노테이션인 @Where 어노테이션을 이용했다. 이 어노테이션으로 해당 엔티티를 조회하는 모든 쿼리에 where절이 추가된다.

@EntityListeners(AuditingEntityListener.class)
@Getter
@Where(clause = "deleted=false")
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Entity
public class Session {

	//...

}

이 어노테이션을 사용할 때 주의해야될 점이 있다. SQL문에 해당 어노테이션의 문구를 삽입하는 것이기때문에, 이미 영속성 컨텍스트 내에 있는 엔티티의 경우 deletedtrue로 바꿔도 영속성 컨텍스트에는 남아있으니 유의해야된다.

참고 자료

https://www.baeldung.com/spring-jpa-soft-delete#how-to-get-the-deleted-data

https://www.baeldung.com/hibernate-dynamic-mapping#filtering-entities-with-where

https://stackoverflow.com/questions/40254962/hibernate-soft-deletion-for-child-table