JAVA/HIGH JAVA

[JAVA] MyBatis

아잠만_ 2024. 5. 22. 12:37

MyBatis

더보기

mybatis (3.5.11) 

jar파일 다운로드 (Maven Repository)

  • sql문을 java에서 작성하지 않고 Mybatis를 통해 jdbc를 통합적으로 관리할 수 있다
  • JAVA에서 DB를 편하게 핸들링할 수 있게 해주는 프레임워크이다
  • SQL문과 Java소스 코드를 분리하고, 파라미터 값만 변경되지 않으면
         Java소스의 변경없이 SQL문만 변경해서 사용할 수 있다.
  • MyBatis의 데이터 매퍼 API를 사용해서 자바빈즈(보통 VO객체) 혹은
         Map객체를 PreparedStatement의 파라미터에 매핑해 주고,
         SQL문의 실행 결과를 자바빈즈(VO객체) 혹은 Map객체에 자동으로 매핑해 준다

사용방법

사용시에 Build Path에 mybatis와 ojdbc6 두 개 jar 설정

mybatis-config.xml

<!DOCTYPE configuration 
PUBLIC "-//mybatis.org/DTD Config 3.0//EN"
 "http://mybatis.org/dtd/mybatis-3-config.dtd">
  • <configuration> 안에서 설정

<configuration>에 빨간 줄이 쳐졌을 경우

더보기

사용자 > (사용자 이름) > .lemminx > cache > http

mybatis.org파일을

폴더 mybatis.org로 바꿔주면 된다

  • <settings> : 기본 설정 값 세팅
  • <typeAliases> : 별칭 등록
    형식) <typeAlias type="패키지명을 포함한 전체이름" alias="별칭이름"/>
  • <environments default=""> : DB연결 정보 설정 (default할 id값 입력)
    • <environment id=""> 
      • <transactionManager type="JDBC"/>
      • <dataSource type="POOLED">
        • <property name="driver" value="${driver}"/>
          (properties에 저장된 키 값 가져오기)
  • <mappers> : DB에서 사용되는 SQL문이 작성된 mapper파일을 등록함
    형식) <mapper resource="경로명/파일명.xml"/>

mapper.xml

<!DOCTYPE mapper
	PUBLIC "-//mybatis.org/DTD Mapper 3.0//EN"
	"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  • <mapper>
    • <mapper>태그의 namespace속성에 설정된 값은 Java소스에서 
      실행할 SQL문을 호출할 때 같이 사용되는 이름이다
    • 태그 안쪽에는 처리할 SQL문에 맞는 태그를 자식 태그로 사용하여 SQL문 작성
<< 사용할 수 있는 자식 태그 >>
<select> select구문 </select>
<insert> insert구문 </insert>
<update> update구문 </update>
<delete> delete구문 </delete>
...
<!-- 이때 작성한 구문에 넣어야할 변수에 ?로 작성하지 않고
 #{vo에작성된변수이름} 으로 넣는다-->
    • id 속성
      해당 자식태그에 id 속성을 붙혀서
      실행할 태그를 Java소스에서 호출할 때 사용되는 이름
       <mapper>태그의 namespace속성값과 연결해서 사용한다
    • parameterType속성
      자식태그의 parameterType속성 작성된 SQL문에 사용될 데이터가 저장된 객체를 기술한다
      • 보통 VO클래스, Java의 기본 자료형이름, Map객체등이 사용된다
        이 속성에 객체를 기술할 때는 해당 클래스의 전체 이름을 기술해야 한다.
         그러나 <typeAlias>태그에 지정한 alias명이 있다면 해당 이름을 사용할 수도 있다
      • parameterType속성에 설정되는 값이 단일값이면 SQL문에 이 값을 나타내는 변수는
        특별히 이름이 정해지지않는다 (즉, 사용자 임의로 지정할 수 있다)
    • resultType 속성
      • select문을 처리한 결과를 저장할 VO클래스나 Java의 기본 자료형 이름,
             Map객체등을 지정할 수 있다  
      • select문을 처리할 결과가 여러개의 레코드이면 java소스에서 'selectList()'
            메서드를 이용해서 호출한다 그러면 검색된 데이터들을 자동으로 List에 담아서 반환한다
      • resultType속성에는 검색할 결과가 여러 개일 경우에도 1개의 레코드가
            저장될 클래스나 자료형 이름을 지정하면 된다

Test.java (mybatis 적용 클래스)

  • myBatis의 환경 설정 파일(mybatis-config.xml)을 읽어와서 처리한 후 > 스트림 활용
    myBatis를 사용할 수 있는 객체를 생성하는 SqlSessionFactory객체를 생성한다.
    이때 스트림을 사용할 때 Resources는 ibatis의 클래스 사용한다

  • 스트림객체 = Resources.getResourceAsStream("config파일경로");
  • SqlSessionFactory객체  = new SqlSessionFactoryBuilder().build(스트림객체);
  • 실제 SQL문을 처리하는 객체 변수
         SqlSession 생성
    세션객체 = SqlSessionFactory객체.openSession(논리값);
         '논리값'이 true이면 AutoCommit이 활성화된 상태이고,
         '논리값'이 생략되거나 false이면 AutoCommit 비활성화된 상태
  • SqlSession객체를 이용하여 처리할 SQL문을 호출하여 실행 사용한 문에 따라 메서드를 달리할 것
    * insert [ update | delete ]의 경우
    SqlSession객체.insert [ update | delete ]("namespace속성값.id속성값" [, 파라미터])
    (반환값 : 작업에 성공한 레코드 수)
    * select의 경우
    • 단일 행
      SqlSession객체.selectOne("namespace속성값.id속성값" [, 파라미터])
      반환값 : mapper의 resultType에 지정한 자료형이 반환된다
                    검색 결과가 없으면 null 반환
    • 여러 행
      SqlSession객체.selectList [ selectMap ]("namespace속성값.id속성값" [, 파라미터])
      반환값 : mapper의 resultType에 지정한 자료형의 Collection값으로 반환된다
  • SqlSession객체를 생성할 때 AutoCommit이 비활성화된 상태에서는
         commit작업을 직접 실행해야한다.

    SqlSession객체.commit();
  • 작업이 끝나면 닫아준다 (finally문)
    SqlSession객체.close();

사용 예시

mybatis-config.xml

<?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>
	<!--  DB연결 정보가 있는 Properties파일 설정  -->
	<properties resource="kr/or/ddit/mybatis/config/dbinfo.properties" />
	
	<!-- MyBatis의 기본 설정값 세팅 -->
	<settings>
		<!-- 데이터가 null로 전달되었으면 빈칸으로 인지되지 않고 null로 인식하는 설정 -->
		<!-- value값은 전부 대문자 -->
		<setting name="jdbcTypeForNull" value="NULL"/>
	</settings>
	
	<typeAliases>
		<!-- MyBatis에서 사용되는 클래스들은 사용할 때 패키지명이 포함된 
			전체 이름을 사용해야되는데 이것을 대신해서 짧은 이름으로 사용하기 위한 별칭을 등록한다.
		형식) <typeAlias type="패키지명을 포함한 전체이름" alias="별칭이름"/>
			-->
			<typeAlias type="kr.or.ddit.vo.LprodVO" alias="lprodVo"/>
	</typeAliases>

	<!-- DB에 연결 할 정보 설정하기 -->
	<environments default="oracleDB">
		<!-- 다른 DB도 연결할 수 있으므로 env는 여러개 올 수 있다 / id는 구분하기 위한 이름 -->
		<environment id="oracleDB"> 
			<transactionManager type="JDBC"/>
			<dataSource type="POOLED">
				<property name="driver" value="${driver}"/><!-- value값에 프로퍼티스의 키값 작성 -->
				<property name="url" value="${url}"/>
				<property name="username" value="${user}"/>
				<property name="password" value="${pass}"/>
			</dataSource>
		</environment>
	</environments>
	
	<!-- DB에서 사용되는 SQL문이 작성된 mapper파일을 등록하는 부분 -->
	<mappers>
		<!-- 
		형식) <mapper resource="경로명/파일명.xml"/>
		 -->
		 <mapper resource="kr/or/ddit/mybatis/mappers/lprod-mapper.xml"/>
	</mappers>
	
</configuration>

mapper.xml

<?xml version="1.0" encoding="UTF-8"?>

<!-- 이 문서는 myBatis에서 처리할 SQL문을 작성하는 문서입니다 -->
<!DOCTYPE mapper
	PUBLIC "-//mybatis.org/DTD Mapper 3.0//EN"
	"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
	
<!-- <mapper>태그의 namespace속성에 설정된 값은 Java소스에서 실행할 SQL문을 호출할 때
	 같이 사용되는 이름이다 -->
<mapper namespace="lprod">
	<!-- 
		이 <mapper> 태그 안쪽에는 처리할 SQL문에 맞는 
		태그를 자식태그로 사용해서 SQL문을 작성한다.
		
		* 사용할 수 있는 자식 태그
		<select> select구문 </select>
		<insert> insert구문 </insert>
		<update> update구문 </update>
		<delete> delete구문 </delete>
		...
	 -->
	 
	 <!-- 
	 * id 속성 ==> 실행할 태그를 Java소스에서 호출할 때 사용되는 이름
	 			 <mapper>태그의 namespace속성값과 연결해서 사용한다
	 			 
	 * parameterType속성 ==> 작성된 SQL문에 사용될 데이터가 저장된 객체를 기술한다
	 	(보통 VO클래스, Java의 기본 자료형이름, Map객체등이 사용된다)
	 	(이 속성에 객체를 기술할 때는 해당 클래스의 전체 이름을 기술해야 한다.
	 	 그러나 <typeAlias>태그에 지정한 alias명이 있다면 해당 이름을 사용할 수도 있다)
	  -->
	 <insert id="insertLprod" parameterType="lprodVo"> <!-- kr.or.ddit.vo.lprodVO -->
	 	insert into lprod (lprod_id, lprod_gu, lprod_nm)
	 	values (#{lprod_id},#{lprod_gu},#{lprod_nm})
	 </insert>
	 
	 <update id="updateLprod" parameterType="lprodVo">
	 	update lprod set lprod_id=#{lprod_id}, lprod_nm=#{lprod_nm}
	 	where lprod_gu=#{lprod_gu}
	 </update>
	 
	 <!-- parameterType속성에 설정되는 값이 단일값이면 SQL문에 이 값을 나타내는 변수는
	 	특별히 이름이 정해지지않는다 (즉, 사용자 임의로 지정할 수 있다) -->
	 <delete id="deleteLprod" parameterType="string"> <!-- 대문자 소문자 다 가능 -->
	 	delete from lprod
	 	where lprod_gu=#{lprod_gu}<!-- 아무 이름도 가능하지만 보통 칼럼명 이름과 동일하게 작성 -->
	 </delete>
	 
	 <!-- 
	 * resultType속성 ==> select문을 처리한 결과를 저장할 VO클래스나 Java의 기본 자료형 이름,
	 					Map객체등을 지정할 수 있다
	 					select문을 처리할 결과가 여러개의 레코드이면 java소스에서 'selectList()'
	 					메서드를 이용해서 호출한다 그러면 검색된 데이터들을 자동으로 List에 담아서 반환한다
	 					그래서 이 resultType속성에는 검색할 결과가 여러 개일 경우에도 1개의 레코드가
	 					저장될 클래스나 자료형 이름을 지정하면 된다
	  -->
	 <select id="getAllLprod" resultType="lprodVo">
	 	select * from lprod
	 </select>
	 
	 <select id="getLprod" resultType="lprodVo" parameterType="int">
	 	select * from lprod where lprod_id=${lprod_id}
	 </select>
</mapper>

LprodMybatisTest.java

package kr.or.ddit.basic;

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

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 kr.or.ddit.vo.LprodVO;

public class LprodMybatisTest {
	// myBatis를 이용하여 DB자료를 처리하는 순서 및 방법
	public static void main(String[] args) {
		Scanner scan = new Scanner(System.in);

		// 1. myBatis의 환경 설정 파일(mybatis-config.xml)을 읽어와서 처리한 후
		// myBatis를 사용할 수 있는 객체를 생성하는 SqlSessionFactory객체를 생성한다.

		InputStream in = null;
		SqlSessionFactory sqlSessionFactory = null;

		try {
			// 1-1 환경설정 파일을 읽어 올 스트림 객체를 생성한다
			in = Resources.getResourceAsStream("kr/or/ddit/mybatis/config/mybatis-config.xml");

			// 1-2 환경설정 파일을 읽어와 처리하고 환경설정이 완료되면
			// sqlSessionFactory객체가 생성된다.
			sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
		} catch (Exception e) {
			// TODO: handle exception
			System.out.println("myBatis 초기화 실패!!");
			e.printStackTrace();
		} finally {
			if (in != null)
				try {
					in.close();
				} catch (IOException e) {
				}
		}

		// 2. mapper에 등록된 SQL문들 중 실행할 SQL문을 호출해서 실행하여 원하는 작업 수행

		// 2-1. insert 연습
//		System.out.println("insert 작업 시작");
//		
//		System.out.print("Lprod_id >> ");
//		int lprod_id = scan.nextInt();
//
//		System.out.print("Lprod_gu >> ");
//		String lprod_gu = scan.next();
//		
//		System.out.print("Lprod_nm >> ");
//		String lprod_nm = scan.next();

//		// 2-2 update 연습
//		System.out.println("update 작업 시작");
//		System.out.print("수정할 Lprod_gu >> ");
//		String lprod_gu = scan.next();
//
//		System.out.print("새로운 Lprod_id >> ");
//		int lprod_id = scan.nextInt();
//		
//		System.out.print("새로운 Lprod_nm >> ");
//		String lprod_nm = scan.next();

		// 2-3 delete 연습
//		System.out.println("delete 작업 시작");
//		System.out.print("삭제할 Lprod_gu >> ");
//		String lprod_gu = scan.next();

		// 2-4 select 연습
//		System.out.println("select 작업시작");

		// 2-5 select 단일행
		System.out.println("select 작업시작 (결과 1개)");
		System.out.print("검색할 Lprod_id >> ");
		int lprod_id = scan.nextInt();

		// 1) 입력받은 자료를 VO에 저장한다
//		LprodVO lvo = new LprodVO();
//		lvo.setLprod_gu(lprod_gu);
//		lvo.setLprod_id(lprod_id);
//		lvo.setLprod_nm(lprod_nm);

		SqlSession session = null; // 실제 SQL문을 처리하는 객체 변수 선언
		try {
			// 2) SqlSessionFactory객체의 openSession()메서드를 이용하여
			// SQL문을 호출해서 실행할 수 있는 SqlSession객체를 생성한다
			// 형식 ) SqlSessionFactory객체.openSession(논리값);
			// '논리값'이 true이면 AutoCommit이 활성화된 상태이고,
			// '논리값'이 생략되거나 false이면 AutoCommit 비활성화된 상태
			session = sqlSessionFactory.openSession();

			// 3) SqlSession객체를 이용하여 처리할 SQL문을 호출하여 실행
			// 형식) SqlSession객체.insert("namespace속성값.id속성값",파라미터)
			// 반환값 : 작업에 성공한 레코드 수

			// insert, update, delete의 경우
//			int insertCnt = session.insert("lprod.insertLprod", lvo);
//			int updateCnt = session.update("lprod.updateLprod", lvo);
//			int deleteCnt = session.delete("lprod.deleteLprod", lprod_gu);

//			if(insertCnt>0) {
//			if(updateCnt>0) {
//			if(deleteCnt>0) {
//				// 4) SqlSession객체를 생성할 때 AutoCommit이 비활성화된 상태에서는
//				// 		commit작업을 직접 실행해야한다.
//				session.commit();
//				System.out.println("작업 성공");
//			} else {
//				System.out.println("작업실패");
//			}

			// select실행 결과가 여러 개의 레코드 인경우
//			List<LprodVO> list = session.selectList("lprod.getAllLprod"); 
//			for(LprodVO vo : list) {
//				System.out.println(vo);
//			}

			// select실행 결과가 한 개의 레코드인 경우
			// 형식 ) SqlSession객체.selectOne("namespace속성값.id속성값", 파라미터)
			// 반환값 : mapper의 resultType에 지정한 자료형이 반환된다
			LprodVO vo = session.selectOne("lprod.getLprod", lprod_id);

			if (vo == null) {
				System.out.println("검색결과가 없습니다");
			} else {
				System.out.println(vo);
			}
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
		} finally {
			// 5) 작업이 끝나면 SqlSession객체를 닫아준다
			session.close();
		}
	}
}