14

我有一个看起来像这样的课程。我需要从两个数据库表中填充它,它们也如下所示。有没有首选的方法来做到这一点?

我的想法是有一个服务类来从 DAO中选择一个List<>via a 。ResultSetExtractor然后foreach在该列表上执行 a ,并List<>通过 another 为个人选择一封电子邮件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)
);
4

3 回答 3

18

这最好通过 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();
于 2013-05-09T12:48:25.867 回答
0

我一直在寻找类似的东西,尽管答案完全有效,但我还是选择了这个不错的库https://simpleflatmapper.org/0203-joins.html

它还与 Spring Boot 完美集成。

主要优点是您有一个干净的存储库层,它使用您的 pojo 并使重构更加容易,并且像休眠一样,您仍然可以映射深度嵌套和复杂的一对多,并且仍然可以控制执行的内容。

它还有一个很好的 jdbctemplate CRUD,Java 13 最终带来了对多行字符串文字的支持,这对 sql 语句的可读性非常好。希望这可以帮助某人:)

于 2020-01-19T18:56:23.007 回答
-2

就我而言,我必须使用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());
    });
}
于 2020-06-26T20:36:39.427 回答