IBATIS/myBatis
2017.05.22 / 18:11

iBATIS in Action (6/14)

ducati
Ãßõ ¼ö 236

iBATIS in Action (6/14)

1. °í±Þ Äõ¸® ±â¹ý

1.1. iBATIS¿¡¼­ XML »ç¿ëÇϱâ

iBATIS ÇÁ·¹ÀÓ¿öÅ©¿¡¼­´Â Äõ¸®¿¡ ÆĶó¹ÌÅ͸¦ Àü´ÞÇÒ ¶§³ª È¤Àº Äõ¸® °á°ú¸¦ ¹Ýȯ¹ÞÀ» ¶§XMLÀ» »ç¿ëÇÒ ¼ö ÀÖ´Ù. µÎ °æ¿ì ¸ðµÎ ²À XMLÀ» »ç¿ëÇÒ ÇÊ¿äµµ ¾øÀ¸¸é¼­ XMLÀ» »ç¿ëÇϴ°ÍÀº ±×´ÙÁö ±ÇÀåÇÒ °ÍÀº ¸øµÈ´Ù. ´ë½Å POJO¸¦ »ç¿ëÇϴ °ÍÀÌ ´ëºÎºÐÀÇ °æ¿ì¿¡ ÈξÀ ´õÈ¿À²ÀûÀ̱⠶§¹®ÀÌ´Ù.

6.1.1 XML ÆĶó¹ÌÅÍ

¿ÏÀüÈ÷ µ¿ÀÏÇÑ ±¸Á¶¸¦ °®Ãß°í Àִ ¹®ÀÚ¿­À̳ª DOM °´Ã¼¸¦ ÅëÇؼ­ XMLÀ» ¸ÅÇΠ±¸¹®¿¡ÆĶó¹ÌÅͷΠ³Ñ°ÜÁÙ ¼ö ÀÖ´Ù.

±¸Á¶ÀÇ ÇüÅ´ ÆĶó¹ÌÅͷΠÀü´ÞÇÒ °ªÀÌ ÆĶó¹ÌÅÍÀÇ À̸§À» ÀǹÌÇϴ ¿ä¼Ò·Î °¨½ÎÁ® ÀÖ°í ±× ¿ä¼Ò¸¦ ´Ù½Ã parameter ¿ä¼Ò·Î °¨½Î°í Àִ °ÍÀÌ´Ù. ¿¹¸¦ º¸ÀÚ.

3

ÀÌ ¿¹¿¡¼­ ¸ÅÇΠ±¸¹®Àº °ªÀÌ 3ÀÌ°í À̸§ÀÌ ¡°accountId¡±ÀΠÆĶó¹ÌÅÍ ÇÑ °³¸¦ Àü´Þ¹Þ°Ô µÈ´Ù. ¿©±â XML ¹®ÀÚ¿­À» ¸ÅÇΠ±¸¹®¿¡ ÆĶó¹ÌÅͷΠ³Ñ°ÜÁִ ¿¹Á¦°¡ ÀÖ´Ù.

String parameter = "3";

Account account = (Account) sqlMapClient.queryForObject(

"Account.getByXmlId",

parameter);

ºñ½ÁÇÑ ¹æ½ÄÀ¸·Î DOM °´Ã¼µµ µ¿ÀÏÇÑ °á°ú¸¦ ³¾ ¼ö ÀÖ°Ô iBATIS·Î ³Ñ°ÜÁÙ ¼ö ÀÖ´Ù.

Document parameterDocument = DocumentBuilderFactory.newInstance()

.newDocumentBuilder().newDocument();

Element paramElement = parameterDocument

.createElement("parameterDocument");

Element accountIdElement = parameterDocument

.createElement("accountId");

accountIdElement.setTextContent("3");

paramElement.appendChild(accountIdElement);

parameterDocument.appendChild(paramElement);

Account account = (Account) sqlMapClient.queryForObject(

"Account.getByXmlId", parameterDocument);

6.1.2 XML·Î °á°ú »ý¼ºÇϱâ

iBATIS ÇÁ·¹ÀÓ¿öÅ©´Â ¸ÅÇΠ±¸¹®¿¡¼­ XML·Î °á°ú¸¦ »ý¼ºÇÒ ¼öµµ ÀÖ´Ù. XMLÀ» ¹ÝȯÇϴ¸ÅÇΠ±¸¹®À» ½ÇÇàÇϸ頰¢°¢ÀÇ ¹ÝȯµÈ °´Ã¼¸¦ ¿ÏÀüÇÑ XML ¹®¼­·Î ¾òÀ» ¼ö ÀÖ´Ù.

ÀÌ ±â´ÉÀ» »ç¿ëÇϱâ À§ÇØ, °á°ú Å¬·¡½º¸¦ ¡°xml¡±·Î ÁöÁ¤ÇÑ ¸ÅÇΠ±¸¹®À» »ý¼ºÇÑ´Ù. ¿©±â°£´ÜÇÑ ¿¹Á¦°¡ ÀÖ´Ù.

String xmlData = (String) sqlMap.queryForObject(

"Account.getByIdValueXml",

new Integer(1));

ÀÌ °æ¿ì, ¹Ýȯ ¹ÞÀº °á°ú´Â ´ÙÀ½°ú °°´Ù.

1

lmeadors

blah

XML ¹®¼­·Î ³Ñ°Ü¹ÞÀº °á°ú°¡ ÇÑ °³ÀÇ ·¹Äڵ常À» °¡Áö°í ÀÖ´Ù¸é Á¤¸»·Î ´Ù·ç±â ½±´Ù. ¸¸ÀÏ ¿©·¯ °³ÀÇ °´Ã¼·Î ¹Þ±â¸¦ ¿øÇѴٸ頱׷¸°Ô ÇÒ ¼öµµ ÀÖ´Ù. ¾Æ·¡¿¡ ¿¹Á¦°¡ ÀÖ´Ù.

List xmlList = sqlMap.queryForList("Account.getAllXml", null);

ÀÌ °æ¿ì °á°ú´Â XML ¹®¼­ÀÇ ¸®½ºÆ®ÀÌ´Ù. ÀÌ·¸°Ô µÇ¸é ÇÑ °³ÀÇ XML¹®¼­·Î ÇÕÄ¡±æ ¿øÇÒ °æ¿ì ¹®ÀÚ¿­ Ã³¸® ÀÛ¾÷À» Çؾ߸¸ ÇÑ´Ù. ÀÌ°ÍÀº ÃÖÀûÀÇ ¹æ¹ýÀÌ ¾Æ´Ï´Ù.

ÀÌ ¹®Á¦¸¦ ÇÇÇØ°¡´Â ¹æ¹ýÀ¸·Î iBATIS°¡ °á°ú¸¦ XML·Î ¹ÝȯÇÏÁö ¾Ê°Ô Çϴ °ÍÀÌ´Ù. °£´ÜÇÑ ¹æ¹ýÀ¸·Î ´Ü¼øÇÑ Ä÷º¼ÇÀ» ¹ÝȯÇϴ iBATISÀÇ ¸ÅÇΠ±¸¹®À» »ç¿ëÇÏ°í ±×·ÎºÎÅÍ XMLÀ»»ý¼ºÇϴ °ÍÀÌ´Ù. À̸¦ ¼öÇàÇϴ ÇÑ °¡Áö °£´ÜÇÑ ¹æ¹ýÀ¸·Î(°á°ú·Î ºóÁ »ç¿ëÇÑ´Ù¸é)¾Æ·¡¿Í °°ÀÌ XML »ý¼ºÀ» µµ¿ÍÁִ ¸Þ¼­µå¸¦ ¸¸µå´Â ¹æ¹ýÀÌ ÀÖ´Ù.

public String toXml(){

StringBuffer returnValue = new StringBuffer("");

returnValue.append("");

returnValue.append("" + getAccountId() +"");

returnValue.append("" + getUsername() + "");

returnValue.append("" + getPassword() + "");

returnValue.append("");

return returnValue.toString();

}

ÀÌ ¹®Á¦¿¡ ´ëÇÑ ¶Ç ´Ù¸¥ Á¢±Ù ¹æ¹ýÀ¸·Î ¸®Ç÷º¼ÇÀ» »ç¿ëÇÏ¿© ºóÁ XML·Î º¯È¯Çϴ Ŭ·¡½º¸¦ »ý¼ºÇϴ ¹æ¹ýÀÌ ÀÖ´Ù. ÀÌ ¹æ¹ýÀº ¾ÆÁÖ °£´ÜÇÏ´Ù. ¾Æ·¡¿¡ ÀÌ ¹æ¹ýÀ» Àû¿ëÇÒ ¶§ »ç¿ëÇÒ ¼ö Àִ ÀÛÀº À¯Æ¿¸®Æ¼°¡ ÀÖ´Ù.

public class XmlReflector {

private Class sourceClass;

private BeanInfo beanInfo;

private String name;

XmlReflector(Class sourceClass, String name) throws Exception {

this.sourceClass = sourceClass;

this.name = name;

beanInfo = Introspector.getBeanInfo(sourceClass);

}

public String convertToXml(Object o) throws Exception {

StringBuffer returnValue = new StringBuffer("");

if (o.getClass().isAssignableFrom(sourceClass)) {

PropertyDescriptor[] pd = beanInfo.getPropertyDescriptors();

if (pd.length > 0){

returnValue.append("<" + name + ">");

for (int i = 0; i < pd.length; i++) {

returnValue.append(getProp(o, pd[i]));

}

returnValue.append("");

} else {

returnValue.append("<" + name + "/>");

}

} else {

throw new ClassCastException("Class " + o.getClass().getName() +

" is not compatible with " + sourceClass.getName());

}

return returnValue.toString();

}

private String getProp(Object o, PropertyDescriptor pd)

throws Exception {

StringBuffer propValue = new StringBuffer("");

Method m = pd.getReadMethod();

Object ret = m.invoke(o);

if(null == ret){

propValue.append("<" + pd.getName() + "/>");

}else{

propValue.append("<" + pd.getName() + ">");

propValue.append(ret.toString());

propValue.append("");

}

return propValue.toString();

}

}

À§ ¿¹Á¦´Â ºóÁ ÆĶó¹ÌÅͷΠ¹Þ¾Æ¼­ XML ¹®¼­°¡ ¾Æ´Ñ XML ±¸¼º ¿ä¼Ò Á¶°¢À¸·Î º¯È¯ÇÑ´Ù. ¾Æ·¡¿¡ ¿¹Á¦°¡ ÀÖ´Ù.

XmlReflector xr = new XmlReflector(Account.class, "account");

xmlList = sqlMap.queryForList("Account.getAll", null);

StringBuffer sb = new StringBuffer(

"");

for (int i = 0; i < xmlList.size(); i++) {

sb.append(xr.convertToXml(xmlList.get(i)));

}

sb.append("");

ÀÌ ±â¹ýÀ» »ç¿ëÇؼ­ ´ë¿ë·®ÀÇ ·¹Äڵ带 Ã³¸®Çϴ °ÍÀº ¸Þ¸ð¸® È¿À²¸é¿¡¼­ ¸Å¿ì ÁÁÁö ¸øÇÏ´Ù. °´Ã¼ ¸®½ºÆ®¿Í XML ¹®¼­¸¦ »ý¼ºÇϱâ À§ÇÑ ¹®ÀÚ¿­ ¹öÆÛ¸¦ ¸Þ¸ð¸®»ó¿¡ ÀúÀåÇϱ⠶§¹®ÀÌ´Ù. 6.3Àý¿¡¼­ ÀÌ ¿¹Á¦¸¦ ´Ù½Ã »ìÆ캸°í ´ë¿ë·®ÀÇ °á°ú¸¦ Ã³¸®Çϴ ´õ¿í È¿À²ÀûÀιæ¹ýÀ» ¾Ë¾Æº¼ °ÍÀÌ´Ù.

1.2. ¸ÅÇΠ±¸¹®À» °´Ã¼¿Í ¿¬°ü½ÃÅ°±â

6.2.1 º¹ÀâÇÑ Ä÷º¼Ç(collection)

4Àå¿¡¼­´Â SELECT ±¸¹®À» ÀÌ¿ëÇØ µ¥ÀÌÅÍ º£À̽º·ÎºÎÅÍ µ¥ÀÌÅ͸¦ °¡Á®¿À´Â ¹æ¹ýÀ» »ìÆ캸¾Ò´Ù. ±× ¿¹Á¦¿¡¼­´Â ¿©·¯ Å×À̺íµéÀ» Á¶ÀÎÇÒ ¶§Á¶Â÷µµ °á°ú·Î´Â ´ÜÀÏ °´Ã¼ Å¸ÀÔ¸¸À»´Ù·ç¾ú´Ù. Á» ´õ º¹ÀâÇÑ °´Ã¼°¡ ÇÊ¿äÇÒ ¶§¿¡µµ iBATIS¸¦ »ç¿ëÇÒ ¼ö ÀÖ´Ù.

ÀÌ·¯ÇÑ ±â´ÉÀº ¿©·¯ºÐÀÌ ¸¸µå´Â ¾ÖÇø®ÄÉÀ̼ÇÀÇ ¸ðµ¨ÀÌ µ¥ÀÌÅÍ ¸ðµ¨Ã³·³ º¸¿´À¸¸é ÇÒ¶§ À¯¿ëÇÏ°Ô »ç¿ëÇÒ ¼ö ÀÖ´Ù. iBATIS¸¦ »ç¿ëÇÏ¿© ¿¬°üµÈ °´Ã¼µé¿¡ °üÇÑ µ¥ÀÌÅÍ ¸ðµ¨À» Á¤ÀÇÇÏ°í, iBATIS·Î ±× °´Ã¼µéÀ» ÇѲ¨¹ø¿¡ ÀоîµéÀÏ ¼ö ÀÖ´Ù. ¿¹¸¦ µé¾î Account ·¹Äڵ尡Order ·¹ÄÚµå¿Í ¿¬°üµÅ ÀÖ°í Order ·¹Äڵ尡 OrderItem ·¹ÄÚµå¿Í ¿¬°üµÅ ÀÖÀ» ¶§, ÀÌ·¯ÇÑ°ü°è¸¦ Á¤ÀÇÇÏ°í Account ¸¦ ¿äûÇϸ頸ðµç Order °´Ã¼¿Í ¸ðµç OrderItem °´Ã¼µé ¶ÇÇÑ °¡Á®¿Ã ¼ö ÀÖ´Ù.

ÀÌ·¯ÇÑ ÀÏÀ» ÇÒ ¼ö ÀÖ°Ô SQL MapÀ» Á¤ÀÇÇϴ ¹æ¹ýÀº ¾Æ·¡¿Í °°´Ù.

PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN"

"http://ibatis.apache.org/dtd/sql-map-2.dtd">

----------------------- (1)

class="org.apache.mapper2.examples.bean.AccountInfo">

column="accountId" />

select="Ch6.getOrderInfoList"

column="accountId" />

----------------------- (2)

class="org.apache.mapper2.examples.bean.OrderInfo">

select="Ch6.getOrderItemList" />

----------------------- (3)

class="org.apache.mapper2.examples.bean.OrderItem">

°á°ú ¸Ê(ResultAccountInfoMap (1), ResultOrderInfoMap (2), ResultOrderItemMap (3)À» º¸¸é Ã³À½ µÎ °³´Â ¸ÅÇΠÇÁ·ÎÆÛƼ ÁßÀÇ Çϳª·Î select ¼Ó¼ºÀ» »ç¿ëÇÔÀ» º¼ ¼ö ÀÖ´Ù.

ÀÌ ¼Ó¼ºÀ» »ç¿ëÇϸé iBATIS´Â ÀÌ ÇÁ·ÎÆÛƼ°¡ select ¼Ó¼ºÀÇ °ªÀ¸·Î ÁöÁ¤µÈ ´Ù¸¥ ¸ÅÇΠ±¸¹®ÀÇ ½ÇÇà °á°ú·Î ¼³Á¤µÈ´Ù°í °£ÁÖÇÏ°Ô µÈ´Ù. ¿¹¸¦ µé¾î getAccountInfoList ±¸¹® (4)À» ½ÇÇàÇÒ ¶§ °á°ú ¸Ê ResultAccountInfoMapÀº À» Æ÷ÇÔÇÏ°í ÀÖ´Ù. ÀÌ°ÍÀº iBATIS¿¡°Ô orderList Æ÷·ÎÆÛƼÀÇ °ªÀ» ¾ò¾î ¿À±â À§ÇØ accountId Ä®·³ °ªÀ» ÆĶó¹ÌÅͷΠ³Ñ°Ü¼­¡°Ch6.getOrderInfoList¡± ¸ÅÇΠ±¸¹®À» ½ÇÇàÇÏ°í(5) ¹Ýȯ µÈ °á°ú µ¥ÀÌÅ͸¦ orderList ÇÁ·ÎÆÛƼ¿¡ ÀúÀåÇ϶ó´Â Àǹ̰¡ µÈ´Ù. ºñ½ÁÇÑ ¹æ½ÄÀ¸·Î °á°ú ¸Ê ResultOrderInfoMap(2) ÀÇorderItemList ÇÁ·ÎÆÛƼÀÇ °ªÀ» °¡Á®¿À±â À§ÇØ getOrderItemList(6) ¸ÅÇΠ±¸¹®À» ½ÇÇàÇϰԵȴÙ.

ÀÌ ±â´ÉÀÌ °¡Áø Æí¸®ÇÔ¿¡µµ ºÒ±¸ÇÏ°í ÀÌ Á¢±Ù ¹æ½ÄÀº µÎ °¡Áö ¹®Á¦Á¡À» °¡Áö°í ÀÖ´Ù. Ã¹Â°·Î ÀÌ ¹æ½ÄÀº ´ë¿ë·®ÀÇ ¸Þ¸ð¸®¸¦ ÇÊ¿ä·Î ÇÒ ¼öµµ ÀÖ´Ù. µÎ ¹ø°·Î ¾Æ·¡¿¡¼­ ´Ù·ê ¡°N+1 Select ¹®Á¦¡±·Î ¾Ë·ÁÁø Çö»óÀ¸·Î ÀÎÇؼ­ µ¥ÀÌÅͺ£À̽º I/O ¹®Á¦¸¦ ÀÏÀ¸Å³ ¼ö ÀÖ´Ù. iBATIS ÇÁ·¹ÀÓ¿öÅ©´Â °¢ ¹®Á¦¿¡ ´ëÇÑ ÇØ°áÃ¥À» °¡Áö°í ÀÖ´Ù. ÇÏÁö¸¸ µÎ °¡Áö ¹®Á¦¸¦ ÇѲ¨¹ø¿¡ ÇØ°áÇÒ ¼ö´Â ¾ø´Ù.

- µ¥ÀÌÅÍ º£À̽º I/O
iBATIS 
°¡ Á¦°øÇϴ ij½Ì ¸ÅÄ¿´ÏÁòÀ» ¾ðÁ¦ ¾î¶»°Ô »ç¿ëÇÒÁö´Â 10Àå¿¡¼­ »ìÆ캻´Ù.
¿¬°üµÈ µ¥ÀÌÅ͸¦ »ç¿ëÇÒ ¶§ ºÎµúÈ÷°Ô µÉ µ¥ÀÌÅͺ£À̽º I/O ¹®Á¦¸¦ »ìÆ캸±âÀ§ÇØ 1000°³ÀÇ °èÁÂ(Account)°¡ ÀÖ°í ±× °¢°¢ 1000°³ÀÇ ÁÖ¹®(Order)À» °¡Áö°í ÀÖÀ¸¸ç, ¶Ç °¢°¢ÀÇ ÁÖ¹®ÀÌ 25°³ÀÇ ÁÖ¹® Ç׸ñ(OrderItem)À» °¡Áö°í ÀÖ´Ù°í»ý°¢Çغ¸ÀÚ. ÀÌ ¸ðµç °ÍÀ» ¸Þ¸ð¸®¿¡ ÀûÀçÇÏ·Á µç´Ù¸é À̴ 1000000 È¸ ÀÌ»óÀÇ SQL ¹®ÀåÀ» ½ÇÇàÇÏ°í ¾à 2500¸¸ °³ÀÇ ÀÚ¹Ù °´Ã¼¸¦ »ý¼ºÇÏ°Ô µÈ´Ù. ÀÌ·±ÀÏÀ» Çϸé Æ²¸²¾øÀÌ ½Ã½ºÅÛ °ü¸®ÀÚ¿¡°Ô ÇÑ ¼Ò¸® µè°Ô µÉ °ÍÀÌ´Ù.

- ¡°N+1 Select¡± ¹®Á¦ »ìÆ캸±â
¡°N+1 Select¡± 
¹®Á¦´Â ºÎ¸ð ·¹Äڵ堸®½ºÆ®¿¡ ¿¬°üµÈ ÀڽĠ·¹Äڵ带 ÀоîµéÀ϶§ ¹ß»ýÇÏ°Ô µÈ´Ù. ºÎ¸ð ·¹Äڵ带 °¡Á®¿À±â À§ÇØ ÇÑ °³ÀÇ Äõ¸®¸¦ ½ÇÇàÇϸéºÎ¸ð°¡ ¾î¶² ¼ö ¡°N¡± °³ ¸¸Å­ ÀÖ°ÔµÇ°í °¢ ºÎ¸ð ·¹Äڵ忡 ¿¬°üµÈ ÀڽĠ·¹Äڵ带 ¾ò±â À§ÇØ ¡°N¡±¹øÀÇ Äõ¸®¸¦ ´õ ½ÇÇàÇؾߠÇÑ´Ù. µû¶ó¼­ ¡°N+1 Select¡± ¶ó´Â°á°ú¸¦ ¾ò´Â´Ù.

- À§ µÎ ¹®Á¦¿¡ ´ëÇÑ ÇØ°áÃ¥
ÀûÀç Áö¿¬(6.2.2 Àý¿¡¼­ ¾Ë¾Æº¼ °ÍÀÌ´Ù.)Àº ÀûÀç Ã³¸® °úÁ¤À» °ü¸®Çϱâ ÁÁÀº¼öÁØÀ¸·Î ÀÛ°Ô ÂÉ°·À¸·Î½á ¸Þ¸ð¸® ¹®Á¦¸¦ ¿ÏÈ­½ÃÄÑÁØ´Ù. ±×·¯³ª ¿©ÀüÈ÷ µ¥ÀÌÅÍ º£À̽º I/O ¹®Á¦°¡ ³²¾ÆÀÖ´Ù.
µ¥ÀÌÅ͸¦ ÀÌ ¹æ½ÄÀ¸·Î ¿¬°ü ½Ãų ¶§ °èÁ¸¦ ÁÖ¹®¿¡, ÁÖ¹®À» ÁÖ¹® Ç׸ñ¿¡ ¿¬°ü½ÃÅ°´Â °ÍÀº °ú¿¬ ÁÁÀº ¿¹Á¦Àϱî? ÁÖ¹®°ú ÁÖ¹® Ç׸ñÀ» ¿¬°ü Áþ´Â °ÍÀº ÀûÀýÇÏ´Ù. ÇÏÁö¸¸ °èÁ¸¦ ÁÖ¹®°ú ¿¬°ü½ÃÅ°´Â °ÍÀº ±×´ÙÁö ½ÇÁúÀûÀΠ°ÍÀº ¸øµÈ´Ù.
ÇÏÁö¸¸ ÀÌ ¿¹Á¦´Â ¿ì¸®¿¡°Ô Ä£¼÷ÇÏ°í ÀÌÇØÇÒ ¼ö Àִ °³³äÀ» »ç¿ëÇÏ¿© ¿©±â¼­ ¹è¿ì°íÀÚ Çϴ ±â¹ýÀ» º¸¿©ÁÙ °ÍÀ̱⿡ ´çºÐ°£Àº ÀÌ ¿¹Á¦¸¦ »ç¿ëÇÒ °ÍÀÌ´Ù.

6.2.2 ÀûÀç Áö¿¬(lazy loading)

¸ÕÀú ¾Ë¾Æº¼ ÇØ°áÃ¥Àº ÀûÀç Áö¿¬ÀÌ´Ù. ÀûÀç Áö¿¬Àº ¸ðµç ¿¬°üµÈ µ¥ÀÌÅÍ°¡ Áï½Ã ÇÊ¿äÇÏÁö´Â ¾ÊÀº °æ¿ì¿¡ À¯¿ëÇÏ´Ù. ¿¹¸¦ µé¾î ¿ì¸®ÀÇ ¾ÖÇø®ÄÉÀ̼ÇÀÌ ¸ðµç °èÁ¸¦ º¸¿©Áִ À¥ÆäÀÌÁö¿¡¼­ È£ÃâµÇ°í, ÆǸŠ´ë¸®ÀÎÀÌ °èÁ¸¦ Å¬¸¯Çϸ頱נ°èÁÂÀÇ ¸ðµç ÁÖ¹®À» º¸°ÔµÇ°í,¸¶Áö¸·À¸·Î Æ¯Á¤ ÁÖ¹®ÀÇ ¸ðµç ¼¼ºÎ ³»¿ªÀ» º¸±â À§ÇØ ÁÖ¹®À» Å¬¸¯ÇÏ°Ô µÈ´Ù°í ÇÏÀÚ. ÀÌ·¯ÇÑ °æ¿ì ¿ì¸®¿¡°Ô ÇÊ¿äÇÑ °ÍÀº °¢ ½ÃÁ¡¿¡¼­ ÇÑ °³ÀÇ ¸®½ºÆ® »ÓÀÌ´Ù. ÀÌ°ÍÀÌ ÀûÀç Áö¿¬ÀÇ ÀûÀýÇÑ »ç¿ë ¿¹ÀÌ´Ù.

ÀûÀç Áö¿¬À» »ç¿ëÇÏ·Á¸é SqlMapConfig.xml ÆÄÀÏÀ» ÆíÁýÇÏ¿© ¿ä¼ÒÀÇ lazyLoadingEnabled¼Ó¼ºÀ» ¡®true¡¯ ·Î ¹Ù²ã À̸¦ È°¼ºÈ­ ½ÃÄѾßÇÑ´Ù. cglib È®ÀåÆÇ ÀûÀç Áö¿¬À» »ç¿ëÇÏ°íÀÚ ÇÑ´Ù¸é cglib¸¦ ´Ù¿î·ÎµåÇÏ¿© ¾ÖÇø®ÄÉÀ̼ÇÀǠŬ·¡½ºÆнº¿¡ Ãß°¡ÇÏ°í ¿ä¼ÒÀÇenhancementEnabled ¼Ó¼ºµµ ¡®true¡¯ ·Î º¯°æÇØ Áָ頵ȴÙ. ÇÑ °¡Áö ÁÖÀÇÇÒ Á¡À¸·Î ÀÌ°ÍÀºÀü¿ªÀûÀΠ¼³Á¤À̹ǷΠÀÌ ¼Ó¼ºµéÀ» È°¼ºÈ­Çϸé SQL Map ÀÇ ¸ðµç ¸ÅÇΠ±¸¹®µéÀÌ ÀûÀç Áö¿¬À» »ç¿ëÇÏ°Ô µÈ´Ù´Â Á¡ÀÌ´Ù.

6.2.3 N+1 Select ¹®Á¦ ÇÇÇØ°¡±â

¡°N+1 Select¡± ¹®Á¦¸¦ ÇÇÇØ°¥ ¼ö Àִ ¹æ¹ýÀº µÎ °¡Áö°¡ ÀÖ´Ù. ÇÑ °¡Áö´Â iBATISÀÇ groupBy¼Ó¼ºÀ» »ç¿ëÇϴ °ÍÀÌ°í ´Ù¸¥ ÇÑ°¡Áö´Â ·Î¿ì Çڵ鷯(Row Handler) ¶ó´Â »ç¿ëÀÚ Á¤ÀÇ ÄÄÆ÷³ÍÆ®¸¦ »ç¿ëÇϴ °ÍÀÌ´Ù.

groupBy ¼Ó¼ºÀ» »ç¿ëÇϴ °ÍÀº ¹Ù·Î Àü¿¡ ¾Ë¾Æº» ±â¹ý°ú ¸Å¿ì À¯»çÇÏ´Ù. °£´ÜÈ÷ ¸»Çؼ­°á°ú ¸ÊÀ» »ç¿ëÇÏ¿© ¿¬°ü °ü°è¸¦ Á¤ÀÇÇÏ°í ÃÖ»óÀ§ °á°ú ¸ÊÀ» ¸ÅÇΠ±¸¹®°ú °áÇÕ½ÃÅ°¸é µÈ´Ù. ¾Æ·¡ ¿¹Á¦´Â À§¿¡ ³ª¿Â ÀûÀç Áö¿¬ ¿¹Á¦¿Í ¿ÏÀüÈ÷ µ¿ÀÏÇÑ ±¸Á¶¸¦ »ý¼ºÇÏÁö¸¸ ¼­¹ö¿¡¼­´Â ´Ü ÇϳªÀÇ SQL ¹®À常ÀÌ ½ÇÇàµÈ´Ù.

¼¼ °¡ÁöÀÇ °á°ú ¸ÊÀÌ ¿¬°üµÅ Àִµ¥ Çϳª´Â °èÁÂ, ¶Ç Çϳª´Â ÁÖ¹® ±×¸®°í ³ª¸ÓÁö´Â ÁÖ¹®Ç׸ñÀ» À§ÇÑ °ÍÀÌ´Ù.

°èÁ¸¦ À§ÇÑ °á°ú ¸ÊÀº ¼¼ °¡Áö ±â´ÉÀ» ÇÑ´Ù.

l °è°ú °´Ã¼µéÀÇ ÇÁ·ÎÆÛƼ¸¦ ¸ÅÇÎÇÑ´Ù.

l iBATIS ¿¡°Ô ¾î¶² ÇÁ·ÎÆÛƼ°¡ »õ·Î¿î °èÁ¸¦ »ý¼ºÇϴµ¥ ÇÊ¿äÇÑÁö ¾Ë·ÁÁØ´Ù.

l iBATIS ¿¡°Ô ¿¬°üµÈ ´ÙÀ½ °´Ã¼ ¹­À½À» ¾î¶»°Ô ¸ÅÇÎÇÒÁö ¾Ë·ÁÁִµ¥, ÀÌ °æ¿ì¿¡ ¿¬°üµÈ °´Ã¼ ¹­À½À̶õ ÇØ´ç °èÁ¿¡ ¿¬°üµÈ ÁÖ¹® °´Ã¼ÀÇ ¹­À½ÀÌ´Ù.

ÁÖÀÇÇؾߠÇÒ ¸Å¿ì Áß¿äÇÑ »çÇ×ÀÌ Çϳª Àִµ¥, groupBy ¼Ó¼ºÀº ÇÁ·ÎÆÛƼÀÇ À̸§À» ÁöÁ¤Çϴ °ÍÀÌÁö Å×À̺í Ä®·³ À̸§À» ÁöÁ¤Çϴ °ÍÀÌ ¾Æ´Ï´Ù.

ÁÖ¹®À» À§ÇÑ °á°ú ¸Êµµ µ¿ÀÏÇÑ ¼¼ °¡Áö ±â´ÉÀ» °¡Áö°í ÀÖ´Ù.

l ÁÖ¹® µ¥ÀÌÅ͸¦ ÁÖ¹® °´Ã¼¿¡ ¸ÅÇÎÇÑ´Ù.

l ¾î¶² ÇÁ·ÎÆÛƼ°¡ »õ·Î¿î ÁÖ¹®À» °¡¸®Å°´ÂÁö ÁöÁ¤ÇÑ´Ù.

l ÀڽĠ·¹ÄÚµåµéÀ» °¡Á®¿À±â À§ÇØ ¾î¶² °á°ú ¸ÊÀ» »ç¿ëÇÒÁö ÁöÁ¤ÇÑ´Ù.

¸¶Áö¸·À¸·Î ÁÖ¹® Ç׸ñ °á°ú ¸ÊÀº ±×³É ÀϹÝÀûÀΠ°á°ú ¸ÊÀ¸·Î ¿ÀÁ÷ ÁÖ¹® Ç׸ñÀ» °´Ã¼·Î¸ÅÇνÃÅ°´Â ¿ªÇÒ¸¸À» ÇÑ´Ù. ¾Æ·¡´Â ÀÌ¿¡ ´ëÇÑ ¸ÅÇΠ¿¹Á¦ÀÌ´Ù.

©¬-------- (1) °èÁ µ¥ÀÌÅ͸¦ À§ÇÑ °á°ú¸Ê ¼±¾ð

class="AccountInfo"

groupBy="account.accountId" >

column="accountId" />

resultMap="Ch6.ResultOrderInfoNMap" />

©¬--------(2) ÁÖ¹® µ¥ÀÌÅ͸¦ À§ÇÑ °á°ú¸Ê ¼±¾ð

class="OrderInfo"

groupBy="order.orderId" >

resultMap="Ch6.ResultOrderItemNMap" />

©¬--------(3) ÁÖ¹®Ç׸ñÀ» À§ÇÑ °á°ú¸Ê ¼±¾ð

class="OrderItem">

column="orderId" />

column="orderItemId" />

 ¿ä¼Ò¿¡ ¹­±â

resultMap="ResultAccountInfoNMap">

select

account.accountId as accountid,

orders.orderid as orderid,

orderitem.orderitemid as orderitemid

from account

join orders on account.accountId = orders.accountId

join orderitem on orders.orderId = orderitem.orderId

order by accountId, orderid, orderitemid

getAccountInfoListN ¸ÅÇΠ±¸¹®À» È£ÃâÇÏ¿© (4) ¾ÕÀÇ µÎ ¿¹Á¦¿¡¼­ º¸¿©ÁØ °Í°ú µ¿ÀÏÇÑ °á°ú µ¥ÀÌÅ͸¦ ¾ò°Ô µÈ´Ù. ÇÏÁö¸¸ ÀÌ °æ¿ì¿¡´Â ¿ÀÁ÷ ÇÑ °³ÀÇ SQL ¹®¸¸À» ½ÇÇàÇϱ⠶§¹®¿¡¾Õ ¿¹Á¦º¸´Ù ÈξÀ ºü¸£´Ù. ÀÌ°ÍÀº getAccoutnInfoListN ¸ÅÇΠ±¸¹® (4)ÀÌ ½ÇÇàµÇ¸é ±× °á°ú´Â groupBy ¼Ó¼ºÀ» »ç¿ëÇϴ resultAccountInfoNMap °á°ú ¸Ê (1)À» ÅëÇؼ­ ¸ÅÇÎÀ» ¼öÇàÇÏ¿© »ý¼ºµÈ´Ù. ÀÌ ¼Ó¼ºÀº iBATIS ¿¡°Ô account.accountId ÇÁ·ÎÆÛƼ°¡ º¯°æµÉ ¶§¿¡¸¸ »õ·Î¿îAccountInfo ÀνºÅϽº¸¦ »ý¼ºÇϸ頵ȴٰí Áö½ÃÇÑ´Ù. Á» ´õ »ìÆ캸¸é orderList ÇÁ·ÎÆÛƼ°¡ ResultOrderInfoNMap °á°ú ¸Ê (2)¿Í ¸ÅÇÎÀÌ µÇ¾î Àֱ⠶§¹®¿¡ Äõ¸® °á°ú·Î ³ª¿Â ·¹Äڵ带 Ã³¸®ÇØ °¡¸é¼­ ÁÖ¹® ¸®½ºÆ®µµ »ý¼ºÇÏ°Ô µÈ´Ù. ResultOrderInfoNMap °á°ú ¸Êµµ ¶ÇÇÑgroupBy ¼Ó¼ºÀ» »ç¿ëÇϱ⠶§¹®¿¡ orderItemList ÇÁ·ÎÆÛƼÀÇ ResultOrderItemNMap °á°ú¸Ê(3)À» ÀÌ¿ëÇÏ¿© orderItemList ¸¦ »ý¼ºÇϴ °úÁ¤À» ¹Ýº¹ÇÒ °ÍÀÌ´Ù.

1.3. »ó¼Ó

6.3.1 »ó¼Ó ¸ÅÇÎÇϱâ

iBATIS´Â ±¸º°ÀÚ(discriminator) ¶ó°í ºÒ¸®´Â Æ¯º°ÇÑ ¸ÅÇÎÀ» »ç¿ëÇÏ¿© »ó¼Ó ±¸Á¶¸¦ Áö¿øÇÑ´Ù. ±¸º°ÀÚ¸¦ »ç¿ëÇϴ °ÍÀ¸·Î µ¥ÀÌÅͺ£À̽ºÀÇ °ª¿¡ ±âÃÊÇÏ¿© °´Ã¼¸¦ »ý¼ºÇҠŬ·¡½ºÀÇŸÀÔÀ» ÆÇ´ÜÇÒ ¼ö ÀÖ´Ù. ±¸º°Àڴ °á°ú¸ÊÀÇ ÀϺÎÀÌ°í switch ±¸¹®Ã³·³ Àß ÀÛµ¿ÇÑ´Ù. ¿¹¸¦µé¸é:

À§ ±¸º°Àڴ ÀÌ·¸°Ô ÀÐÀ» ¼ö ÀÖ´Ù.

- Ä®·³ ¡°TYPE¡± ÀÌ ¡°Book¡± À̶ó´Â °ªÀ» Æ÷ÇÔÇÑ´Ù¸é, ¡°book¡± À̶ó´Â °á°ú¸ÊÀ» »ç¿ëÇ϶ó. ¹Ý¸é¿¡ Ä®·³ ¡°TYPE¡±ÀÌ ¡°Newspaper¡± ¶ó´Â °ªÀ» Æ÷ÇÔÇÑ´Ù¸é, ¡°news¡±¶ó´Â °á°ú¸ÊÀ» »ç¿ëÇ϶ó.

ÇÏÀ§ ¸ÊÀº À̸§À¸·Î ÂüÁ¶Çϴ ÀϹÝÀûÀΠ°á°ú¸ÊÀÌ´Ù. ±¸º°ÀÚ°¡ ÇÏÀ§ ¸Ê Áß Çϳª¿Í ÀÏÄ¡Çϴ °ªÀ» Ã£Áö ¸øÇÑ´Ù¸é, »óÀ§ °á°ú¸ÊÀÌ Àû¿ëµÈ´Ù. ÇÏÁö¸¸ ÀûÀýÇÑ °ªÀÌ Àִٸ頿ÀÁ÷ ÇÏÀ§¸Ê¸¸ÀÌ Àû¿ëµÈ´Ù. ºÎ¸ð¿¡ Á¤ÀǵȠ°á°ú ¸ÅÇÎÀº ´ÙÀ½ ¿¹Á¦¿¡¼­ º¸µíÀÌ ÇÏÀ§ ¸ÊÀÌ ºÎ¸ð ¸ÊÀ» ¸í½ÃÀûÀ¸·Î È®ÀåÇÏÁö ¾Ê´Â ÇÑ Àû¿ëµÇÁö ¾Ê´Â´Ù.

°á°ú¸ÊÀÇ extends ¼Ó¼ºÀº ÂüÁ¶Çϴ °á°ú¸Ê¿¡¼­ ¸ðµç °á°ú ¸ÅÇÎÀ» È¿°úÀûÀ¸·Î º¹»çÇÑ´Ù.¾î·µç ÀÌ°ÍÀº Å¬·¡½º ±¸Á¶¿¡ ´ëÇÑ ¾î¶°ÇÑ °Íµµ ÀǹÌÇÏÁö ¾Ê´Â´Ù. iBATIS´Â °´Ã¼ °ü°è ¸ÅÇΠÇÁ·¹ÀÓ¿öÅ©°¡ ¾Æ´Ï¶ó´Â °ÍÀ» ±â¾ïÇضó. ÀÌ Â÷ÀÌÁ¡Àº iBATIS°¡ Å¬·¡½º¿Í µ¥ÀÌÅͺ£À̽º Å×ÀÌºí °£ÀÇ ¸ÅÇÎÀ» ¾Ë°Å³ª ´Ù·çÁö ¾Ê´Â´Ù´Â °ÍÀÌ´Ù.

1.4. Àâ´ÙÇÑ ´Ù¸¥ È°¿ë¹ýµé

6.4.1 statement Å¸ÀÔ°ú DDL »ç¿ëÇϱâ

ŸÀÔÀº ´Ù¸¥ Å¸ÀÔµé (, , , 

select distinct

p.productId as productId,

o.accountId as accountId,

m.manufacturerId as manufacturerId

from product p

join manufacturer m

on p.manufacturerId = m.manufacturerId

join orderitem oi

on oi.productId = p.productId

join orders o

on oi.orderId = o.orderId

order by 1,2,3


AccountManufacturerProduct 
Ŭ·¡½º´Â ´Ü¼øÇѠŬ·¡½º·Î ¼¼ °¡Áö ÇÁ·ÎÆÛƼ(account, manufacturer, product)¸¦ °¡Áö°í ÀÖ´Ù. ÀÌ °á°ú ¸Ê(AmpRHExample)Àº µ¥ÀÌÅ͸¦ ÆòÆòÇϰԹٶ󺸴 ¹æ½ÄÀ¸·Î »ý¼ºÇÒ ¶§ Ã³·³ °¢ ÇÁ·ÎÆÛƼÀÇ °ªÀ» ÀÚµ¿À¸·Î ¼³Á¤ÇØÁØ´Ù.
ÀÌ ´ÙÀ½¿¡´Â ·Î¿ì Çڵ鷯°¡ ÀÌ °´Ã¼µéÀ» ¹Þ¾Æ¼­ °´Ã¼¸¦ ¸¸³¯¶§¸¶´Ù À̸¦ productId, accountId, manufacturerId ¿¡ µû¶ó ¸Ê °´Ã¼·Î ºÐ·ùÇØ ³Ö´Â´Ù. °¢°¢ÀÇ account È¤Àºproduct¸¦ Ã³À½À¸·Î ¹Þ¾ÆµéÀÏ ¶§ ÇØ´ç °´Ã¼¸¦ accountÀÇ ¸®½ºÆ®³ª productÀÇ ¸®½ºÆ®¿¡ °¢°¢ Ãß°¡ÇÑ´Ù. ¸¸¾à ¼±ÅõȠ°´Ã¼°¡ À̹̠ÀúÀåµÇ¾î ÀÖÀ» °æ¿ì, À̹̠(Map»ó¿¡) Á¸ÀçÇϴ °´Ã¼°¡ µ¥ÀÌÅͺ£À̽º¿¡¼­ ¹æ±Ý °¡Á®¿Â °´Ã¼¸¦ ´ëüÇÏ°Ô µÈ´Ù.
¸¶Áö¸·À¸·Î Æ¯Á¤ account, manufacturer È¤Àº productÀÇ ´ÜÀÏ ÀνºÅϽº¸¦ ¿ÏÀüÈ÷ »ý¼ºÇѵڿ¡ À̸¦ ÀûÇÕÇÑ °´Ã¼¿¡ Ãß°¡ÇÏ°Ô µÈ´Ù. À̴ ´ÙÀ½¿¡¼­ º¼ ¼ö ÀÖ´Ù.

public class AMPRowHandler implements RowHandler {

private Map accountMap

= new HashMap();

private Map manufacturerMap

= new HashMap();

private Map productMap

= new HashMap();

private List productAccountList

= new ArrayList();

private List accountManufacturerList

= new ArrayList();

public void handleRow(Object valueObject) {

AccountManufacturerProduct amp;

amp = (AccountManufacturerProduct)valueObject;

Account currentAccount = amp.getAccount();

Manufacturer currentMfgr = amp.getManufacturer();

AccountManufacturers am;

ProductAccounts pa;

Product currentProduct = amp.getProduct();

if (null == accountMap.get(currentAccount.getAccountId())) {

// this is the first time we have seen this account

am = new AccountManufacturers();

am.setAccount(currentAccount);

accountMap.put(currentAccount.getAccountId(), am);

accountManufacturerList.add(am);

} else {

// Use the accoutn from the account map

am = accountMap.get(currentAccount.getAccountId());

currentAccount = am.getAccount();

}

// am is now the current account / manufacturerlist

if (null ==

manufacturerMap.get(currentMfgr.getManufacturerId())) {

// we have not seen this manufacturer yet

manufacturerMap.put(

currentMfgr.getManufacturerId(),

currentMfgr);

} else {

// we already have this manufacturer loaded, reuse it

currentMfgr = manufacturerMap.get(

currentMfgr.getManufacturerId());

}

am.getManufacturerList().add(currentMfgr);

if (null == productMap.get(currentProduct.getProductId())) {

// this is a new product

pa = new ProductAccounts();

pa.setProduct(currentProduct);

productMap.put(currentProduct.getProductId(), pa);

productAccountList.add(pa);

} else {

// this prodcut has been loaded already

pa = productMap.get(currentProduct.getProductId());

}

// pa is now the current product's product / account list

pa.getAccountList().add(currentAccount);

am.getManufacturerList().add(currentMfgr);

}

public List getProductAccountList() {

return productAccountList;

}

public List getAccountManufacturerList() {

return accountManufacturerList;

}

public Map getProductMap() {

return productMap;

}

public Map getAccountMap() {

return accountMap;

}

}
Äڵ尡 ²Ï º¹ÀâÇØ º¸À̱ä ÇÏÁö¸¸, ÀÌ Äڵ尡 Çϴ ÀÏ ¿ª½Ã ±²ÀåÈ÷ º¹ÀâÇϱ⠶§¹®¿¡ ¾î¿¼ö ¾ø´Ù
.



Ãâó: http://devx.tistory.com/entry/iBATIS-in-Action-614 [Meta Developer Story]