mybatis-spring 모듈을 사용하면, 스프링의 ApplicationContext에 마이바티스 빈을 설정할 수 있다.
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="configLocation" value="classpath:/mybatis-config.xml"/>
<property name="mapperLocations" value="classpath:/sql-map/*.xml"/>
<!-- statement 선언의 오류를 좀 더 빠르게 파악하기 위해서 true로 설정 -->
<property name="failFast" value="true"/>
</bean>
<bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate">
<constructor-arg index="0" ref="sqlSessionFactory"></constructor-arg>
<constructor-arg index="1" value="BATCH" />
</bean>
스프링에서 SqlSessionFactory빈을 만들고 SqlSessionTemplate빈을 만들어서 생성자로 넣어준다. SqlSessionTemplate빈은 thread safe하게 SqlSession 객체를 제공하기 때문에, 여러 개의 스프링 빈에서 동일한 SqlSessionTemplate 객체를 공유할 수 있다. 개념적으로는 SqlSessionTemplate이 스프링 DAO 모듈의 JdbcTemplate과 동일하다.
mapper interface가 있는 패키지를 체크하고 자동으로 mapper interface를 mapper bean으로 등록하기 위해 MapperScannerConfigurer를 사용할 수 있다.
자바코드에서 사용할 때는 Dao 를 두개 만들어야한다. ex) TaskDao, TaskSecondaryDao 그래서 서비스레이어에서 각 dao를 호출해서 dual-write를 수행하고, TaskSecondaryDao 에서는 secondarySqlSessionTemplate 를 주입받아 사용한다.
참고로 호환이 안되는 쿼리 분기는 master, secondary 관계없이 작업해야한다. mssql -> mysql 로 바꿨을 때 master, secondary 가 서로 바뀌는데 이때 영향을 받지 않는다.
동적 SQL
마이바티는 <if>, <choose>, <where>, <foreach>, <trim>과 같은 엘리먼트를 사용해서 동적인 SQL 쿼리를 만들도록 지원한다.
if 조건
if 엘리먼트는 test 조건이 true가 될 때만 해당되는 SQL이 쿼리에 추가된다.
<resultMap type="Course" id="CourseResult">
<id property="courseId" column="course_id"/>
<result property="name" column="name"/>
<result property="description" column="description"/>
<result property="start_date" column="startDate"/>
<result property="end_date" column="endDate"/>
</resultMap>
<select id="searchCourses" parameterType="hashmap" resultMap="CourseResult">
<![CDATA[
select * from courses where tutor_id=#{tutorId}
<if test="courseName != null">
and name like #{courseName}
</if>
<if test="startDate != null">
and start_date >= #{startDate}
</if>
<if test="endDate != null">
and end_date <= #{endDate}
</if>
]]>
</select>
choose, when, otherwise 조건
마이바티스는 <choose>의 test 조건을 확인해서 가장 먼저 true가 되는 조건을 사용한다. 어느 조건도 true가 되지 못하면, <otherwise>절이 사용된다.
select * from courses
<choose>
<when test="searchBy == 'Tutor'">
where tutor_id = #{tutorId}
</when>
<when test="searchBy == 'CourseName'">
where name like #{courseName}
</when>
<otherwise>
where tutor start_date > = now()
</otherwise>
</choose>
where 조건
가끔은 모든 검색 조건 중 하나도 선택하지 않을 수 있다 마이바티스는 이러한 SQL문을 만들기 위해 <where> 엘리먼트를 제공한다. 내부조건을 나타내는 엘리먼트에 의해 리턴되는 내용이 있을 때에만 where를 추가한다(모든 검색 조건이 필수가 아니라 선택할 수 있을 때 사용된다).
select * from courses
<where>
<if test="tutorId != null">
tutor_id=#{tutorId}
</if>
<if test="courseName != null">
and name like #{courseName}
</if>
<if test="startDate != null">
and start_date >= #{startDate}
</if>
<if test="endDate != null">
and end_date <= #{endDate}
</if>
</where>
trim 조건
<trim> 엘리먼트는 <where> 엘리먼트와 유사하지만 접두사/접미사를 추가하거나 제거하는 기능을 추가로 제공한다. <if>조건이 true이면 where절을 추가하고 where 뒤에 접두사 AND나 OR가 있으면 제거한다.
select * from courses
<trim prefix="where" prefixOverrides="AND | OR">
<if test="tutorId != null">
tutor_id=#{tutorId}
</if>
<if test="courseName != null">
and name like #{courseName}
</if>
</trim>
foreach 루프
배열이나 리스트를 통해 반복적인 처리를 하고 AND나 OR 조건을 붙이거나 IN 절을 처리하는 공통적인 요구사항을 담당한다.
tutor_id의 아이디가 1,3,6인 교사가 가르치는 모든 교육과정을 찾는다고 해보자. tutor_id의 아이디 목록을 매핑 구문에 전달하고 <foreach> 엘리먼트를 사용해서 리스트를 반복 처리해서 동적 쿼리를 만들 수 있다.