MyBatis를 사용하는 Data Access Layer는 아래와 같다.
MyBatis-Spring의 주요 컴포넌트의 역할은 아래와 같다.
주요 컴포넌트의 설명은 아래와 같다.
Spring에서 Tomcat 서버를 연결할 때 아래와 같은 설정을 거친다.
Tomcat -> server.xml -> context.xml -> web.xml -> root-context.xml -> member.xml -> ...
주요 사항만 알아보자.
- context.xml
<?xml version="1.0" encoding="UTF-8"?>
<Context>
<Resource name="jdbc/samsung" auth="Container" type="javax.sql.DataSource"
maxTotal="100" maxIdle="30" maxWaitMillis="10000"
username="samsung" password="samsung" driverClassName="com.mysql.cj.jdbc.Driver"
url="jdbc:mysql://localhost:3306/samsungweb?serverTimezone=UTC&useUniCode=yes&characterEncoding=UTF-8"/>
<WatchedResource>WEB-INF/web.xml</WatchedResource>
</Context>
현재까진 클라이언트가 필요로 하면 DB에 연결해 DataSource를 만들었다.
이제는 DB 연결을 톰캣에게 맡겨 DB를 미리 연결해둔다. 따라서 DataSource를 미리 만든다.
- root-context.xml
<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="java:comp/env/jdbc/samsung"></property>
</bean>
가져올 DataSource는 java:comp/env/jdbc/samsung 안에 있는 걸 알려준다.
<bean id="sqlSessionFactoryBean" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="configLocation" value="classpath:mybatis-config.xml"/>
<property name="mapperLocations">
<list>
<value>classpath:mapper/member.xml</value>
</list>
</property>
</bean>
sqlSessionFactoryBean을 만든다. 이 때, DB, mybatis, mapper 정보를 넘겨준다.
<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
<constructor-arg ref="sqlSessionFactoryBean"></constructor-arg>
</bean>
sqlSession을 만든다.
- member.xml (mapper)
<?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.samsung.member.model.mapper.MemberMapper">
<resultMap type="memberDto" id="member">
<result column="user_id" property="userId"/>
<result column="user_name" property="userName"/>
</resultMap>
<select id="idCheck" parameterType="String" resultType="int">
select count(user_id)
from members
where user_id = #{userid}
</select>
<insert id="joinMember" parameterType="memberDto">
insert into members (user_name, user_id, user_password, email_id, email_domain, join_date)
values (#{userName}, #{userId}, #{userPwd}, #{emailId}, #{emailDomain}, now())
</insert>
<select id="loginMember" parameterType="map" resultMap="member">
select user_id, user_name
from members
where user_id = #{userid} and user_password = #{userpwd}
</select>
</mapper>
mapper의 sql을 정의한다.
- MemberServiceImpl.java
import java.util.Map;
import org.apache.ibatis.session.SqlSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.samsung.member.model.MemberDto;
import com.samsung.member.model.mapper.MemberMapper;
@Service
public class MemberServiceImpl implements MemberService {
private SqlSession sqlSession;
@Autowired
public MemberServiceImpl(SqlSession sqlSession) {
super();
this.sqlSession = sqlSession;
}
@Override
public int idCheck(String userId) throws Exception {
return sqlSession.getMapper(MemberMapper.class).idCheck(userId);
}
@Override
public void joinMember(MemberDto memberDto) throws Exception {
sqlSession.getMapper(MemberMapper.class).joinMember(memberDto);
}
@Override
public MemberDto loginMember(Map<String, String> map) throws Exception {
return sqlSession.getMapper(MemberMapper.class).loginMember(map);
}
}
sqlSession에서 설정된 함수를 실제로 실행한다.
Mapper Interface는 mapping 파일에 기재된 SQL을 호출하는 Interface이다.
이를 사용하면 위의 예제에서 바뀌는 부분은 아래와 같다.
- root-context.xml
<bean id="sqlSessionFactoryBean" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="typeAliasesPackage" value="com.samsung.*.model"/> <!-- Alias 지정 가능 -->
<property name="mapperLocations" value="classpath:mapper/*.xml"/>
</bean>
- MemberServiceImpl.java
import java.util.Map;
import org.springframework.stereotype.Service;
import com.samsung.member.model.MemberDto;
import com.samsung.member.model.mapper.MemberMapper;
@Service
public class MemberServiceImpl implements MemberService {
private MemberMapper memberMapper;
public MemberServiceImpl(MemberMapper memberMapper) {
super();
this.memberMapper = memberMapper;
}
@Override
public int idCheck(String userId) throws Exception {
return memberMapper.idCheck(userId);
}
@Override
public void joinMember(MemberDto memberDto) throws Exception {
memberMapper.joinMember(memberDto);
}
@Override
public MemberDto loginMember(Map<String, String> map) throws Exception {
return memberMapper.loginMember(map);
}
}
Spring은 자동 트랜잭션 관리를 지원한다. 해당 코드는 아래와 같다.
<!-- root-context.xml -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager"/>
Exception이 일어나면 rollback, 일어나지 않으면 commit을 자동으로 수행한다.