[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.귀하의 질문에서, 나는 당신이 세 테이블을 가지고 있다고 가정합니다; 고객, 브랜드, 주문. 브랜드와 주문간에 관계가없는 고객 개체에 고객의 브랜드 및 주문 속성을 가져 오려면 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.모든 행을 반복하고 두 개의 다른 객체를 추출하여 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.나는 그의 대답에서 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.만약 정말로해야한다면 ResultSetExtractor보다 RowCallbackHandler를 선호 할 것입니다. RowCallbackHandler API 및 JDBCTemplate API를 참조하십시오.
만약 정말로해야한다면 ResultSetExtractor보다 RowCallbackHandler를 선호 할 것입니다. RowCallbackHandler API 및 JDBCTemplate API를 참조하십시오.
이 경우 핸들러에서 결과 Customers 컬렉션을 직접 수집해야합니다. 세트는 중복을 필터링하는 데 도움이 될 수 있습니다.
from https://stackoverflow.com/questions/13295600/multiple-one-to-many-relations-resultsetextractor by cc-by-sa and MIT license
'SPRING' 카테고리의 다른 글
[SPRING] JPA의 기준 빌더에서 ignorecase (0) | 2019.01.31 |
---|---|
[SPRING] jquery를 사용하여 select의 모든 옵션을 어떻게 업데이트합니까? (0) | 2019.01.31 |
[SPRING] Spring + JDBC에서 autocommit을 끄려면 어떻게해야합니까? (0) | 2019.01.31 |
[SPRING] 요청 매개 변수에 기반한 Spring 보안 인증 (0) | 2019.01.31 |
[SPRING] 하나의 컨트롤러에만 Spring HandlerInterceptor를 바인드한다. (0) | 2019.01.31 |