2013년 7월 31일 수요일

[오라클자바실무교육,자바교육,오라클교육,JAVA ORACLE강의]오엔제이프로그래밍 교육센터 소개합니다.

1998년부터 운영된 오라클자바커뮤니티(www.oraclejavacommunity.co.kr)에서 설립 운영되고 있는 오엔제이 프로그래밍실무학원(www.onjprogramming.co.kr )은 개발자를 위한 실무 SKILL UP 전문 교육센터 입니다.
(2008년5월부터 오엔제이시스템즈에서 운영하던 "오라클자바교육센터"는 2013년5월 양도 하였으며 새로운 오엔제이 프로그래밍 실무교육센터에서 개발자 실무 교육을 이어갈 수 있도록 더욱 더 노력 하겠습니다.)

 자바, 오라클의 기초부터 자바프레임워크(Struts, Spring), 오라클 튜닝, 모델링, 고급SQL, Xinternet(GAUCE, Miplatform, XPlatform), 닷넷(C#, ASP.Net), 스마트폰앱개발교육(안드로이드, 아이폰)까지 실무전문 교육을 진행하고 있습니다.
(본원은 TOBESOFT 공인 교육기관 입니다.)

자바, 스프링, 오라클 교육 받으셨는데 이론으로 교육을 받으셨다고요? IT프로그래밍 교육은 실전예제, 실습을 통해 이론을 습득을 해야 합니다. 본원은 모든 강좌가 실습을 통해 이론을 취득하는 실무중심 교육 입니다.

한번 방문 하시어 실무전문 교육의 진수를 느껴 보시기 바랍니다.

감사합니다.

[오라클강의,자바강의,오라클자바교육,오라클교육,자바교육,자바오라클]Oracle Explicitly Named Indexes(9i이상)

oracle pk index
오라클 9i이상 에서 인덱스는 Primary Key Unique Key와는 별도로 CREATE TABLE
USING INDEX구 안에 CREATE INDEX 문법을 이용해서 정의하는 것이 가능해 졌습니다.


오라클자바커뮤니티에서 설립한 오엔제이프로그래밍 실무교육센터
(오라클SQL, 튜닝, 힌트,자바프레임워크, 안드로이드, 아이폰, 닷넷  실무전문 강의)



아마도 대부분의 사용자들은 다음과 같은 방식을 알고 계실텐데

예제를 보시면서 어떤 것이 바뀌었는지 확인해 보도록 하죠.

SQL> create table test (
  2  c1 varchar2(4) not null,
3  c2 number(10)  not null,
4  constrint pk_test primary key(c1) using index
  4  );

테이블이 생성되었습니다.


위의 create table문은 pk_test라는 이름을 가지는 primary key 제약 조건을 만들며 아울러 pk_test라는 이름을 가진 인덱스를 만듭니다. 이 두가지는 user_ind_colums 뷰와 user_constraints 뷰에서 table_name = TEST라는 조건을 주시면 확인이 가능합니다.

그러나 9i이후에서는 인덱스에 대해 명시적으로 이름을 주는 것이 가능해 졌는데

우선 아래의 예제를 참고 하도록 하죠

SQL> create table test (
  2  c1 varchar2(4) not null,
  3  c2 number(7),
  4  constraint pk_test primary key(c1)
  5  using index
  6      (create index idx_test_c1 on test(c1))
  7  );

테이블이 생성되었습니다.

이 경우는 테이블을 만들면서 primary key를 만드는데 (원래는 default pk를 만들게 되면 그 컬럼으로 유니크 인덱스를 만듭니다.) 인덱스의 이름은 primary key 이름과 다르게 주기 위해 using index 구안에 create index문을 이용해서 인덱스를 생성했습니다.

--------------------------------------------------------------------
아래의 SQL문중 하나를 이용해 인덱스는 놔두고 PK만 삭제할 수 있습니다.
--------------------------------------------------------------------

SQL> alter table test drop primary key keep index;

테이블이 변경되었습니다.

또는

SQL> alter table test drop constraint pk_test;

테이블이 변경되었습니다.

[출처]오라클자바커뮤니티



[오라클교육,자바교육,오라클자바교육]Column Name & Constraints rename 이름 변경(오라클 컬럼이름, 제약조건 이름 변경)

테이블이나 인덱스의 이름을 변경하는 것은 오라클 9iR2 이전에도 가능했지만 9iR2에서는 테이블의 컬럼 명 또는 제약조건의 이름을 변경하는 것이 가능해 졌습니다.



오라클자바커뮤니티에서 설립한 오엔제이프로그래밍 실무교육센터
(오라클SQL, 튜닝, 힌트,자바프레임워크, 안드로이드, 아이폰, 닷넷  실무전문 강의)



SQL> create table test (
  2  c1 varchar2(4) not null,
  3  c2 number(10)  not null
  4  );

테이블이 생성되었습니다.

프라이머리 키를 추가 합니다. 이때 C1컬럼에 대해 인덱스가 생성 됩니다.

SQL> alter table test add (constraint pk_test
  2                        primary key (c1));

테이블이 변경되었습니다.

SQL> desc test;
 이름                                      ?      유형
 ----------------------------------------- -------- --------------

 C1                                        NOT NULL VARCHAR2(4)
 C2                                        NOT NULL NUMBER(10)

사용자의 제약 조건을 확인 할  수 있는 USER_CONSTRAINTS VIEW를 통해 TEST 테이블에 제약조건의 타입이 P 인것 즉 Primary Key인 제약조건을 검색 합니다. 제약조건에는 NOT NULL, UNIQUE, CHECK, PRIMARY KEY등 테이블의 컬럼에 제약을 가하는 조건을 말합니다.

SQL> select constraint_name
  2  from   user_constraints
  3  where  table_name = 'TEST'
  4  and    constraint_type = 'P';

CONSTRAINT_NAME
------------------------------
PK_TEST

이번에는 TEST 테이블에 생성되어 있는 인덱스를 확인 합니다. 위에서 C1 컬럼을 Primary Key로 설정하여 저절로 이 컬럼에 대한 인덱스가 생성되어 있습니다.

SQL> select index_name,
  2         column_name
  3  from   user_ind_columns
  4  where  table_name = 'TEST';

INDEX_NAME           COLUMN_NAME
------------------------------------

PK_TEST                     C1

우선 테이블의 이름을 바꾸어 봅니다. 이 기능은 오라클의 이전 버전에서도 되는 기능 입니다

SQL> alter table test rename to test1;

테이블이 변경되었습니다.

이번에는 컬럼명을 바꾸어 보죠^^

SQL> alter table test1 rename column c1 to code;

테이블이 변경되었습니다.

Primary Ket 제약 조건의 이름을 변경 합니다.

SQL> alter table test1 rename constraint pk_test to pk_test1;

테이블이 변경되었습니다.

이번에는 Primary Key에 걸린 인덱스의 이름을 바꿉니다.

SQL> alter index pk_test rename to pk_test1;

인덱스가 변경되었습니다.

위에서 변경한 내역에 대해 확인해 보겠습니다

SQL> select constraint_name
  2  from   user_constraints
  3  where  table_name = 'TEST1'
  4  and    constraint_type = 'P';

CONSTRAINT_NAME
------------------------------
PK_TEST1

SQL> select index_name,
  2         column_name
  3  from   user_ind_columns
  4  where  table_name = 'TEST1';

INDEX_NAME             COLUMN_NAME
---------------------------------------------

PK_TEST1                    CODE

[출처]오라클자바커뮤니티



[SQL 팁]CASE를 활용한 SQL문장의 통합(오엔제이프로그래밍,오라클,자바실무교육)

1.       개요
동일한 테이블을 사용하고 WHERE 조건이 비슷한 유형으로 전개되는 SQL 문은 하나로 통합될 음을 유의하고 아래 예를 참고하자.


오라클자바커뮤니티에서 설립한 오엔제이프로그래밍 실무교육센터
(오라클SQL, 튜닝, 힌트,자바프레임워크, 안드로이드, 아이폰, 닷넷  실무전문 강의)



[첫번째 SQL]
SQL> select max(empno) from emp3
  2  where deptno > 10;

MAX(EMPNO)
----------
      7902

[두번째 SQL]
SQL>  select count(empno) from emp3
  2   where deptno > 10
  3  and   sal > 2000;

COUNT(EMPNO)
------------
     2097152


동일한 테이블에서 비슷한 조건이면서 하나는 MAX , 하나는 COUNT 값을 구하는 것이다. 번째 SQL 문의 sal > 2000 제외하고 같은 조건 절을 갖고 있다는 것을 있다.

2) 문제점

하나의 SQL 문으로 통합할 있음에도 2 개로 SQL 나누어 수행하였다.

3) 해결 방안

위의 경우 CASE 사용하면 쓰면 개의 SQL 하나로 만들어 테이블을 액세스 하게 있다다음과 같이 CASE 쓰면 SAL>2000 경우 계속 1 더해 줌으로서 전체에 SAL > 2000 값이 있는지 COUNT 해주는 것과 전체 COUNT 값도 있다.  이와 같이 번에 테이블을 액세스 있는 SQL 문을 쓰면 테이블을 번에 걸쳐 읽을 것을 읽고도 처리할 있으므로 보다 효율적인 프로그램이 되는 것이다.


SQL>  select max(empno), sum(case when sal>2000 then 1 else 0 end)
  2   from emp3
  3  where deptno > 10;

MAX(EMPNO) SUM(CASEWHENSAL>2000THEN1ELSE0END)
---------- ----------------------------------
      7902                            2097152



[출처]오라클자바커뮤니티



(오라클,자바 실무교육,SQL) oracle default 키워드 사용 예제

oracle default keyword를 이용한 예문이니 참고하세요~


오라클자바커뮤니티에서 설립한 오엔제이프로그래밍 실무교육센터
(오라클SQL, 튜닝, 힌트,자바프레임워크, 안드로이드, 아이폰, 닷넷  실무전문 강의)



SQL>  create table address (
  2   name varchar2(15) not null primary key,
  3   age number(3) default 0
  4   );
<?XML:NAMESPACE PREFIX = O /> 
Table created.

SQL> insert into address (name, age) values ('jclee1',1);

1 row created.

SQL> insert into address (name, age) values ('jclee2',2);

1 row created.

SQL> commit;

Commit complete.

SQL> select * from address ;

NAME                   AGE
--------------- ----------
jclee1                   1
jclee2                   2

SQL> update address set age=default
  2  where name = 'jclee1';

1 row updated.

SQL> commit;

Commit complete.

SQL> select * from address ;

NAME                   AGE
--------------- ----------
jclee1                   0
jclee2                   2

[출처]오라클자바커뮤니티



2013년 7월 30일 화요일

13. [스프링게시판만들기]커멘트 조회, 입력기능 추가(Spring Framework3.2 Board) ,자바,오라클실무교육학원 오엔제이프로그래밍실무학원

기존 게시판 기능 + Spring 게시판 구현(커멘트 조회, 입력 기능추가)


오라클자바커뮤니티에서 설립한 오엔제이프로그래밍 실무교육센터
(오라클SQL, 튜닝, 힌트,자바프레임워크, 안드로이드, 아이폰, 닷넷  실무전문 강의)




1.     시작하기
-       이번에는 게시판 상세보기(글읽기) 페이지에서 게시글에 커멘트를 입력하고, 입력되어 있는 커멘트를  글을 게시글 조회 시 같이 조회될 수 있는 기능을 추가해 보자.
2.     먼저 커멘트(Comment) 처리를 위한 CommentDTO.java를 작성하자.
[CommentDTO.java]
package onj.board.model;
public class CommentDTO {
       public int seq;       //게시글 번호
       public String name;   //이름
       public String comment;//커멘트
      
       public CommentDTO() {}
      
       public CommentDTO(String name, String comment) {
             this.name = name;
             this.comment = comment;
       }
      
       public int getSeq() {
             return seq;
       }
       public void setSeq(int seq) {
             this.seq = seq;
       }
       public String getName() {
             return name;
       }
       public void setName(String name) {
             this.name = name;
       }
       public String getComment() {
             return comment;
       }
       public void setComment(String comment) {
             this.comment = comment;
       }     
}
3.     먼저 커멘트(Comment) 처리를 위한 DAO쪽 클래스를 작성하자.
BoardDAO.java 인터페이스, SpringBoardDAO.java 클래스에 커멘트 입력, 조회를 위한 insertComment(), commentList() 두개의 메소드를 추가하자.
[BoardDAO.java]
소스 코드 빨강색 부분이 커멘트 조회, 입력 기능을 위해 추가된 부분
package onj.board.dao;
import java.util.List;
import onj.board.model.BoardDTO;
import onj.board.model.CommentDTO;
import org.springframework.dao.DataAccessException;
public interface BoardDAO {
       //게시물 리스트 보기
       public List<BoardDTO> boardList() throws DataAccessException;
      
       //게시물 본문 미리보기
       public String preView(String seq) throws DataAccessException;
      
       //게시물 본문 읽기
       public BoardDTO readContent(String seq) throws DataAccessException;
      
       //읽은 글의 조회수 1증가
       public int updateReadCount(String seq) throws DataAccessException;
      
       //Comment저장
       public int insertComment(CommentDTO commentDTO) throws DataAccessException ;
      
       //Comment조회
       public List<CommentDTO> commentList(String seq) throws DataAccessException;
}
[SpringBoardDAO.java]
package onj.board.dao;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import javax.sql.DataSource;
import onj.board.model.BoardDTO;
import onj.board.model.CommentDTO;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
public class SpringBoardDAO implements BoardDAO {
       private JdbcTemplate jdbcTemplate;
       public void setDataSource(DataSource dataSource) {
             this.jdbcTemplate = new JdbcTemplate(dataSource);
       }
       // /게시판 전체 리스트 보기(list.html)
       public List<BoardDTO> boardList() throws DataAccessException {
             List<BoardDTO> boardList = null;
             String sql = "select * from board";
             boardList = jdbcTemplate.query(sql, new RowMapper() {
                    public Object mapRow(ResultSet rs, int rowNum) throws SQLException {
                           BoardDTO board = new BoardDTO();
                           board.setSeq(rs.getInt("seq"));
                           board.setName(rs.getString("name"));
                           board.setPasswd(rs.getString("passwd"));
                           board.setTitle(rs.getString("title"));
                           board.setContent(rs.getString("content"));
                           board.setFileName(rs.getString("filename"));
                           board.setRegDate(rs.getString("regdate"));
                           board.setReadCount(rs.getInt("readcount"));
                           board.setReply(rs.getInt("reply"));
                           board.setReply_step(rs.getInt("reply_step"));
                           board.setReply_level(rs.getInt("reply_level"));
                           return board;
                    }
             });
             return boardList;
       }
       // 게시물 본문내용 미리보기(/preView)
       public String preView(String seq) throws DataAccessException {
             String sql = "select * from board where seq = ?";
             String preContent = (String) jdbcTemplate.queryForObject(sql,
                           new Object[] { seq }, new RowMapper() {
                                 public Object mapRow(ResultSet rs, int rowNum)
                                              throws SQLException {
                                        return rs.getString("content");
                                 }
                           });
             return preContent;
       }
       // 게시판 상세보기, 게시글 읽기
       public BoardDTO readContent(String seq) throws DataAccessException {
             String sql = "select * from board where seq = ?";
             BoardDTO boardDTO = (BoardDTO) jdbcTemplate.queryForObject(sql,
                           new Object[] { seq }, new RowMapper() {
                                 public Object mapRow(ResultSet rs, int rowNum)
                                              throws SQLException {
                                        BoardDTO board = new BoardDTO();
                                        board.setSeq(rs.getInt("seq"));
                                        board.setName(rs.getString("name"));
                                        board.setPasswd(rs.getString("passwd"));
                                        board.setTitle(rs.getString("title"));
                                        board.setContent(rs.getString("content"));
                                        board.setFileName(rs.getString("filename"));
                                        board.setRegDate(rs.getString("regdate"));
                                        board.setReadCount(rs.getInt("readcount"));
                                        board.setReply(rs.getInt("reply"));
                                        board.setReply_step(rs.getInt("reply_step"));
                                        board.setReply_level(rs.getInt("reply_level"));
                                        return board;
                                 }
                           });
             // 조회수 1증가
             this.updateReadCount(new Integer(boardDTO.getSeq()).toString());
            
             return boardDTO;
       }
       //읽은 글의 조회수를 1증가
       public int updateReadCount(String seq) throws DataAccessException {
             String sql = "update board set readcount = nvl(readcount,0) + 1 where seq = ?";
             Object[] obj = { seq };
            
             return jdbcTemplate.update(sql, obj);
       }
       //커멘트 입력
       public int insertComment(CommentDTO commentDTO) throws DataAccessException {
             String sql = "insert into comment_t(seq, name, comm) values (?, ?, ?)";
            
             Object[] obj = {commentDTO.getSeq(),      //게시글순번
                                   commentDTO.getName(),     //작성자
                                   commentDTO.getComment()}; //커멘트
             return jdbcTemplate.update(sql, obj);
       }
       //커멘트 조회
       public List<CommentDTO> commentList(String seq) throws DataAccessException {
             String sql = "select * from comment_t where seq = ?";
            
             List<CommentDTO> commentList = jdbcTemplate.query
                                    (sql, 
                                     new Object[] { seq },
                          new RowMapper() {
                                    public Object mapRow(ResultSet rs, int rowNum) throws SQLException {
                                           CommentDTO commentDTO = new CommentDTO();
                                           commentDTO.setName(rs.getString("name"));
                                           commentDTO.setComment(rs.getString("comm"));
                                         
                                           return commentDTO;       
                                    }
                                    });
             return commentList;
       }
}
4.  service 클래스를 만들어 보자.
[BoardService.java]
소스 코드 빨강색 부분이 커멘트 입력, 조회를 위해 추가된 부분
package onj.board.service;
import java.util.List;
import onj.board.model.BoardDTO;
import onj.board.model.CommentDTO;
/*
 * 게시판에서 구현할 기능을 인터페이스로 정의
 */
public interface BoardService {
       //게시판 리스트 보기
       public List<BoardDTO> boardList();     
      
       //게시물 미리보기
       public String preView(String seq);
      
       //게시판 본문 내용보기, 게시글 읽기
       public BoardDTO readContent(String seq);
      
       //커멘트 입력
       public int insertComment(CommentDTO commentDTO);
      
       //커멘트 조회
       public List<CommentDTO> commentList(String seq);
}
[SpringServiceImpl.java]
소스 코드 빨강색 부분이 커멘트 조회, 입력 기능을 위해 추가된 부분
package onj.board.service;
import java.util.List;
import onj.board.dao.BoardDAO;
import onj.board.model.BoardDTO;
import onj.board.model.CommentDTO;
public class BoardServiceImpl implements BoardService {
    private BoardDAO boardDAO;
   
    public void setBoardDAO(BoardDAO boardDAO) {
        this.boardDAO = boardDAO;
    }
   
    //게시물 리스트 보기
    public List<BoardDTO> boardList() {
        return boardDAO.boardList();
    }
   
    //게시물 본문 내용 미리보기
    public String preView(String seq) {
        return boardDAO.preView(seq);
    }
    //게시글 읽기
       public BoardDTO readContent(String seq) {
             return boardDAO.readContent(seq);
       }
       //커멘트 입력
       public int insertComment(CommentDTO commentDTO) {
             return boardDAO.insertComment(commentDTO);
       }
       //커멘트 조회
       public List<CommentDTO> commentList(String seq) {
             return boardDAO.commentList(seq);
       }   
}
5.     이번에는 컨트롤러를 수정하자.
조금 달라진 부분은 게시 글을 읽을 때 해당 글의 커멘트도 같이 화면에 보일 수 있도록 뷰에 커멘트 리스트를 매달아서(addObject해서) 보낸다.
[BoardMultiController.java]
소스 코드 빨강색 부분이 커멘트 조회, 입력 기능을 위해 추가된 부분
package onj.board.controller;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import onj.board.model.CommentDTO;
import onj.board.service.BoardService;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.multiaction.MultiActionController;
/*
 * MultiActionController는 비슷하거나 관련있는 로직을 수행하는
 * 다수의 액션을 가지고 있을 때 사용하는 컨트롤러
 * 연관된 요청(Request)를 묶을 때 용이함
 */
public class BoardMultiController extends MultiActionController {
           private BoardService boardService;
          
           public void setBoardService(BoardService boardService) {
                     this.boardService = boardService;
           }
          
           //게시판 리스트 보기, 페이징 기능은 구현 안함 
           public ModelAndView list(HttpServletRequest req, HttpServletResponse res) throws Exception {                     
                    
                     ModelAndView mv = new ModelAndView("list" , "list" , boardService.boardList());
                     return mv;                  
           }         
          
           //게시글 읽기
           public ModelAndView read(HttpServletRequest req, HttpServletResponse res) throws Exception {
                     String seq = req.getParameter("seq");
                    
                     ModelAndView mav = new ModelAndView("read" ,
                                                                  "read" ,
                                                                   boardService.readContent(seq));
                     //해당 글의 커멘트도 함께 내려 보내자.
                     mav.addObject("comments", boardService.commentList(seq));
                     return mav;
                    
           }
          
           //커멘트쓰기
           public ModelAndView comment(HttpServletRequest req, HttpServletResponse res) {
                    
                     String seq = req.getParameter("seq");
                    
                     CommentDTO commentDTO = new CommentDTO();
                     commentDTO.setSeq(seq);
                     commentDTO.setName(req.getParameter("name"));
                     commentDTO.setComment(req.getParameter("comment"));
                     boardService.insertComment(commentDTO);
                    
                     return new ModelAndView("redirect:/read.html?seq=" + seq);
           }
          
}
6.     커멘트 기능이 추가된 뷰페이지 read.jsp를 작성하자.
소스 코드 빨강색 부분이 커멘트 조회, 입력 기능을 위해 추가된 부분
[read.jsp]
<%@ page contentType="text/html; charset=euc-kr" language="java" import="java.sql.*" errorPage="" %>
<%@ page import = "onj.board.model.* , onj.board.service.* , java.util.*" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>게시물 읽기</title>
<meta http-equiv="Content-Type" content="text/html; charset=euc-kr">
<script>
       function write_ok(){
             writeform.submit();
       }
</script>
</head>
<body>
<div style="width:600px;">
<div style="float:enter;">
<table width="600" height="420" border="1" align="center">
  <tr height="20"><h2>오엔제이프로그래밍실무교육센터 게시판</h2></tr>
  <tr>
    <td width="100">* 이름</td>
    <td width="500">: <input name="name" type="text" value="${read.name}" size="50" readonly>
      </td>
  </tr>
  <tr>
    <td>* 제목</td>
    <td>:
    <input name="title" type="text" value="${read.title}" size="50" readonly></td>
  </tr>
  <tr align="center">
    <td colspan="2"><textarea name="content" cols="80" rows="12" readonly>${read.content}</textarea></td>
  </tr>
  <tr>
    <td>* 파일</td>
    <td>:
                    <c:choose>
                           <c:when test="${read.fileName != null}">
                                 ${read.fileName}                                    
                           </c:when>
                           <c:when test="${read.fileName == null}">
                                 파일 없음
                           </c:when>
                    </c:choose>
       </td>
  </tr>
  <tr>
    <td> </td>
    <td><input name="button" type="button" onClick="location.href='./reply.html?seq=${read.seq}'" value="답변">
|
  <input name="button" type="button" value="수정">
|
<input name="button" type="button" onClick="location.href='./delete.jsp?seq=${read.seq}'" value="삭제">
|
<input name="button" type="button" onClick="location.href='./list.html'" value="목록"></td>
  </tr>
  <tr>
    <td height="99" colspan="2">
    <!-- BoardMultiController comment() 메소드 호출 -->
    <form method="post" action="comment.html">
           <table border="1">
             <tr>          
               <td>이름 : </td>
               <td><input type="text" name="name"></td>
               <td>코멘트:</td>
               <td><input type="text" name="comment"></td>
               <td><input type="submit" name="Button" value="쓰기"></td>
             </tr>
           </table>
           <input type="hidden" name="seq" value="${read.seq}">
    </form>
            <!--  달려있는 커멘트 보기 -->
              <table width="789" border="1">
                  <c:forEach var="comment" items="${comments}">
                               <tr>
                              <td width="42" align="center">*</td>
                              <td width="86">${comment.name}</td>
                              <td width="639">${comment.comment}</td>
                            </tr>
                        </c:forEach>
             </table>
      </td>
    </tr>
   
</table>
<br><br>
<table><tr><td><tr><b>http://www.onjprogramming.co.kr</tr></td></tr></table>
<input type="hidden" name="seq" value="${read.seq}">
<input type="hidden" name="reply" value="${read.reply}">
<input type="hidden" name="reply_step" value="${read.reply_step}">
<input type="hidden" name="reply_level" value="${read.reply_level}">
</div>
</div>
</body>
</html>
7.     action-servlet.xml을 수정하자.
소스 코드 빨강색 부분이 커멘트 조회, 입력 기능을 위해 추가된 부분
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
    "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
       <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
             destroy-method="close">
             <property name="driverClassName">
                    <value>oracle.jdbc.driver.OracleDriver</value>
             </property>
             <property name="url">
                    <value>jdbc:oracle:thin:@127.0.0.1:1521:onj</value>
             </property>
             <property name="username">
                    <value>scott</value>
             </property>
             <property name="password">
                    <value>tiger</value>
             </property>
       </bean>
       <!-- 넘어오는 URL 따라 컨트롤러에서 실행될 메소드 매핑 -->
       <!-- PropertiesMethodNameResolver prop key 넘어오는 url 대해 실행할 컨트롤러의 메소드
             정의 -->
       <bean id="userControllerMethodNameResolver"
              class="org.springframework.web.servlet.mvc.multiaction.PropertiesMethodNameResolver">
             <property name="mappings">
                    <props>
                           <!-- list.html 요청이 오면 컨트롤러의 list 메소드 실행 -->
                           <prop key="/list.html">list</prop>
                          
                           <!-- read.html 요청이 오면 컨트롤러의 read 메소드 실행 -->
                           <prop key="/read.html">read</prop>
                          
                           <!-- comment.html 요청이 오면 컨트롤러의 comment 메소드 실행 -->
                           <prop key="/comment.html">comment</prop>                         
                    </props>
             </property>
       </bean>
       <!-- 리졸버 -->
       <bean id="viewResolver"
             class="org.springframework.web.servlet.view.InternalResourceViewResolver">
             <property name="prefix">
                    <value>/jsp/</value>
             </property>
             <property name="suffix">
                    <value>.jsp</value>
             </property>
       </bean>
       <!-- 컨트롤러 매핑 -->
       <bean name="/list.html /read.html /comment.html" class="onj.board.controller.BoardMultiController">
             <property name="methodNameResolver">
                    <ref local="userControllerMethodNameResolver" />
             </property>
             <property name="boardService">
                    <ref bean="boardService" />
             </property>
       </bean>
      
</beans>
실행결과 및 현재까지 만들어진 이클립스 구조
(게시판 리스트보기 + 게시물 본문내용 미리 보기 + 게시글 상세보기 + 커멘트기능)
:namespace prefix = v ns = "urn:schemas-microsoft-com:vml" />




>