Posted by 세상을 살아가는 사람
,

STS4를 사용하여 spring starter project를 Spring Data JPA를 설정하여 생성하면, 데이터베이스 설정이 필요하다.

여기서는 Oracle 19c 버전과 연동을 시키고자 한다. 이를 위해서 다음과 같이 설정이 되어야 한다.

1. build.gradle에 JDBC 라이브러리 추가

  - dependencies에 다음을 추가한다.

    implementation group: 'com.oracle.ojdbc', name: 'ojdbc8', version: '19.3.0.0'

  Project and External Dependencies에 ojdbc8.jar 파일이 생성되는 것을 확인할 수 있다.

2. src/main/resources 폴더에 있는 application.properties 파일에 오라클 데이터베이스 연동을 위한 설정을 추가한다.

spring.datasource.driver-class-name=oracle.jdbc.driver.OracleDriver
spring.datasource.url=jdbc:oracle:thin:@localhost:1521:orcl
spring.datasource.username=study
spring.datasource.password=study

3. Ex2Application.java 파일을 수행하면 에러 없이 실행되는 것을 알 수 있다.

Posted by 세상을 살아가는 사람
,

채규태 지음 스프링 퀵 스타트는 H2 데이터베이스를 사용하고 있다.

나는 오라클 데이터베이스를 사용하여 실습을 진행하고자 한다.

이를 위해 변경사항을 정리해 본다.

1. 데이터베이스 테이블 스페이스 및 사용자 생성

- 사전 전제조건 : Oracle 데이터베이스 19c가 설치되어 있다. SQL developer에서 dba로 접속하여 다음과 SQL 작업을 한다.

- 테이블 스페이스 생성

  + 오라클 데이터베이스가 D:\oraclexe에 설치되어 oradata\ORCL 밑에 테이블 스페이스를 위한 dbf 파일을 생성한다.

create tablespace quickts
datafile 'D:\oraclexe\oradata\ORCL\quickts.dbf' size 100M
autoextend on next 5M;

- 사용자 생성 및 권한 부여

  + username : quick, password : quick

  + quick에게 일반 개발자 권한을 부여한다.

alter session set "_ORACLE_SCRIPT"=true;
create user quick identified by quick
default tablespace quickts temporary tablespace temp;

grant connect, resource to quick;  -- 접속, 자원 사용에 대한 권한
alter user quick quota unlimited on quickts; -- 테이블스페이스 사용 권한

commit;

  + quick 계정을 사용하여 sql developer에 접속 (SID = orcl)

 

2. 데이터베이스 테이블 생성

여기서는 Day 01 Class 6 비지니스 컴포넌트 실습 1을 실습하기 위하여 board 테이블을 생성한다. sql developer를 사용하여 사용자 quick로 접속하여 다음 SQL을 수행한다. seq 컬럼은 12c 이후에 추가된 기능을 사용하여 MySQL과 같이 auto_increment 기능을 적용하였다.

create table board (
    seq INTEGER GENERATED AS IDENTITY,
    title VARCHAR(100) not null,
    writer varchar2(50) not null,
    content varchar2(4000) not null,
    regDate date default sysdate,
    cnt integer default 0
);

alter table board add constraint pk_board primary key (seq);

 

3. JDBC 라이브러리를 사용하여 오라클 데이터베이스를 사용하기 위하여 다음과 같이 Connection을 가져온다. 이때 필요한 driver name, URL, username, password를 설정한다.

- JDBC 드라이브 이름 : oracle.jdbc.driver.OracleDriver

- 데이터베이스 URL : jdbc:oracle:thin:@localhost:1521:orcl

- Username : quick

- Password : quick

package com.springbook.biz.common;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

public class JDBCUtil {
	private static final String DRIVER_NAME = "oracle.jdbc.driver.OracleDriver";
	private static final String URL = "jdbc:oracle:thin:@localhost:1521:orcl";
	private static final String USERNAME = "quick";
	private static final String PASSWORD = "quick";

	public static Connection getConnection() {
		try {
			Class.forName(DRIVER_NAME);
			return DriverManager.getConnection(URL, USERNAME, PASSWORD);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	public static void close(PreparedStatement stmt, Connection conn) {
		if (stmt != null) {
			try {
				if (!stmt.isClosed())
					stmt.close();
			} catch (Exception e) {
				e.printStackTrace();
			} finally {
				stmt = null;
			}
		}
		if (conn != null) {
			try {
				if (!conn.isClosed())
					conn.close();
			} catch (Exception e) {
				e.printStackTrace();
			} finally {
				conn = null;
			}
		}
	}

	public static void close(ResultSet rs, PreparedStatement stmt, Connection conn) {
		if (rs != null) {
			try {
				if (!rs.isClosed())
					rs.close();
			} catch (Exception e) {
				e.printStackTrace();
			} finally {
				rs = null;
			}
		}
		if (stmt != null) {
			try {
				if (!stmt.isClosed())
					stmt.close();
			} catch (Exception e) {
				e.printStackTrace();
			} finally {
				stmt = null;
			}
		}
		if (conn != null) {
			try {
				if (!conn.isClosed())
					conn.close();
			} catch (Exception e) {
				e.printStackTrace();
			} finally {
				conn = null;
			}
		}
	}
}

4. BoardDAO.java를 수정

- 게시글 추가를 위한 SQL 문을 수정 : insert into board(title, writer, content) values(?,?,?)

package com.springbook.biz.board.impl;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;
import org.springframework.stereotype.Repository;
import com.springbook.biz.board.BoardVO;
import com.springbook.biz.common.JDBCUtil;

// DAO(Data Access Object)
@Repository("boardDAO")
public class BoardDAO {
	// JDBC 관련 변수
	private Connection conn = null;
	private PreparedStatement stmt = null;
	private ResultSet rs = null;
	// SQL 명령어들
	private final String BOARD_INSERT = "insert into board(title, writer, content) values(?,?,?)";
	private final String BOARD_UPDATE = "update board set title=?, content=? where seq=?";
	private final String BOARD_DELETE = "delete board where seq=?";
	private final String BOARD_GET = "select * from board where seq=?";
	private final String BOARD_LIST = "select * from board order by seq desc";

	// CRUD 기능의 메소드 구현
	// 글 등록
	public void insertBoard(BoardVO vo) {
		System.out.println("===> JDBC로 insertBoard() 기능 처리");
		try {
			conn = JDBCUtil.getConnection();
			stmt = conn.prepareStatement(BOARD_INSERT);
			stmt.setString(1, vo.getTitle());
			stmt.setString(2, vo.getWriter());
			stmt.setString(3, vo.getContent());
			stmt.executeUpdate();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			JDBCUtil.close(stmt, conn);
		}
	}

	// 글 수정
	public void updateBoard(BoardVO vo) {
		System.out.println("===> JDBC로 updateBoard() 기능 처리");
		try {
			conn = JDBCUtil.getConnection();
			stmt = conn.prepareStatement(BOARD_UPDATE);
			stmt.setString(1, vo.getTitle());
			stmt.setString(2, vo.getContent());
			stmt.setInt(3, vo.getSeq());
			stmt.executeUpdate();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			JDBCUtil.close(stmt, conn);
		}
	}

	// 글 삭제
	public void deleteBoard(BoardVO vo) {
		System.out.println("===> JDBC로 deleteBoard() 기능 처리");
		try {
			conn = JDBCUtil.getConnection();
			stmt = conn.prepareStatement(BOARD_DELETE);
			stmt.setInt(1, vo.getSeq());
			stmt.executeUpdate();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			JDBCUtil.close(stmt, conn);
		}
	}

	// 글 상세 조회
	public BoardVO getBoard(BoardVO vo) {
		System.out.println("===> JDBC로 getBoard() 기능 처리");
		BoardVO board = null;
		try {
			conn = JDBCUtil.getConnection();
			stmt = conn.prepareStatement(BOARD_GET);
			stmt.setInt(1, vo.getSeq());
			rs = stmt.executeQuery();
			if (rs.next()) {
				board = new BoardVO();
				board.setSeq(rs.getInt("SEQ"));
				board.setTitle(rs.getString("TITLE"));
				board.setWriter(rs.getString("WRITER"));
				board.setContent(rs.getString("CONTENT"));
				board.setRegDate(rs.getDate("REGDATE"));
				board.setCnt(rs.getInt("CNT"));
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			JDBCUtil.close(rs, stmt, conn);
		}
		return board;
	}

	// 글 목록 조회
	public List<BoardVO> getBoardList(BoardVO vo) {
		System.out.println("===> JDBC로 getBoardList() 기능 처리");
		List<BoardVO> boardList = new ArrayList<BoardVO>();
		try {
			conn = JDBCUtil.getConnection();
			stmt = conn.prepareStatement(BOARD_LIST);
			rs = stmt.executeQuery();
			while (rs.next()) {
				BoardVO board = new BoardVO();
				board.setSeq(rs.getInt("SEQ"));
				board.setTitle(rs.getString("TITLE"));
				board.setWriter(rs.getString("WRITER"));
				board.setContent(rs.getString("CONTENT"));
				board.setRegDate(rs.getDate("REGDATE"));
				board.setCnt(rs.getInt("CNT"));
				boardList.add(board);
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			JDBCUtil.close(rs, stmt, conn);
		}
		return boardList;
	}
}

5. 테스트 코드의 위치

교재에 있는대로 하면 src/test/java/BoardServiceClient.java가 동작하지 않고, Class Not Found Exception이 발생한다.

따라서 파일을 src/main/java/com.springbook.biz.board 패키지 밑으로 이동하여 실행한다.

게시글이 추가되고, 검색이 됨을 알 수 있다.

sql developer를 사용하여 테이블의 데이터를 확인한다.

Posted by 세상을 살아가는 사람
,

자바를 이용한 스프링 강의를 계속하면서 그동안 변경된 개발 환경과 현재 시점에서 개발환경을 어떻게 설정을 해야 하는지 정리해 본다.
1. JDK 1.8을 사용한 개발 환경
- 처음에는 JDK 1.8을 사용하여 개발을 진행
- 이클립스 : 2020-06-R 버전을 사용하여 JAVA EE을 개발하였고, Eclipse Marketplace를 통해 STS를 설치하여 스프링을 개발하였었다.
- 그랬다가 어느 시점에 이클립스에서 STS plugin을 지원하지 않았다. 그래서 이클립스에서 플러긴을 사용하지 않고, 이클립스 기능을 제공하는 STS를 따로 설치하여 스프링을 개발하였다.
2. 별도의 STS를 사용한 스프링 개발 환경
- JDK 1.8을 지원하기 위하여 STS-3.9.15,RELEASE-e4.16.0을 사용
- 이클립스 버전도 JDK 1.8을 지원하기 위해 e4.16(2020-06-R) 버전인 것이다.
- JSP를 개발하기 위한 JAVA EE IDE도 eclipse-jee-2020-06-R 버전을 사용하였다.
3. JDK 11을 사용한 스프링 개발 환경
- 전자정부표준프레임워크 v4.0에서 JDK 11을 지원하고, 상용으로 JDK 11이 사용되게 되는 것 같다. 따라서 JDK 8을 사용하지 않고, JDK 11을 사용하는 환경을 고려해 본다.
- 자바 버전 : JDK 11.0.15
- 이클립스 : 2021-06-R Java EE IDE
- 이클립스 마켓 플레이스에서 "Spring Tools 3 Add-On for Spring Tools 4 3.9.22.RELEASE" Plugin을 설치하여 스프링 개발환경을 설정한다.
- 이때 pom.xml에서 다음과 같은 에러가 발생하면 다음 plugin 설정을 추가한다.
Description Resource Path Location Type
Could not initialize class org.apache.maven.plugin.war.util.WebappStructureSerializer pom.xml /ex08 line 1 Maven Configuration Problem

            <plugin>
            	<groupId>org.apache.maven.plugins</groupId>
            	<artifactId>maven-war-plugin</artifactId>
            	<version>3.3.1</version>
            </plugin>

- 별도의 STS를 사용하여도 되겠지만, 이클립스를 사용한 JSP 개발환경과의 연속성을 위해 이렇게 설정하는 것도 좋은 방법이다.
4. Spring Tools 4 (aka Spring Tool Suite 4) 4.15.1.RELEASE 설치
이클립스에서 STS plugin으로 . "Spring Tools 3 Add-On for Spring Tools 4 3.9.22.RELEASE"을 설치한 후에, Spring Tools 4 (aka Spring Tool Suite 4) 4.15.1.RELEASE을 설치하면, STS4를 설치할 수 있다.

Posted by 세상을 살아가는 사람
,

스프링에 대하여 공부하는데는 적당한 것 같다. 특히 REST API에 대한 설명이 잘되어 있는 것 같다.



Posted by 세상을 살아가는 사람
,

강의용 교재로 적당할 것 같다. 고급 수준은 아니지만 어느 정도 수준은 되기 때문에 학원 강의용으로는 적당할 것 같다.



Posted by 세상을 살아가는 사람
,

JSP/서브릿부터 스프링 MVC, 그 이상을 다루고 있어 수준이 있는 교재 같다. 비전공자에게는 다소 어려울 것 같아 걱정이 된다.



Posted by 세상을 살아가는 사람
,

이클립스에서 Spring MVC 프로젝트를 만들어서 ojdbc6.jar 를 적용하는 방법을 기술한다.

보통 pom.xml에 maven dependency를 다음과 같이 적용해준다.

<!-- Oracle Driver -->

<dependency>

<groupId>com.oracle</groupId>

<artifactId>ojdbc6</artifactId>

<version>12.1.0.1</version>

</dependency>

그러면 maven repository에 ojdbc6.12.1.0.1.jar 파일이 생기기는 하지만, Eclipse에서 artifactId가 적용되지 않았다고 하면서 에러가 발생한다.

그러면 다음과 같이 처리를 해주어야 한다.

1. oracle 사이트에 가서 ojdbc6.jar 파일을 다운로드 받는다.

  - 아니면 오라클을 설치한 폴더에서 가져온다. 나는 아래와 같은 폴더에 설치

    (D:\database\app\User\product\11.2.0\dbhome_1\jdbc\lib)

  - 나는 C:\raspberry\driver 디렉토리에 저장하였다.

2. windows OS에서 수행되는 mvn을 다운로드 한다.

  - maven.apache.org/download.cgi 사이트에서 binary zip archive를 다운로드

    (apache-maven-3.3.9-bin.zip)

  - 적당한 디렉토리에 옮겨놓고 압축을 해제한다.

  - 환경설정에서 MAVEN_HOME을 등록한다.

    + File Explorer에서 시스템 우클릭>속성을 선택한다.

    + 고급 시스템 설정을 클릭한 후 환경변수 버튼을 클릭

    + 시스템 변수로 MAVEN_HOME을 mvn을 설치하여 압축을 푼 디렉토리 명을 써준다.

      변수 이름(N): MAVEN_HOME

      변수 값(V) : C:\raspberry\apache-maven-3.3.9

    + 시스템 변수 path에 %MAVEN_HOME\bin을 추가한 후 확인을 눌러 빠져 나온다.

3. command 창을 띄우고 다음을 수행한다.

  C:.> mvn install:install-file -Dfile=C:\raspberry\driver\ojdbc6.jar -DgroupId=com.oracle -DartifactId=ojdbc6 -Dversion=12.1.0.1 -Dpacking=jar

  - 빌드 success되고, 그러면 ojdbc6.jar 파일이 자신의 PC에 있는 maven repository에 적용이 된다.

4. 이클립스에서 Meven Clean을 하면 error가 사람짐을 알수 있다.

참고 : https://www.mkyong.com/maven/how-to-add-oracle-jdbc-driver-in-your-maven-local-repository/

Posted by 세상을 살아가는 사람
,

학원에서 스프링 MVC를 적용하여 프로젝트를 학생들이 하고 있는데 Ajax와 첨부파일을 적용하는 것이 어렵다고 하여 정리해 본다.

나의 작업환경은 다음과 같다.

1. 멀티 게시판 : 하나의 Article 데이터베이스 테이블에 여러 개의 게시판의 게시물을 한꺼번에 저장

  - 게시판 테이블 운영

  - ref, step, depth 체계를 가진 게시판

  - 네이버에서 공개한 스마트에디터 사용

  - 본문에 사진 추가 기능 사용

  - 첨부 파일은 5개 까지 적용 가능

  - 오라클 11g DBMS 사용 : Board, Article, PdsItem 테이블 및 각각의 sequence 운영

2. 스마트에디터에 대한 스프링 MVC 적용

  - 소스코드 위치 : src/main/webapp/resources/smarteditor

  - photo_uploader/popup/attach_photo.js 수정

    + html5Upload() function

      * 본문에 삽입되는 사진을 서버에 저장하기 위한 URL : /contextPath/board/file_uploader_html5 (내부적으로 Ajax 처리)

    + callFileUploader() function

      * sUrl : 'contextPath/board/file_uploader'

      * sCallback : 'resources/smarteditor/photo_uploader/popup/callback.html'

  - writeForm.js 수정 : 게시판 쓰기를 위한 jsp 파일의 javascript 파일

    + nhn.husky.EZCreator.createInIframe 수정

      nhn.husky.EZCreator.createInIFrame({

        oAppRef: editor_object,

        elPlaceHolder: "smarteditor",

        sSkinURI: ctx + "/resources/smarteditor/SmartEditor2Skin.html", 

        htParams : {

            // 툴바 사용 여부 (true:사용/ false:사용하지 않음)

            bUseToolbar : true,             

            // 입력창 크기 조절바 사용 여부 (true:사용/ false:사용하지 않음)

            bUseVerticalResizer : true,     

            // 모드 탭(Editor | HTML | TEXT) 사용 여부 (true:사용/ false:사용하지 않음)

            bUseModeChanger : true,

            fOnBeforeUnload : function(){

            }

         }

       });

    + 전송 버튼을 눌렀을 때 처리 : 가비지 컬렉션 처리를 위해 먼저 사진 파일에 대한 관리를 먼저하고, 이후 첨부파일에 대한 저장을 처리

      $("#addBtn").click(function(){

        //id가 smarteditor인 textarea에 에디터에서 대입

        editor_object.getById["smarteditor"].exec("UPDATE_CONTENTS_FIELD", []);

        // 이부분에 에디터 validation 검증

        var el = document.createElement('html');

        el.innerHTML = editor_object.getById["smarteditor"].elPlaceHolder.value;

        var imageF = el.getElementsByTagName('img');

        var url = ctx + "/board/file_uploader_real";

        var params = "";

        for(var i = 0;i < imageF.length;i++) {

          if(i == 0)

            params += ("src=" + imageF[i].src + "&title=" + imageF[i].title);

          else

            params += ("&src=" + imageF[i].src + "&title=" + imageF[i].title);

        }

        sendRequest(url, params, callbackFunction, "POST");

        callTimerProcessing();

      })

    

      function callTimerProcessing() {    // 사진에 대한 처리를 보장하기 위해 loop를 돌다, 응답이 오면 처리

    if(loop) {

      setTimeout(function() {

           callTimerProcessing();

          }, 100);

    }

    else {

          //폼 submit

          $("#frm").submit();

    }

      }


서버에서 처리는 다음에 ...

Posted by 세상을 살아가는 사람
,