Фильтры Hibernate Entity не работают, если назначены в слушателях событий и для некоторых методов JPA в spring-data - PullRequest
1 голос
/ 25 мая 2020

Я использую jpa в моем проекте весенней загрузки для операций CRUD. Перед выполнением какой-либо операции я хочу применить фильтр. Я хочу, чтобы один и тот же фильтр применялся ко всем моим объектам, поэтому я написал EntityListener, который включит фильтр по событиям PrePersist, PreLoad и PreRemove для объекта в процессе работы.

Entity Site и, возможно, другие объекты расширяют AOrganization Класс, в котором определен фильтр. Я включаю этот фильтр в EntityListener. Хотя здесь включается фильтр, он не отражается в результирующем запросе операции.

Пожалуйста, проверьте мой код ниже.

AOrganization. java

import java.io.Serializable;

import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.MappedSuperclass;

import org.hibernate.annotations.Filter;
import org.hibernate.annotations.FilterDef;
import org.hibernate.annotations.ParamDef;

    @MappedSuperclass
    @FilterDef(name = "OrgFilter", parameters = { @ParamDef(name = "allowedOrgIdList", type = "long") })
    @Filter(name = "OrgFilter", condition = "org_id in (:allowedOrgIdList)")
    public class AOrganization implements Serializable {

        @ManyToOne()
        @JoinColumn(name = "org_id", nullable = true)
        private Organization organization;

        public Organization getOrganization() {
            return organization;
        }

        public void setOrganization(Organization organization) {
            this.organization = organization;
        }
    }

Сайт. java

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;


@Entity
@Table(name = "site")
public class Site extends AOrganization{

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "id")
    private long id;

    @Column(name = "site_name")
    private String siteName;

    @Override
    public String toString() {
        return "Site [id=" + id + ", siteName=" + siteName + "]";
    }

    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    public String getSiteName() {
        return siteName;
    }

    public void setSiteName(String siteName) {
        this.siteName = siteName;
    }
}

EntityListener. java

import java.util.Arrays;

import javax.annotation.PostConstruct;
import javax.persistence.EntityManagerFactory;
import javax.persistence.PersistenceUnit;

import org.hibernate.Filter;
import org.hibernate.Session;
import org.hibernate.event.service.spi.EventListenerRegistry;
import org.hibernate.event.spi.AbstractEvent;
import org.hibernate.event.spi.EventType;
import org.hibernate.event.spi.PreDeleteEvent;
import org.hibernate.event.spi.PreDeleteEventListener;
import org.hibernate.event.spi.PreLoadEvent;
import org.hibernate.event.spi.PreLoadEventListener;
import org.hibernate.event.spi.PreUpdateEvent;
import org.hibernate.event.spi.PreUpdateEventListener;
import org.hibernate.internal.SessionFactoryImpl;
import org.springframework.stereotype.Component;


@Component
public class EntityListener implements PreLoadEventListener, PreUpdateEventListener, PreDeleteEventListener {

    @PersistenceUnit
    private EntityManagerFactory entityManagerFactory;

    @PostConstruct
    private void init() {
        SessionFactoryImpl sessionFactory = entityManagerFactory.unwrap(SessionFactoryImpl.class);
        EventListenerRegistry registry = sessionFactory.getServiceRegistry().getService(EventListenerRegistry.class);

        registry.getEventListenerGroup(EventType.PRE_LOAD).appendListener(this);
        registry.getEventListenerGroup(EventType.PRE_UPDATE).appendListener(this);
        registry.getEventListenerGroup(EventType.PRE_DELETE).appendListener(this);
    }

    @Override
    public void onPreLoad(PreLoadEvent event) {
        enableOrgFilter(event, event.getEntity());
    }

    @Override
    public boolean onPreUpdate(PreUpdateEvent event) {
        enableOrgFilter(event, event.getEntity());
        return false;
    }

    @Override
    public boolean onPreDelete(PreDeleteEvent event) {
        enableOrgFilter(event, event.getEntity());
        return false;
    }

    private void enableOrgFilter(AbstractEvent event, Object entity) {

        Class clazz = entity.getClass();

        boolean isExtendingAOrganization = isExtendingAOrganization(clazz);
        if (isExtendingAOrganization) {
            Session session = event.getSession();

            System.out.println(session);

            Filter filter = session.enableFilter("OrgFilter");
            filter.setParameterList("allowedOrgIdList", Arrays.asList(2l));
        }
    }

    private boolean isExtendingAOrganization(Class clazz) {
        boolean isExtendingFromAOrganization = false;

        if (AOrganization.class.isAssignableFrom(clazz)) {
            isExtendingFromAOrganization = true;
        }

        return isExtendingFromAOrganization;
    }

}

SiteServiceImpl. java

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import javax.persistence.EntityManager;

import org.hibernate.Filter;
import org.hibernate.Session;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;


@Service
public class SiteServiceImpl implements SiteService {

    @Autowired
    private EntityManager entityManager;

    @Autowired
    private SiteRepository siteRepository;

    @Override
    public List<Site> getAllSites() {
        Iterable<Site> sites = siteRepository.findAll();

        List<Site> allSites = new ArrayList<>();

        sites.forEach(allSites::add);

        return allSites;

    }

    @Override
    public List<Site> getSiteBySiteName(String siteName) {

        Session session = entityManager.unwrap(Session.class);

        System.out.println(session);

//      Filter filter = session.enableFilter("OrgFilter");
//      filter.setParameterList("allowedOrgIdList", Arrays.asList(2l));

        List<Site> allSites = siteRepository.findBySiteName(siteName);
        return allSites;
    }

    @Override
    public Site updateSiteName(Long id,String siteName) {

        Session session = entityManager.unwrap(Session.class);

        System.out.println(session);

//      Filter filter = session.enableFilter("OrgFilter");
//      filter.setParameterList("allowedOrgIdList", Arrays.asList(2l));

        Site site = siteRepository.findById(id).get();

        List<Site> copy = siteRepository.findBySiteName(site.getSiteName());

        if(site == null)
            return null;

        site.setSiteName(siteName);

        siteRepository.save(site);

        return site;
    }

}

SiteRepository. java

import java.util.List;
import java.util.Optional;

import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;



@Repository
public interface SiteRepository extends CrudRepository<Site, Long> {

    public List<Site> findBySiteName(String siteName);

    public Optional<Site> findById(Long id);
}

Если фильтр включен через EntityListener, он не работает. Но если я включу фильтр в методе SiteServiceImpl getSiteBySiteName, он будет работать.

Кроме того, в SiteServiceImpl изменения фильтра отражаются только для метода findBySiteName, а не в findById.

Есть идеи, почему это происходит, или альтернативное решение? Заранее спасибо.

...