環境
- mybatis-spring-boot-starter: 1.3.1
- mybatis: 3.4.5
- Spring Boot 1.5.9
- Java8
問題
MyBatisのMapperクラスに、オーバロードしてメソッドを定義しました。
CityMapper.java
@Mapper
public interface CityMapper {
@Select("select * from city where state = #{state}")
City findCity(@Param("state") String state);
@Select("select * from city")
City findCity();
}
サーバを起動すると、「Mapped Statements collection already contains value for ~findByState」というエラーが発生しました。
console
2018-01-22 23:55:31.816 ERROR 24176 --- [ restartedMain] o.m.spring.mapper.MapperFactoryBean : Error while adding the mapper 'interface com.example.demo2.mapper.CityMapper' to configuration.
java.lang.IllegalArgumentException: Mapped Statements collection already contains value for com.example.demo2.mapper.CityMapper.findCity
at org.apache.ibatis.session.Configuration$StrictMap.put(Configuration.java:872) ~[mybatis-3.4.5.jar:3.4.5]
原因・解決策
「findByState
が既に含まれている」というエラーメッセージなので、メソッド名を重複しないような名前に変更して、解決しました。
CityMapper.java
@Mapper
public interface CityMapper {
@Select("select * from city where state = #{state}")
City findCityByState(@Param("state") String state);
@Select("select * from city")
City findCity();
}
同様の問題
XMLファイルでidが重複しているときも、「Mapped Statements collection already contains value for ~」という同様のエラーが発生します。
HotelMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.demo2.mybatis.mapper.HotelMapper">
<select id="findHotel" resultType="com.example.demo2.mybatis.domain.Hotel">
select * from hotel where city = #{id}
</select>
<!-- id名が重複している -->
<select id="findHotel" resultType="com.example.demo2.mybatis.domain.Hotel">
select * from hotel
</select>
</mapper>
console
2018-01-23 00:51:47.444 ERROR 14712 --- [ restartedMain] o.s.boot.SpringApplication : Application startup failed
org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name 'hotelDao' defined in file [C:\MyProgram\pleiades_4.7\workspace\demo2\target\classes\com\example\demo2\mybatis\dao\HotelDao.class]:
Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name 'sqlSessionTemplate' defined in class path resource [org/mybatis/spring/boot/autoconfigure/MybatisAutoConfiguration.class]:
Unsatisfied dependency expressed through method 'sqlSessionTemplate' parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'sqlSessionFactory' defined in class path resource [org/mybatis/spring/boot/autoconfigure/MybatisAutoConfiguration.class]:
Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException:
Failed to instantiate [org.apache.ibatis.session.SqlSessionFactory]:
Factory method 'sqlSessionFactory' threw exception; nested exception is org.springframework.core.NestedIOException:
Failed to parse config resource: class path resource [mybatis-config.xml]; nested exception is org.apache.ibatis.builder.BuilderException:
Error parsing SQL Mapper Configuration. Cause: org.apache.ibatis.builder.BuilderException: Error parsing Mapper XML. Cause: java.lang.IllegalArgumentException:
Mapped Statements collection already contains value for com.example.demo2.mybatis.mapper.HotelMapper.findHotel
...
Caused by: java.lang.IllegalArgumentException: Mapped Statements collection already contains value for com.example.demo2.mybatis.mapper.HotelMapper.findHotel
※読みやすくするために、適当な箇所で改行を入れました。