|
1. Mybaits?
마이바티스 구조는 요렇게 생겼다.
SqlMapConfig.xml 은 마이바티스 환경설정파일로, 마이바티스는 이 파일을 읽어 어떤 DMBS와 커넥션을 연결할지,
어떤 SQL Mapper XML 파일들이 등록되어 있는지 알아낸다.
SqlMap.xml 은 등록된 각 SQL 명령어들을 Map 구조로 저장하여 관리한다.
즉, 각각의 SQL 명령어가 가지는 아이디를 중복 없이 Map의 키값으로 등록한다.
그리고 SQL 이 실행될 때 필요한 값들을 input 형태의 데이터로 할당하고,
SQL 이 SELECT 일 때는 output 형태의 데이터로 리턴한다.
2. Mybatis 환경설정 파일
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | <configuration> <!-- Alias 설정 --> <typeAliases> <!-- alias(별명, 별칭), typeAlias는 여러개 등록 가능 --> <!-- com.neverland.mybaits.board 패키지의 BoardVO 클래스를 board 별명으로 설정 --> <!-- SQL Mapper 에서 사용 --> <typeAlias type="com.neverland.mybatis.board.BoardVO" alias="board"></typeAlias> </typeAliases> <!-- Sql Mapper 설정 --> <!-- 여러개의 Mapper 등록 가능 --> <mappers> <mapper resource="mappings/board-mapping.xml" /> </mappers> <!-- DataSource 설정, Spring 과 연동하는 경우, DB 관련 처리는 Srping 에 맡김 --> <!-- Mybatis 에서 DataSource 를 설정하고자 하는 경우 --> <!-- <enviroments default="development"> <enviroment id="development"> <transaction type="JDBC"/> <dataSource type="POOLED"> <property name="driver" value="사용할 DB Driver"/> <property name="url" value="사용할 DB url"/> <property name="username" value="사용할 DB username"/> <property name="password" value="사용할 DB password"/> </dataSource> </enviroment> </enviroments> --> </configuration> | cs |
3. SQL Mapper Elements
<mapper namespace="MybatisBoardDAO" SQL 엘리먼트들... </mapper> |
namespace 속성, DAO 클래스에서 사용할 매퍼 이름 mapper는 루트 엘리먼트로 여러개 등록 가능 SQL 엘리먼트는 유일한 값인 id 속성을 가지는데, 소속된 mapper 엘리먼트가 다르면 같은 id 사용 가능 에러 남 <mapper> <insert id="BoardGoGo"> <delete id="BoardGoGo"> </mapper> 에러 안 남 <mapper> <insert id="BoardGoGo"> </mapper> <mapper> <insert id="BoardGoGo"> </mapper> |
<select id="getBoard" parameterType="board" resultType="board"> SELECT * FROM BOARD WHERE SEQ=#{seq} </select> |
id 속성(모든 SQL 엘리먼트 동일) 필수 속성, DAO 클래스에서 id 로 SQL 실행할 때 사용 ex) DAO 클래스, mybaits.selectOne("MybatisBoardDAO.getBoard", vo) MybatisBoardDAO -> mapper 의 namespace / getBoard -> SQL 엘리먼트의 id parameterType 속성 SQL 실행에 필요한 데이터 설정, 생략 가능(대부분 생략) ex) ① parameterType="com.neverland.mybatis.board.BoardVO" ② 마이바티스 설정파일에 설정한 <typeAlias type="com.neverland.mybaits.board.BoardVO" alias="board"/> alias="board" 사용, parameterType="board" resultType 속성 결과가 필요한 검색 관련 SQL 이 실행될 때, 리턴되는 검색 결과를 자바 객체에 매핑(필수 속성) ex) ① resultType="com.neverland.mybatis.board.BoardVO" ② 마이바티스 설정파일에 설정한 <typeAlias type="com.neverland.mybaits.board.BoardVO" alias="board"/> alias="board" 사용, resultType="board" |
(3) <insert>
<insert id="insertBoard"> <selectKey keyProperty="seq" resultType="int"> SELECT BOARD_SEQ.NEXTVAL AS seq from DUAL INSERT INTO BOARD(SEQ, TITLE, CONTENT) VALUES(#{seq}, #{title}, #{content}) </insert> |
<selectKey> 자식 엘리먼트(생략 가능) auto increment 가 없는 오라클은 시퀸스로 자동 증가 사용, 이 경우 사용(보통은 자동 증가 없이, 서비스나 컨트롤에서 구현) BOARD_SEQ 라는 시퀸스로부터 킷값을 얻어와 seq 로 명명, INSERT INTO 구문에서 사용 |
(4) <update>, <delete>
<update id="updateBoard"> UPDATE BOARD SET TITLE=#{title}, CONTENT=#{content} WHERE SEQ=#{seq} </update> |
<delete id="deleteBoard"> DELETE BOARD WHERE SEQ=#{seq} </delete> |
(5) <resultMap>
<resultMap id="boardResult" type="board"> <id property="seq" column="SEQ"/> <result property="title" column="TITLE"/> <result property="content" column="CONTENT"/> </resultMap> <select id="getBoardList" resultMap="boardResult"> select * from board order by desc </select> |
JOIN 의 경우처럼 검색 결과를 정확하게 하나의 자바 객체로 매핑할 수 없거나(조인 했으니까 테이블 2개, VO 2개), 테이블의 칼럼이름과 매핑에 사용될 자바 객체의 변수 이름이 다를 때 사용 select 엘리먼트의 resultMap 속성 값 => resultMap 의 id 속성 값 |
(6) CDATA Section 사용 및 SQL 대문자로 설정
XML 문법인 CDATA 사용, CDATA 영역 안의 데이터는 단순한 문자 데이터로 XML 파서가 해석하지 않아서, 그대로 DB에 전달 됨
만약 SELECT * FROM BOARD WHERE SEQ <= #{seq} 같은 쿼리문이 있다면 XML 에서 < 와 > 기호는 태그 기호로 인식하기 때문에 에러 발생, XML 파서가 해석하지 못하게 하면 해결됨 ex) <delete id="deleteBoard"> <![CDATA[ DELETE BOARD WHERE SEQ=#{seq} ]]> </delete> |
DB 는 대소문자 구분을 하지 않기 때문에, 식별성을 높이고, 변수명과 확실히 구분하기 위해 SQL 구문은 보통 대문자로 작성 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | <!-- src/main/resources/mappings/board-mapping.xml --> <mapper namespace="BoardDAO"> <resultMap id="boardResult" type="board"> <id property="seq" column="SEQ" /> <id property="title" column="TITLE" /> <id property="writer" column="WRITER" /> <id property="content" column="CONTENT" /> <id property="regDate" column="REGDATE" /> <id property="cnt" column="CNT" /> </resultMap> <insert id="insertBoard" parameterType="board"> <![CDATA[ INSERT INTO BOARD(SEQ, TITLE, WRITER, CONTENT) VALUES((select nvl(max(SEQ),0)+1 from board),#{title},#{writer},#{content}) ]]> </insert> <update id="updateBoard"> <![CDATA[ UPDATE BOARD SET TITLE=#{title},CONTENT=#{content} WHERE SEQ=#{seq} ]]> </update> <delete id="deleteBoard"> <![CDATA[ DELETE BOARD WHERE SEQ=#{seq} ]]> </delete> <select id="getBoard" resultType="board"> <![CDATA[ SELECT * FROM BOARD WHERE SEQ=#{seq} ]]> </select> <select id="updateCnt"> <![CDATA[ UPDATE BOARD SET CNT=#{cnt}+1 WHERE SEQ=#{seq} ]]> </select> <select id="getBoardList" resultType="board"> <![CDATA[ SELECT * FROM BOARD ]]> </select> </mapper> | cs |
4. 스프링 연동 설정
1 2 3 4 5 6 | <bean id="sessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <!--org.apache.commons.dbcp.BasicDataSource 로 생성한 dataSource --> <property name="dataSource" ref="dataSource"/> <!-- 마이바티스 환경설정 파일 주입--> <property name="configLocation" value="classpath:mybatis-config.xml"/> </bean> | cs |
5. DAO 구현(SqlSessionDaoSupport 클래스 상속)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | // SqlSessionDaoFactory 상속 @Repository public class BoardDAOMybatis extends SqlSessionDaoSupport { // SqlSession 객체를 사용하기 위해 // bean 으로 등록한 SqlSessionFactoryBean 객체를 인자로 받아 // 슈퍼클래스인 SqlSessionDaoFactory의 setSqlSessionFactory() 메소드 호출 // // 상속 받은 SqlSessionDaoSupport 클래스 일부 // public abstract class SqlSessionDaoSupport extends DaoSupport{ // // private SqlSession sqlSession; // SqlSessionFactory 객체를 받아서 sqlSession 객체 생성 // public void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) { // if (!this.externalSqlSession) { // this.sqlSession = new SqlSessionTemplate(sqlSessionFactory); // } // sqlSession 객체가 생성되어야 getSqlSession() 가능 // public SqlSession getSqlSession() { // return this.sqlSession; // } // } // // SqlSessionFactoryBean 객체가 생성되는 클래스, FactoryBean<SqlSessionFactory> 를 구현하고 있다 // public class SqlSessionFactoryBean implements FactoryBean<SqlSessionFactory>, InitializingBean, ApplicationListener<ApplicationEvent>{ // 클래스 내용은 생략 // } @Autowired public void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) { super.setSqlSessionFactory(sqlSessionFactory); } public void insertBoard(BoardVO vo) { getSqlSession().insert("BoardDAO.insertBoard", vo); } public void updateBoard(BoardVO vo) { getSqlSession().update("BoardDAO.updateBoard", vo); } public void deleteBoard(BoardVO vo) { getSqlSession().delete("BoardDAO.deleteBoard", vo); } public BoardVO getBoard(BoardVO vo) { return getSqlSession().selectOne("BoardDAO.getBoard", vo); } public List<BoardVO> getBoardList(BoardVO vo) { return getSqlSession().selectList("BoardDAO.getBoardList", vo); } } | cs |
6. DAO 구현(SqlSessionTemplate 클래스 <bean> 등록)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 | // applicationContext.xml 에 SqlSessionTemplate 클래스 bean 등록 // <bean class="org.mybatis.spring.SqlSessionTemplate"> // <constructor-arg ref="sqlSession"/> // </bean> // // SqlSessionTemplate 클래스 일부 // // SqlSessionFactoryBean 객체가 생성되는 클래스, FactoryBean<SqlSessionFactory> 를 구현하고 있기 때문에 // SqlSessionTemplate 클래스 생성자의 SqlSessionFactory 매개변수로 들어갈 수 있다 // public class SqlSessionFactoryBean implements FactoryBean<SqlSessionFactory>, InitializingBean, ApplicationListener<ApplicationEvent>{ // 클래스 내용은 생략 // } // // SqlSession을 구현하고 있다 // public class SqlSessionTemplate implements SqlSession, DisposableBean { // // private final SqlSessionFactory sqlSessionFactory; // // 구현하고 있는 SqlSession 을 위임해서(Proxy pattern) DB 처리 // private final SqlSession sqlSessionProxy; // // 생성자를 통해서 SqlSessionFactory 타입 객체를 받고 있기 때문에 // bean 객체 등록할 때 constructor-arg 를 통해 주입 해야 한다 // public SqlSessionTemplate(SqlSessionFactory sqlSessionFactory) { // this(sqlSessionFactory, sqlSessionFactory.getConfiguration().getDefaultExecutorType()); // } // // @Override // public <T> T selectOne(String statement) { // return this.sqlSessionProxy.<T> selectOne(statement); // } @Repository public class BoardDAOMybatis { @Autowired private SqlSessionTemplate mybatis; public void insertBoard(BoardVO vo) { mybatis.insert("BoardDAO.insertBoard", vo); } public void updateBoard(BoardVO vo) { mybatis.update("BoardDAO.updateBoard", vo); } public void deleteBoard(BoardVO vo) { mybatis.delete("BoardDAO.deleteBoard", vo); } public BoardVO getBoard(BoardVO vo) { return mybatis.selectOne("BoardDAO.getBoard", vo); } public List<BoardVO> getBoardList(BoardVO vo) { return mybatis.selectList("BoardDAO.getBoardList", vo); } } | cs |
7. Dynamic SQL(동적 SQL)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | <select id="getBoardList" resultType="board"> <![CDATA[ SELECT * FROM BOARD WHERE ]]> <if test="searchCondition=='TITLE'"> <![CDATA[ TITLE LIKE '%'||#{searchKeyword}||'%' ]]> </if> <if test="searchCondition=='CONTENT'"> <![CDATA[ AND CONTENT LIKE '%'||#{searchKeyword}||'%' ]]> </if> <![CDATA[ ORDER BY SEQ DESC; ]]> </select> | cs |
'Programming > Spring' 카테고리의 다른 글
JPA 스프링 연동 (0) | 2017.08.14 |
---|---|
JPA (Java Persistence API) 기본 개념 (2) | 2017.08.13 |
Spring Layered Architecture (0) | 2017.08.09 |
Spring MVC (annotation 기반) (0) | 2017.08.08 |
Spring MVC (XML 설정 기반) (0) | 2017.08.08 |
댓글