当前位置: 首页 > 知识库问答 >
问题:

在Dropwizard中使用JDBi3映射到具有多对多关系的DTO类的问题

娄振
2023-03-14


我在DAO界面中使用PostgreSQL查询映射通过JDBi3检索的数据时遇到了问题。在我的Dropwzo应用程序中,我有Book DTO类,它与作者和类别DTO类有多对多关系,并且在将查询的行映射到BookDTO类时遇到了问题。以下是DTO类的代码片段:

class BookDTO {
  private Long bookId;
  // other fields are left for code brevity 
  private List<Long> authors; 
  private List<Long> categories;

  // empty constructor + constructor with all fields excluding Lists + getters + setters
}

class AuthorDTO {
  private Long authorId;
  // other fields are left for code brevity 
  private List<Long> books; 

  // empty constructor + constructor with all fields excluding List + getters + setters
}

class CategoryDTO {
   private Long categoryId;
   // other fields are left for code brevity 
   private List<Long> books;

   // empty constructor + constructor with all fields excluding List + getters + setters
}


…由于我使用JDBi3 DAO接口来执行CRUD操作,这就是我查询数据库中所有书籍的方法的样子:

    @Transaction
    @UseRowMapper(BookDTOACMapper.class)
    @SqlQuery("SELECT book.book_id AS b_id, book.title, book.price, book.amount, book.is_deleted, author.author_id AS aut_id, category.category_id AS cat_id FROM book " +
            "LEFT JOIN author_book ON book.book_id = author_book.book_id " +
            "LEFT JOIN author ON author_book.author_id = author.author_id " +
            "LEFT JOIN category_book ON book.book_id = category_book.book_id " +
            "LEFT JOIN category ON category_book.category_id = category.category_id ORDER BY b_id ASC, aut_id ASC, cat_id ASC")
    List<BookDTO> getAllBooks();


。这是BookDTOACMapper类的映射方法,如下所示:

public class BookDTOACMapper implements RowMapper<BookDTO> {

        @Override
        public BookDTO map(ResultSet rs, StatementContext ctx) throws SQLException {      
            final long bookId = rs.getLong("b_id");
            // normally retrieving values by using appropriate rs.getXXX() methods

            Set<Long> authorIds = new HashSet<>();
            Set<Long> categoryIds = new HashSet<>();
            long authorId = rs.getLong("aut_id");
            if (authorId > 0) {
                authorIds.add(authorId);
            }
            long categoryId = rs.getLong("cat_id");
            if (categoryId > 0) {
                categoryIds.add(categoryId);
            }    

            while (rs.next()) {
                if (rs.getLong("b_id") != bookId) {
                    break;
                } else {
                    authorId = rs.getLong("aut_id");
                    if (authorId > 0) { authorIds.add(authorId); }

                    categoryId = rs.getLong("cat_id");
                    if (categoryId > 0) { categoryIds.add(categoryId); }
                }
            }
            final List<Long> authorIdsList = new ArrayList<>(authorIds);
            final List<Long> categoryIdsList = new ArrayList<>(categoryIds);

            return new BookDTO(bookId, title, price, amount, is_deleted, authorIdsList, categoryIdsList);
        }
}

我遇到的问题是,当调用我的GET方法(在从BookDAO类调用< code>getAllBooks()方法的资源类中定义)时,显示不一致的结果,而查询本身返回正确的结果。

我设法在Stackoverflow,官方JDBi3 Docs API和Google群组上找到的许多问题都在考虑一对多关系,并使用@UseRowReducer注释,其中包含包含LinkedHashMapRowReducer元素的类。

使用的工具版本:
Dropwizard framework 1.3.8
PostgreSQL 11.7
Java8


共有2个答案

凤安然
2023-03-14

正如zloster在他的回答中提到的,我选择了第二个选项(对于多对多的关系,我选择了第二个选项),即在< code >列表上方使用edit my PostgreSQL query < code > @ SQL query 注释

    @UseRowMapper(BookDTOACMapper.class)
    @SqlQuery("SELECT b.book_id AS b_id, b.title, b.price, b.amount, b.is_deleted, ARRAY_AGG(aut.author_id) as aut_ids, ARRAY_AGG(cat.category_id) as cat_ids " +
            "FROM book b " +
            "LEFT JOIN author_book ON author_book.book_id = b.book_id " +
            "LEFT JOIN author aut ON aut.author_id = author_book.author_id " +
            "LEFT JOIN category_book ON category_book.book_id = b.book_id " +
            "LEFT JOIN category cat ON cat.category_id = category_book.category_id " +
            "GROUP BY b_id " +
            "ORDER BY b_id ASC")
    List<BookDTO> getAllBooks();

因此map(…)BookDTOACMapper类的方法必须被编辑,现在看起来像这样:

  @Override
  public BookDTO map(ResultSet rs, StatementContext ctx) throws SQLException {
    final long bookId = rs.getLong("b_id");
    String title = rs.getString("title");
    double price = rs.getDouble("price");
    int amount = rs.getInt("amount");
    boolean is_deleted = rs.getBoolean("is_deleted");

    Set<Long> authorIds = new HashSet<>();
    Set<Long> categoryIds = new HashSet<>();

    /* rs.getArray() retrives java.sql.Array and after it getArray gets
       invoked which returns array of Object(s) which are being casted 
       into array of Long elements */
    Long[] autIds = (Long[]) (rs.getArray("aut_ids").getArray());
    Long[] catIds = (Long[]) (rs.getArray("cat_ids").getArray());

    Collections.addAll(authorIds, autIds);
    Collections.addAll(categoryIds, catIds);

    final List<Long> authorIdsList = new ArrayList<>(authorIds);
    final List<Long> categoryIdsList = new ArrayList<>(categoryIds);

    return new BookDTO(bookId, title, price, amount, is_deleted, authorIdsList, categoryIdsList);
  }

现在所有的结果都是一致的,下面是pgAdmin4中的查询截图。

楚权
2023-03-14
匿名用户

这将太长而无法发表评论:

  1. 这基本上是一个调试问题。为什么

while (rs.next()) { if (rs.getLong(“b_id”) != bookId) { break; } else {

while 之后的第一个if 正在吃掉当前之后的行(调用行映射器时是当前行的行)。您跳过了对bookId,authorId等的处理(将数据放入Java对象中)。这就是为什么你会得到

不一致的结果,而查询本身返回正确的结果。

因此,您需要重新考虑如何处理数据。我看到两条路径:

    < li >当停止给定< code>bookId的处理时,重新访问处理循环的逻辑以存储数据。这可以通过可滚动的< code >结果集来实现,即在< code >制动之前请求一个可滚动的< code >结果集;调用< code>rs.previous()。下次调用行映射器时,处理将从结果集中正确的行开始。 < li >使用SQL/PostgreSQL的强大功能并正确执行:https://DBA . stack exchange . com/questions/173831/convert-right-side-of-join-of-many to-many into-array聚合并调整数据库中的数据。数据库是这项工作的最佳工具。

也慢慢来,查查https://DBA . stack exchange . com/users/3684/Erwin-brands tetter的其他回答。他们对SQL和PostgreSQL给出了宝贵的见解。

 类似资料:
  • 在我的Spring Boot应用程序中,我想将用户角色多对多关系保存在数据库中相应的映射表中,但hibernate给了我一条错误消息。 我的User.java班: 我的Role.java课: 我的跑步方法: Hibernate向我提供了一条错误消息: 无法添加或更新子行:外键约束失败(。, CONSTRAINTFOREIGN KEY()REFERENCES()ON DELETE CASCADE O

  • 我正在hibernate的帮助下开发一个电子购物程序。因为我是jsp、servlet、hibernate的新手,我不知道如何使用关系表中的附加列进行多对多关系映射。我已经阅读了几篇教程,但其中大部分都是关于hibernate社区的注释映射和文档,但没有一篇适合我的情况。 我有三个表,分别是电影信息表、订单详情表和订单详情表(关系表),其中订单详情表的结构如下所示。 我正在尝试使用四个POJO类来实

  • 我想使用XML映射在Hibernate中映射多对多的关系。 我有两个类,和。我想创建一个链接表女巫将包含复合键和3个额外的列

  • 本文向大家介绍MyBatis中多对多关系的映射和查询,包括了MyBatis中多对多关系的映射和查询的使用技巧和注意事项,需要的朋友参考一下 先说一下需求:  在页面上显示数据库中的所有图书,显示图书的同时,显示出该图书所属的类别(这里一本书可能同时属于多个类别) 创建表:  笔者这里使用中间表连接图书表和图书类别表,图书表中没有使用外键关联图书类别表  而是在中间表中引用了图书主键和类别主键  通

  • DBSchema-2表(用户和角色)具有多对多关系,并由postgres中的中间表(用户角色)桥接。我想获取所有角色和创建它的人的姓名。名称在用户表中可用,但所有其他详细信息在角色表中。Roles表中有一个由创建人(创建角色的人的用户id)创建的字段。 我正在尝试构建一个GET请求,以查看给定id的所有角色以及创建id的人的姓名 实体类Users1.java 实体类角色。JAVA 角色。存储库类

  • 我想知道Mapstruct是否以及如何帮助映射具有双向关系的ojects(在我的情况下是一对多): 从/映射到实体会产生。(我希望这会发生)。另一方面,封闭的Mapstruct问题469和1163似乎意味着Mapstruct不会直接支持它。我尝试了这个例子: https://github.com/mapstruct/mapstruct-examples/tree/master/mapstruct-