라이브러리와 프레임워크의 차이점:
라이브러리: 방향과 목적을 개발자가 정한다.= 필요에 의해 선택 할 수 있다.
프레임워크: 틀과 뼈대가 이미 잡혀있다. 자유도가 떨어지는듯.
장점: 1)코드의 일관성
2)lowlevel영역은 프레임워크가 지원해주기 때문에 개발자는 비즈니스 레벨만 개발하면 된다.
예>Mybatis: 커넥션도 관리해준다. 중복적인 lowlevel의 코드를 신경쓰지 않아도 된다.(ORM 프레임워크)
티어를 계층이라고 한다.
뷰단, 비즈니스단, 퍼시스턴트 티어, DB단
퍼시스턴트 티어 = ORM 프레임워크
Mybatis, hibnate..
Mybatis: SQL의 ‘결과값’을 자바객체와 매핑하기 위해서.
=상대적으로 쉽다.
mybatis-conf.xml
=모든 정보를 갖고있다.
<프레임워크는 xml같은 설정파일을 100%갖고있다.>
<xml내에는 커스텀태그로써, 각 태그들이 의미를 갖고있다.>
JNDI: 네이밍을 통해 자료를 가져온다.
data_source 이름 : /jdbc/oracle
=커넥션 풀이 생성되는것임.
=DB와 연결이 이루어졌다.
Mybatis와 DBMS의 연결이 이루어진것임.
typeAliases 원래 kosta.bean.Board로 이름을 써줘야 하지만.. alias로 Board로 써준다.
Mapper File: xml
호출하려면 DAO가 필요하다.
=mybatis_conf.xml이 필요하다고. Mapper에 등록한다.
Mybatis-conf.xml은 DAO가 필요하다.
=mybatis-conf.xml = JAVA 객체화 해야한다.
mybatis-conf.xml을 SqlSession객체로 가져온다.
우리가 사용할 쿼리는 하고자 하는것은 태그 형태로 Board.xml에 내용이 있다.
<다른것과 겹칠 수 있기때문에 nameSpace를 사용한다>
쿼리를 호출하는것은 두가지 방식이 있다.
1)CRUD메서드 5가지
selectOne() = 기본 메서드.
selectList(“kosta.mapper.BoardMapper.listBoard”) =
selectList는 ArrayList를 return한다.
CRUD에서는 nameSpace와 Id를 넣는다
2)Mapper를 호출하는 방식
getMapper(BoardMapper.class).insertBoard(board);
=Mapper를 사용하게되면 메서드 이름이 ID명이 된다.
!Mapper를 만들어야한다. = 인터페이스를 만들어야 한다.=메서드 이름은 Mapper의 ID이름과 같아야 한다.
주의!=Mapper인터페이스 이름이NameSpace와 일치해야 합니다!<kosta.mapper.BoardMapper>
sqlSession객체에서 getMapper()해서 등록한다.
그러면 .하면 insertBoard(board)하면 호출 이끝난당!
*드디어 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인스턴스를 사용
UNPOOLED: 매번 요청마다 dataSource의 구현체를 생성한다.
driver : JDBC driver 명
•url: database 인스턴스의JDBC url
•username : database 사용자아이디
•password : database 사용자패스워드
•driver 옵션설정: database driver에추가정보설정
driver.encoding= UTF8
POOLED : connection을생성하여pool에보관하고, 요청시마다pooling된connection 인스턴스를사용
•poolMaximumActionConnections: 홗성connection의갯수
•poolMaximumIdleConnections: idle 상태의최대connection 개수
•poolMaximumCheckoutTime: connection객체의최대checked out 시갂
(default : 20000ms)
•poolTimeToWait: pooling시최대대기시갂(default : 20000ms)
•poolPingQuery: database와의연결이유효한지알아보기위해실행하는질의문
(default: “NO PING QUERY SET”)
•poolPingEnabled: ping query 사용여부설정(default : false)
•poolPingConnectionsNotUsedFor: 얼마나자주ping query를사용할지설정
(default : 0)
JDNI : JNDI context를통해Container에서제공하는dataSource를사용
•initial_context: initialContext로부터context를lookup하기위해사용됨
initialContext.lookup(initial_context)
생략시initailContext를통해직접context를lookup함.
•data_source: dataSource의인스턴스로참조되는context path
initial_context로부터lookup
<?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;
}
}
댓글