웹/TIL
0421 MyBatis / MyBatis-Spring
행복한 개복치
2022. 4. 22. 16:48
<MyBatis>
- MyBatis를 이용하면 DaoImpl에서 하나씩 직접 작성하던 쿼리문을 간단하게 처리할 수 있음.
<MyBatis 사용을 위한 설정>
1. pom.xml에 mybatis dependency 추가하기
2. scr/main/resources/에 mybatis-config.xml 생성
- envirionments(DB 정보) 와 mappers 는 필수
<?xml version="1.0" encoding="UTF-8" ?>
<!-- mybatis 사용 규약 / dtd에 나와있는 순서대로 xml을 작성해야함 -->
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!-- DB 정보를 담은 문서 -->
<!-- 이를 생성하기 싫다면 아래 el 표기문에 직접 입력해도 됨 -->
<properties resource="dbinfo.properties"/>
<!-- type에 있는 object에 대한 alias(별칭) 등록 -->
<typeAliases>
<typeAlias type="com.ssafy.guestbook.model.GuestBookDto" alias="guestbook" />
<typeAlias type="com.ssafy.guestbook.model.MemberDto" alias="member" />
<typeAlias type="com.ssafy.guestbook.model.FileInfoDto" alias="fileinfo" />
</typeAliases>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${dbid}"/>
<property name="password" value="${dbpwd}"/>
</dataSource>
</environment>
</environments>
<!-- 쿼리문을 작성해준 문서들 -->
<mappers>
<mapper resource="guestbook.xml" />
<mapper resource="member.xml" />
</mappers>
</configuration>
3. 해당 mapper 작성
ex) member.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">
<!-- 보통 필요한 Dao가 있는 위치를 namespace로 지정 -->
<mapper namespace="com.ssafy.guestbook.model.dao.MemberDao">
<!-- id는 dao에 있는 메서드 이름과 동일하게 / parameterType은 어디에서 값을 가져올건지 -->
<insert id="registerMember" parameterType="member">
insert into ssafy_member (userId, userName, userPwd, email, joinDate)
<!-- MemberDto에 있는 property 이름과 동일하게 해줘야 자동으로 값이 들어감 -->
values(#{userId}, #{userName}, #{userPwd}, #{email}, now())
</insert>
<!-- resultType은 어떤걸 반환할건지 -->
<!-- java 내장객체들은 소문자로만 적어줘도 자동매핑됨 (map <- java.util.Map)-->
<select id="login" parameterType="map" resultType="member">
select username, userid, email
from ssafy_member
where userid = #{userId} and userpwd = #{userPwd}
</select>
</mapper>
4. DBUtil.java에서 사용하던 Connection 대신 SqlSessionFactory 사용
- 다른곳에서 SqlSession 사용시 getter를 이용해서 얻어오도록
5. DaoImpl에서 SqlSession을 이용해 db에 접근
- try resource문으로 SqlSession 관리
ex) MemberDaoImpl.java
package com.ssafy.guestbook.model.dao;
import java.sql.SQLException;
import java.util.Map;
import org.apache.ibatis.session.SqlSession;
import org.springframework.stereotype.Repository;
import com.ssafy.guestbook.model.MemberDto;
import com.ssafy.util.SqlMapConfig;
@Repository
public class MemberDaoImpl implements MemberDao {
// 항상 같은 주소로 접근하니까 상수로 작성해둠
private final String NAMESPACE = "com.ssafy.guestbook.model.dao.MemberDao.";
@Override
public int idCheck(String id) throws SQLException {
return 0;
}
@Override
public void registerMember(MemberDto memberDto) throws SQLException {
try (SqlSession sqlSession = SqlMapConfig.getSqlSession()) {
// mapper(member.xml)에 있는 id 호출, 정보를 갖고있는 객체
sqlSession.insert(NAMESPACE + "registerMember", memberDto);
// mybatis는 자동커밋이 기본이 아님
sqlSession.commit();
}
}
@Override
public MemberDto login(Map<String, String> map) throws SQLException {
try (SqlSession sqlSession = SqlMapConfig.getSqlSession()) {
// 객체 하나만 받아옴(로그인하면 사용자 한명의 정보만 필요하므로)
return sqlSession.selectOne(NAMESPACE + "login", map);
}
}
}
<Mybatis-Spring>
Spring에서 mapper 객체관리를 할 수 있도록 해줌
- SqlMapConfig.java 와 mybatis-config.xml 역할을 root-context.xml(비웹부분)에서 대신 해줌
- DaoImpl이 사라지고 mapper(Dao) 인터페이스만 남음
<변경된 부분>
1. root-context.xml
<?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 https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd">
<!-- Root Context: defines shared resources visible to all other web components -->
<context:component-scan base-package="com.ssafy.guestbook.model, com.ssafy.guestbook.aop" />
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
<!-- <bean id="dataSource" class="org.springframework.jdbc.datasource.SimpleDriverDataSource">
<property name="driverClass" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://127.0.0.1:3306/ssafyweb?serverTimezone=UTC&useUniCode=yes&characterEncoding=UTF-8"/>
<property name="username" value="ssafy"/>
<property name="password" value="ssafy"/>
</bean> -->
<bean id="ds" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="java:comp/env/jdbc/ssafy"></property>
</bean>
<!-- mybatis-config.xml 대체 -->
<bean id="sqlSessionFactoryBean" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="ds"></property>
<property name="mapperLocations" value="classpath:mapper/*.xml"></property>
<!-- <property name="configLocation" value="classpath:mybatis-config.xml"></property> -->
<!-- 아래처럼 지정할 경우, alias 이름이 클래스의 이름으로 설정됨 -->
<property name="typeAliasesPackage" value="com.ssafy.guestbook.model"></property>
</bean>
<!-- SqlSession -->
<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
<!-- SST의 디폴트 생성자가 없기때문에 생성자 설정을 해줘야함 -->
<constructor-arg ref="sqlSessionFactoryBean"></constructor-arg>
</bean>
<!-- 트랜잭션 관리 객체 생성-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="ds"></property>
</bean>
<!-- 어노테이션(transactional)으로 관리 가능하도록 -->
<tx:annotation-driven transaction-manager="transactionManager"/>
</beans>
2. ServiceImpl.java
ex) MemberServiceImpl.java
package com.ssafy.guestbook.model.service;
import java.util.Map;
import org.apache.ibatis.session.SqlSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ssafy.guestbook.model.MemberDto;
import com.ssafy.guestbook.model.mapper.MemberMapper;
@Service
public class MemberServiceImpl implements MemberService {
@Autowired
private SqlSession sqlSession;
@Override
public int idCheck(String id) throws Exception {
return 0;
}
@Override
public void registerMember(MemberDto memberDto) throws Exception {
// root-context.xml에서 SqlSession 설정을 해줬기때문에 mapper class(이전 DaoImpl)만 지정하면 알아서 쿼리문과 연결
sqlSession.getMapper(MemberMapper.class).registerMember(memberDto);
}
@Override
public MemberDto login(Map<String, String> map) throws Exception {
return sqlSession.getMapper(MemberMapper.class).login(map);
}
}
+ 트랜잭션이 발생하는 메서드에 @Transactional 어노테이션을 해놓으면
error가 없을때 자동으로 커밋, error 발생 시 자동 롤백이 됨