Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/341.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 带多通的Spring数据JPA投影_Java_Spring Data Jpa_Jpql - Fatal编程技术网

Java 带多通的Spring数据JPA投影

Java 带多通的Spring数据JPA投影,java,spring-data-jpa,jpql,Java,Spring Data Jpa,Jpql,我有以下两个实体: @Entity public class Author { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String userName; // Getters/setters } @Entity public class Comment { @Id @GeneratedValue(strategy

我有以下两个实体:

@Entity
public class Author {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String userName;
    // Getters/setters
}

@Entity
public class Comment {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @ManyToOne
    @JoinColumn(name = "author_id")
    private Author author;

    private String comment;
    // Getters/setters
}
我想在SpringDataJPA存储库中生成一个JPQL查询,它为我提供作者及其所有评论。我的预测是

public interface AuthorProjection {
    String getUserName();
    List<String> getComments();
}
我的测试数据由一位作者和两位注释组成。不幸的是,当我运行这个程序时,我总是得到两个作者(实际上是同一个作者),每个作者都有一条评论。这当然是DB返回每一行的方式(原始SQL看起来不错,应该是这样的)。Hibernate或Spring Data JPA(或任何负责人)是否可以将所有注释合并到列表中,或者我是否需要编写基于作者id合并行的Java代码

如果可能的话,我希望DB已经执行了所有的数据转换,并且有一个结构良好的投影作为查询的输出

我的演示测试是:

@DataJpaTest
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
@Transactional(propagation = Propagation.NOT_SUPPORTED)
class JpatestApplicationTests {

    @Autowired
    private AuthorRepository authorRepository;

    @Autowired
    private CommentRepository commentRepository;

    @Test
    void contextLoads() {
        var author = new Author();
        author.setUserName("John Doe");
        var savedAuthor = authorRepository.save(author);

        var comment1 = new Comment();
        comment1.setComment("First comment").setAuthor(savedAuthor);
        commentRepository.save(comment1);

        var comment2 = new Comment();
        comment2.setComment("Second comment").setAuthor(savedAuthor);
        commentRepository.save(comment2);

        authorRepository.authorsWithComments().forEach(
                projection -> System.out.printf("%s, %s\n", projection.getUserName(), projection.getComments())
        );
    }
}
这将提供以下输出:

John Doe, [First comment]
John Doe, [Second comment]
并直接在PostgreSQL中运行,它提供:

 col_0_0_ | col_1_0_ |    col_2_0_
----------+----------+----------------
        1 | John Doe | First comment
        1 | John Doe | Second comment
(2 rows)
我预期的Java输出是:

John Doe, [First comment, Second comment]

JPA甚至可以这样做吗?

使用
作者
实体中的关系来获取作者的评论

@OneToMany(mappedBy = "author")
private List<Comment> comments = new ArrayList<>();
@OneToMany(mappedBy=“author”)
私有列表注释=新建ArrayList();
那么这样问吧

@Query(value= "SELECT a.userName as userName, a.comments as comments from Author a")
List<AuthorProjection> authorsWithComments();
@Query(value=“选择a.userName作为用户名,a.comments作为作者a的注释”)
使用注释()列出作者;
和投影一样

public interface AuthorProjection {
    String getUserName();
    List<Comment> getComments();
}
公共接口AuthorProjection{
字符串getUserName();
List getComments();
}

您只需查询作者即可获得所有评论。您需要在Author类中添加额外的列表

@OneToMany(mappedBy=“author”,fetch=FetchType.LAZY)
私有列表注释=新建ArrayList();
然后,您可以使用JAP Reposity

@存储库
公共接口AuthorRepository扩展了crudepository{
}

crudepository
已经实现了许多有用的API,例如
findAll()
findById()
,您不需要编写任何sql。

您可以添加原始sql查询吗?我用一个简单的工作示例对其进行了更新。在不更改实体的情况下也可以这样做吗?我的实际查询像这样复杂得多,我不想改变实体。但是我想让数据库做尽可能多的工作。如果你不使用关系,那么JPA如何为作者整合所有评论。您的查询在加入后返回笛卡尔乘积,这就是为什么您只得到一条注释。或者,您必须手动集成作者的所有评论。您尝试过此解决方案吗?我不能,因为没有任何关系,而且我无法说服我的同事让我添加它:-(.最后,我创建了一个事务性@Service方法,在这里我调用了多个存储库,并用Java聚合了结果。我确实想在JPQL中完全尝试,但最后我只需要结果。不过,感谢您的帮助!
@Query(value= "SELECT a.userName as userName, a.comments as comments from Author a")
List<AuthorProjection> authorsWithComments();
public interface AuthorProjection {
    String getUserName();
    List<Comment> getComments();
}