多个一对多关系ResultSetExtractor

假设我有一个具有两个不同的一对多关系的对象。 很像:

Customer 1M BrandsCustomer 1M Orders

让我们说我的对象Customer有两个与这两个对象相关的列表。

我已经阅读了这个例子: http : //forum.springsource.org/showthread.php?50616-rowmapper -with-one-to-many- query ,它解释了如何使用单一的一对多关系来完成它。 为方便起见,这里是ResultSetExtractor覆盖:

 private class MyObjectExtractor implements ResultSetExtractor{ public Object extractData(ResultSet rs) throws SQLException, DataAccessException { Map map = new HashMap(); MyObject myObject = null; while (rs.next()) { Integer id = rs.getInt("ID); myObject = map.get(id); if(myObject == null){ String description = rs,getString("Description"); myObject = new MyObject(id, description); map.put(id, myObject); } MyFoo foo = new MyFoo(rs.getString("Foo"), rs.getString("Bar")); myObject.add(myFoo); } return new ArrayList(map.values());; } } 

我不认为它涵盖了如何与两者合作。 什么是最干净的方法? 有没有比条件迭代更简单的方法? 在这种情况下,套装会比列表更好吗?

从你的问题,我假设你有三张桌子; 客户,品牌,订单。 如果您想要将客户的品牌和订单属性提取到您的客户对象,而品牌和订单之间没有关系,我建议使用UNION查询。 像这样的东西:

 TBL_CUSTOMER ------------ CUSTOMER_ID CUSTOMER_ACCOUNT_NO CUSTOMER_NAME TBL_CUSTOMER_BRANDS ------------------- CUSTOMER_BRAND_ID - UK BRAND_NAME CUSTOMER_ID - FK TBL_ORDERS ------------------- ORDER_ID - UK CUSTOMER_ID - FK 

查询:

 SELECT CUS.*, BRANDS.CUSTOMER_BRAND_ID COL_A, BRANDS.BRAND_NAME COL_B, 1 IS_BRAND FROM TBL_CUSTOMER CUS JOIN TBL_CUSTOMER_BRANDS BRANDS ON (CUS.CUSTOMER_ID = BRANDS.CUSTOMER_ID) UNION ALL SELECT CUS.*, ORDERS.ORDER_ID, '', 0 IS_BRAND FROM TBL_CUSTOMER CUS JOIN TBL_ORDERS ORDERS ON (CUS.CUSTOMER_ID = ORDERS.CUSTOMER_ID) 

您的ResultSetExtractor将成为:

 private class MyObjectExtractor implements ResultSetExtractor{ public Object extractData(ResultSet rs) throws SQLException, DataAccessException { Map map = new HashMap(); while (rs.next()) { Long id = rs.getLong("CUSTOMER_ID"); Customer customer = map.get(id); if(customer == null){ customer = new Customer(); customer.setId(id); customer.setName(rs.getString("CUSTOMER_NAME")); customer.setAccountNumber(rs.getLong("CUSTOMER_ACCOUNT_NO")); map.put(id, customer); } int type = rs.getInt("IS_BRAND"); if(type == 1) { List brandList = customer.getBrands(); if(brandsList == null) { brandsList = new ArrayList(); customer.setBrands(brandsList); } Brand brand = new Brand(); brand.setId(rs.getLong("COL_A")); brand.setName(rs.getString("COL_B")); brandsList.add(brand); } else if(type == 0) { List ordersList = customer.getOrders(); if(ordersList == null) { ordersList = new ArrayList(); customer.setOrders(ordersList); } Order order = new Order(); order.setId(rs.getLong("COL_A")); ordersList.add(order); } } return new ArrayList(map.values()); } } 

我认为没有比迭代所有行更好的方法,提取两个不同的对象并将其添加到Customer对象中的ListList

所以你最终会成为一个客户对象:

 public class Customer { private List brands; private List orders; .... } 

SpringSource上有一个关于多行rowmapper的问题: https ://jira.springsource.org/browse/SPR-7698

但是只有一条注释链接到一对多结果集提取器: https : //github.com/SpringSource/spring-data-jdbc-ext/blob/master/spring-data-jdbc-core/src/main/的java /组织/ springframework的/数据/ JDBC /型芯/ OneToManyResultSetExtractor.java

如果你真的需要热切的提法,我认为你做得对。 如果您需要延迟提取,则可以在运行时加载相应的订单和品牌。 这就是Hibernate和其他ORM框架的作用。 这取决于您的方案以及您对该对象的操作。

我假设James Jithin在他的回答中描述的模型:

 TBL_CUSTOMER ------------ CUSTOMER_ID CUSTOMER_ACCOUNT_NO CUSTOMER_NAME TBL_CUSTOMER_BRANDS ------------------- CUSTOMER_BRAND_ID - UK BRAND_NAME CUSTOMER_ID - FK TBL_ORDERS ------------------- ORDER_ID - UK CUSTOMER_ID - FK 

我建议以下三个,而不是一个查询:

 SELECT CUS.* FROM TBL_CUSTOMER CUS SELECT BRANDS.CUSTOMER_ID, BRANDS.CUSTOMER_BRAND_ID, BRANDS.BRAND_NAME FROM TBL_CUSTOMER_BRANDS BRANDS SELECT ORDERS.CUSTOMER_ID, ORDERS.ORDER_ID FROM TBL_ORDERS ORDERS 

您的RowCallbackHandlers将变为:

 private class CustomerRowCallbackHandler implements RowCallbackHandler { private final Map customerMap; public BrandRowCallbackHandler(Map customerMap) { this.customerMap = customerMap} public void processRow(ResultSet rs) throws SQLException { Long id = rs.getLong("CUSTOMER_ID"); Customer customer = map.get(id); if(customer == null){ customer = new Customer(); customer.setId(id); customer.setName(rs.getString("CUSTOMER_NAME")); customer.setAccountNumber(rs.getLong("CUSTOMER_ACCOUNT_NO")); map.put(id, customer); } } } private class BrandRowCallbackHandler implements RowCallbackHandler { private final Map customerMap; public BrandRowCallbackHandler(Map customerMap) { this.customerMap = customerMap} public void processRow(ResultSet rs) throws SQLException { Long id = rs.getLong("CUSTOMER_ID"); Customer customer = map.get(id); if(customer != null){ List brandList = customer.getBrands(); if(brandsList == null) { brandsList = new ArrayList(); customer.setBrands(brandsList); } Brand brand = new Brand(); brand.setId(rs.getLong("CUSTOMER_BRAND_ID")); brand.setName(rs.getString("CUSTOMER_BRAND_NAME")); brandsList.add(brand); } } } private class OrderRowCallbackHandler implements RowCallbackHandler { private final Map customerMap; public OrderRowCallbackHandler(Map customerMap) { this.customerMap = customerMap} public void processRow(ResultSet rs) throws SQLException { Long id = rs.getLong("CUSTOMER_ID"); Customer customer = map.get(id); if(customer != null){ List ordersList = customer.getOrders(); if(ordersList == null) { ordersList = new ArrayList(); customer.setOrders(ordersList); } Order order = new Order(); order.setId(rs.getLong("ORDER_ID")); ordersList.add(order); } } } 

如果我真的必须这样做,我宁愿使用RowCallbackHandler而不是ResultSetExtractor 。 请参见RowCallbackHandler api和JDBCTemplate api 。

在这种情况下,您需要在处理程序中自己收集生成的Customers集合。 可以帮助过滤掉重复项。