使用 Spring RowMapper 以从 JDBC 结果集中填充 Collection 类型的字段

Using a Spring RowMapper in order to populate a field of type Collection from a JDBC resultset

我正在尝试使用 Spring RowMapper 将 JDBC ResultSet 映射到 POJO,如下所示:

public class AdvertisementMapper implements RowMapper<Advertisement> {

    @Override
    public Advertisement mapRow(ResultSet rs, int rowNum) throws SQLException {
        Advertisement advertisement = new Advertisement();
        advertisement.setId(rs.getLong("id"));
        advertisement.setAdvertisementType(AdvertisementType.valueOf(rs.getString("advertisement_type")));
        advertisement.setNeed(Need.valueOf(rs.getString("need")));
        advertisement.setChildcareWorkerType(ChildcareWorkerType.valueOf(rs.getString("childcare_worker_type")));
        advertisement.setChildcareTypes(null);//COLLECTION!
        advertisement.setDayToTimeSlots(null);//COLLECTION!
        advertisement.setLanguages(null);//COLLECTION!
        advertisement.setDescription(rs.getString("description"));
        advertisement.setCreationDate(rs.getDate("creation_date"));
        advertisement.setExpirationDate(rs.getDate("expiration_date"));
        advertisement.setActive(rs.getBoolean("active"));
        advertisement.setValidated(rs.getBoolean("validated"));
        Member member = new Member();
        member.setId(rs.getLong("memberId"));
        advertisement.setMember(member);
        Address address = new Address();
        address.setLat(rs.getDouble("addressLat"));
        address.setLon(rs.getDouble("addressLon"));
        advertisement.setAddress(address);
        advertisement.setFirstAidTraining(Choice.valueOf(rs.getString("first_aid_training")));
        advertisement.setGiveBath(Choice.valueOf(rs.getString("give_bath")));
        advertisement.setPrepareMeals(Choice.valueOf(rs.getString("prepare_meals")));
        advertisement.setHelpWithHomework(Choice.valueOf(rs.getString("help_with_homework")));
        advertisement.setCleaningIroning(Choice.valueOf(rs.getString("cleaning_ironing")));
        advertisement.setVersion(rs.getInt("version"));
        return advertisement;
    }
}

我对以下类型的三个字段有疑问:java.util.Set(我在上面的 java 代码中向它们添加了 //COLLECTION! 注释。)

这里是 SQL:

SELECT * FROM 
advertisement a, 
advertisement_childcare_types act, 
advertisement_day_to_time_slots adtts, 
day_to_time_slot dtts,
advertisement_languages al,
language l
WHERE 
a.id = act.advertisement AND
a.id = adtts.advertisement AND
adtts.day_to_time_slots = dtts.id AND
a.id = al.advertisement AND
al.languages = l.id

我不确定如何从 ResultSet...

中填充集合/java.util.Set 字段

有人可以帮忙吗?

由于您没有从结果集中的行到 Advertisement 个实例的一对一映射,因此您将无法使用 RowMapper 执行此操作。您将需要使用 RowCallbackHandler or a ResultSetExtractor<List<Advertisement>>RowCallbackHandler 的优点是您不需要处理调用 next().

这是一个非线程安全的,不是超级高效,但清晰的实现:

class AdvertisementRowcallbackHandler implements RowCallbackHandler {

  Map<Long, Advertisement> results = new HashMap<>();

  @Override
  void processRow(ResultSet rs) SQLException {
    long id = rs.getLong("id");
    Advertisement advertisement = new Advertisement();
    advertisement.setChildcareWorkerTypes(new HashSet<>());
    results.putIfAbsent(id, advertisement);
    advertisement = results.get(id);
    // You could be smart about only setting these if it was absent in the map
    advertisement.setId(id);
    advertisement.setDescription(rs.getString("description"));
    advertisement.getChildcareWorkerTypes().add(rs.getString("worker_type"));
    // ...
  }
}

然后你会得到 new ArrayList<>(handler.results.values()) 的结果。