Guys,
Recently we got requirement to build an application where row level filter is required. example: Application provides service to different clients and we have to separate data for each client so no client can access other clients data.
Tech Stack
- Spring
- JPA/Hibernate
- Any Database
Add common field to every Entity
To distinguish data clientwise we have decided to add clientId to each and every table using simple inheritance with @MappedSuperClass
annotation.
Example
@MappedSuperClass Class abstract AbstractEntity{ @Column(name = “client_id”) private long clientId; // getter and setter @PrePersist public void prePersist() { this.clientId = // Get the client id, mainly use static SecurityContextHolder.getContext().getAuthentication() methods to fetch client which you have stored with token for example. } }
Once you extend this entity to any other entity orm will create a clientId
column.
And @PrePersist
will add clientId automatically before saving this entity.
Solution using @Where
You can add this annotation on any entity, orm will add append your condition with where clause.
Example
@Entity @Where(clause = "clientId=1") Class Employee extends AbstractEntity{ }
Condition clientId=1
will be appended to every fetch made on entity Employee.
Limitation
@Where
accept constant value always, you can’t change the condition dynamically. Here we have used clientId=1
which is of no use as we hard coded clientId 1
always.
Solution using @Filter
With the user @Filter
we can
- Change value of condition dynamically, i.e. we can set clientId runtime.
- We can enable/disable filter runtime.
Example
@FilterDef( name = "clientFilter", parameters = @ParamDef(name = "clientId", type = "long") ) @Filter( name = "clientFilter", condition = "clientId = :clientId" ) Class Employee extends AbstractEntity{ }
Here we have applied this filter on class so ORM will look if filter applied on entity is enabled or not, if enable than it will append where on every fetch.
Enable filter runtime
We can enable/disable filter using EntityManager
, you need to unwrap session and set the parameter.
@Autowired private EntityManager entityManager; Session session = entityManager.unwrap(Session.class); Filter filter = session.enableFilter("clientFilter"); filter.setParameter("clientId", clientId);
This will enable clientFilter
and set a clientId dynamically. Better to create separate class and method to perform this operation.
Please contact us if you have any doubt.
Share current post by copy: https://goo.gl/dZhzY2
Happy Learning!
Thanks,
Yogesh P
The post JPA: How to apply Row Level Filter appeared first on kode12.