【发布时间】:2014-03-27 20:42:29
【问题描述】:
我在使用简单的 Spring Data 查询或 @Query 或 QueryDSL 在 Spring Data 中构建查询时遇到问题。
如何选择三列(Study、Country、Login)不同的行并作为查询的结果将是用户的对象类型列表?
表:
-------------------------------------
| 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);
现在正在返回表用户中的所有行。因此,我在 Study 和 Country 中重复了有关用户分配的行,因为我在不需要 Site 的其他表中有 UI 演示。
所以,我需要类似的东西:
select distinct Study, Country, Login from User
但返回对象必须是用户对象,就像方法签名所说的一样(例如匹配结果的第一个)。
怎么做?
-
是否有可能以这种方式或类似方式?如何让它正确?
@Query("SELECT DISTINCT s.study, s.country, s.login FROM user s where s.study = ?1 ") List<User> findByStudyIgnoreCase(String study); 是否可以使用 QueryDSL?
---- 编辑----
我尝试像 TimoWestkämper 建议的那样通过 QueryDSL 编写查询,但我遇到了问题。
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;
}
}
【问题讨论】:
-
这样可以吗?你为什么不试试呢?
-
@JBNizet 我试过了,但我得到的对象不是用户,而是只有研究、国家和登录值,所以这不是我所期望的......
-
这是意料之中的事,因为您的查询选择了研究、国家和登录名。
-
所以您想要用户实例,但根据不同的研究、国家和登录属性进行过滤?
-
@TimoWestkämper 是的。您在回答中的建议很好,但对我不起作用,我更新了我的回答内容
标签: java sql spring-data querydsl