简体   繁体   中英

Querydsl - How to join multiple column's value in select expression?

I'm using Querydsl with spring data jpa. I've implemented custom repository to find out person names. The person entity looks like as follows:

@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
}

The implemented custom repository:

@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();
    }
}

In the select expression, I would like to join three columns to construct full name. If database has a record like the following -

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

then I would like to select as "Mr John Snow". Is there any way to do that?

I don't want to select whole record to concat the value because entity has others column and lots of associations and it's not good to load whole record.

You can select only the 3 columns you need by using 3.2.3. Constructor usage from Querydsl documentation.

This way you will need to join them programmatically, but you will achieve to select only the 3 columns you need.

Create a class that has only the fields you need.

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;
    }
}

Then you can create the query

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

@chris-sekas provide a good solution, but here is another one that seems to be very handy. I've used com.querydsl.core.Tuple instead of creating new 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());

It's very useful when we need few column's information only and don't need to create new DTO.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM