Spring Data JPA映射嵌套实体

3
我对在Spring Data JPA中使用投影有些困惑。我想通过在一个查询中仅请求所需的列(最好)来优化我的查询,而我认为使用投影是一个好主意。但是似乎使用嵌套投影会变得开放,并请求所有列,进一步嵌套是不可能的。
我尝试使用@Query(无法找到如何映射嵌套列表),@EntityGraph(无法找到如何请求指定的列)和@SqlResultSetMapping(无法找到如何映射嵌套列表)寻找解决方案,但这对我没有用。除了手动映射List<Object[]>之外,是否还有其他解决方案?
我有以下实体类(简化问题):
public class TestAttempt{
    private Long id;
    private User targetUser;
    private Test test;
}

public class Test{
    private Long id;
    private String name;
    private Set<Question> questions;
}

public class Question{
    private Long id;
    private String name;
    private Test test;
}

我想写这样的代码(可以只使用null填充未使用的字段):TestAttempt

public interface TestAttemptList {
    Long getId();
    Test getTest();

    interface Test {
        String getName();

        List<Question> getQuestions();

        interface Question {
            String getName();
        }
    }
}

public interface TestAttemptRepository extends JpaRepository<TestAttempt, Long> {
    List<TestAttemptList> getAllByTargetUserId(Long targetUserId);
}

结果会得到类似于这样的东西:

{
    id: 1,
    test: {
        name: test1,
        questions: [{
            name: quest1
        }, {
            name: quest2
        }]
    }
}

这个回答解决了你的问题吗?使用自定义集合属性进行 JPA 投影 - Alan Hay
@AlanHay,我尝试手动编写查询语句,但似乎Spring无法映射具有2个字段的嵌套实体,我得到了“当子查询未引入EXISTS时,选择列表中只能指定一个表达式”的错误提示。即使我在查询中去掉了questions字段,getTest()方法仍会抛出IllegalAccessException异常,因为框架将test映射为String类型。 - Aliar
1个回答

0
我做过类似的事情...您将拥有存储库接口,这些接口将使用完整对象(例如TestAttempt)扩展CrudRepository等。您单独定义投影。投影接口可以包含其他投影接口(例如TestAttemptSummary可以包含TestSummary)。当在给定存储库中使用投影接口时,所定义的方法将应用于配置为该存储库类型的对象类型。就像这样。
public interface TestAttemptSummary {
    Long getId();
    TestSummary getTest();
}

public interface TestSummary {
    String getName();
    List<QuestionSummary> getQuestions();
}

public interface QuestionSummary {
    String getName();
}

public interface TestAttemptRepository extends CrudRepository<TestAttempt, Long> {
    TestAttemptSummary getTestAttemptSummary();
}

我尝试过这样做。但是问题无法通过查询获取(生成的查询看起来像这样:_select ... from test_attempt ta inner join test t on ta.test_id = t.id_),因此当我尝试从测试中获取Questions()时,我会收到LazyInitializationException异常。 - Aliar

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接