我在使用简单的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
的查询,该查询将仅对每个Login
和Country
返回唯一用户,并且不考虑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。