場景
需要根據當前用戶的權限過濾需要顯示的數據。
比如有一張旅館表,主鍵為hotel_code,該值的構成為6位行政區划+4位流水號。杭州用戶只能看到3301開頭的旅館信息,而3302開頭的只能看到寧波的旅館信息。
如:
hotel_code | hotel_name |
---|---|
3301888999 | 杭州測試旅館 |
3302888999 | 寧波測試旅館 |
3303888999 | 溫州測試旅館 |
3304888999 | 嘉興測試旅館 |
用戶表中有個filter_code字段,過濾匹配start_with的數據。如fitler_code=33,則匹配顯示整個浙江省的數據;filter_code=3301則顯示杭州市的數據。
框架
-
springboot
-
spring data jpa
JPA內嵌Hibernate的Filter功能簡介
JPA自身並沒有提供Filter功能,而是由hibernate實現的,
@Filter是Entity上的注解,在添加該注解之后,hibernate會在相應查詢語句中添加where子句以達到過濾的目的。
還是直接看代碼吧。
代碼片段實現
Hotel實體類:
@Entity
@Data
@FilterDef(name = "filterByHotelCode", parameters = {
@ParamDef(name = "filterCode", type = "string")
})
@Filters({
@Filter(name = "filterByHotelCode", condition = "hotel_code like :filterCode")
})
public class Hotel {
@Id
@Column(name = "hotel_code")
private String hotelCode;
private String hotelName;
}
DAO:
public interface HotelRepository extends JpaRepository<Hotel, String> {}
HotelService:
// @EnableFilter為自定義注解以實現切面開啟Filter
// @Transactional 是使用Filter功能的前提、必要條件
@EnableFilter
@Transactional
public PageModel<Hotel> queryByPage(String queryKey, Pageable pageable) {
Page<Hotel> hotelPage = hotelRepository.findHotelsByKey(queryKey, pageable);
return PageModel.build(hotelPage, pageable.getOffset());
}
自定義注解:
public @interface EnableFilter {
}
切面AOP:
@Component
@Aspect
public class DataFilterAdvice {
@PersistenceContext
private EntityManager entityManager;
@Around("@annotation(org.vigack.annotation.EnableFilter)")
public Object doProcess(ProceedingJoinPoint joinPoint) throws Throwable {
try{
ManagerDTO manager =
(ManagerDTO) SecurityUtils.getSubject().getSession(false).getAttribute("MANAGER");
Filter filter = entityManager.unwrap(Session.class).enableFilter("filterByHotelCode");
filter.setParameter("filterCode", manager.getFilterCode() + "%");
return joinPoint.proceed();
}catch (Throwable ex){
ex.printStackTrace();
throw ex;
}finally {
entityManager.unwrap(Session.class).disableFilter("filterByHotelCode");
}
}
}
注意事項
-
Filter的condition比較簡單,對於動態的條件支持度不夠,比如用戶的filter_code如果是一個list,那么實現起來就麻煩了。
-
這個過濾對於懶加載不起作用
-
如果通過主鍵直接查詢,那么過濾器將不起作用