Spring Data Jpa, выберите на основе двух значений столбца - PullRequest
1 голос
/ 23 сентября 2019

Доброе утро,

У меня есть следующая таблица:

_____________________
Name    Status    Num
A       Good      6
B       Bad       6
C       Bad       7

Я хочу выбрать все строки, где "Status = 'Good' AND Num = '6'" OR "Status= 'Bad' AND Num = '7' "

Так что я бы выбрал строки с именами A и C из вышеуказанных справочных данных.

Я надеюсь, что смогу передать в два равныхразмерные списки (упорядоченные так, как я хочу, чтобы запрос был составлен), но не смогли понять это.Запрос стандартных запросов (SelectXByStatusAndNum) генерирует SQL с использованием операторов «IN» и возвращает все 3 строки в приведенных выше данных вместо двух.

Любое понимание приветствуется

Ответы [ 2 ]

0 голосов
/ 23 сентября 2019

Вместо списков одинакового размера я предлагаю создать объект со статусом и номером и предоставить список из них - я назвал его CustomCriteria ниже.Поскольку не существует простого способа справиться с этим с помощью стандартных методов запроса данных Spring, я считаю, что лучший способ - это сделать это с помощью построителя критериев в настраиваемом репозитории, который строит список OR из списка предикатов AND на основе записей критериев впредоставленный список.Например:

    public List<YourTable> findMatching(List<CustomCriteria> customCriteriaList) {
        CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
        CriteriaQuery<YourTable> criteriaQuery = criteriaBuilder.createQuery(YourTable.class);
        Root<YourTable> itemRoot = criteriaQuery.from(YourTable.class);

        List<Predicate> predicates = new ArrayList<>(customCriteriaList.size());
        for (CustomCriteria customCriteria : customCriteriaList) {

            Predicate predicateForNum
                    = criteriaBuilder.equal(itemRoot.get("num"), customCriteria.getNum());
            Predicate predicateForStatus
                    = criteriaBuilder.equal(itemRoot.get("status"), customCriteria.getStatus());
            predicates.add(criteriaBuilder.and(predicateForNum, predicateForStatus));
        }

        Predicate finalPredicate = criteriaBuilder.or(predicates.toArray(new Predicate[predicates.size()]));
        criteriaQuery.where(finalPredicate);
        return entityManager.createQuery(criteriaQuery).getResultList();
    }
0 голосов
/ 23 сентября 2019

Я считаю, что лучше всего использовать аннотацию @Query в репозитории:

@Entity
@Table(name = "table_name")
public class TableName {

  @Id
  @Basic(optional = false)
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  @Column(name = "ID")
  private Long id;

  @Column(name = "name")
  private String name;
  @Column(name = "status")
  private String status;
  @Column(name = "num")
  private Integer num;

/**
* getters/setters, etc
**/

public interface TableNameRepository extends CrudRepository<TableName, Long> {

  @Query("select t from TableName t where (status = :status1 and num = :num1 or status = :status2 and num = :num2)")
  List<TableName> findByStatusAndNumOrStatusAndNum(@Param("status1") String status1,
      @Param("num1") Integer num1, @Param("status2") String status2, @Param("num2") Integer num2);
}

Это способ получить значения для заданных параметров.В случае коллекций в качестве параметров нет встроенного ящика из-за концепции RDBMS.Вы можете просто написать некоторый код Java, основанный на значении ключа, и собрать результаты:

public interface TableNameRepository extends CrudRepository<TableName, Long> {
  List<TableName> findByStatusAndNumIn(String status, Collection<Integer> nums);
}

List<TableName> result = new ArrayList<>();

List<TableName> itemGood = findByStatusAndNumIn("Good", numsGood);
List<TableName> itemBad = findByStatusAndNumIn("Bad", numsBad);

result.addAll(itemGood);
result.addAll(itemBad);
...