我有一个看起来像这样的课程。我需要从两个数据库表中填充它,如下所示。有没有首选的方法呢?
我的想法是让服务类从DAO通过List<>
选择ResultSetExtractor
。然后在该列表上执行foreach
,并通过另一个List<>
为个人选择ResultSetExtractor
个电子邮件,并使用foreach
循环将其附加。
有没有更好的方法,还是这样的好呢?
public class Person {
private String personId;
private String Name;
private ArrayList<String> emails;
}
create table Person (
person_id varchar2(10),
name varchar2(30)
);
create table email (
person_id varchar2(10),
email varchar2(30)
);
答案 0 :(得分:12)
这最好通过ORM解决。使用JDBC,您必须手动执行ORM为您执行的操作。执行N + 1个查询效率非常低。您应该执行单个查询,并手动构建对象。繁琐但不难:
select person.id, person.name, email.email from person person
left join email on person.id = email.person_id
...
Map<Long, Person> personsById = new HashMap<>();
while (rs.next()) {
Long id = rs.getLong("id");
String name = rs.getString("name");
String email = rs.getString("email");
Person person = personsById.get(id);
if (person == null) {
person = new Person(id, name);
personsById.put(person.getId(), person);
}
person.addEmail(email);
}
Collection<Person> persons = personsById.values();
答案 1 :(得分:0)
我一直在寻找类似的东西,尽管答案是完全正确的,但我还是选择了这个不错的库https://simpleflatmapper.org/0203-joins.html
它还与Spring Boot完美集成。
主要优点是您拥有一个干净的存储库层,它使用您的pojo并使重构更加容易,并且像休眠一样,您仍然可以将深层嵌套和复杂的一对多映射,并且仍然可以控制执行的内容。
它也有一个不错的jdbctemplate CRUD,并且Java 13最终带来了对多行字符串文字的支持,这对于sql语句的可读性非常好。希望这对某人有帮助:)
答案 2 :(得分:0)
对于我来说,我必须使用LinkedHashMap
来使查询结果按position
字段排序。
来自JavaDoc :
LinkedHashMap:“此链表定义了迭代顺序,通常是将键插入映射中的顺序(插入顺序)。请注意,如果键,插入顺序不会受到影响重新插入到地图中。”
HashMap:“此类无法保证地图的顺序 ;尤其是,它不能保证顺序随时间保持不变。”
提示:使用getOrDefault
方法可以消除对nullable
对象的额外检查。
public List<BucketDto> findAll() {
var sql = """
SELECT
b.uuid bucket_uuid, b.position bucket_position, b.name bucket_name,
c.uuid card_uuid, c.position card_position, c.name card_name
FROM bucket AS b
LEFT JOIN card AS c ON c.bucket_id = b.id
ORDER BY b.position ASC, c.position ASC
""";
return jdbcTemplate.query(sql, rs -> {
Map<Double, BucketDto> resultMap = new LinkedHashMap<>();
while (rs.next()) {
var position = rs.getDouble("bucket_position");
var bucketDto = resultMap.getOrDefault(position, new BucketDto(
UUID.fromString(rs.getString("bucket_uuid")),
position,
rs.getString("bucket_name")));
if (Optional.ofNullable(rs.getString("card_uuid")).isPresent()) {
bucketDto.addCard(new CardDto(
UUID.fromString(rs.getString("card_uuid")),
rs.getDouble("card_position"),
rs.getString("card_name")));
}
resultMap.put(position, bucketDto);
}
return new ArrayList<>(resultMap.values());
});
}