오후에 시험을 본다

 

MyBatis

  • 쿼리문을 별도 관리, 분리한다
  • 동적 쿼리를 작성할 수 있다.
  • 캐시 기능을 제공해 데이터베이스 연산 속도를 높일 수 있다.

 

동적쿼리란

실행 시점에 조건에 따라 SQL 쿼리를 동적으로 생성하는 것.

데이터 베이스의 검색 조건이나 결과값 등이 동적으로 변환할 때 유용하게 사용된다.

 

src/main/resources > mapping > board-mapping.xml 에서 쿼리문을 처리

BoardDAO에서는 board-mapping.xml에서 적은 쿼리문을 언제 사용할지 정의해준다고 생각하면 됨.

 

 

board-mapping.xml

<?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="BoardDAO">

	<!-- 글 등록 -->
	<insert id="insertBoard">
		insert into board (seq,title,writer,content)
		values ((select nvl(max(seq),0) + 1 from board), #{title}, #{writer}, #{content})
	</insert>
	
	<!-- 글 수정 -->
	<update id="updateBoard">
		update board set title=#{title}, content=#{content}, where seq=#{seq}
	</update>
	
	<!-- 글 삭제 -->
	<delete id="deleteBoard">
		delete board where seq=#{seq}
	</delete>
	
	<!-- 글 상세 조회 -->
	<select id="getBoard" resultType="board">
		select * from board where seq=#{seq}
	</select>
	
	<!-- 글 목록 조회 -->
	<select id="getBoardList" resultType="board">
		select * from board where title like '%'||#{searchKeyword}||'%' 
		order by seq desc
	</select>
	
</mapper>

 

src/main/java > com.springbook.biz.board > BoardServiceClient

package com.springbook.biz.board;

import com.springbook.biz.board.impl.BoardDAO;

public class BoardServiceClient {

	public static void main(String[] args) {
		BoardDAO boardDAO = new BoardDAO();
		BoardVO vo = new BoardVO();
		
		vo.setTitle("myBatis 제목");
		vo.setWriter("홍길동");
		vo.setContent("여름아 부탁해");
		boardDAO.insertBoard(vo);

	}

}

 

이렇게 하고 실행했는데 이런 경고 메세지가 생겨서 보니

WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by org.apache.ibatis.reflection.Reflector (file:/C:/Users/USER/.m2/repository/org/mybatis/mybatis/3.3.1/mybatis-3.3.1.jar) to method java.lang.Object.finalize()
WARNING: Please consider reporting this to the maintainers of org.apache.ibatis.reflection.Reflector
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release

mybatis 버전 문제였다. 3.3.1 버전에서 → 3.5.2 버전으로 업그레이드 한 후 실행했더니 해결

 

pom.xml 수정

    <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
	<dependency>
	    <groupId>org.mybatis</groupId>
	    <artifactId>mybatis</artifactId>
	    <version>3.5.2</version>
	</dependency>

참고) https://sillutt.tistory.com/entry/Mybatis-WARNING-An-illegal-reflective-access-operation-has-occurred

 

[Mybatis] WARNING: An illegal reflective access operation has occurred

원인 테스트 중 다음과 같은 경고가 발생했다. WARNING: An illegal reflective access operation has occurred WARNING: Illegal reflective access by org.apache.ibatis.reflection.Reflector (file:/C:/Users/USER/.m2/repository/org/mybatis/mybatis/

sillutt.tistory.com

 

 

BoardServiceClient.java

package com.springbook.biz.board;

import java.util.List;

import com.springbook.biz.board.impl.BoardDAO;

public class BoardServiceClient {

	public static void main(String[] args) {
		BoardDAO boardDAO = new BoardDAO();
		BoardVO vo = new BoardVO();
		
		// 글 등록
		vo.setTitle("myBatis 제목");
		vo.setWriter("홍길동");
		vo.setContent("여름아 부탁해");
		boardDAO.insertBoard(vo);
		
		vo.setSearchCondition("TITLE");
		vo.setSearchKeyword("");
		
		// 상세글 조회
		//vo.setSeq(19);
		//BoardVO getboard = boardDAO.getBoard(vo);
		//System.out.println("상세글 조회 결과: " + getboard);
		
		// 글 수정
		//vo.setTitle("오늘의 날씨");
		//vo.setContent("맑음");
		//vo.setSeq(17);
		//boardDAO.updateBoard(vo);
	
		// 글 삭제
		//vo.setSeq(29);
		//boardDAO.deleteBoard(vo);
		
		// 전체 글 조회
		List<BoardVO> boardList = boardDAO.getBoardList(vo); 
		
		for (BoardVO board : boardList) {
			System.out.println("==>" + board.toString());
		}

	}

}

 

조회, 수정, 삭제가 안된다..! 미해결과제

 

해결 )

 

스프링 pom.xml 세팅 시 aspectjweaver 태그 위치 설정 관계

0729)금요일에 mybatis 를 기존에 만들어 둔 게시판과 연동했는데 실행 오류가 났다.오늘 오전 다시 파일들을 찬찬히 살펴보며 코드를 수정했는데 pom.xml 에 세팅 오류가 있었다.' 오류 메세지 )Contex

100dumpling.tistory.com

 


 

추가로 알아 둘 것.

 

board-mapping.xml

		<selectkey keyProperty="seq" resultType="int" order="BEFORE">
			select board_seq.nextval as seq from duel
		</selectkey>
		
		insert into board (seq,title,writer,content)
		values (#{seq}, #{title}, #{writer}, #{content})
		
		<!-- 어떤 값을 따로 쓰고 싶을 때 -->
		<!-- order="AFTER" insert 처리가 된 후에 값을 가지고 와라 -->
		<selectkey keyProperty="writer" resultType="int" order="AFTER">
			select writer from board
		</selectkey>
		
	</insert>
	
	<insert id ="hobby">
	insert into hobby (writer) values(#{writer}) <!-- 다른 테이블의 writer를 끌어올 수 있다 -->
	</insert>

시퀀스 객체를 DB에 만들어 두고 시퀀스 객체를 이용할 수 있다.

 

board-mapping.xml

	<!-- 컬럼이름과 VO객체 멤버 이름 비교, 이름이 다르더라도 자동으로 매치가 된다 -->
	<resultMap id="boardResult" type="board">
		<id property="seq" column="SEQ"/>
		<result property="title" column="TITLE"/>
		<result property="writer" column="WRITER"/>
		<result property="content" column="CONTENT"/>
		<result property="regDate" column="REGDATE"/>
		<result property="cnt" column="CNT"/>
	</resultMap>

 

쿼리문을 쓸 때 부등호( <, > ) 인식을 못한다. 그럼으로 부등호를 써야할 때는

	<!-- 조건절에 비교연산자(<, >)을 식으로 인식하기 위해 -->
	<![CDATA[ 
		insert into board (seq,title,writer,content)
		values ((select nvl(max(seq),0) + 1 from board), #{title}, #{writer}, #{content})
	]]>

<![CDATA[ ]]> 안에 비교할 대상의 식이 쓰이게 사용해야 한다.

 

BoardDAO.java

package com.springbook.biz.board.impl;

import java.sql.SQLException;
import java.util.List;

import org.apache.ibatis.session.SqlSession;

import com.springbook.biz.board.BoardVO;
import com.springbook.biz.util.SqlSessionFactoryBean;

public class BoardDAO {
	
	// 원형
//	public List seleList(String statement)
//	public List seleList(String statement, Object parmeter)
//	
//	public int insert(String statement, Object parmeter)
//	public int update(String statement, Object parmeter) throws SQLException
//	public int delete(String statement, Object parmeter) throws SQLException
	
	// SqlSession 타입 mybatis은 xml의 정보를 다 가지고 있다. 
	private SqlSession mybatis;
	
	public BoardDAO() {
		mybatis = SqlSessionFactoryBean.getSqlSessionInstance();
	}
	
	// 글 등록
	public void insertBoard(BoardVO vo) {
		mybatis.insert("BoardDAO.insertBoard", vo); 
		mybatis.commit();
	}
	
	// 글 수정
	public void  updateBoard(BoardVO vo) {
		mybatis.update("BoardDAO.updateBoard", vo);
		mybatis.commit();
	}
	
	// 글 삭제
	public void deleteBoard(BoardVO vo) {
		mybatis.delete("BoardDAO.deleteBoard", vo);
		mybatis.commit();
	}
	
	// 글 상세조회
	public BoardVO getBoard(BoardVO vo) {
		
		return mybatis.selectOne("BoardDAO.getBoard", vo); // 하나만 조회할때 selectOne
	}
	
	// 글 목록 조회
	public List<BoardVO> getBoardList(BoardVO vo) {
		
		return mybatis.selectList("BoardDAO.getBoardList", vo); // 여러 개 조회할때 selectList 
	}
}

 


Spring에 Mybatis 연결하기

 

어떤 프로그램을 사용하기 위해서는 접점이 필요하다

Spring에서도 Mybatis을 사용하기 위해서는 SDK → api 인터페이스가 필요.

SDK 을 통해 Mybatis에 접근한다.

 

자바에서 오라클DB를 쓰는 것과 똑같은 원리. - JDBC가 SDK

 

다이나믹 SQL = 동적 쿼리문

조건절 분기

 

BoardWep > board-mapping.xml

	<!-- 글 목록 조회 -->
	<select id="getBoardList" resultType="board" resultMap="boardResult">
		select * from board where title like '%'||#{searchKeyword}||'%' 
		order by seq desc
	</select>

위와 같은 구문 고정이 title인데 동적 처리를 하면

 

BoardWep > board-mapping.xml

	<!-- 글 목록 조회 -->
	<select id="getBoardList" resultType="board" resultMap="boardResult">
		select * from board 
		where 1=1
		
		<if test="searchCondition == 'TITLE'">
		and title like '%'||#{searchKeyword}||'%'
		</if>
		<if test="searchCondition == 'CONTENT'">
		and content like '%'||#{searchKeyword}||'%' 
		</if>
		order by seq desc
	</select>

이렇게 바꿀 수 있다.

where 절의 중복을 막기 위해 where 1=1 를 쓰고 where 절이 들어가는 곳마다 and 를 쓴다.

 

BoardWep > BoardDAOMybatis

package com.springbook.biz.board.impl;

import java.util.List;

import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import com.springbook.biz.board.BoardVO;

@Repository
public class BoardDAOMybatis {
	// SqlSessionTemplate이 mybatis 기능을 쓰는 라이브러리
	// SqlSessionTemplate 객체를 사용
	
	// 자동의존주입
	@Autowired
	private SqlSessionTemplate mybatis;
	
	public void insertBoard(BoardVO vo) {
		System.out.println("==> Mybatis로 insertBoard() 기능 처리");
		mybatis.insert("BoardDAO.insertBoard", vo);
	}
	
	public void updateBoard(BoardVO vo) {
		System.out.println("==> Mybatis로 updateBoard() 기능 처리");
		mybatis.update("BoardDAO.updateBoard", vo);
	}
	
	public void deleteBoard(BoardVO vo) {
		System.out.println("==> Mybatis로 deleteBoard() 기능 처리");
		mybatis.delete("BoardDAO.deleteBoard", vo);
	}
	
	public BoardVO getBoard(BoardVO vo) {
		System.out.println("==> Mybatis로 getBoard() 기능 처리");
		return mybatis.selectOne("BoardDAO.getBoard", vo);
	}
	
	public List<BoardVO> getBoardList(BoardVO vo) {
		System.out.println("==> Mybatis로 getBoardList() 기능 처리");
		return mybatis.selectList("BoardDAO.getBoardList", vo);
	}
}

 

applicationContext

<?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: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="polymorphism"></context:component-scan> -->
	<context:component-scan base-package="com.springbook.biz"></context:component-scan>
	
	<!-- database.properties 의 파일을 읽어올 수 있게 해준다 -->
	<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>
	<property name="url" value="${jdbc.url}"></property>
	<property name="username" value="${jdbc.username}"></property>
	<property name="password" value="${jdbc.password}"></property>

	</bean>
	
	<!--JdbcTemplate 클래스를 통해 DB에 접근 (crud) -->
	<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
		<property name="dataSource" ref="dataSource"></property>
	</bean>
	
	<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		 <property name="dataSource" ref="dataSource"></property>
	</bean>
	
	<tx:advice id="txAdvice" transaction-manager="txManager">
		<tx:attributes>
		<tx:method name="get*" read-only="true"/> <!-- get메소드 제외하고 트랜잭션 처리를 해줘라 -->
		<tx:method name="*" />
		</tx:attributes>
	</tx:advice>
	
	<bean id="sqlsession" class="org.mybatis.spring.SqlSessionFactoryBean">
	<property name="dataSource" ref="dataSource"/>
	<property name="configLocation" value="classpth:sql-map-config.xml"/>
	</bean>
	
	<bean class="org.mybatis.spring.SqlSessionTemplate"> 
		<!-- 생성자 의존 주입 -->
		<constructor-arg ref="sqlSession"></constructor-arg>
	</bean>
	
	<aop:config>
		<aop:pointcut expression="execution(* com.springbook.biz..*(..))" id="txPointcut"/> <!-- biz 하위의 모든 메소드를 수정하겠다 -->
		
		<aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcut" />
	</aop:config>
	
	
</beans>

 

 

 

+ Recent posts