全局hibernate过滤所有数据库查询

Ang*_*gad 8 java spring hibernate spring-mvc oracle10g

我在我的Web应用程序中使用Spring MVC和Hibernate.我正在寻找一种方法来创建一个全局的hibernate过滤器,它将应用于我的DAO类中的每个查询,而不必在每个DAO方法中显式启用它.

要求是按用户选择的会话变量过滤记录.因此,我们的查询参数将保存在会话中,该会话中的所有DAO查询都需要通过此变量过滤结果.这里的目的是避免每个DAO方法中的所有可重复过滤代码.

欢迎任何和所有的想法!

Ang*_*gad 15

我把处理方式放在这里.以下是基于与@ Rp-的讨论以及此处提出的建议.

配置它的三个主要元素:
- Spring的会话范围bean
- package-info.java
- Spring AOP



我创建了一个会话范围的Spring bean,它将保存我的用户选择的变量.变量将根据用户的请求通过spring Controller映射方法进行修改.由于spring的依赖注入,我可以在Spring应用程序的任何地方访问session变量.

@Component
@Scope(value="session", proxyMode=ScopedProxyMode.TARGET_CLASS)
public class SessionParam implements Serializable{

  private String sessParam;
..
..
}
Run Code Online (Sandbox Code Playgroud)

接下来,我在包级别定义我的hibernate过滤器.这是在package-info.java文件中完成的.因此,此包中的所有实体都继承此过滤器.

 @FilterDef(name="GLOBAL_FILTER",   parameters = {@ParamDef(name="sessParam", type="string")}, 
                                    defaultCondition = "sessParam = :sessParam")

package com.company.app.entity;
import org.hibernate.annotations.FilterDef;
import org.hibernate.annotations.FilterDefs;
import org.hibernate.annotations.ParamDef;
Run Code Online (Sandbox Code Playgroud)


包中的实体使用hibernate的@Filter注释进行注释,如下所示:

@Entity
@Filter(name="GLOBAL_FILTER")
@Table(name = "TABLE_XYZ", schema = "SCHEMA_ABC")
public class TableXyz implements Serializable {
...
}
Run Code Online (Sandbox Code Playgroud)

最后,在hibernate的Session Factory的getCurrentSession()方法中使用AspectJ方面拦截所有DAO查询.

以下是Aspect类.

@Aspect
@Component
public class GlobalFilter {

    @Autowired
    SessionParam sessionParam;


    @Pointcut("execution(* org.hibernate.SessionFactory.getCurrentSession(..))")
    protected void hibernateSessionFetch(){

    }

    @AfterReturning(pointcut = "hibernateSessionFetch()", returning = "result")
    public void enableGlobalFilter(JoinPoint joinPoint, Object result){

        Session session = (Session) result;

        session.enableFilter("GLOBAL_FILTER").setParameter("sessParam", sessionParam.getSessParam());

    }
}
Run Code Online (Sandbox Code Playgroud)

对具有"GLOBAL_FILTER"的实体的所有查询现在都对所需变量进行了条件检查.DAO方法中不需要在每个查询中进行显式条件检查.

  • 请注意,Hibernates @Filter 仅适用于查询,不适用于直接获取。这意味着 em.find() 或 repository.findById() 没有被过滤。(来源:https://docs.jboss.org/hibernate/orm/5.2/userguide/html_single/Hibernate_User_Guide.html) (3认同)