- 우선, STRUTS 에서 구성하는 방법 세가지

1. POJO(Plain Old Java Object)

2. implements Action

3. extends ActionSupport    (유효성 체크 가능 : validate() )

요건 알고 시작해야지!

- 2번째 implements Action 에서 도메인 오브젝트(모델영역 : ex - User.java)

모델영역의 도메인 오프젝트를 독립적으로 분리시킴으로써, 어떤 프레임워크 상에서 어떤 뷰를 사용해서 어떻게 구현하였는지

에 대한 영향을 받지 않도록 하기위함.


MVC 패턴지향의 예(교재 : 스트럿츠2 프로그래밍 입문)

1. Model

2. Action

3. Dao

- 모델(Model : Bean.java) 생성(Getter * Setter) 후 struts.xml 에  <action name="" class=""></action> 등록하고

  package model;

public class User {

    private String userId;
    private String userPw;
    private String userName;

    /* Getter & Setter */
    public String getUserId() {
        return userId;
    }
    public void setUserId(String userId) {
        this.userId = userId;
    }
    public String getUserPw() {
        return userPw;
    }
    public void setUserPw(String userPw) {
        this.userPw = userPw;
    }
    public String getUserName() {
        return userName;
    }
    public void setUserName(String userName) {
        this.userName = userName;
    }

    /* toString */
    @Override
    public String toString() {
        String result;
        result =  "User [userId=" + userId + ", userPw=" + userPw + ", userName="
                + userName + "]";
        return result;
    }// end - toString Method

}// end - UserClass


- <action></action> 밑에 <interceptor-ref name="params"/> 등록해서 입력 폼에서 요청 파리미터와 같은 이름을 가진

   액션 프로퍼티에 값을 저장, 액션 수행 execute() 후 실행할 result 페이지 등록

<struts.xml>

        <!-- 도메인 오브젝트 테스트 -->
        <action name="UserRegForm2">
            <result>/jsp/userRegForm2.jsp</result>
        </action>
        <action name="UserRegAction2" class="action.UserRegAction2">
            <interceptor-ref name="params"/>
            <result name="success">/jsp/userRegSuccess.jsp</result>
        </action>


- action 페이지에서 도메인 오프젝트(Model : Bean) 생성, get, set 생성 후

execute() 메서드에서 Dao 호출하여 DB 작업

<UserRegAction2.java>

  package action;

import model.User;

import com.opensymphony.xwork2.Action;

import dao.UserDao;

public class UserRegAction2 implements Action {

    private User user;

    public User getUser() {
        return user;
    }

    public void setUser(User user){
        this.user = user;
    }

    @Override
    public String execute() throws Exception {
        /* Dao Instance Create */
        UserDao userDao = new UserDao();
        userDao.create(user);
        return SUCCESS;
    }// end - execute Method

}// end - UserRegAction2 class


- action 에서 Model 객체 Dao 넘김 -> Dao 에서 데이타베이트 처리(현 예제는 간단히 Model 객체 출력으로 대처)

<UserDao>

package dao;

import model.User;

public class UserDao {

    public void create(User user) {
        System.out.println("사용자를 추가하였습니다.");
        System.out.println("추가된 사용자의 정보");
        System.out.println(user);
    }// end - create Method

}// end - UserDao class


이런 방식인데. 현 주제의 implements Action 도메인 오브젝트 를 사용하면 입력 폼이 있는 JSP 페이지에서

<form action="action Name"> 으로 넘겨줄때 Parameter 이 액션객체로 넘어갈때. 액션에 생성된 Model 인스턴스명 + 변수명 을

같이 지정해 주어야 한다.

(※ 책에서 그냥 도메인오브젝트명이래서 긴가민가 하다 액션에서 Model 인스턴스명 변경하고 테스트하니 오류 발생)

<input type="text" name="액션에서생성한Model 인스턴스명.변수명"> -> <input type="text" name="user.userId">  이렇게!!!

또. action execute() SUCCESS 이후 struts.xml 에 등록한 <result name="success"></result> 에 등록한 페이지에서 보여줄때도

같은방식으로 보여줘야 한다. 예를 들면 아이디 : ${user.userId} 이렇게!!!!


와~ 신기하다!! 근데 조금만 쓰면 입력 폼이 존재하는 JSP 와 결과를 보여줄 JSP 모든 뷰에서 action 에서 생성한 인스턴스명을 꼭

붙여주여야 해서 어간 불편한게 아닐수 아닐수 아닐수 없을수 없다.

그래서. 사용하는것이 "ModelDriven" 와 "Preparable" 두개이다. 이건 다음장에서 설명









- JAVA 스터디 중 스터디장이 댓글 게시판 숙제로 구글 중 내가 적용한 알고리즘(까먹을까봐-_-)


계층형 게시판을 위한 테이블의 구성 및 알고리즘은 워낙 다양하기 때문에 특별히 정해진 솔류션은 존재하지 않습니다.
여기서는 많은 책자에서 소개되어 있는 간단한 계층형 게시판의 구조와 알고리즘에 대해서 알아봅니다.

 

설명을 위해 테이블에는 다음과 같은 컬럼들만 있다고 가정합니다. 실제로는 더 많겠죠.

No : 글번호(Primary Key)
Title : 글제목
Grp : 같은 주제를 갖는 게시물의 고유번호. 부모글과 부모글로부터 파생된 모든 자식글은 같은 번호를 갖습니다.
Seg : 같은 그룹내 게시물의 순서
Lvl : 같은 그룹내 계층

 

게시판에 첫번째 글이 올라오면, 테이블에는 다음과 같은 정보가 저장됩니다.

====================================
No, Title            , Grp, Seq, Lvl
====================================
 1, '안녕하세요'     ,   1,   1,   0

====================================

새 글에서 No는 시퀀스로부터 받아온 값, Grp는 No와 동일한 값, Seq는 1, Lvl은 0입니다.

 

두번째 글과 세번째 글이 올라옵니다.

====================================
No, Title            , Grp, Seq, Lvl
====================================
 3, '모임이 있습니다',   3,   1,   0
 2, '날씨가 맑습니다',   2,   1,   0
 1, '안녕하세요     ',   1,   1,   0

====================================

 

첫번째 글에 답글이 올라옵니다.

====================================
No, Title            , Grp, Seq, Lvl
====================================
 3, '모임이 있습니다',   3,   1,   0
 2, '날씨가 맑습니다',   2,   1,   0
 1, '안녕하세요     ',   1,   1,   0
 4, '  반가워요     ',   1,   2,   1 

====================================

답글의 경우, Grp는 부모글의 Grp 값, Seq는 부모글의 Seq+1, Lvl은 부모글의 Lvl+1이 됩니다.

 

첫번째 글의 답글에 답글이 올라옵니다. 즉, 네번째 글의 답글이 올라옵니다.

====================================
No, Title            , Grp, Seq, Lvl
====================================
 3, '모임이 있습니다',   3,   1,   0
 2, '날씨가 맑습니다',   2,   1,   0
 1, '안녕하세요     ',   1,   1,   0
 4, '  반가워요     ',   1,   2,   1 
 5, '    감사합니다 ',   1,   3,   2

====================================

 

첫번째 글의 두번째 답글이 올라옵니다.

====================================
No, Title            , Grp, Seq, Lvl
====================================
 3, '모임이 있습니다',   3,   1,   0
 2, '날씨가 맑습니다',   2,   1,   0
 1, '안녕하세요     ',   1,   1,   0
 6, '  환영합니다   ',   1,   2,   1 
 4, '  반가워요     ',   1,   2,   1 
 5, '    감사합니다 ',   1,   3,   2

====================================

 

여기서, 두번째 답글이 첫번째 답글보다 먼저 표시되려면, 동일한 그룹 번호에 있으면서 부모의 Seq 번호보다 큰 게시물의 Seq 번호를 모두 1만큼 증가시킵니다.

====================================
No, Title            , Grp, Seq, Lvl
====================================
 3, '모임이 있습니다',   3,   1,   0
 2, '날씨가 맑습니다',   2,   1,   0
 1, '안녕하세요     ',   1,   1,   0
 6, '  환영합니다   ',   1,   2,   1
 4, '  반가워요     ',   1,   3,   1
 5, '    감사합니다 ',   1,   4,   2

====================================

 

여섯번째 게시물에 답글이 올라옵니다.

====================================
No, Title            , Grp, Seq, Lvl
====================================
 3, '모임이 있습니다',   3,   1,   0
 2, '날씨가 맑습니다',   2,   1,   0
 1, '안녕하세요     ',   1,   1,   0
 6, '  환영합니다   ',   1,   2,   1
 7, '    감사합니다 ',   1,   3,   2
 4, '  반가워요     ',   1,   3,   1
 5, '    감사합니다 ',   1,   4,   2

====================================

 

마찬가지로 동일한 그룹 번호에 있으면서 부모의 Seq 번호보다 큰 게시물의 Seq 번호를 모두 1만큼 증가시킵니다.

====================================
No, Title            , Grp, Seq, Lvl
====================================
 3, '모임이 있습니다',   3,   1,   0
 2, '날씨가 맑습니다',   2,   1,   0
 1, '안녕하세요     ',   1,   1,   0
 6, '  환영합니다   ',   1,   2,   1
 7, '    감사합니다 ',   1,   3,   2
 4, '  반가워요     ',   1,   4,   1
 5, '    감사합니다 ',   1,   5,   2

====================================

 

검색 할 때는 Grp를 내림차순으로 Seq를 오름차 순으로 정렬하면 됩니다. 인덱스는 기본키와 Grp+Seq의 복합 인덱스를 설정하면 됩니다.

 

실제 오라클에서 테이블을 구성하고 검색해봅니다.

 

drop table qnaboard;

 

create table qnaboard
(no number,
 title varchar2(100),
 contents varchar2(4000),
 writer varchar2(20),
 wdate date,
 grp number,
 seq number,
 lvl number);

 

drop sequence qnaboard_no_seq;

 

create sequence qnaboard_no_seq
start with 1
increment by 1;

 

create index qnaboard_no_idx on qnaboard(no) reverse;

 

alter table qnaboard
add constraint qnaboard_no_pk primary key (no);

 

create index qnaboard_grp_seq on qnaboard(grp desc, seq asc);

alter session set nls_date_format='yyyy-mm-dd hh24:mi:ss';

 

첫번째 게시물 입력 - 새 글 입력
insert into qnaboard
values(qnaboard_no_seq.nextval, '안녕하세요', null, '길동', sysdate, qnaboard_no_seq.currval, 1, 0);

 

두번째 게시물 입력 - 새 글 입력
insert into qnaboard
values(qnaboard_no_seq.nextval, '날씨가 맑습니다', null, '철수', sysdate, qnaboard_no_seq.currval, 1, 0);

 

세번째 게시물 입력 - 새 글 입력
insert into qnaboard
values(qnaboard_no_seq.nextval, '모임이 있습니다', null, '영희', sysdate, qnaboard_no_seq.currval, 1, 0);

 

네번째 게시물 입력 - 첫번째 게시물의 답글

답글이 올라오는 경우에는 답글에 부여 할 seq를 먼저 확보해줍니다.
update qnaboard
set seq=seq+1
where grp=1 and seq>1;

 

insert into qnaboard
values(qnaboard_no_seq.nextval, '반가워요', null, '만수', sysdate, 1, 2, 1);

 

다섯번째 게시물 입력 - 네번째 게시물의 답글
update qnaboard
set seq=seq+1
where grp=1 and seq>2;

 

insert into qnaboard
values(qnaboard_no_seq.nextval, '감사합니다', null, '길동', sysdate, 1, 3, 2);

 

여섯번째 게시물 입력 - 첫번째 게시물의 두번째 답글
update qnaboard
set seq=seq+1
where grp=1 and seq>1;

 

insert into qnaboard
values(qnaboard_no_seq.nextval, '환영합니다', null, '찬호', sysdate, 1, 2, 1);
 
일곱번째 게시물 입력 - 여섯번째 게시물의 답글
update qnaboard
set seq=seq+1
where grp=1 and seq>2;

 

insert into qnaboard
values(qnaboard_no_seq.nextval, '감사합니다', null, '길동', sysdate, 1, 3, 2);

 

게시판을 검색하는 경우, grp로 내림차순, seq로 오름차순으로 정렬하면 됩니다.
select case when lvl=0 then no
            when lvl>0 then null end no
, rpad('+', lvl, '-')||title title
, writer
, wdate
from qnaboard
order by grp desc, seq;


   NO TITLE                WRITER     WDATE
----- -------------------- ---------- -------------------
    3 모임이 있습니다      영희       2007-09-15 19:54:00
    2 날씨가 맑습니다      철수       2007-09-15 19:53:55
    1 안녕하세요           길동       2007-09-15 19:53:50
      +환영합니다          찬호       2007-09-15 19:54:21
      +-감사합니다         길동       2007-09-15 19:54:26
      +반가워요            만수       2007-09-15 19:54:08
      +-감사합니다         길동       2007-09-15 19:54:15

스트럿츠2 프레임워크 유효성 검사 지원

1. 신규 회원의 정보를 입력하는 폼에서 입력한 값의 유효성 검사

2. 입력 폼의 <form action=" ">에 struts.xml 에 입력한 action.class(extends ActionSupport) 넘긴 후

    (※ 입력 폼에서 -> action.class 로  웹 페이지의 모든 파라미터 값들이 자동으로 액션의 프로퍼티 값으로 세팅되게

        하려면 struts.xml <action> </action> 내에 <interceptor-ref name="params"/> 가 지정되야 한다.)

3. struts.xml 에 입력한 action.class 에서 유효성 체크 메소드

 public void validate() {

if()

addFielError("FieldName","ErrorMessage");

}

4. action.calss 에서 validate(){} 메서드 중에 if() 에 지정한 유효성에 충족치 않으면.

(※ 2번과 동일하게 validate() 검사를 하기위해서는 struts.xml <action></action> 내에

 <interceptor-ref name="validation"/>

 <interceptor-ref name="workflow"/>

가 존재하여야 한다. 그래야 5번의 RETURN INPUT 으로 반환하고. SUCCESS RESULT 를 실행하지 않는다.)

5. action.class 안에 execute() 메서드의 return 의 값이 SUCCESS 대신 INPUT 이 반환된다.

      6. INPUT 반환 후 에 result 가 INPUT 일때의 포워딩 설정

<action></action> 내에 <result name="input">/userRegForm.jsp</result>

    <result name="success>/userRegSuccess.jsp</result>

---------- 위의 설명에 충족한 struts.xml 참조 ---------

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
    "http://struts.apache.org/dtds/struts-2.3.dtd">
  
<struts>
    <package name="actionSupport" namespace="" extends="struts-default">
        <action name="UserRegForm">
            <result>/userRegForm.jsp</result>
        </action>
        <action name="UserRegAction" class="action.UserRegAction">
            <interceptor-ref name="params"/>
            <interceptor-ref name="validation"/>
            <interceptor-ref name="workflow"/>
            <result name="input">/userRegForm.jsp</result>  -> 유효성 검사 실패시 return INPUT 성공시 SUCCESS
            <result name="success">/userRegSuccess.jsp</result>
        </action>
    </package>
</struts>


- 요소

필터 :URL의 확장자가 action 이면 FilterDispatcher 에 의해서 액션을 실행하기 위한 환경을 구축하도록 한다  (web.xml)

/* web.xml(struts2-core-2.3.4.1.jar) */

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
  <display-name>struts2_ActionSupport</display-name>
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.htm</welcome-file>
    <welcome-file>index.jsp</welcome-file>
    <welcome-file>default.html</welcome-file>
    <welcome-file>default.htm</welcome-file>
    <welcome-file>default.jsp</welcome-file>
  </welcome-file-list>
 
  <!-- Struts2 FilterDispatcher -->
    <filter>
        <filter-name>struts2</filter-name>
        <filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
            <!-- Struts2 인코딩 설정(struts-default 참조) -->
            <init-param>
                <param-name>struts.i18n.encoding</param-name>
                <param-value>UTF-8</param-value>
            </init-param>
            <!-- Struts2 인코딩 설정(struts-default 참조) -->
    </filter>
    <filter-mapping>
        <filter-name>struts2</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
 
</web-app>



액션 : 리절트가 필요로 하는 메시지를 제공한다 (action.java)

/* action.java */

package action;

import com.opensymphony.xwork2.ActionSupport;

/* Struts2 ActionSupport 상속 */
public class UserRegAction extends ActionSupport{

    private String userId;
    private String userPw;
    private String userName;

    /* Getter & Setter */
    public String getUserId() {
        return userId;
    }

    public void setUserId(String userId) {
        this.userId = userId;
    }

    public String getUserPw() {
        return userPw;
    }

    public void setUserPw(String userPw) {
        this.userPw = userPw;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    @Override
    public String execute()throws Exception{
        return SUCCESS;
    }//end - execute Method


    @Override
    public void validate() {
        if(userId == null || userId.equals("")) {
            addFieldError("userId", "회원아이디를 입력해 주십시오");
        }
        if(userPw == null || userPw.equals("")) {
            addFieldError("userPw", "비밀번호를 입력해 주십시오");
        }
        if(userName == null || userName.equals("")) {
            addFieldError("userName", "이름을 입력해 주십시오");
        }
    }// end - validate Method()

}// end - class



매핑액션 : 실행 후 결과를 처리할 리절트와의 매피을 설정  (struts.xml)

/* struts.xml */

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
    "http://struts.apache.org/dtds/struts-2.3.dtd">
   
<struts>
    <package name="actionSupport" namespace="" extends="struts-default">
        <action name="UserRegForm">
            <result>/userRegForm.jsp</result>
        </action>
        <action name="UserRegAction" class="action.UserRegAction">
            <interceptor-ref name="params"/>
            <interceptor-ref name="validation"/>
            <interceptor-ref name="workflow"/>
            <result name="input">/userRegForm.jsp</result>
            <result name="success">/userRegSuccess.jsp</result>
        </action>
    </package>
</struts>



리절트 : 메시지를 출력하기 위한 화면 처리를 담당  (view.jsp)

/* view.jsp */

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>회원가입 결과</title>
</head>
<body>
    <center>
    <b><font color="red">회원 가입이 완료되었습니다.</font></b><p>
    아 이 디 : ${userId}<p>
    비밀번호 : ${userPw}<p>
    이 름 : ${userName}<p>
    </center>
</body>
</html>

1. Statement

- JDBC로드 -> DB Connection 연결 -> 쿼리

/* JDBC 드라이브 로드 */
        Class.forName("oracle.jdbc.OracleDriver");

        /* DB연결 */
        Connection conn = DriverManager.getConnection(
                "jdbc:oracle:thin:@localhost:1521:orcl", "scott", "scott")

String query = "INSERT INTO USERINFO(NAME, ID, PASSWORD) VALUES(" + name + "," + id + "," + password + ")";

if(conn != null){

Statement stmt = conn.createStatement();

stmt.executeUpdate(query);

}



2. PreparedStatement

- JDBC로드 -> DB Connection 연결 -> 쿼리

/* JDBC 드라이브 로드 */
        Class.forName("oracle.jdbc.OracleDriver");

        /* DB연결 */
        Connection conn = DriverManager.getConnection(
                "jdbc:oracle:thin:@localhost:1521:orcl", "scott", "scott")

String query = "INSERT INTO USERINFO(NAME, ID, PASSWORD) VALUES(?, ?, ?)";

if(conn != null){
                PreparedStatement pstmt = conn.prepareStatement(query);
                pstmt.setString(1, name);
                pstmt.setString(2, id);
                pstmt.setString(3, password);
                pstmt.executeUpdate();
            }



※ PreparedStatement 가 훨씬 편함.

    예제)

<%@page import="java.sql.PreparedStatement"%>
<%@page import="java.sql.DriverManager"%>
<%@page import="java.sql.Driver"%>
<%@page import="java.sql.Statement"%>
<%@page import="java.sql.Connection"%>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" errorPage="DBError.jsp"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title></title>
</head>
<body>
    <%
        request.setCharacterEncoding("UTF-8");
   
        String name = request.getParameter("name");
        String id = request.getParameter("id");
        String password = request.getParameter("password");
       
        if(name == null || id ==null || password == null){
            throw new Exception("데이타를 입력하세요");
        }
        Connection conn = null;
        PreparedStatement pstmt = null;
       
        String DBurl = "jdbc:oracle:thin:@localhost:1521:orcl";
        String DBuser = "scott";
        String DBpassword = "scott";
        try{
            Class.forName("oracle.jdbc.OracleDriver");
            conn = DriverManager.getConnection(DBurl, DBuser, DBpassword);
           
            String query = "INSERT INTO USERINFO(NAME, ID, PASSWORD) VALUES(?, ?, ?)";
           
            if(conn != null){
                pstmt = conn.prepareStatement(query);
                pstmt.setString(1, name);
                pstmt.setString(2, id);
                pstmt.setString(3, password);
                pstmt.executeUpdate();
            }
            else {
                throw new Exception("DB 연결 실패!");
            }
        }
        finally{
            pstmt.close();
            conn.close();
        }
        response.sendRedirect("SubscriptionResult.jsp");
        %>
</body>
</html>


- CASE : 기능적 측변에서 DECODE와 흡사하지만 좀 더 확장된 기능을 제공

  • - CASE 함수는 DECODE함수가 제공하지 못하는 비교연산의 단점을 해결할 수 있는 함수이다.
  • - DECODE함수에서 비교연산을 수행하기 위해서는 GREATEST, LEAST등의 함수를 사용해야 하지만, 
  •   CASE함수에서는 조건 연산자를 모두 사용 할 수 있다.
  • - CASE함수는 IF.. THEN .. ELSE 구문과 비슷 하다. WHEN절 다음에 여러 조건이 올 수 있다.


- 사용법

CASE
WHEN (조건1) THEN
(값1)
WHEN (조건2) THEN
(값2)
ELSE
(값3)
END

=> 조건1이면, 값1, 조건2이면 값2, 그 외에는 값3을 출력

- 예제

위의 DECODE예제를 CASE함수로 변환한 예이다.
--위의  DECODE예제를 CASE함수로 변환한 예이다. 
SELECT deptno, 
       CASE deptno
         WHEN 10 THEN 'ACCOUNTING'
         WHEN 20 THEN 'RESEARCH'
         WHEN 30 THEN 'SALES'
         ELSE 'OPERATIONS'
       END as "Dept Name"
  FROM dept;

DEPTNO Dept Name
------- ----------
     10 ACCOUNTING
     20 RESEARCH
     30 SALES
     40 OPERATIONS 

아래는 WHEN절 다음에 연산자가 오는 예제이다.

--급여별로 인상율을 다르게 계산하였다. 
SELECT ename ,
       CASE
          WHEN sal < 1000  THEN sal+(sal*0.8)
          WHEN sal BETWEEN 1000 AND 2000 THEN sal+(sal*0.5)
          WHEN sal BETWEEN 2001 AND 3000 THEN sal+(sal*0.3)
          ELSE sal+(sal*0.1)
       END sal
  FROM emp; 


'공부 > ORACLE_SQL' 카테고리의 다른 글

ORACLE_[ 집계함수(Aggregate function) ]  (0) 2013.05.20
ORACLE_[ OUTER JOIN ]  (0) 2013.05.20
ORACLE_[ JOIN ]  (2) 2013.05.20
ORACLE_[CREATE TABLE]  (0) 2013.01.09
ORACLE_[DECODE문_사용법]  (0) 2012.10.05

- DECODE문 : 자바문법으로 따지면 IF ~ ELSE IF ~ ELSE 와 같은 구조

- DECODE 함수는 조건에 따라 데이터를 다른 값이나 컬럼값으로 추출 할 수 있다.

- DECODE(VALUE, IF1, THEN1, IF2, THEN2...) 형태로 사용 할 수 있다.

- VALUE 값이 IF1일 경우에 THEN1 값을 반환하고, VALUE 값이 IF2일 경우에는 THEN2 값을 반환한다.

- DECODE 함수 안에 DECODE함수를 중첩으로 사용 할 수 있다.


- 구문

DECODE({column | expression}, search1, result1 [,search2,result2] ...

[,default] )

: column 값이 search1 이면, result1 출력, 아니면 default 출력

 

- 예제

아래는 DECODE 함수의 일반적인 예제이다.

-- 부서번호가 10이면 ACCOUNTING, 20이면 RESEARCH, 30이면 SALES
-- 나머지는 OPERATIONS를 출력하는 예제
SELECT deptno, DECODE(deptno, 10 , 'ACCOUNTING' ,
                              20 , 'RESEARCH' ,
                              30 , 'SALES', 'OPERATIONS') name
  FROM dept;

DEPTNO NAME
------ ----------
     10 ACCOUNTING
     20 RESEARCH
     30 SALES
     40 OPERATIONS

아래는 DECODE 함수에서 집계 함수를 사용한 예제이다

-- 10부서는 급여합계를, 20부서는 최대값을, 30부서는 최소값을 출력하는 예제
SELECT deptno, DECODE(deptno, 10 , SUM(sal),
                              20 , MAX(sal),
                              30 , MIN(sal)) sal
  FROM emp
 GROUP BY deptno; 

DEPTNO        SAL
--------- --------
       30      950
       20     3000
       10     8750 

DECODE함수는 집계함수와 함께 통계 데이터를 추출할 때 많이 사용한다. 아래는 부서별로 급여합계를 조회하는 예이다

-- 부서별로 급여 합계를 출력한다. 
SELECT deptno, NVL(SUM(DECODE(deptno, 10, sal)),0) deptno10, 
               NVL(SUM(DECODE(deptno, 20, sal)),0) deptno20,
               NVL(SUM(DECODE(deptno, 30, sal)),0) deptno30,
               NVL(SUM(DECODE(deptno, 40, sal)),0) deptno40
  FROM emp
 GROUP BY deptno; 

DEPTNO   DEPTNO10   DEPTNO20   DEPTNO30   DEPTNO40
------- --------- --------- ---------- ----------
     30         0         0       9400          0
     20         0     10875          0          0
     10      8750         0          0          0 

아래 부서별 급여합계 예를 보면 일반적인 집계함수를 사용할 때는 급여 합계가 행으로 조회가 되지만, DECODE와 MAX함수를 사용하면 열로 값을 표시할 수 있다.

-- 부서별로 급여 합계를 행으로 출력한다. 
SELECT d.deptno, NVL(SUM(e.sal),0) sal
  FROM emp e, dept d
 WHERE e.deptno(+) = d.deptno
 GROUP BY d.deptno; 

DEPTNO        SAL
-------- ----------
      10       8750
      20      10875
      30       9400
      40          0



-- 부서별로 급여 합계를  열로 출력한다. 
SELECT MAX(NVL(SUM(DECODE(deptno, 10, sal)),0)) deptno10, 
       MAX(NVL(SUM(DECODE(deptno, 20, sal)),0)) deptno20,
       MAX(NVL(SUM(DECODE(deptno, 30, sal)),0)) deptno30,
       MAX(NVL(SUM(DECODE(deptno, 40, sal)),0)) deptno40
  FROM emp
 GROUP BY deptno; 

DEPTNO10   DEPTNO20   DEPTNO30   DEPTNO40
--------- ---------- ---------- ----------
    8750      10875       9400          0


'공부 > ORACLE_SQL' 카테고리의 다른 글

ORACLE_[ 집계함수(Aggregate function) ]  (0) 2013.05.20
ORACLE_[ OUTER JOIN ]  (0) 2013.05.20
ORACLE_[ JOIN ]  (2) 2013.05.20
ORACLE_[CREATE TABLE]  (0) 2013.01.09
ORACLE_[CASE문 사용법]  (0) 2012.10.05

- JSTL 의 함수 라이브러리는 익스프레이션 언어(EL) 식 안에서 사용할수 있는 함수 라이브러리

이 함수들은 주로 문자열을 처리하는 일을 하며, 자바 JDK 라이브러리의 java.lang.String 클래스에 속하는 메서드들과 거의 같은 기능을 제공한다.

예) substring, trim

 

- 사용법

 

1. Taglib 등록

<%@ taglib prefix="fn" uri=http://java.sun.com/jsp/jstl/functions %>

 

2. 함수 라이브러리의 함수들

1) substring(str, index1, index2) : str 의 index1 부터 index2 - 까지의 문자열 리턴

2) substringAfter(str1, str2) : str1 에서 str2 를 찾아서 그 후의 부분문자열 리턴

3) substringBefore(str1, str2) : str1 에서 str2 를 찾아서 그 전의 부분문자열 리턴

4) toUpperCase(str) : 모든 소문자를 대문자로 치환한 값을 리턴

5) toLowerCase(str) : 모든 대문자를 소문자로 치환한 값을 리턴

6) trim(str) : 문자열에서 앞뒤 공백 문자를 제거한 결과를 리턴

7) replace(str, src, dest) : str 문자열에 포함된 src 를 dest 로 치환한 결과를 리턴

8) indexOf(str1, str2) : str1에 포함된 str2의 시작 인덱스를 리턴

9) startsWith(str1, str2) : str1이  str2 로 시작하면 true, 그렇지 않으면 false 리턴

10) endsWith(str1, str2) : str1이 str2 로 끝나면 true, 그렇지 않으면 false 리턴

11) contains(str1, str2) str1이 str2를 포함하면 true, 그렇지 않으면 false 리턴(대소문자 구분)

12) containslgnoreCase(str1, str2) : str1이  str2를 포함하면 true, 그렇지 않으면 false 를 리턴,

contains 함수와는 달리 대소    문자 구별하지 않고 비교함.

13) split(str1, str2) : str1을 str2를 기준으로 분리해서 만든 부문자열들의 배열을 리턴

14) join(str1, str2) : arr 배열의 모든 항목을 합쳐서 리턴, 항목사이에는 str2가 들어옴

15) escapeXml(str) : HTML 문법에 의한 특수문자로 취급되는 모든 문자를 이스케이프 시퀀스로 치환하여 결과를 리턴

16) length(obj) : obj가 문자열이면 문자열의 길이, List 나 Collection 이면 항목의 수를 리턴.

 

3, 사용법

<c:set var="greeting" value="How Are You?" />

기본출럭 : ${greeting}

대문자 : ${fn:toUpperCase(greeting)}

소문자 : ${fn:toLowerCase(greeting)}

- 등록할 파일 : TLD 파일(ex : 웹어플리케이션/web-app/WEB-INF/tld/math-functons.tld)

 

- TLD 파일의 골격(TLD 파일 생성하기)

<taglib xmlns="http://java.sun.com/xml/ns/javaee" version="2.1">

                                (TLD 문법의 식별자)                (TLD 문법의 버전)

<tlib-version>1.0</tlib-version> -> 태그 라이브러리의 버젼

<short-name>math</short-name> -> 태그 라이브러리의 이름

<function>

<name>squareroot</name> ->  EL 함수의 이름(나름대로 정한 EL 함수의 명칭)

<function-class>java.lang.Math</function-class> -> 자바 정적메서드(static method)가 속하는 클래스 풀네임

<function-signature>double sqrt(double)</function-signature> -> 정적 메서드의 시그니처

</function>

</taglib>

 

- TLD 파일 생성을 하여도 바로 호출할 수 없다. web.xml 파일에 TLD 파일을 등록해야한다.

<web-app>

<taglib>

<taglib-uri>/math-functions.tld</taglib-uri> -> TLD 파일의 식별자 명칭

<taglib-location>tlds/math-functions.tld</taglib-location> -> TLD 파일의 실제 경로명

</taglib>

</web-app>

 

- JSP 페이지에 호출하기 위해 지시어(<%@ %>) 사용해서 등록하기

<%@taglib uri="/math-functions.tld" prefix="m" %>

 

- JSP 페이지에서 호출해서 사용하기

${m:squareroot(4)}

 설명 : java.lang.Math 클래스의 sqrt 메서드를 'squareroot' 라는 이름의 EL 함수로 등록한다!! 잊어버리자 말자.

 

----------------------------------------------------------------------------------------------------

※ 테스트를 하는데 web.xml 에 <taglib> 태그에서 오류가 발생!!!

    google 검색 결과 답변은...

web.xml 이부분에서
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">

빨간색으로 나타낸 부분을 지우면 된다.
XML 스키마나 DTD 지정은 JSP/Servlet 어플리케이션 지정할 때 매우 민감하게 작용합니다.
요즘에는 Servlet Spec 2.3 이 보통이고, 최근들어 2.4도 많이 쓰는 추세입니다. 2.2는 안쓰게 된지 오래됐습니다.
그러니까 처음에 지정한 DOCTYPE에서 2.2로 지정하면 안됩니다.(DOCTPYE 삭제해버린다) 
Servlet 스펙 2.4(가장 최신)에서는 web.xml 에서 TLD 파일을 지정하는 기능이 없다.

내 이클립스에서 생성된 web.xml version=2.5 에서 오류가 발생하는 것이다. 

해결방법

1. 위의 빨간 밑줄 부분을 삭제한다.

2. web.xml 에 TLD 파일 지정하지않고, 바로 JSP 에서 <%@ taglib uri="tld파일경로 지정" prefix="c" %>

    TLD 설치경로 : 웹 어플리케이션 디렉터리/WEB-INF 서브디렉터리 아래이면 어느 곳이든 상관 없다.

EX> 자바빈 클래스의 예

public class PersonInfo {

private String name;

private int age;

private String tell;

/* Getter & Setter */

    /* getter & setter */
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public void setTell(String tell) {
        this.tell = tell;
    }
    public void setTell(String tell) {
        this.tell = tell;
    }

} // end - class

 

EX> 자바빈 프로퍼티 입력 JSP

<%

PersonInfo personInfo = new PersonInfo();

personInfo.setName("daniel");

personInfo.setAge("27");

personInfo.setTell("177");

request.setAttribute("PERSONINFO", personInfo);

RequestDispatcher dispatcher =

request.getRequestDispatcher("-- forward 시킬 JSP 경로 --");

dispatcher.forward(request, response);

%>

 

EX> 자바빈 프로퍼티 받아서 출력하는 JSP

이름 : ${PERSONINFO.name}<br>

나이: ${PERSONINFO.age}<br>

번호: ${PERSONINFO.tell}<br>

 

※ 제발, 까져먹지말자...

+ Recent posts