Mybatis
JPA와는 동시에 사용하지 않는다.
최근 가장 많이 사용하는 방법.
Spring 또는 Spring Boot와 사용한다.
프레임 워크는 다르지만 코딩하는 입장에선 동일하게 볼 수 있다.
한,두줄의 자바코드로 DB연동이 가능하다.
SQL 명령어를 자바 코드에서 분리하여 XML 파일에 따로 관리한다.
XML 문서에서 특정 데이터를 문자 그대로 해석하도록 지정하는 것을 의미한다.
CDATA 섹션 안에서는 <, >, &, " 등의 특수 문자를 이스케이프하지 않고 그대로 사용할 수 있다.
EX) <element><![CDATA[CDATA Section]]></element>
# TIP : XML 문서에서 <element>는 요소(element)의 시작 태그를 나타낸다.
<?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:p="http://www.springframework.org/schema/p"
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
http://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">
<context:component-scan base-package="com.jungbo.k1" />
<context:property-placeholder location="classpath:config/database.properties"/>
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close" >
<property name="driverClassName" value="${jdbc.driver}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</bean>
<!-- mybatis 설정 ( 추가 ) -->
<bean id="sqlsession" class="org.mybatis.spring.SqlSessionFactoryBean" >
<property name="dataSource" ref="dataSource" />
<property name="configLocation" value="classpath:sql-map-config.xml" />
</bean>
<bean class="org.mybatis.spring.SqlSessionTemplate">
<constructor-arg ref="sqlsession" />
</bean>
<!-- Spring JDBC 설정 -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource" />
</bean>
<!-- 트랜잭션 설정 -->
<bean id="txManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<tx:advice id="txAdvice" transaction-manager="txManager" >
<tx:attributes>
<tx:method name="get*" read-only ="true" />
<tx:method name="*"/>
</tx:attributes>
</tx:advice>
<aop:config proxy-target-class="true">
<aop:pointcut id="txPointcut"
expression="execution(* com.jungbo.k1..*ServiceImpl.*(..))"/>
<aop:advisor pointcut-ref="txPointcut" advice-ref="txAdvice"/>
</aop:config>
</beans>
mybatis설정을 추가하여 사용하도록 한다.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC
"-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<typeAliases>
<typeAlias alias="exam" type="com.jungbo.k1.exam.ExamVO" />
<typeAlias alias="psd" type="com.jungbo.k1.psd.PsdVO" />
<typeAlias alias="shop" type="com.jungbo.k1.shop.ShopVO" />
<typeAlias alias="cart" type="com.jungbo.k1.shop.CartVO" />
</typeAliases>
<mappers>
<mapper resource="mappings/exam-mapping.xml" />
<mapper resource="mappings/psd-mapping.xml" />
<mapper resource="mappings/shop-mapping.xml" />
<mapper resource="mappings/cart-mapping.xml" />
</mappers>
</configuration>
각 mapping에 사용할 리소스의 별칭을 짓고 연결해준다.
<?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="ExamDAO">
<select id="SELECT_ALL" parameterType="exam" resultType="exam">
select * from Examtbl where 1=1
<if test="ch1 == 'sno'">
AND sno like '%'||#{ch2}||'%'
</if>
<if test="ch1 == 'sname'">
AND sname like '%'||#{ch2}||'%'
</if>
order by sno desc
</select>
<select id="SELECT_ONE" parameterType="exam" resultType="exam">
select * from Examtbl where sno=#{sno}
</select>
<insert id="INSERT" parameterType="exam">
insert into Examtbl(sno, sname, kor, eng, math, hist)
values(#{sno}, #{sname}, #{kor}, #{eng}, #{math}, #{hist})
</insert>
<update id="UPDATE" parameterType="exam">
update Examtbl set sname=#{sname}, kor=#{kor} , eng=#{eng}, math=#{math}, hist=#{hist}
where sno=#{sno}
</update>
<delete id="DELETE" parameterType="exam">
DELETE FROM Examtbl WHERE sno=#{sno}
</delete>
</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="PsdDAO">
<select id="SELECT_ALL" parameterType="psd" resultType="psd">
select m_idx, m_sno, m_sname, m_files as m_filesStr, m_etc, m_cnt, m_addr from memberT2 order by m_idx desc
</select>
<select id="SELECT_ONE" parameterType="psd" resultType="psd">
select m_idx, m_sno, m_sname, m_files as m_filesStr, m_etc, m_cnt, m_addr from memberT2 where m_idx=#{m_idx}
</select>
<select id="SELECT_SNO" parameterType="psd" resultType="psd">
select m_idx, m_sno, m_sname, m_files as m_filesStr, m_etc, m_cnt, m_addr from memberT2
<![CDATA[
where m_sno like '%'||#{ch2}||'%' order by m_idx desc
]]>
</select>
<select id="SELECT_SNAME" parameterType="psd" resultType="psd">
select m_idx, m_sno, m_sname, m_files as m_filesStr, m_etc, m_cnt, m_addr from memberT2
<![CDATA[
where m_sname like '%'||#{ch2}||'%' order by m_idx desc
]]>
</select>
<insert id="INSERT" parameterType="psd">
insert into memberT2(m_idx, m_sno, m_sname, m_files, m_etc, m_cnt, m_addr)
values(idx_memberT2.nextval, #{m_sno}, #{m_sname}, #{m_filesStr}, #{m_etc}, '1', #{addr})
</insert>
<update id="UPDATE1" parameterType="psd">
update memberT2 set m_sname=#{m_sname}, m_files=#{m_filesStr}, m_etc=#{m_etc} where m_idx=#{m_idx}
</update>
<update id="UPDATE2" parameterType="psd">
update memberT2 set m_sname=#{m_sname}, m_etc=#{m_etc} where m_idx=#{m_idx}
</update>
<update id="CNT" parameterType="psd">
update memberT2 set m_cnt=m_cnt+1 where m_idx = #{m_idx}
</update>
<delete id="DELETE" parameterType="psd">
delete from memberT2 where m_idx=#{m_idx}
</delete>
</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="ShopDAO">
<!-- 칼럼명과 VO 이름이 다를때 맵핑을 따로 잡아준다 -->
<resultMap type="shop" id="shopResult">
<id property="productId" column="PRODUCT_ID"/>
<result property="productName" column="product_name"/>
<result property="productPrice" column="product_price"/>
<result property="productDesc" column="product_desc"/>
<result property="productImgStr" column="product_img"/>
</resultMap>
<select id="SELECT_ALL" parameterType="shop" resultMap="shopResult">
SELECT * FROM tbl_product order by product_id desc
</select>
<select id="SELECT_ONE" parameterType="shop" resultMap="shopResult">
SELECT * FROM tbl_product WHERE product_id=#{productId}
</select>
<select id="SELECT_ID" parameterType="shop" resultMap="shopResult">
SELECT * FROM tbl_product
<![CDATA[
where product_id like '%'||#{ch2}||'%' order by product_id desc
]]>
</select>
<select id="SELECT_NAME" parameterType="shop" resultMap="shopResult">
SELECT * FROM tbl_product
<![CDATA[
where product_name like '%'||#{ch2}||'%' order by product_id desc
]]>
</select>
<insert id="INSERT" parameterType="shop">
<selectKey keyProperty="productId" resultType="int">
select seq_product.nextval as product_id from dual
</selectKey>
INSERT INTO tbl_product(product_id, product_name, product_price, product_desc, product_img)
VALUES(seq_product.nextval, #{productName}, #{productPrice}, #{productDesc}, #{productImgStr})
</insert>
</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="CartDAO">
<select id="CART_COUNT" parameterType="cart" resultType="cart">
select * from tbl_cart where user_id=#{userId} and product_id=#{productId}
</select>
<select id="CART_SELECT_ALL" parameterType="cart" resultType="cart">
<![CDATA[
select cart_id as cartId, user_id as userId, c1.product_id as productId , amount,
product_price as productPrice , product_name as productName, product_img as productImg from tbl_cart c1 join tbl_product p1
on c1.product_id = p1.product_id where user_id=#{userId}
]]>
</select>
<insert id="CART_INSERT" parameterType="cart">
<selectKey keyProperty="cartId" resultType="int" order="BEFORE">
select seq_cart.nextval from dual
</selectKey>
insert into tbl_cart(cart_id, user_id, product_id, amount)
values (#{cartId}, #{userId}, #{productId}, #{amount})
</insert>
<insert id="CART_INSERT_ORDER" parameterType="cart">
insert into tbl_cart_order(cart_id, user_id, product_id, amount)
values (#{cartId}, #{userId}, #{productId}, #{amount})
</insert>
<update id="CART_UPDATE" parameterType="cart">
update tbl_cart set amount=#{amount} where user_id=#{userId} and cart_id=#{cartId}
</update>
<delete id="CART_DELETE" parameterType="cart">
delete from tbl_cart where cart_id=#{cartId} and user_id=#{userId}
</delete>
<delete id="CART_DELETE_ALL" parameterType="cart">
delete from tbl_cart where user_id = #{userId}
</delete>
</mapper>
각 사용 쿼리문을 태그형식으로 지정하여 맵핑 후 dao에서 불러와 사용한다.
여기서 중요한 점은 데이터베이스의 칼럼명과 VO의 변수명이 다를경우 구분하여 입력해주어야 오류를 방지할 수 있다.
package com.jungbo.k1.exam;
import java.util.List;
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
@Repository
public class ExamDaoImpl implements ExamDao{
@Autowired
private SqlSessionTemplate mybatis;
@Override
public List<ExamVO> getExamList(ExamVO vo) {
return mybatis.selectList("ExamDAO.SELECT_ALL",vo);
}
@Override
public void inserExam(ExamVO vo) {
mybatis.insert("ExamDAO.INSERT", vo);
}
@Override
public void updateExam(ExamVO vo) {
mybatis.update("ExamDAO.UPDATE", vo);
}
@Override
public void deletExam(ExamVO vo) {
mybatis.delete("ExamDAO.DELETE", vo);
}
@Override
public ExamVO getExam(ExamVO vo) {
return mybatis.selectOne("ExamDAO.SELECT_ONE", vo);
}
}
package com.jungbo.k1.psd;
import java.util.List;
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
@Repository
public class PsdDaoImpl implements PsdDao{
@Autowired
private SqlSessionTemplate mybatis;
@Override
public void insertPsd(PsdVO vo) {
System.out.println("insertPsd :" + vo);
mybatis.insert("PsdDAO.INSERT", vo);
}
@Override
public void updatePsd(PsdVO vo) {
System.out.println("==========> updatePsd "+ vo.getM_filesStr());
if (vo.getM_filesStr() == null || vo.getM_filesStr().equals("")) {
System.out.println("==========> updatePsd : 2 ");
mybatis.update("PsdDAO.UPDATE2",vo);
}else {
System.out.println("==========> updatePsd : 1 ");
mybatis.update("PsdDAO.UPDATE1", vo);
}
}
@Override
public void deletePsd(PsdVO vo) {
mybatis.delete("PsdDAO.DELETE",vo);
}
@Override
public PsdVO getPsd(PsdVO vo) {
return mybatis.selectOne("PsdDAO.SELECT_ONE", vo);
}
@Override
public List<PsdVO> getPsdList(PsdVO vo) {
if(vo.getCh1()==null || vo.getCh2()=="" || vo.getCh2().equals("")) {
return mybatis.selectList("PsdDAO.SELECT_ALL");
}else if(vo.getCh1().equals("m_sno")) {
return mybatis.selectList("PsdDAO.SELECT_SNO", vo);
}else if(vo.getCh1().equals("m_sname")) {
return mybatis.selectList("PsdDAO.SELECT_SNAME", vo);
}
return null;
}
@Override
public void cnt(PsdVO vo) {
mybatis.update("PsdDAO.CNT", vo);
}
}
package com.jungbo.k1.shop;
import java.util.List;
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
@Repository
public class ShopDaoImpl implements ShopDao{
@Autowired
private SqlSessionTemplate mybatis;
@Override
public void insertShop(ShopVO vo) {
mybatis.insert("ShopDAO.INSERT",vo);
}
@Override
public ShopVO getShop(ShopVO vo) {
return mybatis.selectOne("ShopDAO.SELECT_ONE",vo);
}
@Override
public List<ShopVO> getShopList(ShopVO vo) {
if(vo.getCh1() == null || vo.getCh2()=="" || vo.getCh2().equals("")) {
return mybatis.selectList("ShopDAO.SELECT_ALL");
}else if(vo.getCh1().equals("product_id")) {
return mybatis.selectList("ShopDAO.SELECT_ID",vo);
}else if(vo.getCh1().equals("product_name")){
return mybatis.selectList("ShopDAO.SELECT_NAME",vo);
}
return null;
}
}
package com.jungbo.k1.shop;
import java.util.List;
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
@Repository
public class CartDaoImpl implements CartDao{
@Autowired
private SqlSessionTemplate mybatis;
@Override
public void insert(CartVO vo) {
mybatis.insert("CartDAO.CART_INSERT", vo);
}
@Override
public void update(CartVO vo) {
mybatis.update("CartDAO.CART_UPDATE", vo);
}
@Override
public List<CartVO> count(CartVO vo) {
return mybatis.selectList("CartDAO.CART_COUNT", vo);
}
@Override
public List<CartVO> getCartList(CartVO vo) {
return mybatis.selectList("CartDAO.CART_SELECT_ALL", vo);
}
@Override
public void delete(CartVO vo) {
mybatis.delete("CartDAO.CART_DELETE", vo);
}
@Override
public void cartOrder(CartVO vo) {
System.out.println("==========>cartOrder CARTVO 의 값"+vo);
mybatis.insert("CartDAO.CART_INSERT_ORDER", vo);
}
@Override
public void cartAllDelete(CartVO vo) {
mybatis.delete("CartDAO.CART_DELETE_ALL", vo);
}
}
SqlSessionTemplate mybatis를 변수로 잡고 @Autowired하여 기존에 사용하던 JdbcTemplate와 같이 사용한다.
<!-- Mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.3.1</version>
</dependency>
<!-- Mybatis Spring -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.2.4</version>
</dependency>
pom 파일에서 Mybatis와 Mybatis Spring을 받아 Maven Dependencies 에 jar 파일이 있는지 확인하고 사용한다.
MyBatis:
- org.mybatis.mybatis 그룹 아래의 mybatis 아티팩트를 사용한다
기본적으로 MyBatis의 핵심 라이브러리이다
- SQL 매핑 파일(XML)을 사용하여 SQL과 자바 코드를 분리할 수 있다
- MyBatis의 주요 기능인 SQL 매핑, 동적 쿼리, 세션 관리 등을 제공한다
- 스프링과 독립적으로 사용될 수 있다
MyBatis-Spring:
- org.mybatis.mybatis 그룹 아래의 mybatis-spring 아티팩트를 사용한다
- MyBatis와 스프링 프레임워크를 통합하는 데 사용된다
- MyBatis의 기능을 스프링과 함께 사용할 수 있도록 지원한다
- 스프링의 트랜잭션 관리, 의존성 주입 등과 연동된다
- MyBatis와 스프링의 설정을 통합하여 관리할 수 있다
- MyBatis-Spring은 MyBatis의 확장 기능으로 볼 수 있다
MyBatis-Spring은 MyBatis의 스프링 통합 버전으로서 스프링과의 통합 기능을 제공하며,
MyBatis만 사용할 때보다 스프링과의 연동 및 설정 관리를 편리하게 할 수 있다.