【问题标题】:How to use Hibernate @Filter without @Transactional?如何在没有 @Transactional 的情况下使用 Hibernate @Filter?
【发布时间】:2022-11-07 19:08:11
【问题描述】:

我正在使用带有 Spring Data 的 Hibernate @Filter 为我的项目中的每个查询添加特定的“where”子句。问题是只要我为我的“findAll”方法使用@Transactional 注释,它就可以工作。有什么办法可以避免使用@Transactional?为什么在这里很重要?

这是过滤器配置:

 @FilterDef(name = "testFilter",
            parameters = @ParamDef(name = "company_id", type = "long"),
            defaultCondition = "company_id=:companyId")
    @Filter(name = "testFilter")
    @EntityListeners(EmployeeListener.class)
    @NoArgsConstructor
    public class Employee {//basic fields}

存储库:

@Repository
public interface EmployeeRepository extends PagingAndSortingRepository<Employee, UUID> {
}

启用过滤器的方面:

@Aspect
@Component
public class TestAspect {

    private final SecurityAspect securityAspect;
    private final Logger logger;

    @PersistenceContext
    private EntityManager entityManager;

    @Autowired
    public TestAspect(SecurityAspect securityAspect, Logger logger) {
        this.securityAspect = securityAspect;
        this.logger = logger;
    }
    

    @Around("execution(* org.springframework.data.repository.CrudRepository+.findAll(..))")
    public Object aroundFindAllTenantAware(ProceedingJoinPoint joinPoint) {
        Session session = this.entityManager.unwrap(Session.class);
        session.enableFilter("testFilter")
                .setParameter("companyId", this.securityAspect.getCompanyId());
        Object retValue = null;
        try {
            retValue = joinPoint.proceed();
        } catch (Throwable throwable) {
            logger.error(throwable.getMessage(), throwable);
        } finally {
            session.disableFilter("testFilter");
        }
        return retValue;

    }
}

最后,我的服务:

@Service
@Transactional
public class EmployeeApiServiceImpl {

private final EmployeeRepository repository;
    
    @Autowired
    public EmployeeApiServiceImpl(EmployeeRepository repository) {
this.employeeRepository = employeeRepository; }
                                
   
    @Override
    public Response listProfiles(SecurityContext securityContext) { 
        List<Employee> employees = repository.findAll();
        return Response.ok().entity(employees).build();
    }

没有@Transactional 注释,它不起作用。当我调试方面时,我可以看到过滤器已启用,但查询没有改变。当我添加注释时,一切正常。但我不明白为什么会这样。这个注释不应该出现在 read 方法上,而且在每个教程中,没有它一切都可以工作,但在我的情况下不是。

【问题讨论】:

  • 请提供足够的代码,以便其他人可以更好地理解或重现该问题。
  • 我猜测了一下,但我认为this.entityManager.unwrap(Session.class)@Transaction 存在一些问题,您得到正确的Session 该交易,但没有您收到的@Transaction 会话可能与查询执行无关
  • 我也有同样的想法。我正在激活与当前查询无关的错误会话。实际上,我不是在做宠物项目,所以很多人也在做它,在我们项目的每个服务中使用@Transactional 是不可接受的。有什么办法可以避免吗?我试图手动处理事务但无济于事......

标签: java spring hibernate jpa filter


【解决方案1】:

问题是 Spring 注入的 EntityManager 代理,它只支持某些没有事务的操作。如果您需要对此的支持,您将需要一个自定义代理实现。见org.springframework.orm.jpa.SharedEntityManagerCreator.SharedEntityManagerInvocationHandler#invoke

【讨论】:

    猜你喜欢
    • 2023-03-10
    • 2014-02-06
    • 2012-09-30
    • 2012-05-23
    • 2011-12-07
    • 2011-01-18
    • 2013-12-03
    • 2012-02-21
    • 2021-10-30
    相关资源
    最近更新 更多