복붙노트

[SPRING] 여러 일대 다 관계 ResultSetExtractor

SPRING

여러 일대 다 관계 ResultSetExtractor

두 개의 일대 다 관계가있는 객체가 있다고 가정 해 봅시다. 훨씬 좋아.

고객 1 <-> M 브랜드 및 고객 1 <-> M 주문

내 개체 고객이 두 개체와 관련된 두 개의 목록을 가지고 있다고 가정 해 봅시다.

이 예를 읽었습니다. http://forum.springsource.org/showthread.php?50617-rowmapper-with-one-to-many-query 단일 일대 다 관계로이를 수행하는 방법을 설명합니다. 귀하의 편의를 위해 여기에있는 ResultSetExtractor 재정의 :

private class MyObjectExtractor implements ResultSetExtractor{

    public Object extractData(ResultSet rs) throws SQLException, DataAccessException {
        Map<Integer, MyObject> map = new HashMap<Integer, MyObject>();
        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<MyObject>(map.values());;
    }
}

두 가지 방법으로 작업하는 방법을 다루지는 않는다고 생각합니다. 가장 깨끗한 접근 방법은 무엇입니까? 조건을 반복하는 것보다 간단한 방법이 있습니까? 이 경우리스트가 목록보다 더 좋을까요?

해결법

  1. ==============================

    1.귀하의 질문에서, 나는 당신이 세 테이블을 가지고 있다고 가정합니다; 고객, 브랜드, 주문. 브랜드와 주문간에 관계가없는 고객 개체에 고객의 브랜드 및 주문 속성을 가져 오려면 UNION 쿼리를 사용하는 것이 좋습니다. 이 같은:

    귀하의 질문에서, 나는 당신이 세 테이블을 가지고 있다고 가정합니다; 고객, 브랜드, 주문. 브랜드와 주문간에 관계가없는 고객 개체에 고객의 브랜드 및 주문 속성을 가져 오려면 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<Long, Customer> map = new HashMap<Long, Customer>();
    
            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<Brand>();
                        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<Order>();
                        customer.setOrders(ordersList);
                    }
                    Order order = new Order();
                    order.setId(rs.getLong("COL_A"));
                    ordersList.add(order);
                }
            }
            return new ArrayList<Customer>(map.values());
        }
    }
    
  2. ==============================

    2.모든 행을 반복하고 두 개의 다른 객체를 추출하여 Customer 객체의 List 및 List 에 추가하는 것보다 더 좋은 방법이 없다고 생각합니다.

    모든 행을 반복하고 두 개의 다른 객체를 추출하여 Customer 객체의 List 및 List 에 추가하는 것보다 더 좋은 방법이 없다고 생각합니다.

    따라서 고객 객체로 끝날 것입니다.

    public class Customer {
         private List<Brand> brands;
         private List<Order> orders;
    ....
    }
    

    여러 행 매퍼 (rowmapper)에 관한 SpringSource에 관한 문제가있었습니다 : https://jira.springsource.org/browse/SPR-7698

    그러나 일대 다 결과 집합 추출기에 연결되는 단 하나의 주석이 있습니다. https://github.com/SpringSource/spring-data-jdbc-ext/blob/master/spring-data-jdbc-core/src/main/java/org/springframework/data/jdbc/core/OneToManyResultSetExtractor.java

    나는 열망하는 가져 오기가 정말로 필요하다면 당신이 바로하고 있다고 생각합니다. 게으른 페칭이 필요한 경우 런타임 중에 액세스 할 때 각각의 주문과 브랜드를로드 할 수 있습니다. 이것이 Hibernate와 다른 ORM 프레임 워크가하는 일입니다. 그것은 당신의 시나리오와 당신이 그 대상으로 무엇을하는지에 달려 있습니다.

  3. ==============================

    3.나는 그의 대답에서 James Jithin이 묘사 한 모델을 가정한다.

    나는 그의 대답에서 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 
    

    RowCallbackHandler는 다음과 같이됩니다.

    private class CustomerRowCallbackHandler  implements RowCallbackHandler {
    
        private final Map<Long, Customer> customerMap;
    
        public BrandRowCallbackHandler(Map<Long, Customer> 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<Long, Customer> customerMap;
    
        public BrandRowCallbackHandler(Map<Long, Customer> 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<Brand>();
                        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<Long, Customer> customerMap;
    
        public OrderRowCallbackHandler(Map<Long, Customer> 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<Order>();
                        customer.setOrders(ordersList);
                    }
                    Order order = new Order();
                    order.setId(rs.getLong("ORDER_ID"));
                    ordersList.add(order);
                }
        }
    }
    
  4. ==============================

    4.만약 정말로해야한다면 ResultSetExtractor보다 RowCallbackHandler를 선호 할 것입니다. RowCallbackHandler API 및 JDBCTemplate API를 참조하십시오.

    만약 정말로해야한다면 ResultSetExtractor보다 RowCallbackHandler를 선호 할 것입니다. RowCallbackHandler API 및 JDBCTemplate API를 참조하십시오.

    이 경우 핸들러에서 결과 Customers 컬렉션을 직접 수집해야합니다. 세트는 중복을 필터링하는 데 도움이 될 수 있습니다.

  5. from https://stackoverflow.com/questions/13295600/multiple-one-to-many-relations-resultsetextractor by cc-by-sa and MIT license