【发布时间】:2019-08-26 00:58:00
【问题描述】:
我正在尝试通过 spring EntityManager 启用休眠过滤器,方法是切入使用自定义注释 @TenantAware 注释的服务实现方法,并将 @Around 建议添加到该方法。我想启用自定义过滤器,它在扩展BaseEntity 的所有实体上添加微分器where tenant_id = :tenantId。因此,我创建了自定义注释并在需要它的@Transactional 方法上使用它。它成功拦截了该方法,但是当我记录它们时变量值显示为空,也没有设置过滤器。
该项目是一个 spring-boot 2 应用程序,我正在使用 spring aop 来创建方面。我使用 Hibernate 5 作为 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> {
}
BaseRepository 接口扩展了 JpaRepository。
而切面配置类是
@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;
}
如果您需要详细信息,这里是自定义注释类
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Inherited
public @interface TenantAware {
}
我需要在会话中启用休眠过滤器,并在后续连接点完成执行后禁用它。但事实并非如此。我错过了什么?
【问题讨论】:
-
当然他们不是记录器。您的日志消息中缺少
{}占位符。 -
谢谢,我想我明白了。但是实体管理器上没有启用过滤器呢?
-
你是如何获取数据的。你只显示服务而不是使用实体管理器或存储库的实际实现。
-
我有一个扩展 spring
JpaRepository接口的存储库接口。我依靠 springSimpleJpaRepository来提供实现。否则,我将不得不实现我自己的存储库实现,这超出了目的。如果需要,我可以在此处发布存储库界面,但正如我所说,它是一个空界面。 -
findById调用entityManager.find并且过滤器在这种情况下不起作用。它们仅在查询时起作用。
标签: spring-boot spring-data-jpa aop spring-aop hibernate-filters