Spring Data JpaSpecificationExecutor 做复杂查询

来源:互联网 发布:福汇软件下载 编辑:程序博客网 时间:2024/05/18 01:03

配置文件以及项目结构和数据表都是没变的

JpaSpecificationExecutor 源码

public interface JpaSpecificationExecutor<T> {    T findOne(Specification<T> spec);    List<T> findAll(Specification<T> spec);    Page<T> findAll(Specification<T> spec, Pageable pageable);    List<T> findAll(Specification<T> spec, Sort sort);    long count(Specification<T> spec);}

PersonJpaSpecificationExecutor 需要继承JpaSpecificationExecutor和
JpaRepository接口 由于JpaSpecificationExecutor没有继承Repository接口所以不能被Spring 容器识别 自动识别为Repository

package com.ncsi.SpringData.Repository;import org.springframework.data.jpa.repository.JpaRepository;import org.springframework.data.jpa.repository.JpaSpecificationExecutor;import org.springframework.stereotype.Repository;import com.ncsi.SpringData.Entity.Person;@Repositorypublic interface PersonJpaSpecificationExecutor extends JpaSpecificationExecutor<Person>,JpaRepository<Person, Integer>{}

所以我们需要继承JpaRepository 才能被xml文件配置的jpa properties所识别

<!-- 加入 jpa 的命名空间 --><jpa:repositories base-package="com.ncsi.SpringData.Repository" entity-manager-factory-ref="entityManagerFactory"></jpa:repositories>

Test:

package com.ncsi.SpringData;import java.util.ArrayList;import java.util.List;import javax.persistence.criteria.CriteriaBuilder;import javax.persistence.criteria.CriteriaQuery;import javax.persistence.criteria.Predicate;import javax.persistence.criteria.Root;import org.junit.Test;import org.junit.runner.RunWith;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;import org.springframework.data.jpa.domain.Specification;import org.springframework.test.context.ContextConfiguration;import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;import com.ncsi.SpringData.Entity.Person;import com.ncsi.SpringData.Repository.PersonJpaSpecificationExecutor;@RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration("classpath:springdata.xml")public class TestPersonJpaSpecificationExecutor {      @Autowired(required=false)      PersonJpaSpecificationExecutor personJpaSpecificationExecutor;      @Test      public void testpersonJpaSpecificationExecutor(){          Person p=new Person();          p.setLastName("liu");          p.setEmail("@qq.com");           List<Person> persons=personJpaSpecificationExecutor.findAll(new Specification<Person>(){            @Override            public Predicate toPredicate(Root<Person> root,CriteriaQuery<?> query, CriteriaBuilder cb) {                // TODO Auto-generated method stub                List<Predicate> list=new ArrayList<Predicate>();                list.add(cb.equal(root.get("lastName").as(String.class),p.getLastName()));                list.add(cb.equal(root.get("email").as(String.class),p.getEmail()));                Predicate[] p2 = new Predicate[list.size()];                query.where(cb.and(list.toArray(p2)));                return query.getRestriction();            }      });    System.out.println(persons);}}
Hibernate:     select        person0_.id as id1_0_,        person0_.birth as birth2_0_,        person0_.email as email3_0_,        person0_.last_name as last_nam4_0_     from        jpa_person person0_     where        person0_.last_name=?         and person0_.email=?17:55:55.351 [main] DEBUG o.s.orm.jpa.JpaTransactionManager - Initiating transaction commit17:55:55.351 [main] DEBUG o.s.orm.jpa.JpaTransactionManager - Committing JPA transaction on EntityManager [org.hibernate.ejb.EntityManagerImpl@7561db12]17:55:55.351 [main] DEBUG o.s.orm.jpa.JpaTransactionManager - Closing JPA EntityManager [org.hibernate.ejb.EntityManagerImpl@7561db12] after transaction17:55:55.351 [main] DEBUG o.s.o.jpa.EntityManagerFactoryUtils - Closing JPA EntityManager[Person [id=1, lastName=liu, email=@qq.com, birth=0912]]

这里面只是查询了where 条件的两个字段 当在项目中查询 插入数据是否在数据库中有相同数据的时候就可以使用这个,当然是在表的字段有许多个的时候,就可以用这个 返回的就是某些字段相同的数据的集合

为什么不直接继承Repository呢

当在继承Repository时 PersonJpaSpecificationExecutor 不会报错,只有一个警告,但是在运行时会出现PersonJpaSpecificationExecutor
no such bean这样的错误 也就是说没有起作用

我也试着直接在xml文件中以<bean id="personJpaSpecificationExecutor" class="com.ncsi.SpringData.Repository.PersonJpaSpecificationExecutor"/>的形式注册这个接口到容器中 但是由于我是注册的接口,所以我的理解是没有实现类只是一个接口 也就无法被容器实例化了
这两样都是不行的 暂时还没想到不继承JpaRepository 又能运行不报错的方法