MyBatis 스프링에서 사용하기(XML 방식)

오의석·2022년 10월 25일

스프링

목록 보기
11/16

1. porm.xml에서의 세팅

<dependency>
  <groupId>org.mybatis</groupId>
  <artifactId>mybatis-spring</artifactId>
  <version>2.0.7</version>
</dependency>

2. 톰캣에서의 설정 (혹은 META-INF/context.xml)

<Context>
	<Resource name="jdbc/db" auth="Container" type="javax.sql.DataSource" 
			maxTotal="100" maxIdle="30" maxWaitMillis="10000" 
			username="root" password="123456" driverClassName="com.mysql.cj.jdbc.Driver" 	
			url="jdbc:mysql://localhost:3306/ssafyweb?serverTimezone=UTC&amp;useUniCode=yes&amp;characterEncoding=UTF-8"/> 
    <WatchedResource>WEB-INF/web.xml</WatchedResource>
</Context>

3. servlet-context.xml

dl 방식으로 db를 읽어와서 Jndi에 세팅한다.
sqlSession을 설정한다.

	<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
		<property name="jndiName" value="java:comp/env/jdbc/db"></property>
	</bean>

	<bean id="sqlSessionFactoryBean"
		class="org.mybatis.spring.SqlSessionFactoryBean">
		<property name="dataSource" ref="dataSource"></property>
		<property name="typeAliasesPackage" value="com.main.*.model"></property>
		<property name="mapperLocations"
			value="classpath:mapper/*.xml"></property>
	</bean>
    <mybatis-spring:scan base-package="com.main.*.model.mapper"/>
    

추가 트랜젝션 컨트롤까지 하고싶은 경우

<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource" ref="dataSource"></property>
	</bean>
	<tx:annotation-driven transaction-manager="transactionManager" />

4. mapper.xml

<mapper namespace="com.main.board.model.mapper.BoardMapper">
<resultMap type="boardDto" id="article">
		<result column="article_no" property="articleNo"/>
		<result column="user_id" property="userId"/>
		<result column="user_name" property="userName"/>
		<result column="hit" property="hit"/>
		<result column="register_time" property="registerTime"/>
</resultMap>
<delete id="deleteArticle" parameterType="int">
		delete from board
		where article_no = #{articleNo}
</delete>

5. interface 만들기(BoardMapper.java)

public interface BoardMapper {
	void deleteArticle(int articleNo) throws SQLException;
}

추가 설명

1. 상속 , 자료구조

<resultMap type="boardDto" id="viewArticle" extends="article">
		<collection property="fileInfos" column="article_no" javaType="list" ofType="fileInfoDto" select="fileInfoList"/>
	</resultMap>

collection는 자료구조 사용 가능. (javaType으로 list사용을 알 수 있음)
ofType => List<"ofType">
'fileInfoList'라는 이름의 sql문으로 데이터를 불어오겠다라는 의미.
property는 자바에서의 변수명
column는 테이블에서의 컬럼명

2. 자료구조의 기능을 이용하여 1:N의 테이블을 같이 가지고 오는 방식

	<resultMap type="boardDto" id="article">
		<result column="article_no" property="articleNo"/>
		<result column="user_id" property="userId"/>
		<result column="user_name" property="userName"/>
		<result column="subject" property="subject"/>
		<result column="content" property="content"/>
		<result column="hit" property="hit"/>
		<result column="register_time" property="registerTime"/>
	</resultMap>
	
	<resultMap type="boardDto" id="viewArticle" extends="article">
		<collection property="fileInfos" column="article_no" javaType="list" ofType="fileInfoDto" select="fileInfoList"/>
	</resultMap>

	<select id="getArticle" parameterType="int" resultMap="viewArticle">
		select b.article_no, b.user_id, b.subject, b.content, b.hit, b.register_time, m.user_name 
		from board b, members m
		where b.user_id = m.user_id
		and b.article_no = #{articleNo}
	</select>
	
	<select id="fileInfoList" resultMap="file">
		select save_folder, original_file, save_file
		from file_info
		where article_no = #{articleNo}
	</select>

순서
getArticle를 호출
-> viewArticle라는 resultMap으로 값을 받아옴
-> 그런데 viewArticle에는 collection이 존재함. 해당 collection은 fileInfoList라는 sql문으로 받아온다.
-> getArticle라는 sql문 결과 하나하나당 fileInfoList라는 sql문 결과가 다 저장된다.

3.동적 sql문(자중 사용하는 where 동적sql문)

<where>
<if test=”state != null”>
 state = #{state}
 </if>
 <if test=”title != null”>
 AND title like #{title}
 </if>
 <if test=”author != null and author.name != null”>
 AND author_name like #{author.name}
 </if>
 </where>

4. selectKey사용

selectKey로 order로 설정한 순서에 따라, 해당 값은 keyProperty의 이름으로 저장한다.
그 후 그 값을 이용해서 insert하면 그 값을 입력으로 들어간다.
아래 코딩의 경우 boardDto 객체의 articleNo에 같이 들어 간 것이다.
그리고 그 다음 insert에서 boardDto 객체의 articleNo를 읽어서, 테이블에 저장되는 것이다.

<insert id="writeArticle" parameterType="boardDto">
		insert into board (user_id, subject, content, hit, register_time)
		values (#{userId}, #{subject}, #{content}, 0, now())
		<selectKey resultType="int" keyProperty="articleNo" order="AFTER">
			select last_insert_id()
		</selectKey>
	</insert>
	
	<insert id="registerFile" parameterType="boardDto">
		insert into file_info (article_no, save_folder, original_file, save_file)
		values
		<foreach collection="fileInfos" item="fileinfo" separator=" , ">
			(#{articleNo}, #{fileinfo.saveFolder}, #{fileinfo.originalFile}, #{fileinfo.saveFile})
		</foreach>
	</insert>

last_insert_id 함수는 테이블의 마지막 auto_increment 값을 리턴한다.

5.트랜젝션을 직접 관리

트랜젝션을 직접 관리할 경우(자바에서는 어노테이션을 @Transactional 으로 설정한다.)
보통 select를 제외하고 설정해주면 된다. 다만, mapper 클래스가 아니라 service 클래스에서 하는 것이 좋다. 이유는 특정 서비스는 insert를 두번할 수도 있고, 그 sql문이 둘 다가 될 때만 적용 시키고 싶을 수도 있기 때문이다.

	<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource" ref="dataSource"></property>
	</bean>
	<tx:annotation-driven transaction-manager="transactionManager" />

역할 : 오류발생에 따라, 롤백과 commit를 제어하기 위함

profile
끊임없이 나아가는 사람이 되어볼게요.

0개의 댓글