본문 바로가기
Today I learned

2019년 1월2일

by soheemon 2019. 1. 2.
*드디어 MyBatis
MyBatis 설정 시작해봅시다.
MyBatis 설정 1)mybatis-conf.xml 파일을 생성합니다.
=참고: typeAlias는 클래스명을 약어로 접근할수 있게 해준다.

=참고:environments는 복수개의 db에 접근할 수 있게 해준다.(db당 하나의 SessionFactory를 생성해야한다.)

=참고:transactionManage 트랜잭션 관리자 설정
   JDBC: DataSource를 통해 획득 가능한 connection에 의존적

   MANAGED: container에서(우리는톰캣) transaction의 lifecycle을 관리.
=참고: mappers: mapped statement 설정 파일 참조 선언
   resource: classpath 경로에서 mapper설정파일 참조
   url: 파일시스템레벨에서 xml설정 참조

=참고: dataSource: db에 접근하기 위한 connection을 제공받는 방법 설정
    UNPOOLED: 매번 요청마다 dataSource의 구현체를 생성한다.
    POOLED: connection을 생성하여 pool에 보관하고 요청시마다 pooling된 connection인스턴스를 사용
    
<?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 type="kosta.bean.Board" alias="Board"/>
</typeAliases>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="JNDI">
<property name="data_source" value="java:comp/env/jdbc/oracle"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="kosta/mapper/Board.xml"/>
</mappers>
</configuration>

*이때 dataSource의 value는 server.xml에서 Resource name과 일치해야 한다.
       <Context docBase="jsp" path="/jsp" reloadable="true" source="org.eclipse.jst.jee.server:jsp">
      <Resource auth="Container" driverClassName="oracle.jdbc.driver.OracleDriver" 
maxActive="100" maxIdle="30" maxWait="10000" 
name="jdbc/oracle" password="1234" type="javax.sql.DataSource" 
url="jdbc:oracle:thin:@localhost:1521:XE" username="kosta192"/>
      </Context>

MyBatis 설정 2)도메인 객체와 SQL쿼리를 매핑하는 XML파일을 생성합니다.
물론, mybatis-conf.xml mapper태그에 해당 XML파일이 들어가 있어야 합니다.
<mapper namespace="kosta.mapper.BoardMapper">
<cache />
<insert id="insertBoard" parameterType="Board">
insert into board values(board_seq.nextval, #{title}, 
#{writer} ,#{contents} , sysdate, 0)
</insert>
<select id="listBoard" resultType="Board">
select * from board order by seq desc
</select>
</mapper>

MyBatis 설정 3) Mapper interface 선언
DAO 메서드와 SQL쿼리를 Mapping해주는 interface를 선언한다.
package Mapper;

import java.util.List;

import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Update;

import kostaServlet.Board;
import kostaServlet.Search;

public interface BoardMapper {
int insertBoard(Board board);
List<Board> listBoard(Search search);
Board detailBoard(int seq);
@Update("UPDATE board " +
"SET title = #{title}," +
"contents = #{contents}" +
"WHERE seq = #{seq}")
int updateBoard(Board board);
@Delete("DELETE board " +
"WHERE seq = #{seq}")
int deleteBoard(int seq);
}


MyBatis 설정 4) DAO 구현
JSP에서 쿼리대신 사용 할 메서드를 구현한다.
최종적으로 JSP에서는 해당 클래스의 객체에서 메서드를 호출하여 쿼리를 날리는것이다.
package kostaServlet;

import java.io.InputStream;
import java.util.List;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import Mapper.BoardMapper;

public class BoardDao2 {
private static BoardDao2 dao = new BoardDao2();
public static BoardDao2 getInstance() {
return dao;
}
public SqlSessionFactory getSqlSessionFactory() {
String resource = "mybatis-config.xml";
InputStream in = null;
try {
in= Resources.getResourceAsStream(resource);
} catch (Exception e) {
e.printStackTrace();
}
return new SqlSessionFactoryBuilder().build(in);
}
public int insertBoard(Board board) {
int re =-1;
SqlSession sqlSession = getSqlSessionFactory().openSession();
try {
re = sqlSession.getMapper(BoardMapper.class).insertBoard(board);
// 트렌젝션 처리>> 성공하면 커밋 실패하면 롤백 >>DML코드에 대해서는 트랜젝션처리를 해야한다.
if(re>0) {
sqlSession.commit();
}else {
sqlSession.rollback();
}
} catch (Exception e) {
e.printStackTrace();
}finally {
sqlSession.close();
}
return re;
}

*Mybatis 관련 

*많이 실수하는것 1)
insert update delete <DML>코드 사용시
반드시 트랜잭션 처리를 해줘야 한다. return에 따라서 commit, rollback.

*많이 실수하는것 2) 
Board객체=Mapping객체는 반드시 Secializable 을 implements해줘야 한다.

*MapState 에서 가장 중요한것!

resultType이 가장 중요하다! 먼저 생각하고 작성하자.

작성하기 전에 미리 parameterType도 고려한다.

=select는 파라미터가 있을수도 있고 없을수도 있다.


*XML을 이용한 SQL 매퍼 설정 태그들.

*sql요소<sql>
SQL코드조각 재사용
<sql id=“authorColumns”>
ID,PASSWORD,NAME
</sql>

<selectid=“findList”parameterType=“int”resultType=“hashmap”>
SELECT<includerefid=“authorColumns”/>
FROMAUTHOR
WHEREID=#{id}
</select>


*resultMap <resultMap>

- resultType과 resultMap


dto의 변수명과 table의 column 명이 같다면, resultType으로 바로 mapping이 가능하다.

하지만 dto변수에는 보통 낙타표기법을 쓰므로, 같지 않을 경우가 많다. 이럴 땐 resultMap을 사용하여 mapping한다.

=출처: http://bombay.tistory.com/6 [취향창고]


우리가 조회할 컬럼명과 클래스의 멤버변수명이 서로 일치하지 않을때가 있다.

그때 resultMap을 사용하면 서로 이름이 다르다고 할 지라도 맵핑 해준다.


//property는 클래스의 멤버변수형이고 column은 DB컬럼명이다.

//두개를 mapping해준다는것이다.


<resultMap id=“authorResultMap” type=“Author”>

<id property=“authorId” column=“author_id”/>

<result property=“authorPassword” column=“author_password”/>

<result property=“authorName” column=“author_name”/>

</resultMap>



<select id=“find” parameterType=“int” resultMap=“authorResultMap”>

SELECT ID,PASSWORD,NAME FROM AUTHOR WHERE ID=#{id}

</select>


*AS방식 resultMap보다 많이 쓴다.

as를 써서 이름을 바꾼다

resultMap에서 변수명을 쓰면 된다.



*동적SQL

사용자의 입력에 따라 쿼리를 변경해야 할 때가 있다.

예> SELECT * FROM 테이블명 WHERE 검색조건.

=조건 절은 계속 변화한다. 

MYBATIS를 사용하지 않으면 코드가 굉장히 복잡해 진다. <JSP에서 쿼리날리던거 생각해보자!>

<!> 해당설정은 mapperFile에서 한다.

*if/choose

//if test구문 수행한 boolean값으로 element body의 SQL구문 추가 결정.

<select id=“findActiveBlogWithTitleLike” parameterType=“Blog” resultType=“Blog”>

SELECT * FROM blog

WHERE state='ACTIVE'

<if test=”title != null”>

AND title like=#{title}

</if>

<if test=“author != null && author.name != null”>

AND title like#{author.name}

</if>

</select>


//choose 복수의 옵션중 하나를 선택 해야 할 때

<select id=“findActiveBlogWithTitleLike” parameterType=“Blog” resultType=“Blog”>

SELECT * FROM blog

WHERE state='ACTIVE'

<choose>

<when test=”title!=null”>

AND title like=#{title}

</when>

<when test=“author!=null&&author.name!=null”>

AND title like#{author.name}

</when>

<otherwise>

AND featured = 1

</otherwise>

</choose>

</select>

*where
if 또는 choose구문을 통해서 해결되지 않는 동적 SQL 구문 처리
if를 만족하면 sql문 조각을 붙이고, 만족하지 않으면 그냥 넘어간다.

<select id=“findActiveBlogWithTitleLike” parameterType=“Blog” resultType=“Blog”>

SELECT * FROM blog

<where>

<if test=“state!=null”>

state=#{state}

</if>

<if test= “title != null”>

AND title like #{title}

</if>

<if test=“author!=null&&author.name!=null”>

AND title like#{author.name}

</if>

</where>

</select>


*foreach

collection 객체에 대해 반복이 필요한 경우 사용

in 연산자 안에 ,가 들어가고,

(가 들어간다.

이때, foreach를 사용해서 동적으로 사용 할 수 있다.

open으로 (열어주고 중간중간에 ,로 구분해주고 다 끝나면 close해준다.


//

<select id=“selectPostIn” resultType=“Post”>

SELECT *

FROM POSTasp

WHERE ID in

<foreach item=“item”index=“index”collection=“list”

open = “(“ separator = “,” close = “)”>

#{item}

</foreach>

</select>


*DAO클래스 내에서 메서드 구현

=참고 SqlSession

   Sql 매핑 설정정보를 통해 Sql구문수행(mybatis-config.xml을 참조하기 때문이다)

   Db에 질의를 수행하기 위한 메서드를 보유

   매핑 인터페이스객체를 통해 매핑정보 활용가능

   매핑된 SQL 구문을 SqlSession객체를 통해 수행가능


=참고 XML 매핑 설정의 id를 이용하는 방법 CRUD방식 <! 현변환이 필요하다!>

   매퍼인터페이스의 메서드를 이용하는 방법 Sql매퍼를 메서드로 검색하므로  문자열입력 오류가능성을 줄였다.

package kostaServlet;


public class BoardDao2 {

private static BoardDao2 dao = new BoardDao2();

public static BoardDao2 getInstance() {

return dao;

}

public SqlSessionFactory getSqlSessionFactory() {

String resource = "mybatis-config.xml";

InputStream in = null;

try {

in= Resources.getResourceAsStream(resource);

} catch (Exception e) {

e.printStackTrace();

}

return new SqlSessionFactoryBuilder().build(in);

}

 public List<Board> listBoard(Search search){ 

 SqlSession sqlSession = getSqlSessionFactory().openSession(); 

 List<Board> list = null; 

 try { 

 //매퍼방식 

 list = sqlSession.getMapper(BoardMapper.class).listBoard(search); 

 //crud방식 

list = (List<Board>) sqlSession.selectList("kosta.mapper.BoardMapper.listBoard"); 

 } catch (Exception e) {

     e.printStackTrace(); 

 }

 return list; 

 }

}


'Today I learned' 카테고리의 다른 글

1월7일  (0) 2019.01.07
1월3일  (0) 2019.01.03
12월28일  (0) 2019.01.02
12월14일  (0) 2018.12.27
12월27일  (0) 2018.12.27

댓글