back-end/기타

(MyBatis)MVC2패턴- 게시판

doheun 2023. 3. 24. 15:16
반응형

MyBatis

MyBatis는 개발자가 관계형 데이터베이스와 더 쉽게 상호작용할 수 있도록 도와주는 객체-관계형 매핑(ORM) 솔루션을 제공하는 Java 기반 데이터 매핑 프레임워크

  • XML 또는 주석을 사용하여 Java 개체를 SQL 문에 매핑하고 사용자 지정 SQL 쿼리를 쉽게 작성하고 실행가능
  • 트랜잭션, 캐싱 및 동적 SQL 생성을 지원하므로 Java 애플리케이션에서 데이터베이스 작업을 위한 도구

기존

1단계~6단계 모두 구현

  1. 드라이버 로딩
  2. DB연결
  3. Dto.id=DB.id dto.getId(rs.getString(2)) dto.getName(rs.getString(3))
  4. 쿼리준비
  5. 쿼리실행
  6. 쿼리결과받기
  7. DB닫기

MyBatis

작업지시서 (환경설정)

  • configuration.xml : 전체적인 작업 메뉴얼
  • sqlMapper.xml : SQL쿼리작성
  • DB.properties : driver,url,user,password
  • 작업자 생성(SqlMapConfig.java)
    • sqlSessionFactory 객체 구해주는 작업
    • sqlSession 객체 (insert(),selectList(),selectOne(),update(),delete()

DAO가 간단해짐 -> 처음부터 구조를 설계하고 시작

reader Resource -> configuration.xml을 읽는 resource 생성

Exploring Mapped SQL Statements

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.mybatis.example.BlogMapper">
  <select id="selectBlog" resultType="Blog">
    select * from Blog where id = #{id}
  </select>
</mapper>

select태그
id: 태그의 이름
resultType : 결과를 담을 타입

Blog blog = session.selectOne(
  "org.mybatis.example.BlogMapper.selectBlog", 101);

101 : 전달 파라미터
#{id}에 101전달

mybatis라이브러리

com.hk.config - SqlMapConfig
configuraion.xml을 읽는 reader를 Resources.getResourceAsReader를 통해 얻고
factoryBuilder로 부터 reader를 build하는 객체생성

sql패키지(3),config패지키는 다른 프로젝트를 할 때도 재사용

Dao에서 namespace private 멤버필드 생생 -> namespace + queryId를 사용하기 위해
sqlMapconfig상속받아 사용하려는 메서드에 sqlSessionFactory로부터 sqlSession객체를 구해서 쿼리실행

sql쿼리 BoardMapper.xml에 따로 저장

Dao반복

SqlSession sqlSession=null;
//1.sqlSessionFactory객체 구해야 됨 -> SqlSession객체를 쓸 수 있다
    SqlSessionFactory sqlSessionFactory=getSqlSessionFactory();
//2.sqlSession객체 구하기
    sqlSession=sqlSessionFactory.openSession();//autocommit =true로 설정

--->
SqlSession sqlSession=null;
sqlSession=getSqlSessionFactory().openSession(true);

글여러개 삭제 처리는 아래와 같은 형태로 IN을 사용

  • SqlMapper에서 제공하는 foreach사용
  • 배열을 map에 담아서 전달
       <delete id="mulDel" parameterType="Map" >
           DELETE FROM HKBOARD WHERE SEQ IN 
           <foreach collection="seqs" item="seq" separator="," open="(" close=")">
               #{seq}
           </foreach>
       </delete>

Building SqlSessionFactory from XML

String resource = "org/mybatis/example/mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory =
  new SqlSessionFactoryBuilder().build(inputStream);
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
  PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
  "https://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!--     DB접속정보 파일의 경로 설정 -->
  <properties resource="sql/db.properties"/>
<!--   dto객체의 변수설정 -->
  <typeAliases>
      <typeAlias type="com.hk.dtos.HkDto" alias="hkDto"/>
  </typeAliases>
  <environments default="development">
    <environment id="development">
      <transactionManager type="JDBC"/>
      <dataSource type="POOLED">
        <property name="driver" value="${driver}"/>
        <property name="url" value="${url}"/>
        <property name="username" value="${username}"/>
        <property name="password" value="${password}"/>
      </dataSource>
    </environment>
  </environments>
  <mappers>
    <mapper resource="sql/BoardMapper.xml"/>
  </mappers>
</configuration>
  • 이때 property로 들어가는 value값(EL태그)은 db.properties파일안의 변수명과 일치해야한다
  • 가독성을 위해서 typeAliases를 사용하는 것이 좋음

MyBatis실습

DB를 관리하는 프레임워크기 때문에 기존의 실습파일의 DAO쪽만 바꿔주면된다
자바소스관리 폴더에
sql패키지-db.properties
sql패키지-other-xml File-BoardMapper.xml
myBatis Building SqlSessionFactory from XML에서 불러오기
DB접속정보 파일의 경로 설정

  • Configuration.xml에서 관련 부분 불러오기 - configuration하위 properties에 sql/db.properties추가
    dto객체의 변수설정
  • typeAliases사용
    쿼리가 작성되어 있는 mapper.xml의 경로설정
  • mapper를 통해 resourse 경로 설정

SqlMapConfig.java(환경세팅)

package com.hk.config;

import java.io.IOException;
import java.io.Reader;

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

public class SqlMapConfig {
    //작업을 하기 위한 객체를 선언
    private SqlSessionFactory sqlSessionFactory;

    //작업을 하기 위한 객체를 구하는 메서드
    public SqlSessionFactory getSqlSessionFactory() {
        //환경설정 내용이 작성되어 있는 파일의 경로 설정
        String resource="sql/Configuration.xml";

        try {
            //Reader: 작업매뉴얼 , Resources : 작업메뉴얼을 만드는 객체
            Reader reader=Resources.getResourceAsReader(resource);
            sqlSessionFactory=new SqlSessionFactoryBuilder().build(reader);
            reader.close();

        } catch (IOException e) {
            e.printStackTrace();
        }
        return sqlSessionFactory;
    }
}

HkDao.java

글목록조회
public List<HkDto> getAllList(){
        List<HkDto> list=new ArrayList<>();    
        SqlSession sqlSession=null;
        try {
            //1.sqlSessionFactory객체 구해야 됨 -> SqlSession객체를 쓸 수 있다
            SqlSessionFactory sqlSessionFactory=getSqlSessionFactory();
            //2.sqlSession객체 구하기
            sqlSession=sqlSessionFactory.openSession();//autocommit =true로 설정
            //3.쿼리실행
            list=sqlSession.selectList(namespace+"getAllList");
        } catch (Exception e) {

            e.printStackTrace();
        }finally {
            sqlSession.close();
        }
        return list;
    }
글상세조회
public HkDto getBoard(int seq){
        HkDto dto=new HkDto();//row하나를 담을 객체

        SqlSession sqlSession=null;

        try {
            sqlSession=getSqlSessionFactory().openSession(true);
            dto=sqlSession.selectOne(namespace+"getBoard",seq);

        } catch (Exception e) {
            System.out.println("JDBC실패:해당클래스는 "+getClass());
            e.printStackTrace();
        } finally {

        }
        return dto;
    }
글추가
public boolean insertBoard(HkDto dto) {
        int count=0;
        SqlSession sqlSession=null;

        try {
            sqlSession=getSqlSessionFactory().openSession(true);
            count=sqlSession.insert(namespace+"insertBoard",dto);
        } catch (Exception e) {
            System.out.println("JDBC실패:해당클래스는 "+getClass());
            e.printStackTrace();
        }finally {

        }

        return count>0?true:false;//삼항연산자
    }
글수정
public boolean updateBoard(int seq, String title , String content) {
        int count=0;

        SqlSession sqlSession=null;
        Map<String,Object>map=new HashMap<>();
        map.put("seq", seq);
        map.put("title", title);
        map.put("content", content);

        try {
            sqlSession=getSqlSessionFactory().openSession(true);
            count=sqlSession.update(namespace+"updateBoard",map);
        } catch (Exception e) {
            System.out.println("JDBC실패:updateBoard():"+getClass());
            e.printStackTrace();
        }finally {
            //기본타입 : 0 , 0.0  , 참조타입: null

        }
        return count>0?true:false;
    }
글삭제
public boolean delBoard(String seq) {
        int count=0;
        SqlSession sqlSession=null;


        try {
            sqlSession=getSqlSessionFactory().openSession(true);
            count=sqlSession.delete(namespace+"delBoard",seq);
        } catch (Exception e) {
            System.out.println("JDBC실패:delBoard():"+getClass());
            e.printStackTrace();
        }finally {

        }
        return count>0?true:false;
    }
글여러개삭제

BoardMapper.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="com.hk.board">
     <select id="getAllList" resultType="hkDto">
         SELECT SEQ, ID, TITLE, CONTENT, REGDATE FROM HKBOARD 
        ORDER BY REGDATE DESC
     </select>
     <select id="getBoard" parameterType="int" resultType="hkDto">
         SELECT SEQ, ID, TITLE, CONTENT, REGDATE 
        FROM HKBOARD WHERE SEQ=#{seq}    
     </select>
     <insert id="insertBoard" parameterType="hkDto">
         INSERT INTO HKBOARD VALUES(null,#{id},#{title},#{content},SYSDATE())
     </insert>
     <update id="updateBoard" parameterType="Map">
         UPDATE HKBOARD SET TITLE=#{title}, CONTENT=#{content},REGDATE=SYSDATE() 
         WHERE SEQ=#{seq}
     </update>
     <delete id="delBoard" parameterType="String" >
         DELETE FROM HKBOARD WHERE SEQ=#{seq}
     </delete>
 </mapper>
  • mapper는 파일의 위치를 나타내기 떄문에 정의를 미리 해두는 게 편함
  • #{}괄호내부에 들어가는 것은 자바쪽에서 파라미터로 전달해준값을 의미

기타참고

  1. Dao에서 sql쿼리문에 값을 전달할때 두개 이상이면 Map객체를 생성해야한다
    SqlSession객체에서 제공하는 메서드
  • selectList("namespace"+DAO메서드",param): param(Map, DTO,int/string ) 값한개
  • selectList("namespace"+DAO메서드",Map): 값여러개 한번에 보내기
    BoardMapper.xml
    param받을 때 #{id} , 이때 id라는 이름은 Map의 저장된 값의 key와 동일
  1. 동적 쿼리 (map에 담아서 전달)

  2. 자주쓰는 sql문 (BoardMapper.xml)

     <sql id="isSeq">
          WHERE SEQ=#{seq}
      </sql>
      <delete id="delBoard" parameterType="int" >
          DELETE FROM HKBOARD <include refid="isSeq"></include>
      </delete>
반응형

'back-end > 기타' 카테고리의 다른 글

(Python) 웹 크롤링  (0) 2023.05.02