我在使用简单的Spring Data查询或@Query或QueryDSL在Spring Data中构建查询时遇到问题。

如何选择三列(研究,国家/地区,登录名)不同的行,并且作为查询的结果将成为用户的对象类型列表?

表:

-------------------------------------
| User |
-------------------------------------
| Id | Study | Country | Site | Login | -------------------------------------
| 1 | S1 | US | 11 | user1 |
| 2 | S1 | US | 22 | user1 |
| 3 | S1 | US | 33 | user1 |
| .. | .. | .. | .. | .. |
-------------------------------------

我需要一个仅基于Study的查询,该查询将仅对每个LoginCountry返回唯一用户,并且不考虑Site列。

方法签名如下:

List<User> findByStudyIgnoreCase(String study);


现在从表Users返回所有行。因此,我在研究和国家/地区重复了有关用户分配的行,因为在其他表中有UI演示文稿,其中不需要Site

所以,我需要这样的东西:

select distinct Study, Country, Login from User


但是返回的对象必须是User对象,就像方法签名所说的一样(例如,首先匹配结果)。

怎么做到呢?


有可能以这种方式或类似的方式吗?如何使其正确?

@Query("SELECT DISTINCT s.study, s.country, s.login FROM user s where s.study = ?1 ")List<User> findByStudyIgnoreCase(String study);
可以使用QueryDSL吗?


----编辑----

我试图通过QueryDSL编写查询,如TimoWestkämper建议的那样,但我遇到了问题。

    public List<User> findByStudyIgnoreCase(String study) {
        QUser $ = QUser.user;
        BooleanExpression studyExists = $.study.equalsIgnoreCase(study);

        List<Users> usersList = from($)
            .where(studyExists)
            .distinct()
            .list(Projections.bean(User.class, $.study, $.country, $.id.login));

        return usersList;
    }


调用上面的查询后,发生异常:

org.springframework.dao.InvalidDataAccessApiUsageException: The bean of type: com.domain.app.model.User has no property called: study; nested exception is java.lang.IllegalArgumentException: The bean of type: com.domain.app.model.User has no property called: study


为什么会这样呢?

----编辑2 ----

我的User课:

@Entity
@Table(name="USER")
@Immutable
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Getter @EqualsAndHashCode @ToString
@FieldDefaults(level=AccessLevel.PRIVATE)
public class User {

    @EmbeddedId
    UserId id;

    @Column(name="CONTACT_UNIQUE_ID")
    String contactUniqueId;

    String country;

    @Column(name="COUNTRY_CODE")
    String countryCode;

    @Column(name="STUDY")
    String study;

    String firstname;

    String lastname;

    String email;

    String role;
}


可嵌入的UserId类:

@Embeddable
@Getter @EqualsAndHashCode @ToString
@NoArgsConstructor
@AllArgsConstructor
@FieldDefaults(level=AccessLevel.PRIVATE)
public class UserId implements Serializable {

    private static final long serialVersionUID = 1L;

    String site;
    String login;

}


生成的QUser类:

@Generated("com.mysema.query.codegen.EntitySerializer")
public class QUser extends EntityPathBase<User> {

    private static final long serialVersionUID = 1646288729;

    private static final PathInits INITS = PathInits.DIRECT;

    public static final QUser user = new User("user");

    public final StringPath contactUniqueId = createString("contactUniqueId");

    public final StringPath country = createString("country");

    public final StringPath countryCode = createString("countryCode");

    public final StringPath study = createString("study");

    public final StringPath email = createString("email");

    public final StringPath firstname = createString("firstname");

    public final QUser id;

    public final StringPath lastname = createString("lastname");

    public final StringPath role = createString("role");

    public QUser(String variable) {
        this(User.class, forVariable(variable), INITS);
    }

    @SuppressWarnings("all")
    public QUser(Path<? extends User> path) {
        this((Class)path.getType(), path.getMetadata(), path.getMetadata().isRoot() ? INITS : PathInits.DEFAULT);
    }

    public QUser(PathMetadata<?> metadata) {
        this(metadata, metadata.isRoot() ? INITS : PathInits.DEFAULT);
    }

    public QUser(PathMetadata<?> metadata, PathInits inits) {
        this(User.class, metadata, inits);
    }

    public QUser(Class<? extends User> type, PathMetadata<?> metadata, PathInits inits) {
        super(type, metadata, inits);
        this.id = inits.isInitialized("id") ? new QUser(forProperty("id")) : null;
    }

}

最佳答案

我可以回答Querydsl部分。它通过

List<User> users = query.from(user)
  .where(user.study.eq(arg))
  .distinct()
  .list(Projections.fields(User.class, user.study, user.country, user.login));


您将获得带有填充的研究,国家和登录字段的用户实例。 User实例不是托管的JPA实体,而是填充的Bean。

或者,您可以像这样查询Tuple实例

List<Tuple> tuples = query.from(user)
  .where(user.study.eq(arg))
  .distinct()
  .list(user.study, user.country, user.login);


但是当您使用Spring Data时,您可能希望返回Users。

10-08 16:35