728x90
반응형
728x90
반응형
728x90
반응형

필요한 기능이 있어서 추가한 코드에서 갑작스런 에러가 났다.

원인은 간단하다. select 구문의 결과를 받을 resultType 또는 resultMap이 누락된거다.

 

1. SELECT COUNT(*) FROM MEMBER

WHERE MEM_TP = 'USER'

AND DEL_YN = 'N'

{executed in 8 msec}

org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.executor.ExecutorException: A query was run and no Result Maps were found for the Mapped Statement 'packagename.core.schedule.mapper.ScheduleMapper.getMemberTypeCount'. It's likely that neither a Result Type nor a Result Map was specified.

at org.mybatis.spring.MyBatisExceptionTranslator.translateExceptionIfPossible(MyBatisExceptionTranslator.java:92)

at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:440)

at com.sun.proxy.$Proxy104.selectOne(Unknown Source)

at org.mybatis.spring.SqlSessionTemplate.selectOne(SqlSessionTemplate.java:159)

at org.apache.ibatis.binding.MapperMethod.execute(MapperMethod.java:87)

at org.apache.ibatis.binding.MapperProxy$PlainMethodInvoker.invoke(MapperProxy.java:144)

at org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:85)

at com.sun.proxy.$Proxy127.getMemberTypeCount(Unknown Source)

at packagename.core.schedule.service.ScheduleService.common(ScheduleService.java:966)

at packagename.core.schedule.service.ScheduleService.start(ScheduleService.java:793)

at packagename.core.schedule.service.ScheduleService$$FastClassBySpringCGLIB$$5a06c0f7.invoke()

at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)

at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:779)

at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)

at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:750)

at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:123)

at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:388)

at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119)

at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)

at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:750)

at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:692)

at packagename.core.schedule.service.ScheduleService$$EnhancerBySpringCGLIB$$370f28bf.startTistoryUrlCrawling()

at packagename.web.BaseController.getTest(BaseController.java:101)

at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)

at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)

at java.lang.reflect.Method.invoke(Unknown Source)

at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:197)

at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:141)

at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:106)

at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:894)

at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808)

at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)

at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1060)

at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:962)

at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)

at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898)

at javax.servlet.http.HttpServlet.service(HttpServlet.java:626)

at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)

at javax.servlet.http.HttpServlet.service(HttpServlet.java:733)

at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:227)

at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)

at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)

at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)

at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)

at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)

at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)

at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)

at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)

at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)

at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)

at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)

at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)

at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)

at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)

at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)

at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)

at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202)

at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97)

at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:542)

at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:143)

at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)

at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78)

at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:346)

at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:374)

at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)

at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:887)

at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1684)

at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)

at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)

at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)

at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)

at java.lang.Thread.run(Unknown Source)

Caused by: org.apache.ibatis.executor.ExecutorException: A query was run and no Result Maps were found for the Mapped Statement 'packagename.core.schedule.mapper.ScheduleMapper.getMemberTypeCount'. It's likely that neither a Result Type nor a Result Map was specified.

at org.apache.ibatis.executor.resultset.DefaultResultSetHandler.validateResultMapsCount(DefaultResultSetHandler.java:289)

at org.apache.ibatis.executor.resultset.DefaultResultSetHandler.handleResultSets(DefaultResultSetHandler.java:191)

at org.apache.ibatis.executor.statement.PreparedStatementHandler.query(PreparedStatementHandler.java:65)

at org.apache.ibatis.executor.statement.RoutingStatementHandler.query(RoutingStatementHandler.java:79)

at org.apache.ibatis.executor.SimpleExecutor.doQuery(SimpleExecutor.java:63)

at org.apache.ibatis.executor.BaseExecutor.queryFromDatabase(BaseExecutor.java:324)

at org.apache.ibatis.executor.BaseExecutor.query(BaseExecutor.java:156)

at org.apache.ibatis.executor.CachingExecutor.query(CachingExecutor.java:109)

at com.github.pagehelper.PageInterceptor.intercept(PageInterceptor.java:108)

at org.apache.ibatis.plugin.Plugin.invoke(Plugin.java:61)

at com.sun.proxy.$Proxy193.query(Unknown Source)

at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:147)

at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:140)

at org.apache.ibatis.session.defaults.DefaultSqlSession.selectOne(DefaultSqlSession.java:76)

at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)

at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)

at java.lang.reflect.Method.invoke(Unknown Source)

at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:426)

... 71 more

 

 

 

 

언제나 느끼는 오늘의 교훈 ㅎ

수정하면 테스트 해보자. 에러 좀 자세히 봐라.

728x90
반응형
728x90
반응형

mybatis로 조회된 쿼리문의 결과에서 unread로 컬럼정보가 표시되는 경우가 있었다.

 

 

1. mybatis의 쿼리 내용

1
2
3
4
5
6
7
8
<mapper namespace="com.sample.mapper.memberMapper">
    <!-- unread 발생 -->
    <select id="read" resultType="com.sample.mapper.MemberVO">
        SELECT SEQ, NAME, SEX, EMAIL_ADDR, PASSWORD, BIRTH, ADDR, THUMB, PROFILE 
       FROM MEMBER WHERE SEQ = #{seq}
    </select>
</mapper>
 
cs

 

2. resultType의 MemberVO 내용

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class MemberVO {
    
    private int seq;
    private String name;
    private int sex;
    private String email;
    private String passWord;
    private String birth;
    private String add;
    private String thumb;
    private String profile;
    private int is_delete;
 
}
cs

3. DB 테이블 정보

 

 

문제는 원인은 MemberVO클래스의 변수와 DB 컬럼명이 다르다.

그러니 누가 누구와 연결되는지 명확하지가 않다. (대소문자는 구분하지 않음)

그래서 클래스 변수와 DB의 컬럼명을 맵핑하여 이 문제를 해결한다.

 

4. 1번의 mybatis에서 컬럼명과 변수를 맵핑하는 정보를 추가

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<mapper namespace="com.sample.mapper.memberMapper">
    <!-- resultMap 사용으로 unread 해결 --> 
    <select id="read" resultMap="mapping_memberlist">
        SELECT SEQ, NAME, SEX, EMAIL_ADDR, PASSWORD, BIRTH, ADDR, THUMB, PROFILE 
       FROM MEMBER WHERE SEQ = #{seq}
    </select>
    
    <!-- 쿼리 결과에 대한 맵핑 변수명 vs 컬럼명 -->
    <resultMap type="com.sample.mapper.MemberVO" id="mapping_memberlist">
        <result property="seq" column="SEQ"/>
        <result property="name" column="NAME"/>
        <result property="sex" column="SEX"/>
        <result property="email" column="EMAIL_ADDR"/>
        <result property="passWord" column="PASSWORD"/>
        <result property="birth" column="BIRTH"/>
        <result property="add" column="ADDR"/>
        <result property="thumb" column="THUMB"/>
        <result property="profile" column="PROFILE"/>
        <result property="is_delete" column="IS_DELETE"/>
    </resultMap>
</mapper>
 
cs

1) resultMap을 통해 클래스 변수와 DB 컬럼을 하나하나 매칭 시킨다.

 (property는 클래스의 변수명, column은 DB 컬럼명)

2) 매칭 시 부여한 id를 통해 쿼리 결과를 지정하여 준다.

 

5. 적용후

 

 

 

결론적으로 이 방법은 잘 사용하면 유용할 것이다.

실제 변수명이나 클래스 명이 길어지는 것이 부담스러워 일부러 축약시켜 사용하는 경우도 있다.

또한 DB와 코딩을 각각 작업하게 되는 경우 똑같이 작성할 수 없는 경우도 있다.

이럴때 미리 resultMap으로 한번만 정리해 둔다면 유용하게 사용할 수 있을 것이다.

 

 

참고URL

 

[MyBatis] resultMap collection

resultMap에 클래스를 맵핑할때 인자로 다른 클래스가 있을 경우 어떻게 받아올지 찾다가 발견! mybatis에서 테이블간의 1:N관계를 select 할때 resultMap을 통한 일종의 서브쿼리 형식으로 데이터를 가져

ssodang.tistory.com

 

 

728x90
반응형

+ Recent posts