Оригинальная статья: 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; } }