【问题标题】:Querydsl - How to join multiple column's value in select expression?Querydsl - 如何在选择表达式中加入多个列的值?
【发布时间】:2019-12-30 13:50:12
【问题描述】:

我正在将 Querydsl 与 spring data jpa 一起使用。我已经实现了自定义存储库来找出人名。 person 实体如下所示:

@Entity
@Table(name = "persons")
public class Person {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id", nullable = false, updatable = false)
    private Long id;

    @Column(name = "initial")
    private String initial;

    @Column(name = "first_name")
    private String firstName;

    @Column(name = "last_name")
    private String lastName;

    @Column(name = "archived")
    private Boolean archived;

    //Other columns here.. && Getter setter goes here
}

实现的自定义存储库:

@Repository
public class PersonRepositoryImpl extends QueryDslRepositorySupport 
        implements PersonRepositoryCustom {
    public PersonRepositoryImpl() {
        super(Person.class);
    }

    @Override
    public List<String> getPersonNames() {
        return getQuerydsl()
                .createQuery()
                .from(QPerson.person)
                .where(QPerson.person.archived.eq(Boolean.FALSE))
                .select(/* 
                    want to select as a full name like
                    initial + firstName + lastName
                  */)
                .fetch();
    }
}

在选择表达式中,我想加入三列来构造全名。如果数据库有如下记录 -

id | initial | firstName | lastName | archived | ...
----------------------------------------------------
1  | "Mr"    | "John"    | "Snow"   | 0        | ...

那么我想选择“Mr John Snow”。 有什么办法吗?

我不想选择整条记录来连接值,因为实体有其他列和很多关联,加载整条记录不好。

【问题讨论】:

  • 搜索JPA投影。

标签: java jpa spring-data-jpa querydsl


【解决方案1】:

您可以使用 Querydsl 文档中的 3.2.3. Constructor usage 仅选择您需要的 3 列。

这样您将需要以编程方式加入它们,但您将实现只选择您需要的 3 列。

创建一个只包含您需要的字段的类。

public class PersonDTO {
    private String initial;
    private String firstName;
    private String lastName;

    public PersonDTO(String initial, String firstName, String lastName) {
        this.initial = initial;
        this.firstName = firstName;
        this.lastName = lastName;
    }
}

然后你可以创建查询

           query.from(QPerson.person)
                .select(Projections.constructor( 
                        PersonDTO.class, 
                        QPerson.person.initial, 
                        QPerson.person.firstName, 
                        QPerson.person.lastName))
                .fetch();

【讨论】:

  • 感谢您的回答,我找到了另一种解决方案,请在评论中提出。
【解决方案2】:

@chris-sekas 提供了一个很好的解决方案,但这里有另一个似乎非常方便的解决方案。我使用 com.querydsl.core.Tuple 而不是创建新的 DTO。

QPerson person = QPerson.person;
List<Tuple> tuples = getQuerydsl()
        .createQuery()
        .from(person)
        .where(person.archived.eq(Boolean.FALSE))
        .select(person.initial, 
                person.firstName,
                person.lastName)
        .fetch();

List<String> names = tuples.stream()
        .map(t ->
                t.get(person.initial) +
                " " +
                t.get(person.firstName) +
                " " +
                t.get(person.lastName))
        .distinct()
        .collect(Collectors.toList());

当我们只需要很少的列信息并且不需要创建新的 DTO 时,它非常有用。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-07-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-19
    • 2019-04-05
    • 1970-01-01
    相关资源
    最近更新 更多