2022. 3. 10. 20:56ใ๊ฐ๋ ์ ๋ฆฌ ์์ ์ค/๋ฌธ์ ์ ๋ฆฌ
โ ๏ธ ๋ฌธ์ ๋ฐ์!
2022-03-10 20:27:27.536 ERROR 2422 --- [nio-8080-exec-2] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): com.devcommunity.junyharang.mapper.support.DevInquryMapper.devInquryList] with root cause
org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): com.devcommunity.junyharang.mapper.support.DevInquryMapper.devInquryList
at org.apache.ibatis.binding.MapperMethod$SqlCommand.<init>(MapperMethod.java:235) ~[mybatis-3.5.6.jar:3.5.6]
at org.apache.ibatis.binding.MapperMethod.<init>(MapperMethod.java:53) ~[mybatis-3.5.6.jar:3.5.6]
at org.apache.ibatis.binding.MapperProxy.lambda$cachedInvoker$0(MapperProxy.java:115) ~[mybatis-3.5.6.jar:3.5.6]
at java.base/java.util.concurrent.ConcurrentHashMap.computeIfAbsent(ConcurrentHashMap.java:1705) ~[na:na]
at org.apache.ibatis.binding.MapperProxy.cachedInvoker(MapperProxy.java:102) ~[mybatis-3.5.6.jar:3.5.6]
at org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:85) ~[mybatis-3.5.6.jar:3.5.6]
at com.sun.proxy.$Proxy81.devInquryList(Unknown Source) ~[na:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:566) ~[na:na]
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:344) ~[spring-aop-5.3.16.jar:5.3.16]
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:198) ~[spring-aop-5.3.16.jar:5.3.16]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-5.3.16.jar:5.3.16]
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:137) ~[spring-tx-5.3.16.jar:5.3.16]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.16.jar:5.3.16]
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:215) ~[spring-aop-5.3.16.jar:5.3.16]
at com.sun.proxy.$Proxy82.devInquryList(Unknown Source) ~[na:na]
at com.devcommunity.junyharang.service.support.DevInquryServiceImpl.devInquryList(DevInquryServiceImpl.java:39) ~[classes/:na]
at com.devcommunity.junyharang.service.support.DevInquryServiceImpl$$FastClassBySpringCGLIB$$146fea12.invoke(<generated>) ~[classes/:na]
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) ~[spring-core-5.3.16.jar:5.3.16]
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:783) ~[spring-aop-5.3.16.jar:5.3.16]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-5.3.16.jar:5.3.16]
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:753) ~[spring-aop-5.3.16.jar:5.3.16]
at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:123) ~[spring-tx-5.3.16.jar:5.3.16]
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:388) ~[spring-tx-5.3.16.jar:5.3.16]
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119) ~[spring-tx-5.3.16.jar:5.3.16]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.16.jar:5.3.16]
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:753) ~[spring-aop-5.3.16.jar:5.3.16]
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:698) ~[spring-aop-5.3.16.jar:5.3.16]
at com.devcommunity.junyharang.service.support.DevInquryServiceImpl$$EnhancerBySpringCGLIB$$ebd8eac5.devInquryList(<generated>) ~[classes/:na]
at com.devcommunity.junyharang.controller.support.DevInquryController.devInquryList(DevInquryController.java:75) ~[classes/:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:566) ~[na:na]
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205) ~[spring-web-5.3.16.jar:5.3.16]
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:150) ~[spring-web-5.3.16.jar:5.3.16]
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:117) ~[spring-webmvc-5.3.16.jar:5.3.16]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895) ~[spring-webmvc-5.3.16.jar:5.3.16]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808) ~[spring-webmvc-5.3.16.jar:5.3.16]
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-5.3.16.jar:5.3.16]
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1067) ~[spring-webmvc-5.3.16.jar:5.3.16]
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:963) ~[spring-webmvc-5.3.16.jar:5.3.16]
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) ~[spring-webmvc-5.3.16.jar:5.3.16]
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909) ~[spring-webmvc-5.3.16.jar:5.3.16]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:681) ~[tomcat-embed-core-9.0.58.jar:4.0.FR]
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883) ~[spring-webmvc-5.3.16.jar:5.3.16]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:764) ~[tomcat-embed-core-9.0.58.jar:4.0.FR]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:227) ~[tomcat-embed-core-9.0.58.jar:9.0.58]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.58.jar:9.0.58]
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) ~[tomcat-embed-websocket-9.0.58.jar:9.0.58]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.58.jar:9.0.58]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.58.jar:9.0.58]
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[spring-web-5.3.16.jar:5.3.16]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) ~[spring-web-5.3.16.jar:5.3.16]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.58.jar:9.0.58]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.58.jar:9.0.58]
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:197) ~[tomcat-embed-core-9.0.58.jar:9.0.58]
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97) ~[tomcat-embed-core-9.0.58.jar:9.0.58]
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:540) ~[tomcat-embed-core-9.0.58.jar:9.0.58]
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:135) ~[tomcat-embed-core-9.0.58.jar:9.0.58]
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) ~[tomcat-embed-core-9.0.58.jar:9.0.58]
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78) ~[tomcat-embed-core-9.0.58.jar:9.0.58]
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:359) ~[tomcat-embed-core-9.0.58.jar:9.0.58]
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:399) ~[tomcat-embed-core-9.0.58.jar:9.0.58]
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) ~[tomcat-embed-core-9.0.58.jar:9.0.58]
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:889) ~[tomcat-embed-core-9.0.58.jar:9.0.58]
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1735) ~[tomcat-embed-core-9.0.58.jar:9.0.58]
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) ~[tomcat-embed-core-9.0.58.jar:9.0.58]
at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191) ~[tomcat-embed-core-9.0.58.jar:9.0.58]
at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659) ~[tomcat-embed-core-9.0.58.jar:9.0.58]
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) ~[tomcat-embed-core-9.0.58.jar:9.0.58]
at java.base/java.lang.Thread.run(Thread.java:829) ~[na:na]
MyBatis๋ฅผ ๊ณต๋ถ ํด๋ณด๊ณ , ์ฒ์ ์ฌ์ฉ ํด ๋ณด๋๋ฐ, ์ ์ ์๋ Exception์ ๋นํฉ์ ํ ๊ฒ์ด์์.
๐ค ์์ธ ๋ถ์
ํด๋น Exception์ MyBatis๋ฅผ ์ฌ์ฉํ๊ฒ ๋๋ฉด ํํ ๋ง๋๊ฒ ๋๋ Exception์ด๋ผ ํด์.
์ด ๋ฌธ์ ๋ ๋๋ต 5๊ฐ์ง์ ์์ธ์ผ๋ก ์ธํด ๋ฐ์ํ ์ ์๋ต๋๋ค!
โ Mapper Interface์ Mapper-XML์ ์คํ
- ํน์ Mapper Interface์ XML์ ์คํ๊ฐ ์๋์ง ํ์ธ ํด ๋ด์ผ ํ๋ ๊ฒ์ด์์.
<select> ๋ฌธ ๋ฑ์์ ์ ์ธํ๋ id ์์ฑ ๋ถ์์ ์คํ๊ฐ ์์์๋ ์๊ณ , ์ ์ธ๋์ด ์๋ id ์์ฑ์ด Mapper Interface
์ถ์ Method์ ์ด๋ฆ์ด ๋ค๋ฅธ์ง ํ์ธํด๋ณด๋ ๊ฒ์ด์์. Interface ์ด๋ฆ๊ณผ XML์ ์ด๋ฆ์ด ๋ฌ๋ผ์ Exception์ด
ํฐ์ง ์ ์๋ ๊ฒ์ด์์.
๐ฝ DevInquryMapper.java - devInquryList(DevInquryVO devInquryVO)
๐ฝ DevInquryMapper.xml - devInquryList(DevInquryVO devInquryVO)
<!-- Q&A ๋ชฉ๋ก ์กฐํ -->
<select id="devInquryList" parameterType="com.devcommunity.junyharang.model.vo.support.DevInquryVO" resultType="com.devcommunity.junyharang.model.vo.support.DevInquryVO">
select row_number() over(order by i.INQRY_SN asc) as INQRY_INDEX , i.INQRY_SN, i.INQRY_USER_SN , i.FILE_SN , i.INQRY_CN , i.INQRY_SJ , i.SECRET_AT , i.ANSWER_AT , i.ANSWER_CN , i.ANSWER_USER_SN , i.ANSWER_DT , i.CREAT_DT , i.UPDT_DT , i.UPDUSR_SN, u.USER_ID
from tb_com_inqry i inner join tb_user u
on i.INQRY_USER_SN = u.user_sn
where 1=1
<if test=' srchType neq null and srchType neq "" '>
<choose>
<when test="srchType eq '1'.toString()">
and INQRY_SJ like CONCAT('%', #{srchWord}, '%')
</when>
<when test="srchType eq '2'.toString()">
and INQRY_CN like CONCAT('%', #{srchWord}, '%')
</when>
<when test="srchType eq '3'.toString()">
and u.USER_ID like CONCAT('%', #{srchWord}, '%')
</when>
</choose>
</if>
order by INQRY_SN desc
<if test=' pageStart neq null and perPageNum neq null '>
LIMIT #{pageStart}, #{perPageNum}
</if>
</select>
๐ฝ DevInquryMapper.java - devInquryReadhitCount(DevInquryVO devInquryVO)
๐ฝ DevInquryMapper.xml - devInquryReadhitCount(DevInquryVO devInquryVO)
ํ์ง๋ง, ์ฃผ๋ํ๋์ด ์์ฑํ ๊ฒ์ ๋ณด์์ ๋, ์ด ๋ฌธ์ ๋ ์๋ ๊ฒ์ด์์.
โ mapper-locations
- Query๊ฐ ์์ฑ๋ mapper XML์ด ์์นํ ๊ฒฝ๋ก๋ฅผ application.properties ํน์ application.yml์ ์ ์๋ฅผ ํด์ค์ผ
ํ๋๋ฐ, ํ์ง ์์์ ๋ฐ์ํ ์๋ ์๋ ๊ฒ์ด์์. ์ ํํ ๊ฒฝ๋ก๋ Project์ ๋ฐ๋ผ ๋ณ๊ฒฝ ํด ์ฃผ๋ฉด ๋๋ ๊ฒ์ด์์.
๐ฝ application.yml
์๋ฌด๊ฒ๋ ์์ฑ์ด ๋์ด ์์ง ์์ ๊ฒ์ด์์.
โ ๋์ผํ ์ด๋ฆ / ๋ค๋ฅธ Packge Path
- Mapper์ ์ด๋ฆ์ ๊ฐ์ผ๋, Package name์ด ๋ฌ๋ผ์ IDE์์ Compile Error๊ฐ ๋ฐ์ํ์ง ์๋ ๊ฒฝ์ฐ์ผ ์ ์๋ ๊ฒ์ด์์. ์ด๋ฐ ๊ฒฝ์ฐ์๋ Application ๊ตฌ๋ ๊ณผ์ ์์ Exeption์ด ํฐ์ง ์ ์๋ ๊ฒ์ด์์.
โ yaml File ๋ด ์คํ
- Project Config(์ค์ ) File์ธ application์ ํ์ฅ์๊ฐ properties๊ฐ ์๋ yaml๋ก ์์ฑํ ์๋ ์๋ ๊ฒ์ด์์.
yaml์ ๊ณ์ธต ๊ตฌ์กฐ๋ก ์์ฑ๋์ด ๊ฐ๋
์ฑ์ด ๋ ์ข๋ค๋ ์ฅ์ ์ ๊ฐ๋ ๊ฒ์ด์์. ๊ทธ๋ฐ๋ฐ, ์๋ ์ฌ์ง๊ณผ ๊ฐ์ด ๋ค์ฌ์ฐ๊ธฐ ๋ฑ์ ์ ๋ชป
๋ง์ถ๋ฉด Exception์ด ํฐ์ง๋ ๊ฒ์ด์์. ์๋ฅผ ๋ค์๋ฉด ์ต์๋จ์ ์ ์ธ๋ spring ๋ฐ์ ์์นํ๋ ๊ฒ์ด ์๋๋ผ,
์ต์๋จ์ mybatis๊ฐ ์์นํด์ผ ํ๋๋ฐ, spring ๋ฐ์ ์์ฑ๋์ด ๋ฒ๋ฆฌ๋ฉด ๋ฌธ์ ๊ฐ ๋ฐ์ํ ์ ์๋ ๊ฒ์ด์์.
โ DataSource Configuration
- DataSource๋ฅผ ์ค์ ํ๋ Configuration Class๋ฅผ ํ๋ฒ ์ ๊ฒ ํด ๋ณผ ํ์๊ฐ ์๋ ๊ฒ์ด์์.
SessionFactory๊ฐ ์ค์ ๋์ด ์๋ค๋ฉด setMapperLocations Method ๋ฑ์ผ๋ก Mapper XML์ ์์น๋ฅผ ์ ์ธํ๊ฒ
๋๋๋ฐ, ์๋ํ ๋๋ก ์ ์์ฑ ๋์๋์ง ํ์ธ์ด ํ์ํ ๊ฒ์ด์์. @MapperScan์ด ์ ์ธ๋ ๊ฒฝ์ฐ Mapper Interface๊ฐ
์๋ ์์น์ ์ผ์นํ๋์ง๋ ํ์ธ ํด ๋ณผ ํ์๊ฐ ์๋ ๊ฒ์ด์์.
๐ป ๋ฌธ์ ํด๊ฒฐ!
๋จผ์ DataBase์ ์ฐ๊ฒฐ ์ ๋ณด์ mybatis๊ด๋ จ ์ค์ ์ ๋ณด๋ฅผ ๋ฃ์ด์ค ๊ฒ์ด์์.
์ด๋ ๊ฒ ํ๋ ๋ฌธ์ ๋ ๊น๋ํ๊ฒ ํด๊ฒฐ ๋์๋ต๋๋ค!
์ฃผ๋ํ๋์ ๊ฒฐ๊ตญ mapper-locations ์ค์ ์ ํด์ฃผ์ง ์์ ๋ฐ์ํ ๋ฌธ์ ์๋ ๊ฒ์ด์์.