JPA/HIBERNATE:如何查询返回非实体对象或带有内部非实体对象的对象列表?

问题描述:

是否可以将自定义对象作为另一个自定义对象的内部对象包括在内? 例如,我有两个实体:

Is there a way to include a custom object as an inner object of the other custom object? For example, I have two Entites:

@Entity
class Foo {
    @Id
    private int id;

    @Column
    private String a;

    @Column
    private String b;

    @OneToMany(...)
    private Set<Bar> bars;

    ...
}

@Entity
class Bar {
    @Id
    private int id;

    @Column
    private String x;

    @Column
    private String y;

    @Column
    private String z;

    ...
}

我想编写一个查询,选择一个FooQueryResult对象,例如:

I'd like to write a query which select a FooQueryResult object like:

class FooQueryResult {
    private String a;
    private Set<BarQueryResult> bars;

    ...
}

class BarQueryResult {
    private String id;
    private String x;

    ...
}

我正在尝试以下类似的方法

I'm trying something like below

String query =
        "SELECT " +
                "s.a, " +
                "new package.BarQueryResult(f.bars.id, f.bars.x) " +
        "FROM Foo as f " +
        "WHERE f.id = ?1";

FooQueryResult site = factory.createEntityManager()
        .createQuery(query, FooQueryResult.class)
        .setParameter(1, fooId)
        .getSingleResult();

但这以错误结尾:

QuerySyntaxException: unexpected token: , near line 1, column 14 [SELECT s.a, new package.BarQueryResult(f.bars.id, f.bars.x) FROM package.Foo as f WHERE f.id = ?1]

有可能这样做吗?

开箱即用是不可能的.您应该使用select new构造函数表达式,但是有一个限制-不支持嵌套构造函数调用,您不能编写select new FooQueryResult(..., new BarQueryResult)
或者您可以使用自定义的ResultSetTransformer.但是我建议创建Transformer类并手动进行.

It's impossible out of the box. You should use select new constructor expression, but there is a restriction - the nesting constructor calls isn't supported, you can't write select new FooQueryResult(..., new BarQueryResult)
or you can use your custom ResultSetTransformer. But I suggest to create Transformer class and do it manually.