ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 학원 day36. ibatis
    기록 2022. 10. 26. 12:57

    => 메소드 작성할 때 select(조회) 빼고 insert, update, delete는 모두 void로 메소드 반환타입을 작성한다. (반환값 없음)

    select는 데이터를 가져와야 하기 때문에 void가 아니다.

    조회하는 작업에서는 객체 하나인지 여러개를 반환하는지 확인해야 한다. (primary key, Unique 외에는 여러 개가 나올 수 있다.)

    입력과 출력정보가 파악이 되면 메소드를 만들 수 있다.

     

    SERVICE 클래스

    업무로직이 구현되는 클래스

    메소드 - 요구사항 하나와 대응

        * 대체로 요구사항 하나마다 업무로직 메소드 하나가 필요하다.

        * 업무로직을 구현하기 위해서는 대체로 1번 이상의 데이터베이스 엑세스 작업이 필요하다.

        * 업무로직을 구현하기 위해서 DAO객체의 메소드를 1번 이상 호출하게 된다.

     

    DAO 클래스 

    데이터베이스 엑세스 작업이 구현되는 클래스 (sql을 데이터베이스에 보내는 역할을 담당)

    데이터베이스에 대한 CRUD작업을 실행하는 메소드들이 작성되어있다.

    메소드 - SQL 하나와 대응

      * SQL문 하나마다 메소드 하나가 필요하다.

      * CRUD 작업을 구현한다.

    - CRUD 작업

      Create : Insertvoid

      Read : Select문 기본자료형, 객체, List<객체>

      Update : Updatevoid

      Delete : Deletevoid

     

    UserService.java의 주요 메소드
    // 회원가입
    * 입력정보
    사용자아이디, 비밀번호, 이름, 이메일, 전화번호, 성별 
    * 출력정보
    회원가입 성공/실패 여부 출력
    public void registerUser(User user) {
    1. 아이디로 회원정보 조회 - 있으면 예외발생 select * from sample_users where user_id = ?
    2. 이메일로 회원정보 조회  - 있으면 예외발생 select * from sample_users where user_email = ?
    3. 회원정보 저장하기 insert into sample_users (user_id, user_pasword, user_name, user_email, user_tel, user_gender) values (?,?,?,?,?,?)
    }

    -> sql을 register메소드에 작성해놓으면 다른 곳에서 재사용할 수 없다.

    sql을 실행하는 작업을 별도의 클래스(DAO) 안에 별도의 메소드로 만들어 놓는다. 


    // 내 정보 보기
    * 입력정보
    사용자아이디, 비밀번호
    * 출력정보
    사용자 상세정보를 출력 (controller에서 출력기능 담당)
    public User getUserInfo(String id, String password) {
    1. 아이디로 회원정보 조회 select * from sample_users where user_id = ?
    2. 비밀번호가 일치하지 않으면 - 예외발생
    3. 회원정보 제공
    }

    // 내 정보 수정(비밀번호 변경)
    * 입력정보
    사용자아이디, 비밀번호, 새 비밀번호
    * 출력정보
    정보수정 성공/실패 여부 출력
    public void updateUserInfo(String id, String oldPassword, String password) {
    1. 아이디로 회원정보 조회 select * from sample_users where user_id = ?
    2. 비밀번호가 일치하지 않으면 - 예외발생
    3. 회원정보의 비밀번호 변경 update sample_users set user_password = ? where user_id = ?
    }

    // 회원 탈퇴
    * 입력정보
    사용자아이디, 비밀번호
    * 출력정보
    회원탈퇴 성공/실패 여부 출력
    public void disabledUser(String id, String password) {
    1. 아이디로 회원정보 조회 select * from sample_users where user_id = ?
    2. 비밀번호가 일치하지 않으면 - 예외발생
    3. 회원정보의 enabled를 'N'으로 변경 update sample_users set user_enabled = 'N' where user_id = ?
    }

    UserDao.java의 주요 메소드

    select * from sample_users where user_id = ?
    * 입력 - 사용자 아이디
    * 출력 - 사용자정보 하나
    public User getUserById(String id) {

    }

    select * from sample_users where user_email = ?'
    * 입력 - 사용자 이메일
    * 출력 - 사용자정보 하나
    public User getUserByEmail(String email) {

    }

    insert into sample_users (user_id, user_pasword, user_name, user_email, user_tel, user_gender) values (?,?,?,?,?,?)
    * 입력 - 사용자정보
    * 출력 - 없음
    public void insertUser(User user) {

    }

    update sample_users set user_password = ? where user_id = ?
    * 입력 - 사용자 아이디, 비밀번호
    * 출력 - 없음
    public void updateUserPassword(String id, String password) {

    }

    update sample_users set user_enabled = 'N' where user_id = ?
    * 입력 - 사용자 아이디
    * 출력 - 없음
    public void updateUserEnabled(String id) {

    }

     

    => SELECT인 경우에만 반환타입(객체 하나가 반환되는 타입(primary key, Unique), 객체가 여러개 반환되는 타입)을 생각하면 된다.


    ibatis

    - SQL Mapper Framework

    - SQL과 객체를 매핑시켜서 데이터베이스 엑세스 작업을 수행하는 라이브러리다.

    - parameterClass : 쿼리실행에 필요한 값을 갖고있는, 전해줄 수 있는 객체

    - resultClass : 쿼리 실행 결과 값을 담고 있는 클래스

     

    Product라는 객체 안에 쿼리문을 담아서 전해줄테니까 안에서 꺼내서 실행하라고 ibatis에게 알려줌

    쿼리실행에 필요한 정보는 어떤 객체에 담아서 ibatis라는 라이브러리에게 전달해줄 것인지 결정해야 함.

    값이 여러개 일때는 객체나 Map이랑 매핑된다.

    값이 한개일 때는 기본자료형타입에 해당하는 Integer, long, double, String이랑 매핑된다.

     

    ibatis에게 전달해주는 방법

    => ibatis는 sql과 객체를 매핑하는 작업을 insert라는 태그를 만들어서 자기가 전달받은 Product라는 객체에서 name이라는 변수안에 들어있는 값을 #name#에 넣고, maker라는 변수에 들어있는 값을 #maker#에 넣고 쿼리를 실행한다.

    우리가 해야할 건 객체와 쿼리를 매핑하는 것이다.

     

    ibatis 프레임워크와 프로젝트 연동하기


    1. ibatis와 오라클 드라이버를 클래스패스에 추가한다
    - ibatis-sqlmap-2.3.4.726.jar 파일(ibatis라이브러리 파일)을 클래스패스에 추가한다.
    - ojdbc11.jar 파일(JDBC 드라이버 파일)을 클래스패스에 추가한다.

    2. ibatis용 환경설정파일과 mapper 파일을 저장하는 소스폴더를 추가한다.
    - 프로젝트에 resources 소스폴더를 추가한다.
    - resources소스폴더 하위에 META-INF 폴더를 추가한다.
    - META-INF 폴더 하위에 ibatis 폴더를 추가한다.

    3. ibatis 환경설정파일 추가하기
    - resources/META-INF/ibatis 폴더에 ibatis-config.xml 파일을 추가한다.

    4. ibatis-config.xml에 데이터베이스 연결정보 설정
    <transactionManager type="JDBC">
    <dataSource type="SIMPLE">
    <property name="JDBC.Driver" value="oracle.jdbc.OracleDriver" />
    <property name="JDBC.ConnectionURL" value="jdbc:oracle:thin:@localhost:1521:xe" />
    <property name="JDBC.Username" value="hr" />
    <property name="JDBC.Password" value="zxcv1234" />
    </dataSource>
    </transactionManager>

    * JDBC.Driver : 오라클 JDBC 드라이버의 패키지 경로 및 클래스명
    * JDBC.ConnectionURL : jdbc URL
    * JDBC.Username : 데이터베이스 사용자 계정명
    * JDBC.Password : 데이터베이스 사용자 비밀번호

    5. ibatis mapper  파일 등록
    - resources/META-INF/ibatis/mappers 폴더에 users.xml 파일을 추가한다.

    6. ibatis-config.xml에 users.xml  등록
    <sqlMap resource="META-INF/ibatis/mappers/users.xml" />

    나중에는 proudct, carts도 등록할 것임.

    7. ibatis 헬프 클래스 등록
    - com.sample.util 패키지 생성
    - SqlMapper.java 클래스를 추가한다.

    users.xml, products.xml 등을 ibatis-config.xml설정파일에 등록시킨다.

    xml이 정의되어 있는 파일을 Mapper파일이라고 부른다. (users.xml, products.xml 등) 

    ibatis에게 ibatis-config.xml설정파일을 읽어가라고 sqlMapper.java에 정의되어 있다. 

    sqlMapClientBuilder가 ibatis 실행 엔진을 생성시킨다. 

    UserDao가 실행엔진에게 실행에 필요한 id와 값(객체)를 알려준다.

    UserDao의 insertUser가 sqlMapper의 String id로 대입되고, user가 Object param으로 대입된다.

    실행엔진은 자기한테 등록되어있는 xml 중에서 insertUser를 찾고 실행할 쿼리를 가져와서 실행한다.

    실행엔진 안에서는 connection을 연결하고 PreparedStatement를 생성하고 #변수명# 자리에 User객체에 저장된 값을 바인딩한다.

    그리고 sql을 데이터베이스에 전송하고 실행한다.

     

    +) sqlMapClient를 바로 가져다 써도 되지만 예외처리해야 되는 걸 던져서 sqlMapper를 만든 것임. 예외처리 안해도 되는 걸로 바꿈. 객체 생성안하고 쓸 수 있도록 static으로 만듦. 

     

    Dao에 users.xml에 작성해놓은 내가 실행할 쿼리의 아이디, 값을 전해줄 수 있는 메소드를 작성한다. 


    < users.xml >

    <!-- 사용자 정보 insert  -->
    <!-- 
       <insert />
                INSERT SQL 구문을 정의한다.
          id="insertUser"
                이 SQL구문을 식별하기 위한 아이디값을 지정한다.
          parameterClass="com.sample.vo.User"
                이 SQL구문 실행에 필요한 값을 포함하고 있는 객체의 타입을 지정한다.
                이 SQL구문 실행에 필요한 사용자정보는 User객체로 전달받는다
          #변수명#
                parameterClass로 지정한 객체의 변수명이다.
                해당 객체의 변수에 저장된 값이 #변수명#에 바인딩된다.
     -->

     

    <!-- 
      <delete />
               DELETE SQL 구문을 정의한다.
           id="deleteUser"
               이 SQL구문을 식별하기 위한 아이디값을 지정한다.
           parameterClass="string"
               이 SQL구문 실행에 필요한 값은 문자열타입의 값이다.
           #value#
               parameterClass의 타입이 VO객체나 Map객체가 아니고 문자열, 정수, 실수 일때 사용한다.
               #value# 위치에 해당 값이 바인딩된다.
               SQL 실행시 필요한 값이 오직 하나일 때 사용한다.
     -->

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE sqlMap PUBLIC "-//iBATIS.com//DTD SQL Map 2.0//EN" 
    	"http://ibatis.apache.org/dtd/sql-map-2.dtd">
     
    <sqlMap>
    	
    	<insert id="insertUser" parameterClass="com.sample.vo.User">
    		insert into sample_users
    		(user_id, user_password, user_name, user_email, user_tel, user_gender)
    		values
    		(#id#, #password#, #name#, #email#, #tel#, #gender#)
    	</insert>
    	
        
    	 <delete id="deleteUser" parameterClass="string">  <!-- ="string" 붙여써야 한다! string은 java.lang.String에 대한 별칭이다. -->
    		delete from sample_users
    		where user_id = #value#
    	 </delete>
         
    </sqlMap>

    * 위에 코드에서는 객체의 변수 안에 값이 들어있기 때문에 #변수명#으로 작성하고  아래의 코드에서는 String x = "happy"이라고 작성하는 것처럼 x자체가 "happy"이라는 값을 갖고 있다고 보고 #value# 라고 적는다.

     

    <!-- 
      <select />
             SELECT SQL 구문을 정의한다.
          id="getAllUsers"
              이 SQL구문을 식별하기 위한 아이디값을 지정한다.
          resultClass="com.sample.vo.User"
              이 SQL구문 실행 후 조회된 데이터를 저장할 객체의 클래스 타입을 지정한다.
               resultClass에서 지정하는 클래스 타입은 행 하나를 어느 객체에 담을 것인지 지정하는 것이다
              조회결과(ResultSet) 핸들링
              1. ibatis 엔진은 SQL 구문을 실행한 후, resultClass에 지정된 클래스로 객체를 생성한다.
              2. ibatis 엔진은 1번에서 생성한 객체에 값을 저장할 때, 컬럼명과 동일한 이름의 변수에 값을 저장한다.
                  * 컬럼명과 변수명이 서로 다르면 컬럼명을 변수이름과 같은 이름의 별칭으로 지정한다.

    *** SELECT 구문의 실행결과 여러 행이 획득되는 경우
        List SqlMapper.selectList(String id)
        List SqlMapper.selectList(String id, Object param)으로 이 SQL 구문을 실행한다.
        * List객체를 생성한 다음 조회된 행의 갯수만큼 resultClass에 지정된 객체를 생성해서 값을 담고, 그 객체를 List에 저장시키고, List를 반환한다.
        * 조회된 행이 하나도 없으면 길이가 0인 List객체가 반환된다.(결코 null이 반환되지 않는다.)

    *** SELECT 구문의 실행결과가 언제나 한 행만 획득되는 경우
        Object SqlMapper.selectOne(String id)
        Object SqlMapper.selectOne(String id, Object param)으로 이 SQL 구문을 실행한다.
        * resultClass에 지정된 객체를 생성해서 값을 담고, 그 객체를 반환한다.
        * 조회된 행이 하나도 없으면 null이 반환된다.
     -->

    	<select id="getAllUsers" resultClass="com.sample.vo.User">
    		 select user_id				as id,
    				user_password		as password,
    				user_name			as name,
    				user_email			as email,
    				user_tel			as tel,
    				user_gender			as gender,
    				user_point			as point,
    				user_enabled		as enabled,
    				user_created_date	as createdDate,
    				user_updated_date	as updatedDate
    		from sample_users
    		order by user_id asc
    	</select>
    	
    	<select id="getUserById" parameterClass="string" resultClass="com.sample.vo.User">
    		 select user_id				as id,
    				user_password		as password,
    				user_name			as name,
    				user_email			as email,
    				user_tel			as tel,
    				user_gender			as gender,
    				user_point			as point,
    				user_enabled		as enabled,
    				user_created_date	as createdDate,
    				user_updated_date	as updatedDate
    		from sample_users
    		where user_id = #value#
    	</select>
    </sqlMap>

    * insert, update, delete는 parameterClass가 있어야 한다.

    * select는 결과를 획득하게 된다. 이를 resultClass에 담는다.

    * ibatis는 resultClass에 명시되어 있는 객체를 생성하고, 컬럼이름과 똑같은 이름의 변수에 값을 담는다. 

       그런데, user_id라는 이름의 변수가 없어서 값이 안담긴다. 그래서 변수이름과 같은 이름의 별칭을 작성해준다.

    * resultClass 지정하는 클래스 타입은 행 하나를 어느 객체에 담을 것인지 지정하는 것이다. 여러행이 얻어진다고 List가 오면 안된다.

     

    => xml에서 작성한 쿼리를 실행할 메소드를 dao가서 만든다.

     

    < UserDao.java >

    package com.sample.dao;
    
    import java.util.List;
    
    import com.sample.util.SqlMapper;
    import com.sample.vo.User;
    
    public class UserDao {
    
    	public void insertUser(User user) {
    		SqlMapper.insert("insertUser", user);
    	}
    	
    	public void deleteUserById(String userId) {
    		SqlMapper.delete("deleteUser", userId);
    	}
    	
    	@SuppressWarnings("unchecked")
    	public List<User> getAllUsers() {
    		List<User> users = (List<User>) SqlMapper.selectList("getAllUsers");
    		return users;
    	}
    	
    	public User getUserById(String userId) {
    		User user = (User) SqlMapper.selectOne("getUserById", userId);
    		return user;
    	}
    }

     

    < App3.java >

    package com.sample;
    
    import java.util.List; 
    
    import com.sample.dao.UserDao;
    import com.sample.vo.User;
    
    public class App3 {
    
    	public static void main(String[] args) {
    		
    		UserDao userDao = new UserDao();
       
    		List<User> users = userDao.getAllUsers();
    		for (User user : users) {
    			System.out.println(user.getId() + "," + user.getName() + ", " + user.getEmail());
    		}
    		
    		System.out.println("### 아이디로 사용자 정보 조회");
    		User user = userDao.getUserById("kim");
    		System.out.println(user.getId() + "," + user.getName() + ", " + user.getEmail());
    	}
    }


    SqlMapper의 주요 API


    - INSERT 구문 실행
      void insert(String id)
      void insert(String id, Object param)
    - UPDATE  구문 실행
      void update(String id)
      void update(String id, Object param)
    - DELETE 구문 실행
      void delete(String id)
      void delete(String id, Object param)
    - SELECT 구문 실행
      Object selectOne(String id)   // 조회 조건이 없는 경우 사용
      Object selectOne(String id, Object param)  // 파라미터로 조회 조건을 전달할 수 있음. 두 번째 파라미터로 전달된 객체는 SQL Mapper XML 파일에서 지정한 SQL의 `paramterType`에 해당하는 객체임
      List<?> selectList(String id)
      List<?> selectList(String id, Object param)

     

     

     

     

    댓글

Designed by Tistory.