Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Global hibernate filter on all database queries

I am using Spring MVC and Hibernate for my web application. I am looking for a way to create a global hibernate filter of sorts that would apply to each query in my DAO classes without me having to explicitly enable it in each DAO method.

The requirement is to filter records by a user selected session variable. So our query parameter would be held in session and all DAO queries in that session need to filter results by this variable. The purpose here is to avoid all the repeatable filtering code in every DAO method.

Any and all ideas are welcome!

like image 270
Angad Avatar asked Sep 15 '14 19:09

Angad


1 Answers

Putting out the way I handled this down here. Below is based on the discussion with @Rp- and suggestions made here.

Three major elements went into configuring this:
- Spring's session scoped beans
- package-info.java
- Spring AOP



I created a session scoped Spring bean that will hold my user selected variable. The variable would get modified upon user's request through a spring Controller mapping method. Being held in a spring managed bean, I have access to the session variable anywhere in my application by virtue of spring's dependency injection.

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

  private String sessParam;
..
..
}

Next I define my hibernate filter at package level. This is done in package-info.java file. All entities in this package thus inherit this filter.

 @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;


Entities in the package are annotated with hibernate's @Filter annotation as below:

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

Lastly, all DAO queries are intercepted using an AspectJ aspect on hibernate's Session Factory's getCurrentSession() method.

Below is the Aspect class.

@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());

    }
}

All queries on entities with "GLOBAL_FILTER" now have a conditional check on the required variable. No explicit conditional checks in each query is required in the DAO methods.

like image 56
Angad Avatar answered Sep 30 '22 06:09

Angad