[Spring] 에러 : Mapped Statements collection already contains value for 오류 해결
Spring 프로젝트를 시작 하기 전, DB 테이블 테스트를 위해 Mybatis를 연동하는 도중 생긴 오류!
프로젝트를 실행하니 404(페이지를 찾을 수 없음)과 함께 오류가 떴다.
오류의 내용은 아래와 같다.
ERROR: org.springframework.web.context.ContextLoader - Context initialization failed org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userDAO': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private org.mybatis.spring.SqlSessionTemplate com.my.app.user.impl.UserDAO.mybatis; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.mybatis.spring.SqlSessionTemplate#0' defined in class path resource [applicationContext.xml]: Cannot resolve reference to bean 'sqlSession' while setting constructor argument; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sqlSession' defined in class path resource [applicationContext.xml]: Invocation of init method failed; nested exception is org.springframework.core.NestedIOException: Failed to parse mapping resource: 'class path resource [mappings/user-mapping.xml]'; nested exception is org.apache.ibatis.builder.BuilderException: Error parsing Mapper XML. Cause: java.lang.IllegalArgumentException: Result Maps collection already contains value for UserDAO.userResult
대충 보면 sqlSession 객체 의존성 주입에 실패했다는 에러로 보였다.
하지만 오류는 맨 끝에서 제대로 된 얘기를 해주고 있었다!
오류를 제대로 안읽어서 단순 의존성 주입 문제인 줄 알고 열심히 어노테이션과 xml파일만 뒤적뒤적 했었다. (바보)
맨 뒤에 적힌 'Result Maps collection already contains value for' 라는 오류!
mapper가 이미 존재한다는 이야기인 것 같은데.. 내 mapping 파일은 현재 1개뿐인 상황..ㅠㅠ
열심히 구글링을 해서 얻은 에러 원인에 대한 정보는
1. mapper id 가 틀린 경우
2. Parameter와 bean의 field 명이 틀린 경우
3. sql.xml 에서 정의된 namespace와 DAO에서 호출하는 namespace가 다를 경우
4. mapper가 정의가 되어 있지 않거나 Spelling 이 틀린 경우
5. mapper에 정의 된 namespace 명칭이 같은 Application 내에 중복 될 경우
하지만 나는 아무것도 해당이 안되는 상태였다.
왜 중복됐다고 하는지 모르겠어서 sqlSession <bean>을 만들어준 xml 파일을 살펴보았다.
applicationContext.xml
1
2
3
4
5
6
7
8
9
10
|
<bean id="sqlSession" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="configLocation" value="classpath:/sql-map-config.xml"></property>
<property name="mapperLocations" value="classpath:/mappings/user-mapping.xml"/>
<property name="dataSource" ref="dataSource" />
</bean>
<bean class="org.mybatis.spring.SqlSessionTemplate">
<constructor-arg ref="sqlSession"></constructor-arg>
</bean>
|
cs |
sqlSession bean을 만들 때 적어둔 property 속성에서 mapperLoccations를 적어준 다른 사람들의 코드를 보고 따라 적었었다.
근데 여기에 적은 mapper가 configLocation파일(sql-map-config.xml) 안에도 적혀있어서 중복 에러가 난 것!
sql-map-config.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!-- Alias 설정 -->
<typeAliases>
<typeAlias alias="user" type="com.my.app.user.UserVO" />
</typeAliases>
<!-- Sql Mapper 설정 -->
<mappers>
<mapper resource="mappings/user-mapping.xml"/>
</mappers>
</configuration>
|
cs |
여기도 mapper가 정의되어 있어서 중복 정의로 충돌이 난 것이다.
applicationContext.xml의 mapperLoactins property만 지우고 파일을 저장 후, 실행하니 정상 동작했다.
(mapper 중복이니 sql-map-config.xml의 mapper 설정을 지워줘도 실행이 될 것이다.)
수정 후 applicationContext.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.2.xsd">
<context:component-scan base-package="com.my.app"></context:component-scan>
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
<!-- DataSource 설정 -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="org.mariadb.jdbc.Driver" />
<property name="url" value="jdbc:mariadb://localhost:3306/test" />
<property name="username" value="root" />
<property name="password" value="maria1234" />
</bean>
<!-- Spring JDBC 설정 -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource" />
</bean>
<bean id="sqlSession" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="configLocation" value="classpath:/sql-map-config.xml"></property>
<property name="dataSource" ref="dataSource" />
</bean>
<bean class="org.mybatis.spring.SqlSessionTemplate">
<constructor-arg ref="sqlSession"></constructor-arg>
</bean>
</beans>
|
cs |