【问题标题】:JPA specification to select unique rows based on single distinct column基于单个不同列选择唯一行的 JPA 规范
【发布时间】:2020-04-27 11:40:58
【问题描述】:

我想选择具有不同电子邮件的行,请参见下面的示例表:

+----+---------+-------------------+-------------+
| id | title   | email             | commentname |
+----+---------+-------------------+-------------+
|  3 | test    | rob@hotmail.com   | rob         |
|  4 | i agree | rob@hotmail.com   | rob         |
|  5 | its ok  | rob@hotmail.com   | rob         |
|  6 | hey     | rob@hotmail.com   | rob         |
|  7 | nice!   | simon@hotmail.com | simon       |
|  8 | yeah    | john@hotmail.com  | john        |
+----+---------+-------------------+-------------+

期望的结果是:

+----+-------+-------------------+-------------+
| id | title | email             | commentname |
+----+-------+-------------------+-------------+
|  3 | test  | rob@hotmail.com   | rob         |
|  7 | nice! | simon@hotmail.com | simon       |
|  8 | yeah  | john@hotmail.com  | john        |
+----+-------+-------------------+-------------+

我不在乎返回哪个 id 列值。可以为此使用什么 JPA 规范?

这里是规范类,

public class UserSearchSpecification implements Specification<UserSearch> {

    private static final Logger LOGGER = LogManager.getLogger(UserSearchSpecification.class);

    private static final long serialVersionUID = 1L;
    private List<SearchCriteria> list;

    /**
     * Custom JPA Specification Constructor
     * 
     */
    public UserSearchSpecification() {
        this.list = new ArrayList<>();
    }

    public void add(SearchCriteria criteria) {
        list.add(criteria);
    }

    @Override
    public Predicate toPredicate(Root<UserSearch> root, CriteriaQuery<?> arg1, CriteriaBuilder builder) {
         //create a new predicate list
        List<Predicate> predicates = new ArrayList<>();

        //add add criteria to predicates
        for (SearchCriteria criteria : list) {
            if (criteria.getOperation() == (SearchOperation.GREATER_THAN)) {
                predicates.add(builder.greaterThan(
                        root.get(criteria.getKey()), criteria.getValue().toString()));
            } else if (criteria.getOperation() == (SearchOperation.LESS_THAN)) {
                predicates.add(builder.lessThan(
                        root.get(criteria.getKey()), criteria.getValue().toString()));
            } else if (criteria.getOperation() == (SearchOperation.GREATER_THAN_EQUAL)) {
                predicates.add(builder.greaterThanOrEqualTo(
                        root.get(criteria.getKey()), criteria.getValue().toString()));
            } 
        }

        return builder.and(predicates.toArray(new Predicate[0]));
    }

}

【问题讨论】:

  • 在你的仓库界面中使用@Query
  • @GolamMazidsajib 我正在为此编写规范。你能就此提出建议吗?
  • 但这并不是不同的工作方式。不同的只有电子邮件和评论名
  • 显示你的规范类
  • @SimonMartinelli 我只是以上表为例。我有一张不同的桌子,这只是一个用例。

标签: spring-boot jpa spring-data-jpa


【解决方案1】:

我非常讨厌 JPAs Criteria API 来生成实际代码,但基本思想是您创建以下构造:

from MyEntity e 
where e.id in (
    select min(id) 
    from MyEntity e2 
    where e.email = e2.email
)

这应该可以用 Criteria API 来表达,因此也可以用 Spring Data JPA 规范来表达。

【讨论】:

    猜你喜欢
    • 2012-01-06
    • 1970-01-01
    • 1970-01-01
    • 2020-03-03
    • 1970-01-01
    • 2019-10-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多