我使用 Hibernate @Filter 和 Spring Data 为项目中的每个查询添加特定的“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注解,它就不起作用。当我调试方面时,我可以看到过滤器已启用,但查询没有更改。当我添加注释时,一切正常。但我不明白为什么会这样。这个注释不应该出现在读取方法上,而且在每个教程中,没有它一切都可以工作,但在我的例子中不行。