@Pointcut вокруг JpaRepository не работает с методами по умолчанию

#java #spring #spring-data-jpa #spring-aop

#java #весна #spring-data-jpa #spring-aop

Вопрос:

У меня есть проект Spring Boot 2.3. Я широко использую Spring Data REST, Spring JPA, спящий режим.

Типичный репозиторий в моем приложении выглядит так:

 @Transactional
public interface ContactRepository extends JpaRepository<Contact, Long>, ContactCustomRepository<Contact, Long>, JpaSpecificationExecutor<Contact> {

    @Transactional(readOnly = true)
    @Query("FROM Contact c WHERE c.id=:id")
    Optional<ContactType> findByIdTest(@Param("id") long id);
}
  

Это мой фильтр:

 @Aspect
@Order(1)
@Component
@Log4j2
public class EntityCustomerFilterAspect {

    @Pointcut("execution(public * javax.persistence.EntityManager .*Query(..))")
    private void createQuery() {
    }

    @Around(value = "createQuery() amp;amp; target(entityManager)")
    public Object applyFilter(ProceedingJoinPoint pjp, Object entityManager) throws Throwable {
        try {
            if (SecurityUtils.getLoggedRoles().contains(Role.ROLE_CUSTOMER)) {
                if (SecurityUtils.getLoggedId() != null) {
                    ((EntityManager) entityManager).unwrap(Session.class).enableFilter("customerFilter").setParameter("contactId", SecurityUtils.getLoggedId());
                    log.trace(">>>>Enabling filter customer {}", SecurityUtils.getLoggedUser().getSid());
                } else {
                    ((EntityManager) entityManager).unwrap(Session.class).enableFilter("customerFilter").setParameter("contactId", -1l);
                    log.warn("Logged ID is null. Customer filter cannot be applied");
                }
            }
        } catch (Exception e) {
            log.warn("Unable to enable filter");
        }
        return pjp.proceed();
    }

}
  

Когда из контроллера REST я вызываю метод findByIdTest , с помощью EntityCustomerFilterAspect которого применяется определенный фильтр. Напротив, если вместо этого я вызываю Spring JPA по умолчанию findById , фильтр не применяется.
Я не понимаю, что не так и почему @Pointcut не работает с методами по умолчанию.

Комментарии:

1. findById не использует запрос, а скорее использует find метод EntityManager , даже если вы сможете перехватить это, фильтры в этом случае не будут применяться, они применяются только к запросам, а не к EntityManager.find методу.

2. @M.Deinum вы видите хороший способ решить эту проблему? Моя цель — добавить автоматический фильтр, когда клиент регистрируется в моем приложении. Я хочу, чтобы он мог видеть только свои данные. Фильтр, который, как я догадался, был лучшим способом сделать это, поэтому я не рискую забыть указать условие в запросе.

3. Фильтр — отличное решение, но он просто не будет работать, когда вы выполняете прямой запрос через JPA на основе первичного ключа. EntityManager.find . Поэтому, если у вас нет метода HTTP или иного, который напрямую вызывает это на основе идентификатора в запросе, это не должно быть проблемой. Если вы хотите обойти это, вам нужно будет повторно реализовать findById using запрос (что может привести к проблемам из-за игнорирования сопоставления JPA!). Тем не менее, если кто-то напрямую использует EntityManager.find вместо репозитория, у вас по-прежнему возникает та же проблема отсутствия фильтров.

4. @M.Deinum Спасибо. На самом деле SDR предоставляет эти методы как ресурсы REST. Поэтому я должен настроить контроллер и вызвать пользовательский findByIdCustom, чтобы избежать проблемы. Еще раз спасибо за разъяснения!