3

Я использую JpaSpecificationExecutor для создания пользовательских запросов. Как создать спецификацию для следующего SQL?Как создать спецификацию с помощью JpaSpecificationExecutor путем объединения таблиц?

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

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 

      } 
     } 

ответ

6

Вот тест, который работает

@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 выглядит следующим образом

@Repository 
public interface EmployeeRepository extends JpaRepository<Employee, Long>, JpaSpecificationExecutor<Employee> { 

    List<Employee> findByIdAndNameAndAddressCity(Long id, String name, String city); 
} 

Entity выглядит следующим образом

@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; 

Надеется, что это помогает.

+0

Я согласен, что это отлично работает для одного стола. В приведенном выше коде у вас есть одна таблица (EMPLOYEE) для хранения данных Employee и Address. Но у меня есть две таблицы EMPLOYEE и ADDRESS отдельно. Мне нужно запросить обе таблицы, используя спецификацию. Любое предложение? – Deepak

+0

Извиняюсь за то, что не прочитал вопрос, я исправил ответ. –

+0

Спасибо, что работает отлично! – Deepak