ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 학원 day84. 스프링 데이터베이스 엑세스, Mybatis
    기록 2023. 1. 2. 12:52

    메이븐 프로젝트 만들기

    project - Maven - Maven Project - Create a simple project 체크 

    pom.xml, logback.xml 복붙

    오른쪽버튼 Maven - update Project 클릭 

     

    스프링과 데이터베이스 엑세스

       - 스프링의 데이터베이스 엑세스 작업은 jdbc 연동, ibatis/mybatis 연동, JPA/hibernate 연동 등

          다양한 데이터베이스 엑세스 기술과 연동해서 데이터베이스 엑세스 작업을 구현할 수 있다. 

       - 스프링의 데이터베이스 엑세스 작업 특징

              * 다양한 데이터베이스 엑세스 라이브러리와의 연동을 지원한다. 

                ( jdbc , ibatis/mybatis, JPA/hibernate 등)

              * 일관된 데이터베이스 엑세스 예외처리를 지원한다.

                (기술 종류에 상관없이 동일한 Exception이 발생한다.) 

                  - 모든 데이터베이스 엑세스 오류에 대해서 DataAccessException이라는 예외를 발생시킨다.

                  - DataAccessException 클래스는 RuntimeException의 하위 클래스여서 예외처리를 강제하지 않는다. 

                  - 데이터베이스의 종류와 상관없이 오류 상황에 맞는 적절한 예외 객체를 발생시킨다. 

                (데이터베이스 종류마다 다른 이름의 오류를 발생시킨다. sql-error-codes.xml에 다양한 오류코드를 정의해놓았다.)

                  - 예외 클래스의 이름도 예외상황에 맞는 이름이기 때문에 오류 상황을 더 쉽게 파악할 수 있다. 

             * 데이터베이스와 연결을 유지하는 Connection객체는 Connection Pool을 이용해서 획득하고, 사용 후 반납한다.

                  - Connection Pool은 데이터베이스와 연결을 유지하는 Connection 객체를 관리하는 객체다. 

                  - Connection Pool 객체를 스프링 컨테이너가 생성하게 하거나, 생성된 Connection Pool을 스프링 컨테이너에 등록한다.

    Connection연결을 하면 데이터베이스 내에서 DB 엑세스 작업을 지원하는 프로세스를 생성한다. 데이터베이스 엑세스 작업이 완료되면 프로세스도 제거된다.

    데이터베이스 입장에서 프로세스를 생성하고 제거하는 일은 부하가 큰 작업이다. 

    그래서 Connection Pool을 사용한다. 

    Connection들이 미리 여러개 만들어져 있는 Connection Pool을 사용하는 것이다.

    스프링 컨테이너에 bean태그로 객체를 생성한다. 

    Connection Pool객체를 만들어서 그 안에 미리 Connection들을 여러개 만들어 둔다. 

    미리 만들어둔 Connection들은 데이터베이스와 연결되어 있다. 

    그럼 데이터베이스 안에 프로세서가 만들어져 있다.

    DAO객체에서 다양한 기술들을 이용해서 DB 엑세스를 할 것이다.

    데이터베이스에 SQL을 전송하기 위해 Connection을 이용한다. 

     

    질문.

    Q. 데이터베이스 연결해제할 때 미리 만들어둔 Connection과 프로세서는 연결이 끊어지지 않는건가?

    A. 안끊어진다. 서버 꺼질 때까지. 

     

    Q, 커넥션은 언제 데이터베이스와 연결되는거지?

    A. 커넥션은 일반적으로 JDBC 드라이버를 사용하여 데이터베이스와 연결됩니다. 
    JDBC DriverManager 클래스의 getConnection() 메소드를 호출하여 데이터베이스와 연결하는 것이 일반적인 방법입니다. 이 메소드는 Connection 객체를 리턴하며, 이 객체를 사용하여 데이터베이스와의 통신을 수행할 수 있습니다.
    getConnection() 메소드는 데이터베이스 URL, 사용자 이름, 암호 등의 정보를 인자로 받습니다. 이 정보들은 데이터베이스와 실제로 연결할 때 사용됩니다. 
    따라서, 애플리케이션이 데이터베이스와 연결하려면, JDBC 드라이버를 로드하고, DriverManager.getConnection() 메소드를 호출하여 Connection 객체를 얻어와야 합니다. 이렇게 얻어온 Connection 객체를 사용하여 데이터베이스와 통신할 수 있습니다. (출처 : OPEN AI)

     

    * 선언적 트랜잭션 처리를 지원한다. 

       - 프로그램 코딩없이 간단한 설정만으로 트랜잭션처리 기능을 지원받을 수 없다. 

    --------------------------------------------------------------------------------------------------------------------------------------------------------------

    Spring-jdbc 연동하기

           * spring-jdbc는 데이터베이스 엑세스를 지원하는 JdbcTemplate 객체를 제공한다.

           * jdbcTemplate는 spring-jdbc의 핵심 객체다. 

           * jdbcTeplate는 Insert,Update,Delete,Select를 실행하는 메소드를 제공한다. 

           * 사용자정의 Dao 클래스는 jdbcTemplate객체를 의존성 주입받아서 데이터베이스 엑세스 작업을 수행한다. 

         1. 필요한 라이브러리 의존성 추가

                * jdbc 드라이버 라이브러리 의존성 추가

                * spring-jdbc 라이브러리 의존성 추가

        2. 스프링 빈 설정 파일에 Connection Pool 객체를 스프링 컨테이너에 등록하기 

    DriverManagerDataSource는 우리가 어떤 데이터베이스를 쓰는지 모르니까 어떤 계정이 있는지 모르니까 우리가 주입해줘야 한다. 따로 properties파일로 만들어둔다. setter메소드가 미리 만들어져 있다.

       3. spring-jdbc 라이브러리가 지원하는 JdbcTemplate 객체를 스프링 컨테이너에 등록하기

    update는 insert, update, delete 작업을 수행

    queryForObject, queryForList는 select 작업을 수행

    내가 만든 클래스들은 자동 의존성 주입, 스프링이 제공해주는 것들은 우리가 뭘해주는지 모르니까 수동 의존성 주입을 해준다. 

    DB엑세스 작업과 핵심 업무로직을 분리해놓았다. 

     

    4. DAO 클래스와 Service 클래스를 스캔해서 스프링 컨테이너가 객체를 생성하고, 의존하는 객체를 자동 의존성 주입시키기

    <context:annotation-config />
    <context:component-scan base-package="com.sample" />

     

    5. 데이터베이스 엑세스 작업을 구현하는 DAO에 JdbcTemplate 객체를 의존성 주입받을 수 있도록 구현하기

    @Repository
    public class UserDao {
           @Autowired
            private JdbcTemplate template;
    }

     

    6. 핵심 업무로직을 구현하는 Service에 DAO객체를 의존성 주입받을 수 있도록 구현하기

    @Service
    public class UserService {
         @Autowired
         private UserDao userDao;
    }

     

    초기 설정이 많은데, 초기 설정부담을 줄여주는게 스프링부트이다.

    아래 연결관계를 잘 기억하자!!

     

    mybatis

    - SQL Mapping Framework다.

        * SQL Mapping Framework는 

                SQL 실행에 필요한 정보를 포함하고 있는 객체

                SQL 실행 결과를 저장하는 객체를

                SQL과 매핑하면 해당 SQL를 실행시키고, 결과값을 반환하는 프레임워크다. 

    - ibatis의 후속 버전이다. 

          * ibatis와 많은 부분이 유사하다.  

    - mybatis의 주요 구성요소 (Mapper인터페이스, Mapper파일, Mapper인스턴스)

          Mapper 인터페이스

                  * 데이터베이스 엑세스 작업이 정의된 인터페이스다. (테이블당 하나씩 정의한다.) 

                  * 개발자가 작성한다. 

                  * 인터페이스의 구현체는 mybatis가 자동으로 만들어준다. 

                  * 예시 

          Mapper 파일

                * SQL과 객체 매핑 정보가 정의된 XML 파일이다.

                * Mapper 인터페이스의 전체이름을 namespace로 설정한다. (어떤 Mapper인터페이스와 관련있는지를 식별한다.)

                 ( 인터페이스 클래스명을 드래그하고 오른쪽버튼 Copy Qualified Name을 클릭하여 복사한다.)

                * 개발자가 작성한다.

                * id는 반드시 Mapper인터페이스 메소드명과 같아야 한다.

    * ibatis와 mybatis

        - parameterClass -> parameterType, resultClass -> resultType으로 변경되었다.

        - #파라미터명#  ->  #{파라미터명}로 변경되었다.

        - dynamic 쿼리에서 <if>, <choose> ~ <when> ~ <otherwise>, <foreach> 태그를 사용해서 조건식처리, 반복처리가 가능해졌다. 

        - dynamic 쿼리에서 <where>, <set> 태그를 사용해서 불필요한 and와 ,를 제거할 수 있게 되었다.   

    더보기

    mybatis 매퍼파일의 <where> 태그

    ==================================================================
    = <where> 태그를 사용하지 않는 경우
    ==================================================================
    select
    *
    from 
    web_products
    where
    <if test="deleted != null">
    product_deleted = #{deleted}
    </if>
    <if test="minPrice > 0">
    and product_price >= #{minPrice}
    </if>
    <if test="maxPrice > 0">
    and product_price <= #{maxPrice}
    </if>
    <if test="categoryNo != null">
    and product_category_no = #{categoryNo}
    </if>


    --------------------------------------------------------
    Map<String, Object> param = new HashMap<>();
    param.put("deleted", 'N');
    param.put("minPrice", 10000);

    select
    *
    from 
    web_products
    where
    product_deleted = #{deleted}
    and product_price >= #{minPrice}
    --------------------------------------------------------
    Map<String, Object> param = new HashMap<>();

    select
    *
    from 
    web_products
    where   -- 문법 오류가 발생한다.
    --------------------------------------------------------
    Map<String, Object> param = new HashMap<>();
    param.put("minPrice", 10000);
    param.put("maxPrice", 50000);

    select
    *
    from 
    web_products
    where
    and product_price >= #{minPrice} -- 문법 오류가 발생한다.
    and product_price <= #{maxPrice}
    --------------------------------------------------------


    ==================================================================
    = <where> 태그를 사용하는 경우
    ==================================================================
    select
    *
    from 
    web_products
    <where>
    <if test="deleted != null">
    product_deleted = #{deleted}
    </if>
    <if test="minPrice > 0">
    and product_price >= #{minPrice}
    </if>
    <if test="maxPrice > 0">
    and product_price <= #{maxPrice}
    </if>
    <if test="categoryNo != null">
    and product_category_no = #{categoryNo}
    </if>
    </where>

    --------------------------------------------------------
    Map<String, Object> param = new HashMap<>();
    param.put("deleted", 'N');
    param.put("minPrice", 10000);

    select
    *
    from 
    web_products
    where
    product_deleted = #{deleted}
    and product_price >= #{minPrice}

    * <where>과 </where>사이에 동적으로 추가되는 조건이 하나라도 있으면
       where 키워드가 추가된다.
    --------------------------------------------------------
    Map<String, Object> param = new HashMap<>();

    select
    *
    from 
    web_products

    * <where>과 </where>사이에 동적으로 추가되는 조건이 하나도 없으면 
       where 키워드는 추가되지 않는다.
    --------------------------------------------------------
    Map<String, Object> param = new HashMap<>();
    param.put("minPrice", 10000);
    param.put("maxPrice", 50000);

    select
    *
    from 
    web_products
    where
    product_price >= #{minPrice}
    and product_price <= #{maxPrice}

    * <where>과 </where>사이에 동적으로 추가되는 조건이 있고,
       첫번째 조건에 and 키워드가 있으면, and를 제거한다.
    --------------------------------------------------------------------------------------------------------------------------------

     

      Mapper 인스턴스

               * Mapper 인터페이스를 구현한 객체다.

               * 개발자가 구현하지 않는다.

               * mybatis와 mybatis-spring 라이브러리에서 Mapper인터페이스를 구현한 객체를 자동으로 생성하고, 스프링 컨테이너의 빈으로 등록시킨다.


    파이널 프로젝트 주제 정하기

     

    댓글

Designed by Tistory.