Оригинальная статья: http://borislam.blogspot.hk/2012/07/adding-hibernate-entity-level-filter.html
Те, кто использовал функции фильтрации данных hibernate, должны знать, что он очень мощный. Вы можете определить набор критериев фильтрации для класса сущностей или коллекции. Spring data JPA — очень удобная библиотека, но у нее нет подходящих функций. В этой статье я покажу, как добавить функции фильтра гибернации на уровне объекта. Вы можете использовать эти функции при использовании Hibernate Entity Manager . Мы можем просто определить аннотацию в интерфейсе вашей репозитории, чтобы включить эту функцию.
Шаг 1. Определите фильтр на уровне объекта как обычно. Просто используйте hibernate @FilterDef аннотацию
@Entity
@Table(name = "STUDENT")
@FilterDef(name="filterBySchoolAndClass", parameters={@ParamDef(name="school", type="string"),@ParamDef(name="class", type="integer")})
public class Student extends GenericEntity implements Serializable {
// add your properties ...
}
Шаг 2. Определите две пользовательских аннотации.
Эти две аннотации должны использоваться в ваших интерфейсах репозитория. С помощью этих аннотаций можно применить фильтр гибернации, определенный на шаге 1, к конкретному запросу.
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface EntityFilter {
FilterQuery[] filterQueries() default {};
}
@Retention(RetentionPolicy.RUNTIME)
public @interface FilterQuery {
String name() default "";
String jpql() default "";
}
Шаг 3. Добавьте метод в базовый репозиторий JPA данных Spring.
Этот метод будет читать аннотацию, которую вы определили (т. Е. @FilterQuery), и применить к запросу фильтр гибернации, просто развернув EntityManager. В этом методе вы можете указать параметр в своем фильтре гибернации, а также параметр в запросе.
Если вы не знаете, как добавить пользовательский метод в базовый репозиторий JPA данных Spring, см. Мою предыдущую статью о том, как подробно настроить базовый репозиторий JPA данных Spring . В предыдущей статье вы можете видеть, что я намеренно предоставляю интерфейс репозитория (то есть свойство springDataRepositoryInterface) в GenericRepositoryImpl. Эти маленькие хитрости позволяют мне легко получить доступ к аннотации в интерфейсе репозитория.
public List<T> doQueryWithFilter( String filterName, String filterQueryName, Map inFilterParams, Map inQueryParams){
if (GenericRepository.class.isAssignableFrom(getSpringDataRepositoryInterface())) {
Annotation entityFilterAnn = getSpringDataRepositoryInterface().getAnnotation(EntityFilter.class);
if(entityFilterAnn != null){
EntityFilter entityFilter = (EntityFilter)entityFilterAnn;
FilterQuery[] filterQuerys = entityFilter.filterQueries() ;
for (FilterQuery fQuery : filterQuerys) {
if (StringUtils.equals(filterQueryName, fQuery.name())) {
String jpql = fQuery.jpql();
Filter filter = em.unwrap(Session.class).enableFilter(filterName);
//set filter parameter
for (Object key: inFilterParams.keySet()) {
String filterParamName = key.toString();
Object filterParamValue = inFilterParams.get(key);
filter.setParameter(filterParamName, filterParamValue);
}
//set query parameter
Query query= em.createQuery(jpql);
for (Object key: inQueryParams.keySet()) {
String queryParamName = key.toString();
Object queryParamValue = inQueryParams.get(key);
query.setParameter(queryParamName, queryParamValue);
}
return query.getResultList();
}
}
}
}
}
return null;
}
Последний шаг: пример использования
В вашем репозитории определите, к какому запросу вы хотите применить фильтр гибернации, используя аннотации @EntityFilter и @FilterQuery.
@EntityFilter (
filterQueries = {
@FilterQuery(name="query1",
jpql="SELECT s FROM Student LEFT JOIN FETCH s.Subject where s.subject = :subject" ),
@FilterQuery(name="query2",
jpql="SELECT s FROM Student LEFT JOIN s.TeacherSubject where s.teacher = :teacher")
}
)
public interface StudentRepository extends GenericRepository<Student, Long> {
}
В вашем сервисе или бизнес-классе, который внедряет ваш репозиторий, вы можете просто вызвать метод doQueryWithFilter (), чтобы включить функцию фильтрации.
@Service
public class StudentService {
@Inject
private StudentRepository studentRepository;
public List<Student> searchStudent( String subject, String school, String class) {
List<Student> studentList;
// Prepare parameters for query filter
HashMap<String, Object> inFilterParams = new HashMap<String, Object>();
inFilterParams.put("school", "Hong Kong Secondary School");
inFilterParams.put("class", "S5");
// Prepare parameters for query
HashMap<String, Object> inParams = new HashMap<String, Object>();
inParams.put("subject", "Physics");
studentList = studentRepository.doQueryWithFilter(
"filterBySchoolAndClass", "query1",
inFilterParams, inParams);
return studentList;
}
}