안녕하세요.
Spring으로 Web Application을 개발해 보신 분들은 SQL문을 xml로 관리하는 mapper 방식 개발을 해보셨을 겁니다.
MyBatis 라이브러리에서 지원하는 mapper-xml 형식으로 많이들 하셨을 건데요.
Node에서도 Spring과 동일하게 mybatis-mapper 모듈을 지원하더라구요.
Node.js와 oracledb 모듈을 이용한 오라클 디비 연결하는 방법에 대해 포스팅을 해드렸는데요.
https://meyouus.tistory.com/66
SQL 조회하는 부분을 mybatis-mapper 모듈을 이용하여 xml-mapper로 변경을 해보겠습니다.
▼사전 준비 작업
- Node 설치
https://meyouus.tistory.com/62 참고
- Oracle Instance Client 설치
다운로드 페이지 : https://www.oracle.com/database/technologies/instant-client/downloads.html
설치 참고 : https://sora-muck.tistory.com/12
- Node 개발 편집기로 Visual Studio Code 설치
다운로드 페이지 : https://code.visualstudio.com/nodejs
설치 참고 : https://meyouus.tistory.com/21
- Request / Response 테스트를 위한 Postman 설치
다운로드 페이지 : https://www.getpostman.com/downloads/
사용법 : https://meetup.toast.com/posts/107
- DB 데이터 EMP, DEPT 생성
https://meyouus.tistory.com/50 참고
▼ oracledb 모듈(라이브러리) 설치
npm install oracledb --save
▼ express 모듈 설치 모듈(라이브러리) 설치
npm install express --save
▼ body-parser 모듈 설치
npm install body-parser --save
▼ mybatis-mapper 모듈 설치
npm install mybatis-mapper --save
▼ 기본설정
// mybatis-mapper 추가
var mybatisMapper = require('mybatis-mapper');
// Mapper Load
mybatisMapper.createMapper([ './mapper/oracle-mapper.xml' ]);
// Oracle Auto Commit 설정
oracledb.autoCommit = true;
var dbConfig = require('./config/dbConfig');
// Express 기본 모듈 불러오기
var express = require('express')
, http = require('http')
, path = require('path');
// 익스프레스 객체 생성
var app = express();
// 기본 속성 설정
app.set('port', process.env.PORT || 3000);
// body-parser
var bodyParser = require('body-parser');
app.use(bodyParser.urlencoded({extended:true}));
app.use(bodyParser.json());
// 라우터 객체 참조
var router = express.Router();
// mybatis-mapper 추가
var mybatisMapper = require('mybatis-mapper');
// Mapper Load
mybatisMapper.createMapper([ './APP/mapper/oracle-mapper.xml' ]);
// Oracle Auto Commit 설정
oracledb.autoCommit = true;
▼ dbConfig.js 설정
- dbConfig.js : db 연결 정보
/* DB Info */
module.exports =
{
user : process.env.NODE_ORACLEDB_USER || "*****",
password : process.env.NODE_ORACLEDB_PASSWOR || "********",
connectString : process.env.NODE_ORACLEDB_CONNECTIONSTRING || "localhost/orcl"
}
▼ xml-mapper 파일 설정
- oracle-mapper.xml 생성
▷ 조회(SELECT) - 사번(empno) 정보가 있는경우 해당하는 사번의 정보, Null인경우 전체 사원정보 조회
<select id="selectEmpInfo">
SELECT
*
FROM
EMP
WHERE EMPNO IS NOT NULL
<if test="empno != null and empno != ''" >
AND EMPNO = #{empno}
</if>
</select>
▷ 등록(INSERT) - 사원정보 저장
<insert id="insertEmpInfo">
INSERT INTO EMP( EMPNO ,ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO)
VALUES( #{empno} ,#{ename}, #{job}, #{mgr}, SYSDATE, #{sal}, #{comm}, #{deptno} )
</insert>
▷ 전체
<?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="oracleMapper">
<select id="selectEmpInfo">
SELECT
*
FROM
EMP
WHERE EMPNO IS NOT NULL
<if test="empno != null and empno != ''" >
AND EMPNO = #{empno}
</if>
</select>
<insert id="insertEmpInfo">
INSERT INTO EMP( EMPNO ,ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO)
VALUES( #{empno} ,#{ename}, #{job}, #{mgr}, SYSDATE, #{sal}, #{comm}, #{deptno} )
</insert>
</mapper>
▼ Application 파일 설정
- app.js : Oracle 연결, CURD 처리, Request / Response 처리
▷ 조회 Request 처리 : /dbTestSelect
// 데이터 조회 처리
router.post('/dbTestSelect', function(request, response){
oracledb.getConnection({
user : dbConfig.user,
password : dbConfig.password,
connectString : dbConfig.connectString
},
function(err, connection) {
if (err) {
console.error(err.message);
return;
}
//조회할 파라미터
var param = {
empno : request.body.empno
}
// 쿼리문 형식
let format = {language: 'sql', indent: ' '};
//첫번째는 xml의 namespace, 두번째는 해당 xml id값, 세번째는 파라미터, 마지막은 포맷.
let query = mybatisMapper.getStatement('oracleMapper', 'selectEmpInfo', param, format);
console.log(query); // 쿼리 출력
connection.execute(query, [], function (err, result) {
if (err) {
console.error(err.message);
doRelease(connection);
return;
}
console.log(result.rows); // 데이터
doRelease(response, connection, result.rows); // Connection 해제
});
});
});
▷ 등록 Request 처리 : /dbTestInsert
// 데이터 입력 처리
router.post('/dbTestInsert', function(request, response){
oracledb.getConnection({
user : dbConfig.user,
password : dbConfig.password,
connectString : dbConfig.connectString
},
function(err, connection) {
if (err) {
console.error(err.message);
return;
}
//조회할 파라미터
var param = {
empno : Number(request.body.empno),
ename : request.body.ename,
job : request.body.job,
mgr : request.body.mgr,
sal : Number(request.body.sal),
comm : Number(request.body.comm),
deptno : Number(request.body.deptno)
}
// 쿼리문 형식
let format = {language: 'sql', indent: ' '};
//첫번째는 xml의 namespace, 두번째는 해당 xml id값, 세번째는 파라미터, 마지막은 포맷.
let query = mybatisMapper.getStatement('oracleMapper', 'insertEmpInfo', param, format);
console.log(query); // 쿼리 출력
connection.execute(query, [], function (err, result) {
if (err) {
console.error(err.message);
doRelease(connection);
return;
}
console.log('Row Insert: ' + result.rowsAffected);
doRelease(response, connection, result.rowsAffected); // Connection 해제
});
});
});
▼ app.js
var oracledb = require('oracledb');
var dbConfig = require('./config/dbConfig');
// Express 기본 모듈 불러오기
var express = require('express')
, http = require('http')
, path = require('path');
// 익스프레스 객체 생성
var app = express();
// 기본 속성 설정
app.set('port', process.env.PORT || 3000);
// body-parser
var bodyParser = require('body-parser');
app.use(bodyParser.urlencoded({extended:true}));
app.use(bodyParser.json());
// 라우터 객체 참조
var router = express.Router();
// mybatis-mapper 추가
var mybatisMapper = require('mybatis-mapper');
// Mapper Load
mybatisMapper.createMapper([ './mapper/oracle-mapper.xml' ]);
// Oracle Auto Commit 설정
oracledb.autoCommit = true;
// 데이터 조회 처리
router.post('/dbTestSelect', function(request, response){
oracledb.getConnection({
user : dbConfig.user,
password : dbConfig.password,
connectString : dbConfig.connectString
},
function(err, connection) {
if (err) {
console.error(err.message);
return;
}
//조회할 파라미터
var param = {
empno : request.body.empno
}
// 쿼리문 형식
let format = {language: 'sql', indent: ' '};
//첫번째는 xml의 namespace, 두번째는 해당 xml id값, 세번째는 파라미터, 마지막은 포맷.
let query = mybatisMapper.getStatement('oracleMapper', 'selectEmpInfo', param, format);
console.log(query); // 쿼리 출력
connection.execute(query, [], function (err, result) {
if (err) {
console.error(err.message);
doRelease(connection);
return;
}
console.log(result.rows); // 데이터
doRelease(response, connection, result.rows); // Connection 해제
});
});
});
// 데이터 입력 처리
router.post('/dbTestInsert', function(request, response){
oracledb.getConnection({
user : dbConfig.user,
password : dbConfig.password,
connectString : dbConfig.connectString
},
function(err, connection) {
if (err) {
console.error(err.message);
return;
}
//조회할 파라미터
var param = {
empno : Number(request.body.empno),
ename : request.body.ename,
job : request.body.job,
mgr : request.body.mgr,
sal : Number(request.body.sal),
comm : Number(request.body.comm),
deptno : Number(request.body.deptno)
}
// 쿼리문 형식
let format = {language: 'sql', indent: ' '};
//첫번째는 xml의 namespace, 두번째는 해당 xml id값, 세번째는 파라미터, 마지막은 포맷.
let query = mybatisMapper.getStatement('oracleMapper', 'insertEmpInfo', param, format);
console.log(query); // 쿼리 출력
connection.execute(query, [], function (err, result) {
if (err) {
console.error(err.message);
doRelease(connection);
return;
}
console.log('Row Insert: ' + result.rowsAffected);
doRelease(response, connection, result.rowsAffected); // Connection 해제
});
});
});
// DB 연결 해제
function doRelease(response, connection, result) {
connection.release(function (err) {
if (err) {
console.error(err.message);
}
// DB종료까지 모두 완료되었을 시 응답 데이터 반환
response.send(''+result);
});
}
// 라우터 객체를 app 객체에 등록
app.use('/', router);
// 등록되지 않은 패스에 대해 페이지 오류 응답
app.all('*', function(req, res) {
res.status(404).send('<h1>ERROR - 페이지를 찾을 수 없습니다.</h1>');
});
// Express 서버 시작
http.createServer(app).listen(app.get('port'), function(){
console.log('Express server listening on port ' + app.get('port'));
});
// 예상치 못한 에러처리
process.on("uncaughtException", function (err) {
//비정상 에러시 로그를 넘길 수 있도록 timeout을 준다.
setTimeout(function () {
logger.error("[[[ Uncaught Exception ]]]\n" + err.stack);
}, 1000);
});
▼ launch.json <-- Visual Studio Run and Debug Mode 설정
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "Launch Program",
"skipFiles": [
"<node_internals>/**"
],
"program": "${workspaceFolder}\\app.js",
"outputCapture": "std"
}
]
}
▼ Test
1. 조회 : http://localhost:3000/dbTestSelect
API : http://localhost:3000/dbTestSelect
1-1. empno 지정 -> 해당 사원정보가 있는경우 1건 Response
- Log
1-2. empno 지정안함 -> 전체 사원정보 Response
- Log
2. 사원정보 저장
API : http://localhost:3000/dbTestInsert
- Log
이상으로 mybatis-mapper 모듈을 이용한 mapper-xml 개발에 대해 설명을 드렸습니다.
업무에 도움이 되셨으면 합니다.
감사합니다.
'IT > NodeJS' 카테고리의 다른 글
Nodejs Express 이용한 post 호출시 request body에서 undefined 발생 해결 (3) | 2019.12.10 |
---|---|
Node.js oracledb를 통한 오라클 연결 (0) | 2019.12.09 |
Visual Studio Code 디버깅(debugging) for Node.js (0) | 2019.12.08 |
Node.js 설치와 NPM 이해하기 (0) | 2019.12.07 |
최근댓글