当前位置: 首页 > 知识库问答 >
问题:

无法使用spring aop在spring EntityManager中启用hibernate筛选器

暴德运
2023-03-14

我试图通过springEntityManager启用hibernate过滤器,方法是tyring指向一个用自定义注释注释的服务实现方法@tenantaware并向该方法添加@around建议。我希望启用自定义筛选器,它在扩展baseEntity的所有实体上添加一个差异器,其中tenant_id=:tenantid。因此,我创建了自定义注释,并在需要的@transaction方法上使用它。它成功地拦截了该方法,但当我记录变量值时,变量值显示为空,过滤器也没有设置。

该项目是一个Spring-Boot2应用程序,我使用spring aop创建方面。我使用Hibernate5作为JPA实现提供程序。

SimpleJparepository.class的加载时间编织是不可能的,因为它不公开noarg构造函数。

这是我的TenantFilterAdvisor类。

package org.foo.bar.advisors;

@Aspect
@Slf4j
@Component
public class TenantFilterAdvisor {

    @PersistenceContext
    private EntityManager entityManager;

    public TenantFilterAdvisor() {
        log.debug("###########################################################################");
        log.debug("###################### Tenant Advisor Filter Started ######################");
        log.debug("###########################################################################");
    }

    @Pointcut(value = "@annotation(org.foo.bar.TenantAware)")
    public void methodAnnotatedWithTenantAware() {
    }

    @Pointcut(value = "execution(public * * (..))")
    public void allPublicMethods() {

    }

    @Around(value = "methodAnnotatedWithTenantAware() && allPublicMethods()")
    public Object enableTenantFilter(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {

        log.debug("###########################################################################");
        log.debug("###################### Before enabling tenant filter ######################");
        log.debug("###########################################################################");

        if (null != entityManager) {

            log.debug("Tenant filter name: ", "tenantFilter");
            log.debug("Tenant filter property: ", "tenantId");
            log.debug("Setting tenant id to: ", new Long(10));

            Session session = entityManager.unwrap(Session.class);
            Filter filter = session.enableFilter("tenantFilter");
            filter.setParameter("tenantId", new Long(10));

        }


        Object result = proceedingJoinPoint.proceed();

        // Code to disable the hibernate filter goes here.
        log.debug("###########################################################################");
        log.debug("###################### After disabling tenant filter ######################");
        log.debug("###########################################################################");

        return result;

    }

}
public interface InventoryService {
    Inventory getInventoryById(Long id);
}
@Service
public class InventoryServiceImpl implements InventoryService {

    @Autowired
    private InventoryRepository repo;

    @Override
    @Transactional
    @TenantAware
    public Inventory getInventoryById(Long id) {
       LOG.debug("getInventoryById() called  with: id = {}", id);
        final Optional<Inventory> inventoryOp = repo.findById(id);

        if (inventoryOp.isPresent()) {
            return inventoryOp.get();
        } else {
            throw new InventoryNotFoundException(String.format(MESSAGE_INVENTORY_NOT_FOUND_FOR_ID, id));
        }
    }
}
@Repository
@Transactional(readOnly = true)
public interface InventoryRepository extends BaseRepository<Inventory, Long> {  
}
@Configuration
@ComponentScan(basePackages = {"org.foo.bar.advisors"})
@EnableAspectJAutoProxy(proxyTargetClass = true)
public class AOPConfig {
}

最后,由其他类继承的相关MappedSuperClass将过滤器定义为

@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@MappedSuperclass
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
@FilterDef(
        name = "tenantFilter",
        parameters = @ParamDef(name = "tenantId", type = "long")
)
@Filter(name = "tenantFilter", condition = "tenant_id = :tenantId")
public abstract class BaseTransactionalEntity extends BaseEntity {

    @Column(name = "tenant_id", nullable = false)
    private Long tenantId;

}

如果需要详细信息,下面是cutom注释类

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Inherited
public @interface TenantAware {
}

我需要在会话中启用hibernate筛选器,并在后续连接点完成执行后禁用该筛选器。但事实并非如此。我错过了什么?

共有1个答案

谭梓
2023-03-14

正如Hibernate Reference Guide中所解释的,过滤器只适用于实体查询,而不适用于直接获取。在您的代码中,您正在通过findbyid执行直接提取,这将转换为entitymanager.find,因此是直接提取。

您可以重写Spring JPA存储库,并重新实现findbyid为实体查询,而不是直接获取,以解决此问题。

 类似资料:
  • 我正在尝试使用Spring Boot和Spring数据通过鉴别器实现多租户。 我创建了一个抽象类来表示多租户实体。类似于此: 如何全局启用多租户Hibernate过滤器?

  • 问题内容: 我正在尝试CSS过滤器,但在我的Firefox(15.0)浏览器中不起作用。 HTML: CSS: 问题答案: GrayScale具有使用-moz-filter在Firefox中运行的限制。 要使其正常工作,请使用以下代码段:

  • 我正在尝试在Spring Cloud Gateway中启用RequestRateLimiter。我havr配置了其他过滤器,甚至是自定义过滤器,但当我将其添加到我的路由中时: 我得到了这个异常(当然,如果我移除RequestRateLimiter筛选器并只保留StripPrefix条目,一切正常。我已经删除了异常的代码):

  • 我尝试在我的java play应用程序上启用CORS过滤器。我正在使用angularjs访问localhost以获取一些数据。这是我在play应用程序端所做的, 应用形态 过滤器。JAVA 当我试图打电话给我的服务时,它给了我一个错误, 无法加载XMLHttpRequesthttp://localhost:9000/app/search/0/10.对飞行前请求的响应未通过访问控制检查:请求的资源上

  • 我正试图返回一份基于用户给定日期的患者名单。但每次我运行该方法时,它都会返回所有医生的列表,而不是经过筛选。 主屏幕上的代码 过滤方法 搜索患者日期的方法 我初始化了两个患者,即patient1和patient 2。病人1的医生叫李医生,病人2的医生叫詹姆斯医生。首先,我为patient1输入以下信息,而patient2现在什么都没有。 当我拿到医生名单时,问题就来了。即使日期是错误的,它仍会继续

  • 我的JUnitRunner无法选择具有JBehave中指定的meta标记的场景。 以下是我的故事: 下面是我的运行程序文件: 当我作为JUnit test运行上述类时,没有调用带有烟雾标记的实际测试,也没有执行任何内容。 下面是我在执行上面的代码时得到的结果