{"id":1554,"date":"2014-06-16T02:37:57","date_gmt":"2014-06-16T02:37:57","guid":{"rendered":"http:\/\/brain.payzip.co.kr\/?p=1554"},"modified":"2014-06-16T02:37:57","modified_gmt":"2014-06-16T02:37:57","slug":"mybatis-%ec%bf%bc%eb%a6%ac-%eb%b0%98%ec%98%81spring-mybatis-%ed%99%98%ea%b2%bd%ec%97%90%ec%84%9c-xml-%ed%8c%8c%ec%9d%bc-%eb%b3%80%ea%b2%bd%ec%8b%9c-%ec%84%9c%eb%b2%84-%ec%9e%ac%ec%8b%9c%ec%9e%91","status":"publish","type":"post","link":"https:\/\/blog.goorigo.com\/?p=1554","title":{"rendered":"[mybatIs \ucffc\ub9ac \ubc18\uc601]Spring + mybatIs \ud658\uacbd\uc5d0\uc11c xml \ud30c\uc77c \ubcc0\uacbd\uc2dc \uc11c\ubc84 \uc7ac\uc2dc\uc791 \uc5c6\uc774 \ubc18\uc601 \ubc29\ubc95"},"content":{"rendered":"<p>&nbsp;<\/p>\n<p>\ucd9c\ucc98 : http:\/\/sbcoba.tistory.com\/16<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>\uc694\uc998 ORM\uc73c\ub85c\ub294 \ud558\uc774\ubc84\ub124\uc774\ud2b8, JPA\ub4f1 \ub9ce\uc774 \uc0ac\uc6a9\ud558\uace0 \uc788\uc73c\ub098, \uc5ed\uc2dc SI \ucabd\uc740 mybatis(ibatis)\ub97c \ub9ce\uc774 \uc0ac\uc6a9\ub41c\ub2e4.<\/p>\n<p>\ubb38\uc81c\ub294 mybatis\ub294 xml\ub85c sql\uc744 \uad00\ub9ac\ud558\uace0 \uc788\ub294\ub370 \ubcf4\ud1b5 \uc870\uae08 \ubc14\uafc0\ub54c \ub9c8\ub2e4 \uc11c\ubc84\ub97c \uc7ac\uad6c\ub3d9 \uc2dc\ucf1c\uc57c \ub418\ub294 \ubb38\uc81c\uac00 \ub41c\ub2e4.<\/p>\n<p>\uc2dc\uc2a4\ud15c\uc774 \ud074 \uacbd\uc6b0 \uc7ac\uc2dc\uc791\uc2dc \uc624\ub79c \uc2dc\uac04 \uac78\ub9ac\uace0 session \uc0ac\uc6a9\uc2dc \ub610 \ub85c\uadf8\uc778\uc744 \ud574\uc57c \ud558\ub294\ub4ef \uac1c\ubc1c\uc758 \ud750\ub984\uc774 \ub04a\uc5b4\uc9c0\ub294 \ubb38\uc81c\uac00 \ub9ce\uc774 \ubc1c\uc0dd\ud55c\ub2e4.<\/p>\n<p>\uc608\uc804\uc5d0 ibatis\ub97c \uc0ac\uc6a9 \ud588\uc744\uc2dc\uc5d0\ub3c4 \uadf8\ub7f0 \ubd80\ubd84\uc774 \ub9ce\uc774 \ubd88\ud3b8\ud588\uc5c8\ub294\ub370, \uc608\uc804 \ub300\uc6b0\uc815\ubcf4\uc2dc\uc2a4\ud15c\uc758 JCF \ud504\ub808\uc784\uc6cc\ud06c\uc5d0\uc11c \uc0ac\uc6a9\ub41c\ub2e4\uace0 Refresh \ub418\ub294\u00a0\ud074\ub798\uc2a4 \uc18c\uc2a4\uac00 \ud55c\ubc88 \uacf5\uac1c \ub41c\uc801\uc774 \uc788\uc5c8\ub2e4. ( \uba87\ub144\uc804\uc778\uc9c0 \uae30\uc5b5\uc740 \uc548\ub098\uc9c0\ub9cc,\u00a0\ub2f9\uc2dc \uc778\ud130\ub137 \uac80\uc0c9\uc73c\ub85c \ucc3e\uc558\uc5c8\ub2e4. )<\/p>\n<p>\uadf8\uac83\uc774 \ubc84\uc804\uc774 \ubb38\uc81c\uc778\uc9c0 \ubc14\ub85c \uc0ac\uc6a9\uc774 \uc548\ub418\uc5b4\uc11c \ucee4\uc2a4\ud130\ub9c8\uc774\uc9d5\ud558\uace0 \uc0ac\uc6a9\uc744 \uc798\uc0ac\uc6a9 \ud588\uc5c8\ub2e4.<\/p>\n<p>\uadf8\ub7f0\ub370 \uc9c0\uae08 \ud504\ub85c\uc81d\ud2b8\uac00 mybatis\ub85c \uc9c4\ud589\ud558\uae30 \ub54c\ubb38\uc5d0 \uc608\uc804\uacfc \uac19\uc740 \ubd88\ud3b8\ud568\uc774 \ub610 \uc0dd\uae30\uac8c \ub418\uc5c8\ub294\ub370, \uc774 \ubc88\uc5d0\ub294 \uadf8 \uc18c\uc2a4\ub97c mybatis\uc5d0 \ub9de\ub3c4\ub85c \ucee4\uc2a4\ud130\ub9c8\uc774\uc9d5 \ud558\uae30\ub85c \ud588\ub2e4.<\/p>\n<p>\uc77c\ub2e8 \uc0ac\uc804 \uc870\uac74\uc740<\/p>\n<p><b>JDK 1.5 \uc774\uc0c1<\/b>,\u00a0Spring, mybatis,\u00a0<b>spring-mybatis<\/b>\u00a0\ub77c\uc774\ube0c\ub7ec\ub9ac\uac00 \uc124\uce58\ub418\uc5b4 \uc788\ub294 \ud658\uacbd\uc5d0\uc11c\ub9cc \ub41c\ub2e4.<\/p>\n<p>&nbsp;<\/p>\n<p>\uc77c\ub2e8 \uae30\uc874\u00a0Spring \uc5d0\uc11c mybatis \uc124\uc815\uc744 \ubcf4\uaca0\ub2e4.<\/p>\n<p>\ubcf4\ud1b5 sqlSessionFactory\ub97c \uc774\ub807\uac8c \uc124\uc815 \ud55c\ub2e4.<\/p>\n<div>\n<p>&lt;bean id=&#8221;sqlSessionFactory&#8221; p:mapperLocations=&#8221;<b>classpath*:\ud328\ud0a4\uc9c0\uacbd\ub85c\/**\/mapper.xml<\/b>&#8221; p:configLocation=&#8221;classpath:\/MapperConfig.xml&#8221; p:dataSource-ref=&#8221;dataSource&#8221;\/&gt;<\/p>\n<\/div>\n<p><b>classpath*:\ud328\ud0a4\uc9c0\uacbd\ub85c\/**\/mapper.xml\u00a0<\/b><b>\u00a0&lt;-<\/b>\uc774\ubd80\ubd84\uc774 \uc7ac\ub85c\ub529 \ub420 xml \ud30c\uc77c\uacbd\ub85c\u00a0<b>( \uc790\uc2e0\uc758 \ud504\ub85c\uc81d\ud2b8\uc5d0 \ub530\ub77c \ubcc0\uacbd )<\/b><\/p>\n<p>\uc774\ubd80\ubd84\uc5d0\uc11c\u00a0<b>\uad75\uac8c \ud45c\uc2dc\ud55c class<\/b>\u00a0\ubd80\ubd84\ub9cc \uc0c8\ub85c \ub9cc\ub4e0 \ud074\ub798\uc2a4\ub85c \ubc14\uafb8\uba74 \ubaa8\ub4e0\uac8c \ud574\uacb0\ub41c\ub2e4.<\/p>\n<div>\n<p>&lt;bean id=&#8221;sqlSessionFactory&#8221; p:mapperLocations=&#8221;<b>classpath*:\ud328\ud0a4\uc9c0\uacbd\ub85c\/**\/mapper.xml<\/b>&#8221; p:configLocation=&#8221;classpath:\/MapperConfig.xml&#8221; p:dataSource-ref=&#8221;dataSource&#8221;\u00a0\/&gt;<\/p>\n<\/div>\n<p><b>RefreshableSqlSessionFactoryBean.java<\/b><\/p>\n<div>\n<p>import java.io.IOException;<\/p>\n<p>import java.lang.reflect.InvocationHandler;<\/p>\n<p>import java.lang.reflect.Method;<\/p>\n<p>import java.lang.reflect.Proxy;<\/p>\n<p>import java.util.ArrayList;<\/p>\n<p>import java.util.HashMap;<\/p>\n<p>import java.util.List;<\/p>\n<p>import java.util.Map;<\/p>\n<p>import java.util.Timer;<\/p>\n<p>import java.util.TimerTask;<\/p>\n<p>&nbsp;<\/p>\n<p>import org.apache.commons.logging.Log;<\/p>\n<p>import org.apache.commons.logging.LogFactory;<\/p>\n<p>import org.apache.ibatis.session.SqlSessionFactory;<\/p>\n<p>import org.mybatis.spring.SqlSessionFactoryBean;<\/p>\n<p>import org.springframework.beans.factory.DisposableBean;<\/p>\n<p>import org.springframework.core.io.Resource;<\/p>\n<p>&nbsp;<\/p>\n<p>import java.util.concurrent.locks.Lock;<\/p>\n<p>import java.util.concurrent.locks.ReentrantReadWriteLock;<\/p>\n<p>&nbsp;<\/p>\n<p>\/**<\/p>\n<p>* mybatis mapper \uc790\ub3d9 \uac10\uc9c0 \ud6c4 \uc790\ub3d9\uc73c\ub85c \uc11c\ubc84 \uc7ac\uc2dc\uc791\uc774 \ud544\uc694 \uc5c6\uc774 \ubc18\uc601<\/p>\n<p>*<\/p>\n<p>* @author sbcoba<\/p>\n<p>*<\/p>\n<p>*\/<\/p>\n<p>public class RefreshableSqlSessionFactoryBean extends SqlSessionFactoryBean implements DisposableBean {<\/p>\n<p>&nbsp;<\/p>\n<p>private static final Log log = LogFactory .getLog(RefreshableSqlSessionFactoryBean.class);<\/p>\n<p>&nbsp;<\/p>\n<p>private SqlSessionFactory proxy;<\/p>\n<p>private int interval = 500;<\/p>\n<p>&nbsp;<\/p>\n<p>private Timer timer;<\/p>\n<p>private TimerTask task;<\/p>\n<p>&nbsp;<\/p>\n<p>private Resource[] mapperLocations;<\/p>\n<p>&nbsp;<\/p>\n<p>\/**<\/p>\n<p>* \ud30c\uc77c \uac10\uc2dc \uc4f0\ub808\ub4dc\uac00 \uc2e4\ud589\uc911\uc778\uc9c0 \uc5ec\ubd80.<\/p>\n<p>*\/<\/p>\n<p>private boolean running = false;<\/p>\n<p>&nbsp;<\/p>\n<p>private final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();<\/p>\n<p>private final Lock r = rwl.readLock();<\/p>\n<p>private final Lock w = rwl.writeLock();<\/p>\n<p>&nbsp;<\/p>\n<p>public void setMapperLocations(Resource[] mapperLocations) {<\/p>\n<p>super.setMapperLocations(mapperLocations);<\/p>\n<p>this.mapperLocations = mapperLocations;<\/p>\n<p>}<\/p>\n<p>&nbsp;<\/p>\n<p>public void setInterval(int interval) {<\/p>\n<p>this.interval = interval;<\/p>\n<p>}<\/p>\n<p>&nbsp;<\/p>\n<p>\/**<\/p>\n<p>*<\/p>\n<p>* @throws Exception<\/p>\n<p>*\/<\/p>\n<p>public void refresh() throws Exception {<\/p>\n<p>if (log.isInfoEnabled()) {<\/p>\n<p>log.info(&#8220;refreshing sqlMapClient.&#8221;);<\/p>\n<p>}<\/p>\n<p>w.lock();<\/p>\n<p>try {<\/p>\n<p>super.afterPropertiesSet();<\/p>\n<p>&nbsp;<\/p>\n<p>} finally {<\/p>\n<p>w.unlock();<\/p>\n<p>}<\/p>\n<p>}<\/p>\n<p>&nbsp;<\/p>\n<p>\/**<\/p>\n<p>* \uc2f1\uae00\ud1a4 \uba64\ubc84\ub85c SqlMapClient \uc6d0\ubcf8 \ub300\uc2e0 \ud504\ub85d\uc2dc\ub85c \uc124\uc815\ud558\ub3c4\ub85d \uc624\ubc84\ub77c\uc774\ub4dc.<\/p>\n<p>*\/<\/p>\n<p>public void afterPropertiesSet() throws Exception {<\/p>\n<p>super.afterPropertiesSet();<\/p>\n<p>&nbsp;<\/p>\n<p>setRefreshable();<\/p>\n<p>}<\/p>\n<p>&nbsp;<\/p>\n<p>private void setRefreshable() {<\/p>\n<p>proxy = (SqlSessionFactory) Proxy.newProxyInstance(<\/p>\n<p>SqlSessionFactory.class.getClassLoader(),<\/p>\n<p>new Class[] { SqlSessionFactory.class },<\/p>\n<p>new InvocationHandler() {<\/p>\n<p>public Object invoke(Object proxy, Method method,<\/p>\n<p>Object[] args) throws Throwable {<\/p>\n<p>\/\/ log.debug(&#8220;method.getName() : &#8221; + method.getName());<\/p>\n<p>return method.invoke(getParentObject(), args);<\/p>\n<p>}<\/p>\n<p>});<\/p>\n<p>&nbsp;<\/p>\n<p>task = new TimerTask() {<\/p>\n<p>private Map&lt;Resource, Long&gt; map = new HashMap&lt;Resource, Long&gt;();<\/p>\n<p>&nbsp;<\/p>\n<p>public void run() {<\/p>\n<p>if (isModified()) {<\/p>\n<p>try {<\/p>\n<p>refresh();<\/p>\n<p>} catch (Exception e) {<\/p>\n<p>log.error(&#8220;caught exception&#8221;, e);<\/p>\n<p>}<\/p>\n<p>}<\/p>\n<p>}<\/p>\n<p>&nbsp;<\/p>\n<p>private boolean isModified() {<\/p>\n<p>boolean retVal = false;<\/p>\n<p>&nbsp;<\/p>\n<p>if (mapperLocations != null) {<\/p>\n<p>for (int i = 0; i &lt; mapperLocations.length; i++) {<\/p>\n<p>Resource mappingLocation = mapperLocations[i];<\/p>\n<p>retVal |= findModifiedResource(mappingLocation);<\/p>\n<p>}<\/p>\n<p>}<\/p>\n<p>&nbsp;<\/p>\n<p>return retVal;<\/p>\n<p>}<\/p>\n<p>&nbsp;<\/p>\n<p>private boolean findModifiedResource(Resource resource) {<\/p>\n<p>boolean retVal = false;<\/p>\n<p>List&lt;String&gt; modifiedResources = new ArrayList&lt;String&gt;();<\/p>\n<p>&nbsp;<\/p>\n<p>try {<\/p>\n<p>long modified = resource.lastModified();<\/p>\n<p>&nbsp;<\/p>\n<p>if (map.containsKey(resource)) {<\/p>\n<p>long lastModified = ((Long) map.get(resource))<\/p>\n<p>.longValue();<\/p>\n<p>&nbsp;<\/p>\n<p>if (lastModified != modified) {<\/p>\n<p>map.put(resource, new Long(modified));<\/p>\n<p>modifiedResources.add(resource.getDescription());<\/p>\n<p>retVal = true;<\/p>\n<p>}<\/p>\n<p>} else {<\/p>\n<p>map.put(resource, new Long(modified));<\/p>\n<p>}<\/p>\n<p>} catch (IOException e) {<\/p>\n<p>log.error(&#8220;caught exception&#8221;, e);<\/p>\n<p>}<\/p>\n<p>if (retVal) {<\/p>\n<p>if (log.isInfoEnabled()) {<\/p>\n<p>log.info(&#8220;modified files : &#8221; + modifiedResources);<\/p>\n<p>}<\/p>\n<p>}<\/p>\n<p>return retVal;<\/p>\n<p>}<\/p>\n<p>};<\/p>\n<p>&nbsp;<\/p>\n<p>timer = new Timer(true);<\/p>\n<p>resetInterval();<\/p>\n<p>&nbsp;<\/p>\n<p>}<\/p>\n<p>&nbsp;<\/p>\n<p>private Object getParentObject() throws Exception {<\/p>\n<p>r.lock();<\/p>\n<p>try {<\/p>\n<p>return super.getObject();<\/p>\n<p>&nbsp;<\/p>\n<p>} finally {<\/p>\n<p>r.unlock();<\/p>\n<p>}<\/p>\n<p>}<\/p>\n<p>&nbsp;<\/p>\n<p>public SqlSessionFactory getObject() {<\/p>\n<p>return this.proxy;<\/p>\n<p>}<\/p>\n<p>&nbsp;<\/p>\n<p>public Class&lt;? extends SqlSessionFactory&gt; getObjectType() {<\/p>\n<p>return (this.proxy != null ? this.proxy.getClass()<\/p>\n<p>: SqlSessionFactory.class);<\/p>\n<p>}<\/p>\n<p>&nbsp;<\/p>\n<p>public boolean isSingleton() {<\/p>\n<p>return true;<\/p>\n<p>}<\/p>\n<p>&nbsp;<\/p>\n<p>public void setCheckInterval(int ms) {<\/p>\n<p>interval = ms;<\/p>\n<p>&nbsp;<\/p>\n<p>if (timer != null) {<\/p>\n<p>resetInterval();<\/p>\n<p>}<\/p>\n<p>}<\/p>\n<p>&nbsp;<\/p>\n<p>private void resetInterval() {<\/p>\n<p>if (running) {<\/p>\n<p>timer.cancel();<\/p>\n<p>running = false;<\/p>\n<p>}<\/p>\n<p>if (interval &gt; 0) {<\/p>\n<p>timer.schedule(task, 0, interval);<\/p>\n<p>running = true;<\/p>\n<p>}<\/p>\n<p>}<\/p>\n<p>&nbsp;<\/p>\n<p>public void destroy() throws Exception {<\/p>\n<p>timer.cancel();<\/p>\n<p>}<\/p>\n<p>}<\/p>\n<\/div>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>\ub9cc\uc57d\uc5d0 \uc7ac\ub85c\ub529 \ub418\ub294 \uc2dc\uac04\uc744 \ubc14\uafb8\uace0 \uc2f6\uc73c\uba74<\/p>\n<div>\n<p>&lt;bean id=&#8221;sqlSessionFactory&#8221; p:mapperLocations=&#8221;classpath*:<b>\ud328\ud0a4\uc9c0\uacbd\ub85c<\/b>\/**\/mapper.xml&#8221; :configLocation=&#8221;classpath:\/MapperConfig.xml&#8221; p:dataSource-ref=&#8221;dataSource&#8221;\u00a0<b><span style=\"text-decoration: underline;\">p:interval=&#8221;1000&#8243;<\/span><\/b>\u00a0\/&gt;<\/p>\n<\/div>\n<p>p:interval=&#8221;1000&#8243; \uc774\ubd80\ubd84\uc744 \uc218\uce58\ub97c \uc815\ud574\uc8fc\uba74\ub41c\ub2e4. ( \ub514\ud3f4\ud2b8\ub294 500,\u00a0\ub2e8\uc704 ms )<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>\uc774\uc81c \uc124\uc815\uc744 \uc11c\ubc84\ub97c \uc2dc\uc791\ud574\uc11c \uc704\uc5d0 \ub85c\ucf00\uc774\uc158 \ud574\ub2f9\ud558\ub294 mapper.xml ( sql\uc774 \uc788\ub294 xml\u00a0, \uc124\uc815\uc5d0 \ub530\ub77c \ub2e4\ub984)\uc5d0\uc11c<\/p>\n<p>sql\uc744 \ubc14\uafd4 \ubcf4\uc790 \uadf8\ub9ac\uace0 \ud074\ub77c\uc774\uc5b8\ud2b8\uc5d0\uc11c \ubc14\ub010\uc9c0 \ud655\uc778\ud574\ubcf4\uc790<\/p>\n<p>\ud070 \ubb38\uc81c\uac00 \uc5c6\ub2e4\uba74 \ubc18\uc601\ub420\uac83\uc774\ub77c\uace0 \uc0dd\uac01\ub41c\ub2e4.<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p><b>\uc544 \ub2e8 \uc6b4\uc601 \uc2dc\uc2a4\ud15c\uc5d0 \uc0ac\uc6a9\uc740 \ubcf4\uc7a5 \ubabb\ud569\ub2c8\ub2e4~ \uac1c\ubc1c\uc2dc\uc5d0\uc11c\ub9cc \uc0ac\uc6a9\ud558\uc138\uc694~<\/b><\/p>\n<p>&nbsp;<\/p>\n<p>\uc774 \uc18c\uc2a4\ub294 \uc608\uc804\uc5d0 \uc778\ud130\ub137\uc5d0\uc11c \ub098\ub3cc\ub358\u00a0RefreshableSqlMapClientFactoryBean \uc18c\uc2a4\ub97c \ucee4\uc2a4\ud130\ub9c8\uc774\uc9d5\ud55c \uc18c\uc2a4\uc778\ub370 \ubb38\uc81c\uac00 \uc788\ub2e4\uba74 \uc5f0\ub77d\uc8fc\uc2dc\uae38\ubc14\ub78d\ub2c8\ub2e4.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>&nbsp; \ucd9c\ucc98 : http:\/\/sbcoba.tistory.com\/16 &nbsp; &nbsp; &nbsp; \uc694\uc998 ORM\uc73c\ub85c\ub294 \ud558\uc774\ubc84\ub124\uc774\ud2b8, JPA\ub4f1 \ub9ce\uc774 \uc0ac\uc6a9\ud558\uace0 \uc788\uc73c\ub098, \uc5ed\uc2dc SI \ucabd\uc740 mybatis(ibatis)\ub97c \ub9ce\uc774 \uc0ac\uc6a9\ub41c\ub2e4. \ubb38\uc81c\ub294 mybatis\ub294 xml\ub85c sql\uc744 \uad00\ub9ac\ud558\uace0 \uc788\ub294\ub370 \ubcf4\ud1b5 \uc870\uae08 \ubc14\uafc0\ub54c \ub9c8\ub2e4&hellip; <\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[1],"tags":[],"_links":{"self":[{"href":"https:\/\/blog.goorigo.com\/index.php?rest_route=\/wp\/v2\/posts\/1554"}],"collection":[{"href":"https:\/\/blog.goorigo.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.goorigo.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.goorigo.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.goorigo.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1554"}],"version-history":[{"count":0,"href":"https:\/\/blog.goorigo.com\/index.php?rest_route=\/wp\/v2\/posts\/1554\/revisions"}],"wp:attachment":[{"href":"https:\/\/blog.goorigo.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1554"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.goorigo.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1554"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.goorigo.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1554"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}