study/TIL🐥

[JSP] Mybatis와 Oracle 연동하기

서나쓰 2020. 12. 29. 16:55
728x90

기존에 수업 예제는 Mybatis와 MySQL을 연동했다.

Oracle의 프로시저 SQL을 배우면서 MyBatis와 연동하면 기존 MySQL보다 구문이 더 깔끔해 질 것이라고 했다.

기존의 모델은 위쪽의 모델이였다면, 이번엔 아래쪽의 모델로 작성해 볼 계획이다.

✅ 아래쪽의 모델은 개발이 아닌 DB에 중점을 맞추는 작업이다. 위쪽의 모델은 개발이 중점, 빠른 시간 내에 개발을 할 경우에 사용하도록 하고, 아래쪽의 모델은 DB 중점, 오랜 시간 개발해야 하는 프로젝트에 사용된다.
최종 프로젝트의 경우 위쪽으로 진행할 예정이다. 지금 이것은 그냥 스터디!

1. 오라클 접속 확인

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

public class OracleEx01 {

	public static void main(String[] args) {
		String driver = "oracle.jdbc.driver.OracleDriver";
		String url = "jdbc:oracle:thin:@localhost:1521:xe";
		String user = "hr";
		String password = "hr";
		
		Connection conn = null;
		try {
			Class.forName(driver);
			System.out.println("jdbc driver 로딩 성공");
			conn = DriverManager.getConnection(url, user, password);
			System.out.println("오라클 연결 성공");
		} catch (ClassNotFoundException e) {
			System.out.println("jdbc driver 로딩 실패");
		} catch (SQLException e) {
			System.out.println("오라클 연결 실패");
		}
		
		/*접속 해제 처리*/
		try {
			conn.close();
			System.out.println("연결 해제");
		} catch (Exception e) {
			System.out.println("해제 오류");
		}
		conn=null;

	}

}
  • MySQL과는 다르게 DB 정보가 없다.
  • 기존 자신의 주소를 사용할 경우 localhost, 혹은 127.0.0.1 사용
  • 포트 번호는 오라클 접속 시에 특별하게 건든 게 없다면 1521 사용
  • xe는 SID를 의미
  • SID는 sqlplus에서 select name from v$database; 명령어 치면 확인할 수 있다.

접속이 매우 잘 된다!

 

2. 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>
	<!-- Oracle 접속 정보를 지정한다. -->
    <properties>
        <property name="hostname" value="localhost" />
        <property name="portnumber" value="1521" />
        <property name="username" value="hr" />
        <property name="password" value="hr" />
    </properties>

    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC" />
            <dataSource type="POOLED">
                <property name="driver" value="oracle.jdbc.driver.OracleDriver" />
                <property name="url" value="jdbc:oracle:thin:@${hostname}:${portnumber}/xe" />
                <property name="username" value="${username}" />
                <property name="password" value="${password}" />
            </dataSource>
        </environment>
    </environments>

    <!-- 실행할 SQL문을 정의한 Mapper XML의 경로를 지정한다. -->
	<mappers>
		<mapper resource="study/java/myschool/mapper/DepartmentMapper.xml" />
		<mapper resource="study/java/myschool/mapper/ProfessorMapper.xml" />
		<mapper resource="study/java/myschool/mapper/StudentMapper.xml" />
	</mappers>
</configuration>
  • Oracle 접속 방법 확인한 예제처럼, 기존에 MySQL 접속 정보를 지우고 Oracle 접속 정보 설정해 준다.

3. MyBatisMyBatisConnectionFactory.java 

package study.java.myschool;

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

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

public class MyBatisConnectionFactory {
	//데이터베이스 접속객체
	private static SqlSessionFactory sqlSessionFactory;
	
	//XML에 명시된 접속 정보 읽어들인다
	//클래스 초기화 블럭 : 클래스 변수의 복잡한 초기화에 사용
	//클래스가 처음 로딩될 때 한번만 수행
	static {
		//접속 정보를 명시하고 있는 XML 경로 읽기
		try {
			Reader reader = Resources.getResourceAsReader("study/java/myschool/config.xml");
			//selSessionFactory가 존재하지 않는다면 생성 -> DBHelper의 기능을 대체
			if(sqlSessionFactory == null) {
				sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	//데이터베이스 접속 객체를 통해 db 접속한 세션 리턴
	public static SqlSession getSqlSession() {
		return sqlSessionFactory.openSession();
	}
}

 

이 상태로 Mapper를 건들이지 않고 select문이 들어간 조회 jsp 파일을 실행하게 되면,

java.sql.SQLSyntaxErrorException:ORA-00933: SQL 명령어가 올바르게 종료되지 않았습니다

에러가 발생하게 된다. 이때, 이 에러는 구문 에러로서 보통 MyBatis에서는 세미콜론(;) 때문에 발생한다.

Mapper에 있는 모든 SQL 구문에 세미콜론을 지우면 매우 정상 작동한다!


4. org.apache.ibatis.executor.ExecutorException:Error getting generated key or setting result to parameter object. org.apache.ibatis.executor.result.ResultMapException:Error attempting to get column #1 from result set. java.sql.SQLException:부적합한 변환이 요청됨.

insert 구문에서 발생한 내용인데, MyBatis 에러이다.

MySQL을 사용하면 자동 증가 Autoincrement를 사용하게 되는데, 그 기능에 맞게 MyBatis insert 설정시 

이 기능을 사용하게 된다. insert 구문에 있는 이 옵션을 삭제해 줬더니 에러는 사라졌지만....


5. add는 됐지만 add 된 데이터를 불러올 수가 없다

add가 완료된 데이터의 dpetno를 파라미터로 받아와야하는데 읽어오질 않는다...

그리고 웃긴건 다시 리스트로 가면 또 추가는 되어있어서 select로는 조회가 된다..

그래서 삭제하려고 들어가서 삭제를 하려고 했더니

또 9903 ^^....

뭔가 했더니 이 프로젝트는 서로 테이블간의 참조키가 걸려있어서 department를 삭제하려면 연관된 student와 professor을 모두 삭제해야한다. student와 professor의 세미콜론을 모두 지워주도록 하자..

그랬더니 삭제가 깔끔하게 완료되었다.


6. add가 완료되었지만 add_ok에서 list로 안 넘어가는 상황 해결

프로그램 순서가 add.jsp 에서 추가될 정보들을 받고, add_ok.jsp에서 insert 작업을 완료한 다음, deptno 파라미터를 받아와서 list로 넘어가는 형식인데, add_ok에서 넘어가지 않는 것이, deptno를 파라미터로 못 받아오는 상황임을 확인했다.

보통 Oracle에서 sequence 객체에서 nextval 함수로 로 자동 일련번호 증가를 사용하게 되는데, 자동으로 추가된 PK의 값을 확인해야 하는 상황이 올 수 있다. 지금이 딱 그 상황!

이럴 때는 <SelectKey> 태그를 통해 PK의 값을 미리(BEFORE) SQL로 통해서 처리하고, 특정한 이름으로 보관하는 형식을 처리해야 한다.

<insert id="add_department" 
	    	parameterType="study.java.myschool.model.Department" 
	    	keyProperty="deptno">
	    	<selectKey keyProperty="deptno" order="BEFORE" resultType="int">
	    		select seq_department.nextval from dual
	    	</selectKey>
		<!-- "#{변수명}" 으로 표시된 곳에 Beans의 멤버변수가 치환된다. -->
		INSERT INTO department (deptno, dname, loc) VALUES (${deptno}, #{dname}, #{loc})
</insert>

그러면 add_ok에서 막히지 않고 아주 잘 돌아가는 현상을 확인 할 수 있다.

728x90

'study > TIL🐥' 카테고리의 다른 글

ERP란?  (0) 2021.01.05
하드디스크 연결 규격  (0) 2021.01.05
컴퓨터 Memory  (0) 2020.12.29
MySQL의 마스코트는 왜 돌고래인가?  (0) 2020.12.28
파일시스템과 데이터베이스  (0) 2020.12.28