Search code examples
jpaeclipselinksoft-delete

Disable additional criteria only in some entity relations


I am making an application based on JPA/EclipseLink, I implemented a soft delete functionality using @AdditionalCriteria in the root class of the hierarchy of entities (all entities inherit from this).

My problem is that now, I need to create a special entity that contains multiple relationships with other entities; and I need recover all relationed entities, including soft deleted ones. It is possible disabled @AdditionalCriteria only in the relations of this special entity with EclipseLink? If not, what is the best option to do this? My code looks like the following:

////Example of my top entity class (all others inherit from this)
@AdditionalCriteria("this.deleted = false")
public abstract class TopHierarchyClass {
  ···
  @Column(name = "deleted")
  protected boolean deleted = false;
  ···
}

//Example of entity that needs recover all relationed entities including soft deleted
@Entity
@Table(name = "special_entities")
public class SpecialEntity extends EntityBase {
  ···
  @JoinColumn(name = "iditem", referencedColumnName = "id")
  @ManyToOne(fetch = FetchType.LAZY)
  private Item item;
  ···
}

@Entity
@Table(name = "items")
public class Item extends EntityBase {
  ···
}

Thanks in advance


Solution

  • Create a new entity for the same table without the @AdditionalCriteria. This way you can retrieve all records from that table without applying the additional filter.

    For example:

    public interface Person {
        Long getId();
        void setId(Long id);
        Date getDeletedAt();
        void setDeletedAt(Date deletedAt);
    }
    
    @MappedSupperclass
    public class PersonEntity implements Person {
        @Id
        private Long id;
        private Date deletedAt;
    
        public Long getId() { return id; }
        public void setId(Long id) { this.id = id; }
    
        public Date getDeletedAt() { return deletedAt; }
        public void setDeletedAt(Date deletedAt) { this.deletedAt = deletedAt; }
    }
    
    @Entity
    @Table(name = "people")
    @AdditionalCriteria("this.deletedAt is null")
    public class ActivePersonEntity extends PersonEntity {
    }
    
    @Entity
    @Table(name = "people")
    public class RawPersonEntity extends PersonEntity {
    }
    
    public class PeopleRepository {
        @PersistenceContext
        private EntityManager em;
    
        public List<Person> all() {
           return all(false);
        }
    
        public List<Person> all(boolean includeSoftDeleted) {
           if (!includeSoftDeleted) {
               return em.createQuery("select p from ActivePersonEntity p", ActivePersonEntity.class).getResultList();
           } else {
               return em.createQuery("select p from RawPersonEntity p", RawPersonEntity.class).getResultList();
           }
        }
    }
    

    Also, if your @AdditionalCriteria is in a super class, you may override it by declaring a new empty @AdditionalCriteria in a sub class:

    You can define additional criteria on entities or mapped superclass. When specified at the mapped superclass level, the additional criteria definition applies to all inheriting entities, unless those entities define their own additional criteria, in which case those defined for the mapped superclass are ignored.

    @AdditionalCriteria doc