我在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
正如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中的查询截图。
这将太长而无法发表评论:
while (rs.next()) { if (rs.getLong(“b_id”) != bookId) { break; } else {
while
之后的第一个if
正在吃掉当前之后的行(调用行映射器时是当前行的行)。您跳过了对bookId,authorId等的处理(将数据放入Java对象中)。这就是为什么你会得到
不一致的结果,而查询本身返回正确的结果。
因此,您需要重新考虑如何处理数据。我看到两条路径:
也慢慢来,查查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-