【问题标题】:How to create specification using JpaSpecificationExecutor by combining tables?如何通过组合表使用 JpaSpecificationExecutor 创建规范?
【发布时间】:2016-05-14 02:23:08
【问题描述】:

我正在使用JpaSpecificationExecutor 创建自定义查询。如何为以下 SQL 创建规范?

select * from employee e, address a where e.id=23415 and e.name="Foo" and a.city="London";

Java 类:

public static Specification<Employee> searchEmployee(final Map<String,String> myMap) {
    
    return new Specification<Employee>(){
        @Override
        public Predicate toPredicate(Root<Employee> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
               
             //Need to query two tables Employee and Address  
             
           }
      }

【问题讨论】:

    标签: java spring-data-jpa spring-data jpa-2.0 criteria-api


    【解决方案1】:

    这是一个有效的测试

    @Test
    public void test1() {
    
        repository.save(makeEmployee("billy", "London"));
        repository.save(makeEmployee("noby", "London"));
        repository.save(makeEmployee("fred", "London"));
    
        assertEquals(3, repository.count());
    
        final Long id = 3l;
        final String name = "noby";
        final String city = "London";
    
        Specification<Employee> specification = new Specification<Employee>() {
            public Predicate toPredicate(Root<Employee> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
                List<Predicate> predicates = new ArrayList<Predicate>();
                predicates.add(builder.equal(root.get("id"), id));
                predicates.add(builder.equal(root.get("name"), name));
                predicates.add(builder.equal(root.get("address").get("city"), city));
                return builder.and(predicates.toArray(new Predicate[predicates.size()]));
            }
        };
    
        List<Employee> find = repository.findByIdAndNameAndAddressCity(id, name, city);
        assertEquals(1, find.size());
    
        find = repository.findAll(specification);
        assertEquals(1, find.size());
    }
    
    private Employee makeEmployee(String name, String city) {
    
        Address address = new Address();
        address.setCity(city);
    
        Employee employee = new Employee();
        employee.setName(name);
        employee.setAddress(address);
        return employee;
    }
    

    }

    存储库看起来像这样

    @Repository
    public interface EmployeeRepository extends JpaRepository<Employee, Long>, JpaSpecificationExecutor<Employee> {
    
        List<Employee> findByIdAndNameAndAddressCity(Long id, String name, String city);
    }
    

    实体看起来像这样

    @Entity(name = "EMPLOYEE")
    public class Employee {
    
        @Id
        @GeneratedValue(strategy = GenerationType.AUTO)
        private Long id;
    
        @Column(name = "NAME")
        private String name;
    
        @Column(name = "DATE_OF_BIRTH")
        private Date dob;
    
        @OneToOne(cascade=CascadeType.ALL)
        @JoinColumn(name = "address_id", referencedColumnName = "id", nullable = false)
        private Address address;
    

    希望这会有所帮助。

    【讨论】:

    • 我同意这适用于一张桌子。在上面的代码中,您有一个表(EMPLOYEE)来保存员工和地址的详细信息。但我分别有 2 个表 EMPLOYEE 和 ADDRESS 表。我需要使用规范查询两个表。有什么建议吗?
    • 抱歉没有阅读这个问题,我已经更正了答案。
    • @OneToMany 在 Employee 上,因此它希望 FK 到 Address PK 在 Employee 表上。即员工上应该有一个 address_id 列。不知道为什么你得到上述,我觉得不合适。
    • 我在表中有一个 FK 参考。问题在于定义谓词。我已经使用以下方法来克服它在规范内 Join join = root.join("address");在构建谓词而不是使用 root 时,我使用了 predicates.add(builder.equal(join.get("city"), city));
    猜你喜欢
    • 2014-01-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-20
    • 2016-06-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多