Spring 시작하기-1

Spring 2007.01.27 22:02
20070122116945808128301_JPG
 

Spring로드존슨이만든오픈소스프레임워크이며,그의책인Expert one-on-one : j2ee design and development처음소개되었다한다.어라...이책봤는데..왜 몰랐지…

책에서스프링의원래이름은interface21었다.

 

스프링에대한감을잡기 위한 설명은…

 

1.경량

크기와부하의측면에서경량이고1MB크기의jar파일로배포된다.그리고스프링은침입적이지않다고한다.무슨말인지..스프링을도입한애플리케이션의객체가보통의경우스프링의특정클래스에대한의존성을갖지않는다는의미라고한다.그냥ejb비해의존성이없다는얘기로이해하고넘어가야겠다

 

2.제어역행

제어역행(IoC, Inversion of Control)이라는기술을통해애플리케이션의느슨한결합을도모한다.

말은기본개념은객체를생성하거나찾는대신,구현되는 방법을 기술하는 것이다. 컴포넌트와 서비스들을 코드에 직접 연결하지는 않지만, 설정 파일에서 어떤 컴포넌트가 어떤 서비스를 요구하는지를 기술한다. 컨테이너(이 경우, Spring 프레임웍, IOC 컨테이너)는 이 모든 것을 연결한다.

 

3.관점지향

관점지향프로그래밍(AOP, Aspect-Oriented Programming)위한풍부한지원을한다.여기서관점지향 프로그래밍이란 비즈니스로직을프로그램밍하게만한다는것이다.트랜잭션과시스템감시같은것은 관련모듈을이용하면된다.

http://aopalliance.soureforge.net참고하면된다.

 

4.컨네이너

어플리케이션객체의생명주기와설정을포함하고관리한다는점에서스프링은일종의컨테이너이고,빈을생성,빈의연관설정등있다고한다.

 

5.프레임워크

스프링에서는파일내에선언적으로구성하여애플리케이션객체를생성하며어플리케이션로직개발은개발자에게맡기고이외는기능은모듈로서제공한다.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Spring 프레임웍을 구성하는 각 모듈(또는 컴포넌트)은 독립적이거나, 다른 모듈들과 함께 구현된다. 각 컴포넌트의 기능은 다음과 같다.

  • 코어 컨테이너(core container): Spring 프레임웍의 핵심 기능을 제공한다. 코어 컨테이너의 주요 컴포넌트는BeanFactory(Factory 패턴의 구현)이다.BeanFactoryInversion of Control(IOC) 패턴을 사용하여 애플리케이션의 설정 및 의존성 스팩을 실제 애플리케이션 코드에서 분리시킨다.
  • Spring 컨텍스트(Spring context): Spring 프레임웍에 컨텍스트 정보를 제공하는 설정 파일이다. Spring 컨텍스트에는 JNDI, EJB, 국제화, 밸리데이션, 스케줄링 같은 엔터프라이즈 서비스들이 포함된다.
  • Spring AOP 모듈(Spring AOP): 설정 관리 기능을 통해 aspect 지향 프로그래밍 기능을 Spring 프레임웍과 직접 통합시킨다. 따라서 Spring 프레임웍에서 관리되는 모든 객체에서 AOP가 가능하다. Spring AOP 모듈은 Spring 기반 애플리케이션에서 객체에 트랜잭션 관리 서비스를 제공한다. Spring AOP에서는 EJB 컴포넌트에 의존하지 않고도 선언적 트랜잭션 관리를 애플리케이션과 결합할 수 있다.
  • Spring DAO: Spring JDBC DAO 추상 레이어는 다른 데이터베이스 벤더들의 예외 핸들링과 오류 메시지를 관리하는 중요한 예외 계층을 제공한다. 이 예외 계층은 오류 핸들링을 간소화하고, 예외 코드의 양도 줄여준다. Spring DAO의 JDBC 예외는 일반 DAO 예외 계층에 순응한다.
  • Spring ORM: 프레임웍은 여러 ORM 프레임웍에 플러그인 되어, Object Relational 툴 (JDO, Hibernate, iBatis SQL Map)을 제공한다. 이 모든 것은 Spring의 일반 트랜잭션과 DAO 예외 계층에 순응한다.
  • Spring Web module: 웹 컨텍스트 모듈은 애플리케이션 컨텍스트 모듈의 상단에 구현되어, 웹 기반 애플리케이션에 컨텍스트를 제공한다. Spring 프레임웍은 Jakarta Struts와의 통합을 지원한다. 웹 모듈은 다중 요청을 핸들링하고, 요청 매개변수를 도메인 객체로 바인딩하는 작업을 수월하게 한다.
  • Spring MVC framework: MVC 프레임웍은 완전한 기능을 갖춘 MVC 구현이다. MVC 프레임웍은 전략 인터페이스를 통해 설정할 수 있으며, JSP, Velocity, Tiles, iText, POI 같은 다양한 뷰 기술을 허용한다.

 

Pasted from <http://www-128.ibm.com/developerworks/kr/library/wa-spring1/>


신고
Posted by The.민군
20070119116918296764501_jpg
20070119116918294915901_jpg
20070119116918290437701_jpg

Spring 설치- 서론 spring 설치

 

서론...

작년에 한 것도 없고 요즘 재미도 없고 해서

올해는 spring을 알아보려 합니다.

아는것도 없는데 저의 취미생활로 하니까 돌은 던지기 말아주시면 감사합니다. ^^*

얼마전에 회사에서 Spring in action 이라는 책을 신청해서 나와서

책보면서 작성해 보려 합니다.

 

spring 설치

 

전 myeclipse를 사용합니다.

 Visithttp://www.myeclipseide.com/

여기서 받으시면 됩니다.

이 툴을 사용하는 이유는 플러그가 자동으로 설치되고

spring 개발을 쉽게 도와주기 때문입니다.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

그림에서Add Spring Capabilities…클릭하시면

(주의:반드시프로젝트를하나만들고해야합니다.)

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

그림이나타나고finish하죠

 

그런 다음http://www.springframework.org에서 spring 최신 버젼을 받습니다.

책에서는 1.2.7 기준이라고 하는데 홈페이지에서는 벌써

2.0.2 이네요 걍~~~ 2.0.2로 하려 합니다.

다운을 하려고 보면 파일이 두입니다.

 

 

 

 

 

 

 

 

 

 

 

 

 

파일은큰것으로보아서드파티라이브러리가포함된것이고아래는코아만들어있다고하네요

윗것으로다운받습니다

물론myeclipse에서1.2 버전지원하는데2.0다운받아수동으로라이브러리추가하려고합니다.

근데아마도책은1.2 버전기준이기때문에나중2.0사용하지않을까하네요^^*

 

 

Spring라이브러리

 

Jar파일

용도

의존대상

Spring-core.jar

스프링핵심컨테이너와유틸리티

커먼스로깅,선택사항:Log4J

Spring-aop.jar

스프링aop프레임워크메타데이터지원

Spring-core.jar, AOP연맹

선택사항:cglib,커먼스어트리뷰츠

Spring-context.jar

애플리케이션컨텍스트,유효성검증프레임워크,템를릿지원

(벨로시티,프리마커),리모팅(jax-rpc, hessian, burlap), EJB지원,

스케쥴링

Spring-core.jar

선택사항:벨로시티,프리마커,javamail,

Ejb,jax-rpc,hessian, burlap,쿼츠

Spring-dao.jar

Jdbcdao지원,트랜잭션기반구조

Spring-core.jar

선택사항:spring-aop.jar, jta

Spring-orm.jar

하이버네이트, jdo,아이바티스를포함한orm프레임워크지원

Spring-core.jar

선택사항:하이버네이트,jdo,아이바티스

Spring-web.jar

애플리케이션컨텍스트유틸리티,멀티파트파일업로드지원

Spring-cotext.jar,서블릿

선택사항:커먼스파일업로드,cos

Spring-webmvc.jar

스프링mvc프레이워크

Spring-web.jar

선택사항:jsp,jstl,타일즈,itext, poi

Spring.jar

다른jar파일들을포함한스프링프레임워크전체

위의모든사항들을포함

 

사실나도모르는용어들이많다사용해본것도개정도있다.

앞으로알아가면재미(?)같다.ㅎㅎㅎㅎㅎ

신고
Posted by The.민군

DBUtils에서 number 타입의 컬럼이 int형으로 안넘어올때..

 

데이터베이스의 컬럼이 NUMBER 타입인데 VO객체의 int형 setter를 통해 그 값이 안넘어 오는 경우가 있습니다

 

데이터베이스 테이블 스크립트

CREATE TABLE user_t (

    user_id VARCHAR2(12) PRIMARY KEY NOT NULL,

    user_point NUMBER(8)

);

 

데이터베이스의 값을 저장하는 VO 객체

public class UserVO {

    String user_id;

    int user_point;

 

    public void setUser_id(String user_id) { this.user_id = user_id; }

    public void setUser_point(int user_point) { this.user_point = user_point; }

    public String getUser_id() { return user_id; }

    public int getUser_point() { return user_point; }

}

 

 

JSP

...

ResultSetHandler rsh = new BeanListHandler(UserVO.class);

QueryRunner qr = new QueryRunner();

List list = (List)qr.query(conn, "SELECT user_id, user_point FROM user_t WHERE user_id = ?", new String[]{"unicorn"}, rsh);

...

 

간단히 위와 같이 코딩을 하면 다음과 같은 에러 메세지가 납니다

java.sql.SQLException Cannot set user_point : argument type mismatch Query

user_point 컬럼이랑 먼지 모르지만 아규먼트랑 type이 맞지 않는다는 말 같군요

 

DBUtils 받아서 차근차근 소스를 보다보니..

org.apache.commons.dbutils.BasicRowProcessor.java

private voidcallSetter(
    Object target,
    PropertyDescriptor prop,
    Object value)
    throws SQLException {

 

    Method setter = prop.getWriteMethod();
    if (setter == null) {
        return;
    }

    Class[] params = setter.getParameterTypes();
    try {

        // Don't call setter if the value object isn't the right type
        if (this.isCompatibleType(value, params[0]))
           setter.invoke(target, new Object[] { value });  //--

 

    } catch (IllegalArgumentException e) {
        throw new SQLException(
            "Cannot set " + prop.getName() + ": " + e.getMessage());

    } catch (IllegalAccessException e) {
        throw new SQLException(
            "Cannot set " + prop.getName() + ": " + e.getMessage());

    } catch (InvocationTargetException e) {
        throw new SQLException(
            "Cannot set " + prop.getName() + ": " + e.getMessage());
    }
}

 

의 setter.invoke 에서IllegalArgumentException가 throw 되고 있었습니다

즉 값에 해당하는 setter 함수를 찾다가 setUser_point(int user_point) 가 있음에도 불고하고 적당한 것이 없어서 Exception을 던지고 있는 실정입니다

원인은 value 때문이었는데, 이는

value = rs.getObject(i+1)

와 같이 resultset에서 받아온 값입니다

invoke 함수에 두번째 파라미터로 Object형태의 객체형태로 넘겨주어야 하는데 이넘은 Integer형이 아닌것 같았습니다

Integer.class.isInstance(value) 로 값을 찍어보니 역시나 false가 리턴되었습니다

 

그래서 다음과 같이 약간 수정하였습니다

 

private voidcallSetter(
    Object target,
    PropertyDescriptor prop,
    Object value)
    throws SQLException {

 

    Method setter = prop.getWriteMethod();
    if (setter == null) {
        return;
    }

    Class[] params = setter.getParameterTypes();
    try {

        // Don't call setter if the value object isn't the right type

 

       if (params[0].equals(Integer.TYPE)) {
            value = new Integer(value.toString());  //-- ②
       }


        if (this.isCompatibleType(value, params[0]))
            setter.invoke(target, new Object[] { value });  //-- ①

 

    } catch (IllegalArgumentException e) {
        throw new SQLException(
            "Cannot set " + prop.getName() + ": " + e.getMessage());

    } catch (IllegalAccessException e) {
        throw new SQLException(
            "Cannot set " + prop.getName() + ": " + e.getMessage());

    } catch (InvocationTargetException e) {
        throw new SQLException(
            "Cannot set " + prop.getName() + ": " + e.getMessage());
    }
}

 

과 같이 명시적으로 Integer 타입일때 Integer형태를 만들어 주었습니다

MySQL과 Oracle 두가지 테스트해보았는데, MySQL에서는 발생하지 않았지만 Oracle에서는 위와같은 문제가 발견되었습니다

아마도 M$SQL에서도 동일한 문제가 발생할것 같습니다

소스는 동일한데 어디선 되고 안되고를 보니 JDBC영향일것으로 추측이 되는데, JDBC 소스를 보아도 별 특별한데는 아직 찾지 못했습니다

 

사실 DBUtils는 잘쓰면 무척 편합니다

하지만 많이 좋아졌다고는 하나 reflect에 대한 비용 없잖아 들겁니다

DBUtils는 그 자체로 괜찮지만 아마 사용하다보면 소스에 손을 데야될겁니다

한글 인코딩, 디코딩이나 쿼리등을 DBUtils에 심어놓으면 코딩은 아마 더 줄어들겁니다

 



신고
Posted by The.민군

Installing Tomcat with commons-daemon (jsvc)

Most installation that I've seen of Tomcat is made with tomcat running as root. This could potentially be a disasters security hole. Most Linux systems only allow the root to listen to port 80...which is why many users of tomcat under Linux run tomcat as root. With jscv, the process will start off as root but later on will change owner to a user of your choice.

 

 

Installation

Create the user to run tomcat under with

useradd tomcat

 

This will create a directory under

 

/home/tomcat

 

Download and install tomcat under /usr/tomcat. This is how my tomcat directory looks like

 

ls -l /home/tomcat
drwxr-xr-x  3 tomcat tomcat  4096 Dec 13 02:51 bin
drwxr-xr-x  6 tomcat tomcat    56 Sep 23 09:42 common
drwxr-xr-x  3 tomcat tomcat  4096 Dec 13 05:18 conf
-rw-r--r--  1 tomcat tomcat 11357 Sep 23 09:44 LICENSE
drwxr-xr-x  2 tomcat tomcat    25 Dec 13 02:51 logs
-rw-r--r--  1 tomcat tomcat   688 Sep 23 09:44 NOTICE
-rw-r--r--  1 tomcat tomcat  6403 Sep 23 09:42 RELEASE-NOTES
-rw-r--r--  1 tomcat tomcat  7006 Sep 23 09:44 RUNNING.txt
drwxr-xr-x  5 tomcat tomcat    44 Sep 23 09:42 server
drwxr-xr-x  4 tomcat tomcat    30 Sep 23 09:42 shared
drwxr-xr-x  2 tomcat tomcat     6 Sep 23 09:42 temp
drwxr-xr-x  3 tomcat tomcat    35 Dec 13 05:17 webapps
drwxr-xr-x  3 tomcat tomcat    21 Dec 13 02:52 work

 

Compile the jscv code by following the instructions onhttp://tomcat.apache.org/tomcat-5.0-doc/setup.html


 

Run As Service


Tomcat 5.x ship with a tomcat service file which you can use and modify. However, it's written to be used with Java 1.4. To use it with Java 1.5 you need to tweak it some more or use the following file. Please note the items in red. Tomcat user and the JDK path which you must update to fit your system. Also make sure the DAEMON_HOME executable is in the right place.


#!/bin/sh
#
# Startup script for Tomcat, the Apache Servlet Engine
#
# chkconfig: 345 80 20
# description: Tomcat is the Apache Servlet Engine
# processname: tomcat
# pidfile: /var/run/tomcat.pid
#
# Mike Millson <*******@meritonlinesystems.com>
#
# version 1.02 - Clear work directory on shutdown per John Turner suggestion.
# version 1.01 - Cross between Red Hat Tomcat RPM and Chris Bush scripts

 

TOMCAT_PROG=tomcat
JAVA_HOME='/usr/java/jdk1.5.0_06'
CATALINA_HOME='/home/tomcat/'
DAEMON_HOME=$CATALINA_HOME/bin/jsvc
TMP_DIR=/var/tmp
CATALINA_OPTS=
CLASSPATH=\
$JAVA_HOME/lib/tools.jar:\
$CATALINA_HOME/bin/commons-daemon.jar:\
$CATALINA_HOME/bin/bootstrap.jar

 

# if TOMCAT_USER is not set, use tomcat like Apache HTTP server
if [ -z "$TOMCAT_USER" ]; then
 TOMCAT_USER="tomcat"
fi

 

RETVAL=0

 

# start and stop functions
start() {
    echo -n "Starting tomcat: "
    chown -R $TOMCAT_USER:$TOMCAT_USER /home/tomcat/*
    $DAEMON_HOME \
    -user $TOMCAT_USER \
    -home $JAVA_HOME \
    -Dcatalina.home=$CATALINA_HOME \
    -Djava.io.tmpdir=$TMP_DIR \
    -Djava.awt.headless=true \
    -outfile $CATALINA_HOME/logs/catalina.out \
    -errfile '&1' \
    $CATALINA_OPTS \
    -cp $CLASSPATH \
    org.apache.catalina.startup.Bootstrap
    # To get a verbose JVM
    #-verbose \
    # To get a debug of jsvc.
    #-debug \

    RETVAL=$?
    echo
    [ $RETVAL = 0 ] && touch /var/lock/subsys/tomcat
    return $RETVAL
}

 

stop() {
    echo -n "Stopping tomcat: "
    PID=`cat /var/run/jsvc.pid`
    kill $PID
    RETVAL=$?
    echo
    [ $RETVAL = 0 ] && rm -f /var/lock/subsys/tomcat /var/run/tomcat.pid
}

 

# See how we were called.
case "$1" in
  start)
        start
        ;;
  stop)
        stop
        ;;
  restart)
        stop
        # Ugly hack
        # We should really make sure tomcat
        # is stopped before leaving stop
        sleep 5
        start
        ;;
  *)
        echo "Usage: $0 {start|stop|restart}"
        exit 1
esac

 

exit $RETVAL

 


Start and Stop

To start tomcat, use (on redhat)

service tomcat start

 

To stop

service tomcat stop

 

fromhttp://waelchatila.com/2005/12/13/1134504717808.html

 

commons의 daemon을 이용해서 일반유저로 톰캣을 80포트로 올리는 법입니다

이전에 jsvc가 이미 make 되어 있어야 합니다

신고
Posted by The.민군

Jakarta Commons Net 에서 FTP 사용시 목록이 안보일 경우

 

 

Jakarta Commons Net 기본http://www.jakartaproject.com/article/jakarta/1113911351166

Commons net APIhttp://jakarta.apache.org/commons/net/apidocs/index.html

Commons net http://jakarta.apache.org/commons/net/

 

조회 권한이 없는 경우

   로그인한 유저의 권한이 적당한지 체크해 본다

   또는 텔넷을 통해 해당 유저로 ftp 테스트를 해 본다

 

Passive mode를 사용해 본다

   FTPClient ftpClient = new FTPClient();

   ftpClient.connect(server);

   ...

   ftpClient.login(username, password);

   ftpClient.enterLocalPassiveMode();

   ...

 

관련 함수
  enterLocalActiveMode()
  enterLocalPassiveMode()
  enterRemoteActiveMode(InetAddress host, int port)
  enterRemotePassiveMode()
 
 
날짜 포맷을 변경한다
현재 서버의 날짜가 한글로 나오도록 설정 되었다면 목록이 안나올 수가 있습니다
 
FTPClient ftpClient = new FTPClient();
FTPClientConfigconfig = new FTPClientConfig(FTPClientConfig.SYST_NT); 
config.setServerLanguageCode("ko");
config.setDefaultDateFormat("d MMM yyyy");
config.setRecentDateFormat("d MMM HH:mm");
ftpClient.configure(config);
ftpClient.connect(server);
...
 
운영체제에 맞게 설정하세요
  FTPClientConfig.SYST_NT
  FTPClientConfig.SYST_MVS
  FTPClientConfig.SYST_OS2
  FTPClientConfig.SYST_OS400
  FTPClientConfig.SYST_UNIX
  FTPClientConfig.SYST_VMS
 
언어설정값은http://ftp.ics.uci.edu/pub/ietf/http/related/iso639.txt 에서 확인하세요
날짜 포맷은 java.text.SimpleDateFormat 의 형식을 따릅니다
 
또다른 방법이 있으면 올려주세요 ^^;


신고
Posted by The.민군

DbUtils 몇가지 예제

 

DBUtils 기본은 다음 링크를 참조하세요

http://www.jakartaproject.com/article/jakarta/1108193481660

 

설정방법 

   DB유틸 설정 방법은 특별히 없습니다  그냥 다운받은 클래스 패스 잡으시면 됩니다

   Application에서 사용시에는 환경변수나 실행시 클래스 패스를 잡으면 되고요,

   웹에서 사용한다면 해당 어플리케이션의 /WEB-INF/lib/ 에 commons-beanutils.jar 를 복사하면 됩니다

 

   기본적인 문서는http://www.jakartaproject.com/article/jakarta/1108193481660 를 보세요

 

   Downloadhttp://jakarta.apache.org/site/downloads/downloads_commons-dbutils.cgi

   APIhttp://jakarta.apache.org/commons/dbutils/apidocs/index.html

 

SELECT 예제 (여러건)

 

<%@ page contentType="text/html;charset=EUC_KR" %>
<%@ page import="com.jakartaproject.board.vo.*,org.apache.commons.dbutils.*,java.sql.*,java.util.*, org.apache.commons.dbutils.handlers.*" %>

<%
       Connection conn = null;

       try {

           DbUtils.loadDriver("com.mysql.jdbc.Driver");

           conn = DriverManager.getConnection("jdbc:mysql://localhost/test", "test", "1111");

 

           ArrayList params = new ArrayList();
           params.add("1%");

 

           ResultSetHandler rsh = newBeanListHandler(BoardVO.class);

           QueryRunner qr = new QueryRunner();

           List list = (List)qr.query(conn, "SELECT boardTitle, boardContent, userNick FROM board_test_t WHERE userIp like ?", params.toArray(), rsh);

 

           for (int i = 0; i < list.size(); i++) {

               BoardVO board = (BoardVO)list.get(i);

               System.out.println(board.getBoardTitle());

               System.out.println(board.getBoardContent());

               System.out.println(board.getUserNick());

          }

       } catch (Exception e) {

           System.out.println(e);

       } finally {

           DbUtils.closeQuietly(conn);

       }
%>

 

SELECT 예제 (한건)

select 처리 건수가 1건일 경우에는 MapHandler를 사용하면 됩니다

<%@ page contentType="text/html;charset=EUC_KR" %>
<%@ page import="org.apache.commons.dbutils.*,java.sql.*,java.util.*, org.apache.commons.dbutils.handlers.*" %>

<%
       Connection conn = null;

       try {

           DbUtils.loadDriver("com.mysql.jdbc.Driver");

           conn = DriverManager.getConnection("jdbc:mysql://localhost/test", "test", "1111");

 

           ResultSetHandler rsh = newMapHandler();

           QueryRunner qr = new QueryRunner();

          Mapmap = (Map)qr.query(conn, "SELECT count(*) cnt FROM board_test_t", rsh); 

           System.out.println(map.get("cnt"));

           

       } catch (Exception e) {

           System.out.println(e);

       } finally {

           DbUtils.closeQuietly(conn);

       }
%>

핸들러에는 아래와 같이 여러 종류의 핸들러 들이 있으며,

ArrayHandler,ArrayListHandler,BeanHandler,BeanListHandler,ColumnListHandler,KeyedHandler,MapHandler,MapListHandler,ScalarHandler

그때그때 맞춰 사용하면 됩니다

 

 

UPDATE 예제

이 예제는 Unicorn 소스에 있는 예입니다

Unicorn 소스를 다운받아 /src/com/jakartaproject/admin/dao/AdminMySqlDAO.java 를 열어 보시면 Update, Insert 예제를 볼수 있습니다

 

public void setBoardCommonSecurity(ConnectionContext connectioncontext,

                                                  AdminForm adminForm) throws BaseException {


        String updateQuery = "UPDATE board_common_t SET badIp=?, badId=?, badNick=?, badContent=?, inputPerMin=?, tryLogin=?";

        try {
            ArrayList params = new ArrayList();
            params.add(encode(adminForm.getBadIp()));
            params.add(encode(adminForm.getBadId()));
            params.add(encode(adminForm.getBadNick()));
            params.add(encode(adminForm.getBadContent()));
            params.add(String.valueOf(adminForm.getInputPerMin()));
            params.add(String.valueOf(adminForm.getTryLogin()));

            QueryRunner queryRunner = new QueryRunner();
            queryRunner.update(connectioncontext.getConnection(), encode(updateQuery), params.toArray());

        } catch (Exception e) {
            logger.error("Error at AdminDAO.setBoardCommonSecurity",e);
            BaseException baseException = new BaseException("errors.sql.problem");
            throw baseException;
        }

        logger.info("AdminDAO.setBoardCommonSecurity was executed");
    }

 

신고
Posted by The.민군

from http://www.javaservice.net/~java/bbs/read.cgi?m=resource&b=qna2&c=r_p&n=1131692449&p=1&s=t

 

제목 : POI로 엑셀파일 읽을때, Invalid header signature 에러
글쓴이: 손님(guest) 2005/11/11 11:37:30 조회수:20 줄수:44
poi를 이용하여 클라이언트의 엑셀문서를 서버에 업로드후 읽어내는 작업을 하려합니다.작업의 목적은 화면상에 입력필드가 너무 많아서(대략 240여개 정도 됩니다),일일이 입력하기에 불편함이 초래되어,엑셀로 다운받은 다음에 해당 입력값들을 엑셀에서 입력후,입력한 값을 다시 화면상에 뿌려주려는 것입니다.업로드 완료후 엑셀파일을 읽을때,Error occurred : Invalid header signature; read 5789751444030890300, expected -2226271756974174256java.io.IOException: Invalid header signature; read 5789751444030890300, expected -2226271756974174256        at org.apache.poi.poifs.storage.HeaderBlockReader.<init>(HeaderBlockReader.java:88)        at org.apache.poi.poifs.filesystem.POIFSFileSystem.<init>(POIFSFileSystem.java:83)....... 위와 같은 에러가 발생합니다.해당 라인을 쫓아가보면,POIFSFileSystem fs = new POIFSFileSystem(new FileInputStream(filePath + fileName));이부분입니다.읽으려 하는 엑셀은 jsp내에서,response.setContentType("application/vnd.ms-excel;charset=euc-kr"); response.setHeader("Content-Disposition", "attachment; filename="+jspName+".xls"); response.setHeader("Content-Description", "JSP Generated Data"); 을 이용해서 생성한것입니다.해당 엑셀파일을 일반 텍스트 에디터에서 열어보면,<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html xmlns:o="urn:schemas-microsoft-com:office:office"xmlns:x="urn:schemas-microsoft-com:office:excel"xmlns="http://www.w3.org/TR/REC-html40"><head><meta http-equiv=Content-Type content="text/html; charset=ks_c_5601-1987"><meta name=ProgId content=Excel.Sheet>(이하 생략)meta 태그내의 'content="text/html;' 부분이 의심이 갑니다만.엑셀을 생성하는 jsp내의 meta 태그부분을 삭제해도,생성된 엑셀을 보면 해당부분이 들어가있는데요.다시 처음으로 와서,content='text/html' 부분때문에 Invalid header signature...의 오류가 발생하는것인지요?jsp에서 생성된 엑셀이 아닌 일반 엑셀문서로 테스트 해봤을때는 이상없이 제대로 실행됩니다.제가 의심한 부분이 맞는것이라면, 해결책은 어떤것이 있을런지 조언 부탁드립니다.
제목 : Re: 실제 엑셀파일이 아니라서 그런거 같습니다.
글쓴이: 손님(guest) 2005/11/11 16:00:49 조회수:7 줄수:16
Invalid Header라는 에러메시지의 의미가 파일 헤더가 엑셀타입이 아니라서 그런거 같습니다. POI가 해석하는 엑셀파일은 MS OLE Compound로 생성된 파일포맷일 경우에만 해당됩니다..html의 header를 excel이라 조작해서 생성된 엑셀파일은 실제론 텍스트파일일뿐 OLE 타입이 아니라서요. 서버에서 생성시 jsp로 생성하지 말고 poi를 이용해서 서버측에 실제 엑셀파일을 생성한 후 클라이언트로 스트리밍을 통해 다운로드 해주는 방식을 택해야할 것같네요.
제목 : Re: 답변 고맙습니다.
글쓴이: 손님(guest) 2005/11/11 16:31:58 조회수:2 줄수:5
그렇군요.실제로 jsp내에서 생성되는 엑셀을 다른이름으로 저장해서 'Micrisoft Excel 통합문서' 형식으로 저장하니,정상적으로 실행이 되는군요.충고해주신데로, poi를 이용해서 엑셀을 생성하는 쪽으로 다시 해봐야겠습니다.답변 고맙습니다.좋은 주말 되세요.

신고
Posted by The.민군
 

활용

 1.데이터 무결성의 강화

  -전체 데이터베이스에 걸쳐 영향 받은 테이블을 연속적으로 변경함으로서 데이터 무결성을 강화하는데 사용될 수 있다.

  - 중복되었거나 파생된 데이터에 대해 트리거를 사용하는 것이 좋다.

 

 

2.참조 무결성의 강화

  -연속적인 삭제 / 갱신이 일어날 필요가 있을 때 적절한 작업을 하도록 보장하는데 유용하다.

  - FOREIGN KEY, REFERENCE 제약을 사용할 수도 있다.

  - 자신의 오류 메시지를 정의할 수 있다.

 

3.업무 규칙의 설정

  - 제약에 의해 표현될 수 있는 것보다 복잡한 제약을 표현할 수 있다.

 

4.감사기능의확장

  -상세한 변경 내역을 추적하려면, 트리거를 적용하거나 Log Miner를 이용해 아카이브 로그를 뒤지는 수 밖에 없음

  -감사 목적으로 적용되는 트리거는 성능적으로 심각한 부담을 줍니다

 

고려사항

       - 트리거는 각 테이블에 최대 3개까지 존재할 수 있다.

         UPDATE, INSERT, DELETE트리거가 각각 하나씩 존재할 수 있다.

         이미 트리거가 정의된 작업에 대해 다른 트리거를 정의하면 기존의 것을 대체한다.

       - 테이블의 소유자만이 트리거를 생성하거나 삭제할 수 있다.

       - 뷰나 임시 테이블을 참조할 수 있으나 뷰나 임시 테이블에 대해 생성할 수 는 없다.

       - 데이터 무결성이나 업무 규칙 처리에만 사용하는 것이 좋다.

       - 트리거의 동작은 이를 삭제하지 않는 한 계속된다.

       - 테이블의 삭제는 관련 트리거의 삭제를 유발한다

 

트리거에서 사용할 수 없는 SQL 명령들

       - CREATE... /DROP ...

       - ALTER TABLE, ALTER DATABASE

       - TRUNCATE TABLE

       - GRANT, REVOKE

       - UPDATE STATISTICS

       - RECONFIGURE

       - LOAD DATABASE, LOAD TRANSACTION

       - DISK ...

       - SELECT INTO

 

트리거의 성능

  -오버헤드는 적다.

  -트리거를 실행하는데 걸리는 대부분의 시간은 다른 테이블을 참조 하는데 사용된다.

  - 트리거에 의해 참조되는 다른 테이블의 위치가 작업 시간을 결정 짓는다.

  -inserted 테이블과 deleted 테이블은 논리적 테이블이고 매우 작으며 항상 메모리에 있다.

 

트리거의 제한

-트리거는 트랜잭션 제어문(COMMIT, ROLLBACK, SAVEPOINT)을 사용할 수 없습니다.

-트리거는 트리거링 문장의 실행부분으로써 실행되고 트리거링 문장과 같은 트랜잭션에 있습니다.

-트리거링 문장이 COMMIT, ROLLBACK될때 트리거의 작업도 COMMIT, ROLLBACK 됩니다.

 

트리거의 종류

 -문장 트리거 ; 전체 transaction 작업에 대해 1번발생되는 트리거 ,default

 -행 트리거 ; 각 행에 대해서 트리거가 발생된다. (for each row)

 

 

형식

 

-트리거생성

create[or replace]  trigger 트리거명 before insert

                                                after   delete

                                                          update [of 컬럼….] on 테이블명

 

               [for each row]행트리거    

 [when] 조건    

 begin    

   트리거의 내용   

end;    

 

-트리거의 삭제 : drop trigger 트리거명

-트리거의 활동을 enabled/disabled

-alter trigger 트리거명 {enable/disable}

 

- BEFORE : INSERT, UPDATE, DELETE문이 실행되기 전에 트리거가 실행됩니다.

- AFTER : INSERT, UPDATE, DELETE문이 실행된 후 트리거가 실행됩니다.

- trigger_event : INSERT, UPDATE, DELETE 중에서 한 개 이상 올 수 있습니다.

- FOR EACH ROW : 이 옵션이 있으면 행 트리거가 됩니다.

 

 

행 trigger

 · 테이블이 Triggering 문장에 의해 영향을 받을 때마다 실행

 · 영향을 받는 각 행에 대해 한번씩 실행

 · Trigger 작업의 코드가 Triggering 명령문이나 영향을 받는 행에 의해 제공되는 데이터에 따라 다를

 경우에 유용 

 

명령문 trigger

 · 테이블에서 Triggering 명령문에 의해 영향을 받는 행 수에 (영향을 받는 행이 없다 해도) 관계 없이 트리거링 명령문 대신 한 번 실행

 · 트리거 작업의 코드가 Triggering 명령문이나 영향을 받은 행에 의해 제공되는 데이터에 종속되지 않을 때 유용 

 

 

Before trigger Vs. After trigger

 

· Before trigger : triggering문 앞에 trigger 작업 실행

     ▶ trigger 작업이 triggering 문장의 종료 여부를 결정할 수 있을 때

         → trigger 작업에서 발생된 예외 경우에서의 우발적인 롤백과 불필요한 처리제거

     ▶ triggering 삽입 혹은 수정문을 종료하기 전에 명확한 칼럼값들을 조정하기 위해 사용

· After trigger : 실행된 triggering문 앞에 trigger 작업 실행

     ▶ trigger작업실행 이전에 triggering문을 종료하기를 원할 때

     ▶ Before trigger가 미리 제시되면 같은 triggering문에서 다른 작업 수행 

 

 

결합에 의한 네가지 타입의 Trigger

 

· Before 명령문 trigger : triggering문의 실행전에 trigger 작업 실행

· Before 행 trigger :

     ▶ triggering문에 의해 영향 받는 각 행을 수정하기 전에

     ▶ 해당 무결성 제약 조건을 검사하기 전에

       → trigger 제한 사항에 위배되지 않으면 실행

· After 명령문 trigger : triggering문을 실행하여 파생된 무결성 제약 조건을 적용한 후 트리거 작업이 수행됨.

· After 행 trigger :

     ▶ triggering문에 의해 영향을 받는 각 행을 수정하고 가능한 해당 무결성 제약 조건을 적용한 후 트리거 제한 사항에 위배되지 않는 현재 행에 대해 수행됨.

     ▶ Before 행 trigger와 달리 행을 잠금.

 

 

 실행 모델과 무결성 제약 조건

 

 -제약 조건 검사와 복합 trigger들의 적절한 실행 순서를 유지 관리하기 위해 

 · 실행 모델 Ⅰ

     (1) 문장에 알맞은 모든 Before문장 trigger 실행

     (2) SQL문에 의해 영향받는 각 행을 위한 루프

         1)문장에 알맞은 모든 Before 행 trigger 실행

         2)행을 lock한 후 바꾸고 무결성 제한 채킹을 실행(lock은 트랜젝션이 완료될 때까지 해제되지

           않음)

         3)문장에 알맞은 모든 After 행 trigger를 실행

     (3) 유예된 무결성 제한 점검 완료

     (4) 문장에 알맞은 모든 After 문장 trigger를 실행

 · 실행 모델 Ⅱ

     (1) 오라클 SQL 문을 지시

     (2) BEFORE 행 트리거를 실시

     (3) AFTER 문장 트리거는 BEFORE 행 트리거에서 update함으로써 실시됨

     (4) AFTER 문장 트리거의 문장들을 실행

     (5) 테이블상의 무결성 제한은 체크된 AFTER문장 트리거에 의해 바뀜

     (6) BEFORE 행 트리거의 문장들을 실행

     (7) 테이블상의 무결성 제한은 체크된 BEFORE 행 트리거에 의해 바뀜

     (8) SQL문 실행

     (9) SQL문으로부터 무결성 제한을 체크

 

 

 

예제1

 

Aborting Triggers with Error

Triggers can often be used to enforce contraints. The WHEN clause or body of the trigger can check for the violation of certain conditions and signal an error accordingly using the Oracle built-in function RAISE_APPLICATION_ERROR. The action that activated the trigger (insert, update, or delete) would be aborted. For example, the following trigger enforces the constraint Person.age >= 0:

create table Person (age int);

 

CREATE TRIGGER PersonCheckAge

AFTER INSERT OR UPDATE OF age ON Person

FOR EACH ROW

BEGIN

   IF (:new.age < 0) THEN

       RAISE_APPLICATION_ERROR(-20000, 'no negative age allowed');

   END IF;

END;

.

RUN;

 

If we attempted to execute the insertion:

insert into Person values (-3);

we would get the error message:

 

ERROR at line 1:

ORA-20000: no negative age allowed

ORA-06512: at "MYNAME.PERSONCHECKAGE", line 3

ORA-04088: error during execution of trigger 'MYNAME.PERSONCHECKAGE'

 

and nothing would be inserted. In general, the effects of both the trigger and the triggering statement are rolled back.

 

예제2

The following template shows how to raise an error when a DML statement violates a business rule:

 

CREATE OR REPLACE TRIGGER secure_del_trigger

  BEFORE DELETE

  ON emp

  FOR EACH ROW

DECLARE

  unauthorized_deletion  EXCEPTION;

BEGIN

  IF <your business rule is violated> THEN

    RAISE unauthorized_deletion;

  END IF;

EXCEPTION

  WHEN unauthorized_deletion

  THEN

     raise_application_error (-20500,

       'This record cannot be deleted');

END;

/

 

 

참고1

1. MUTATING ERROR란 무엇인가?

어느 TABLE에 DML(INSERT, UPDATE, DELETE 등)이 실행될 때마다 프로그램에

구애받지 않고 특정 작업을 수행하려할 때 database trigger를 사용한다.

예)EMP table에 data insert, update, delete 시 부서별 평균 급여 table에

updating 하는 경우.

 

이 경우 trigger를 사용하지 않고 같은 작업을 하려면 평균 급여를 구하는

PL/SQL program을 개발하여 EMP 테이블에 action이 발생 시마다 call하여 사용

하든가, 아니면 각 action 발생 후 동일한 routine을 반복 수행시켜야 한다.

이 때 만일 user가 EMP table에 update 시마다 EMP table에 어떤 처리를 수행

하는 trigger를 만든다면 원치 않는 결과를 일으킬 수 있고 OS memory가 소진

될 때까지 trigger가 trigger를 recursive하게 fire시켜 마치 looping

program과 같은 상황을 초래할 수도 있다.

이러한 trigger를 recursive trigger라 부르며 이런 불상사를 막기 위해

ORACLE은 EMP table에 row trigger를 만들어 원천적으로 trigger 내에서

EMP table을 아예 access 할 수 없도록 하고 있고, 이와 같은 원칙에 위배될

경우 발생되는 error를 mutating error 라고 부른다.

이 경우 user가 trigger를 만든 후 DML(insert, update, delete)을 수행 시

"ORA-4091:table SCOTT.EMP is mutating, trigger/function may not see

it." 와 같은 error를 만나게 된다.

 

2. ERROR가 발생하는 조건.

TRIGGER에는 다음과 같은 두 종류가 있다.

*row trigger - 프로그램에서 한 row 단위로 처리 시 처리할 때마다

fire되는 trigger.

*statement trigger - 프로그램 당 한번만 fire되는 trigger.

위와 같으므로 만일 application에서 한 row만 처리한다면 두 type에는 차이가

없고 여러 row를 처리할 경우 두 type 간의 차이가 발생한다.

Statement trigger는 일부 제한은 있으나 원칙적으로 mutating error를 발생

시키지 않는다.

Row trigger는 하나의 row 처리 후 해당 table에 대한 계속된 row 처리가 있을

수 있으므로 작업이 완료되기까지 해당 table을 access하는 것이 금지되지만

statement trigger는 일단 하나의 statement가 완료되었다는 보장을 할 수

있으므로 mutating의 기본 속성인 "현재 변화되고 있는 table" 이라는 범위에

들지 않는다.

따라서, mutating error는 row trigger에서의 제한 사항이라 해도 무리가 없다.

 

3. 해결 방법.

위에서 보았듯 mutating error를 피해 나가려면 statement trigger를 사용하면

어려움이 없으나 statement trigger에서는 row trigger에서와 같이 row 단위로

변경 전 후 column data를 handling할 수 없다는 단점이 있다.

즉 :new.column, :old.column을 사용하지 못한다.

 

이와 같은 문제로 인하여 row trigger를 사용 시는 temp table 이나 PL/SQL

table을 이용하여 피해갈 수가 있다.

 

 

참고2

 

INSTEAD OF Trigger

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

 

1. 개념

INSTEAD OF trigger는 Oracle8에서 새로이 소개된 방법으로, DML문장에 의해

직접 변경할 수 없는 view를 변경하기 위해 사용된다. 즉, base table이 fire

하는 trigger를 생성하는 것이 아니고 view를 대상으로 trigger를 생성하여

view에 대한 DML문장을 수행시 대신 trigger가 fire되어 base table을 직접

변경하게 되는 것이다.

 

기본적으로 DML이 불가능한 view는 다음 사항들을 포함하고 있는 경우이

다. 이러한 사항을 포함한 view들에 대해서 instead of trigger를 생성하면 DML을

수행할 수 있게 된다.

(1) DISTINCT operator

(2) group functions: AVG, COUNT, MAX, MIN, STDDEV, SUM, VARIANCE등

(3) set operations: UNION, MINUS 등

(4) GROUP BY, CONNECT BY, START WITH clauses

(5) ROWNUM pseudocolumn

(6) join (updatable join view인 경우는 제한적으로 DML수행가능 <Bul:11642>참

조)

 


신고
Posted by The.민군

ORA-08002: 시퀀스 **.CURRVAL은 이 세션에서는 정의 되어 있지 않습니다

 

NEXTVAL 하기 전까지는 CURRVAL을 동일세션에서 사용할 수 없습니다

굳이 필요하다면 다음과 같이 해야합니다

 

 

SELECTLAST_NUMBER

  FROMUSER_SEQUENCES
WHERESEQUENCE_NAME = '시퀀스명(대문자)'

 

신고
Posted by The.민군

현재 사용하고 있는 모든 SQL 보기

 

SELECT*

FROMv$sqltext

ORDER BY address, piece

 

command_type

2 : insert

3 : select

6 : update

7 : delete

17 : grant

42 : alter

...

 

좀더 자세한 정보보기

SELECT*
FROMv$sqlarea or v$sql

 

현재 세션 SQL보기

SELECT *
FROM v$sqlareaa,v$sessionb
WHERE sql_address = address
AND status = 'ACTIVE'

 

 

신고
Posted by The.민군
문제 설명
Oracle은OPEN_CURSORS매개변수를 사용하여 세션이 동시에 취할 수 있는 최대 열린 커서 개수를 지정합니다. 최대 개수를 초과하면 Oracle은ORA-01000오류를 보고합니다. 이 오류가 WebLogic Server로 전송되면SQLException이 발생합니다.

java.sql.SQLException: ORA-01000: maximum open cursors exceeded


이 패턴은 WebLogic Server를 사용할 때 오류를 발생시키는 원인과 해결 방법에 대해 설명합니다.

문제 해결
다음 항목을 모두 수행해야 하는 것은 아닙니다. 어떤 경우에는 다음 중 일부만 수행하여도 해결할 수 있습니다.

항목 바로가기


진단 조회
다음 SQL 조회는ORA-01000문제를 진단하는 데 유용합니다. 이런 조회를 실행하려면 데이터베이스에 관리자로 로그인하거나 데이터베이스 관리자가 사용자에게v$뷰에서 SELECT 명령문을 실행할 수 있는 권한을 승인해야 합니다.

1. 데이터베이스의 OPEN_CURSORS 매개변수 값을 확인합니다.
Oracle은OPEN_CURSORS초기화 매개변수를init.ora에 사용하여 세션이 동시에 취할 수 있는 최대 커서 개수를 지정합니다. 디폴트값은 50이지만, WebLogic Server와 같은 시스템에는 너무 작습니다. 다음 조회를 사용하여 데이터베이스에서OPEN_CURSORS매개변수 값을 찾을 수 있습니다.
 
SQL> show parameter open_cursors;

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
open_cursors                         integer     1000

 

OPEN_CURSORS값을 충분히 큰 값으로 설정하여 응용 프로그램에서 열린 커서가 부족하지 않도록 해야 합니다. 이 수는 응용 프로그램에 따라 다릅니다. 세션이OPEN_CURSORS에 지정된 커서 개수만큼 열지 않는 경우 이 값을 실제 필요한 값보다 크게 설정해도 오버헤드가 추가되지 않습니다.

2. 열린 커서의 수를 확인합니다.
아래 조회는 사용자 'SCOTT'가 각 세션에 대해 연 커서 개수를 내림차순으로 표시합니다.
 
SQL> select o.sid, osuser, machine, count(*) num_curs
  2  from v$open_cursor o, v$session s
  3  where user_name = 'SCOTT' and o.sid=s.sid
  4  group by o.sid, osuser, machine
  5 order by  num_curs desc;       SID OSUSER               MACHINE                                              NUM_CURS
---------- ---------------- ------------------------------------------------- ----------
       217                                m1                                                           1000
        96                                 m2                                                            10
       411                                m3                                                             10
        50                                test                                                              9


WebLogic Server에서 커넥션 풀을 사용할 때 커넥션을 커넥션 풀에서 가져온 경우 이 조회의user_name은 커넥션을 생성하는데 사용한user_name이어야 합니다. 조회 결과는 시스템 이름도 출력합니다. 조회 결과를 통해 열린 커서의 개수가 큰SID와 WebLogic Server를 실행하는 시스템 이름을 식별할 수 있습니다.

v$open_cursordbms_sql.open_cursor()를 사용하여 연 동적 커서인PARSEDNOT CLOSED를 세션에 대해 추적할 수 있습니다. 구문 분석 하지 않은 열린 동적 커서는 추적하지 않습니다. 응용 프로그램에서 동적 커서의 사용은 흔하지 않습니다. 이 패턴은 동적 커서가 사용되지 않는 것으로 간주합니다.

3. 커서에 대해 실행 중인 SQL을 확인합니다.
위의 조회 결과에서 식별한 SID를 취하고 다음 조회를 실행합니다.

SQL> select q.sql_text
  2  from v$open_cursor o, v$sql q
  3  where q.hash_value=o.hash_value and o.sid = 217;

SQL_TEXT
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
select * from empdemo where empid='212'
select * from empdemo where empid='321'
select * from empdemo where empid='947'
select * from empdemo where empid='527'
...

 

결과는 커넥션 상에서 실행 중인 조회를 표시합니다. 이를 기준으로 열린 커서의 출처를 역추적할 수 있습니다.

페이지 맨 위

일반적인 원인과 문제 해결
다음 단계는 문제의 원인을 파악하고 가능한 해결 방법을 모색하는 절차입니다.

코드 연습
이 문제의 가장 일반적인 원인은 JDBC Object가 정상적으로 닫히지 않은 경우입니다. 모든 JDBC Object가 정상적으로 닫혔는지 확인하기 위해 응용 프로그램 코드에서 역추적하려면진단 조회에 타사의 조회 결과를 사용합니다. 모든 JDBC Object가 정상적인 상태나 예외 조건에서 닫히도록 하려면finally블록에서 Connections, Statements 및 ResultSets 같은 JDBC Object를 명시적으로 닫는 것이 좋습니다. 다음은 일반적인 예제입니다.
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;

try {
    conn = getConnection(); //Method getConnection will return a JDBC Connection
    stmt = conn.createStatement();
    rs = stmt.executeQuery("select * from empdemo");
    // do work
} catch (Exception e) {
    // handle any exceptions
} finally {
    try {
        if(rs != null)
            rs.close();
    } catch (SQLException rse) {}
    try {
        if(stmt != null)
            stmt.close();
    } catch (SQLException sse) {}
    try {
        if(conn != null)
            conn.close();
    } catch (SQLException cse) {}
}

 

JDBC Object를 버리는 코딩 습관을 피하십시오. 다음 연습은 각 루프 반복에서 새 Connection, Statement 및 ResultSet를 얻지만 각 반복에 대해 JDBC Object를 닫지는 않습니다. 그러므로 JDBC Object leak이 발생합니다.

Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
String[] queries = new String[10];
//Define queries

try {
    for(int i = 0; i < 10; i++) {
        conn = getConnection();
        stmt = conn.createStatement();
        rs = stmt.executeQuery(queries[i]);
        // do work
    }
} catch (Exception e) {
    // handle any exceptions
} finally {
    try {
        if(rs != null) 
            rs.close();
    } catch (SQLException rse) {}
    try {
        if(stmt != null) 
            stmt.close();
    } catch (SQLException sse) {}
    try {
        if(conn != null) 
            conn.close();
    } catch (SQLException cse) {}
}


Connection을 닫을 때 Statement와 ResultSet를 닫아야 하지만 JDBC 사양에 따라 하나의 Connection Object에 여러 Statement를 작성한 경우에는 사용한 직후 Statement와 ResultSet를 명시적으로 닫는 것이 좋습니다. Statement와 ResultSet를 명시적으로 즉시 닫지 않으면 커서가 누적되어 Connection이 닫히기 전에 데이터베이스에 허용된 최대 개수를 초과할 수 있습니다. 예를 들어, 아래 코드 부분에서는finally블록에서 Connection을 닫을 때 ResultSet와 Statement도 닫아야 합니다. 그러나 이 코드 부분은 하나의 Connection에 여러 Statement와 ResultSet를 생성합니다. 루프가 끝나기 전에 "maximum open cursors exceeded(열린 최대 커서 개수 초과)" 문제가 발생했을 수 있습니다.


Connection conn = null;

try{
    conn = getConnection();

    for(int i = 0; i < NUM_STMT; i++) {
        Statement stmt = null;
        ResultSet rs = null;
 
         stmt = conn.createStatement();
         rs = stmt.executeQuery(/*some query*/);
        //do work
    }
} catch(SQLException e) {
     // handle any exceptions
} finally {
    try{
        if(conn != null)
            conn.close();
    } catch(SQLException ignor) {}
}


페이지 맨 위

명령문 캐시
성능 향상을 위해 WebLogic Server는 커넥션 풀을 사용할 때 prepared statements와 callable statements를 캐시하는 기능을 제공합니다. WebLogic Server가 prepared statements나 callable statements를 캐시할 때 많은 경우에 DBMS는 열린 각 명령문에 대해 커서를 유지합니다. 그러므로 명령문 캐시 기능은 "maximum open cursors exceeded(열린 최대 커서 개수 초과)" 문제의 원인이 될 수 있습니다. 명령문 캐시 크기 속성은 커넥션 풀의 각 인스턴스에서 각 커넥션에 대해 캐시할 prepared statements와 callable statements의 전체 개수를 결정합니다. 명령문을 너무 많이 캐시하면 데이터베이스 서버의 열린 커서 개수가 최대 개수를 초과할 수 있습니다.

WebLogic Server에서 디폴트 명령문 캐시 크기는 버전마다 다를 수 있습니다. 예를 들면 다음과 같습니다. 

""maximum open cursors exceeded(열린 최대 커서 개수 초과)" 문제가 명령문 캐시와 관련이 있는지 확인하려면 명령문 캐시 크기를 0으로 설정하여 이 기능을 해제하거나 캐시 크기를 줄여 오류가 계속 발생하는지 확인할 수 있습니다. 캐시 크기를 줄여도 문제가 발생하지 않으면 커넥션 풀의 원래 명령문 캐시 크기가 너무 크거나 DBMS의 최대 열린 커서 개수 제한이 너무 적은 것이므로, 이 중 하나의 값을 조정해야 할 수 있습니다. 커넥션에 열린 커서의 개수가 계속 증가하다가 명령문 캐시 크기를 0으로 설정했을 때 이런 동작이 나타나지 않으면 커서 leak 문제일 수 있습니다. 사용 중인 JDBC 드라이버가 원인이거나 WebLogic Server 버그일 수도 있습니다. 다른 JDBC 드라이버를 사용해 보십시오. 다른 JDBC 드라이버를 사용할 때도 동일한 문제가 발생하면 기술 지원 엔지니어가 이 문제를 세부적으로 조사하여 WebLogic Server 버그인지 확인할 수 있도록 BEA에 보고하십시오.

페이지 맨 위

데이터베이스 드라이버
""maximum open cursors exceeded(열린 최대 커서 개수 초과)" 문제는 JDBC 드라이버가 원인일 수 있습니다. 드라이버가 문제인지 WebLogic 커넥션 풀이 문제인지 파악하기 위해 재현 가능한 테스트 케이스가 있으면 다음을 시도해 볼 수 있습니다.

1. 드라이버에서 커넥션을 직접 가져옵니다.
테스트 케이스에서 JDBC 커넥션은 드라이버에서 직접 가져오고 WebLogic 커넥션 풀은 우회합니다. 커넥션을 닫지 말고 배열이나 일부 다른 구조에 열어 두고 커서 leak 문제가 계속 발생하는지 확인합니다. 커넥션을 닫지 않는 이유는 커넥션 풀을 사용할 때의 동작을 시뮬레이션하기 위해서 입니다. 커넥션 풀을 사용할 때connection.close()는 커넥션을 실제로 닫지는 않으나 대신에 커넥션을 풀로 반환합니다.

2. 다른 JDBC 드라이버로 시도합니다.
타사의 JDBC 드라이버나 드라이버의 업데이트 버전으로 시도하여 문제가 계속 발생하는지 확인합니다. 메타 데이터를 사용하여 올바른 드라이버가 사용되었는지 확인할 수 있습니다. 샘플 코드는 다음과 같습니다.

Connection conn = getConnection();
DatabaseMetaData dmd = conn.getMetaData();
System.out.println("JDBC Driver Name is " + dmd.getDriverName()); 
System.out.println("JDBC Driver Version is " + dmd.getDriverVersion());


3. XA 드라이버 버그.
Oracle XA 드라이버를 사용 중이고 데이터베이스에 "SELECT count (*) FROM SYS.DBA_PENDING_TRANSACTIONS" 같은 쿼리가 많은 경우 Oracle XA 드라이버에 커서 leak 문제가 발생할 수 있습니다. 이 문제는 MetaLink Case 3151681에 설명되어 있으며 버전 10.1.0.2에서 수정되었습니다.
또한 XA 드라이버를 사용할 때http://e-docs.bea.com/wls/docs81/jta/thirdpartytx.html#1075181에 설명된 대로 데이터베이스 서버에 XA 사용을 설정해야 합니다. 즉,grant select on dba_pending_transactions to public명령을 실행해야 합니다.

JDBC 드라이버가 문제이고 이 드라이버를 사용해야 할 경우 커서 leak 문제의 해결 방법은 WebLogic 커넥션을 가끔씩 재설정하거나 커넥션 풀을 축소하는 것입니다. 재설정하는 방법이나 커넥션 풀을 축소하는 방법은 WebLogic 설명서를 참조하십시오. 버전 8.1의 경우http://e-docs.bea.com/wls/docs81/ConsoleHelp/domain_jdbcconnectionpool_control.html에 설명되어 있습니다.


페이지 맨 위

알려진 문제
사용하고 있는 WLS 버전의 릴리스 정보를 주기적으로 검토하여 서비스 팩에서 알려진 문제나 해결된 문제를 확인하고 ORA-01000 / 커서 Leak 관련 문제를 검색할 수 있습니다.다음을 참조하십시오.
특별 정보의 경우, 각 버전의 서비스 팩 릴리스 정보에서 해결된 것으로 표시된 다음 CR를 참고하십시오. 

검색하면 릴리스 정보뿐 아니라추가 도움말에서 언급된 기타 지원 솔루션 및 CR 관련 정보도 알 수 있습니다. 계약 고객은http://support.bea.com/에 로그인한 다음 Browse 포틀릿에서 Solutions 및 Bug Central을 검색하여 제품 버전별로 사용 가능한 최신 CR을 찾을 수 있습니다.

페이지 맨 위

추가 도움말이 필요하십니까?
패턴대로 작업했지만 추가 도움말이 필요한 경우 다음과 같이 할 수 있습니다.
  1. http://support.bea.com/의 AskBEA에서"ORA-01000: maximum open cursors exceeded" 등으로 문제를조회하여 게시된 다른 해결 방법을 찾아봅니다. 계약 지원 고객: 제공되는 CR 관련 정보에 액세스할 수 있는 권한으로 로그온합니다
  2. http://forums.bea.com에서 BEA 뉴스그룹에 보다 자세한 내용을 질문합니다.
이렇게 해도 문제를 해결할 수 없는 경우 유효한 유지 보수 계약이 되어 있다면http://support.bea.com/에 로그인하여 지원요청할 수 있습니다.
신고
Posted by The.민군

Oracle lock이 걸렸을 때 blocker 찾기

 

SELECT/*+ ordered use_hash( sw l ) */
  s.sid
 ,s.serial#
 ,s.module
 ,s.program
 ,sw.seconds_in_wait Sec
 ,TO_CHAR(l.sid) ||','||TO_CHAR(s1.Serial#)|| ':' || sw1.event ||decode(sw1.seconds_in_wait,0,NULL,'('||sw1.seconds_in_wait||'secs)')  holder
 FROM  

        v$session_wait sw
,       v$session      s
,       v$lock         l
,       v$session s1
,       v$session_wait sw1
WHERE  sw.event like 'enq%'
AND    S.sid    = sw.sid
AND    l.id1(+) = sw.p2
AND    l.id2(+) = sw.p3
AND    l.lmode(+) > 0
AND    l.sid(+) <> sw.sid
AND    s1.sid=sw1.sid
AND    l.sid=s1.sid
ORDER BYl.sid, sw.seconds_in_wait DESC;

 

http://database.sarang.net/?inc=read&aid=29191&criteria=oracle&subcrit=qna&id=&limit=20&keyword=&page=1

 


신고
Posted by The.민군

톰캣이 사용하는 8080를 오라클놈이 먼저 점유해 버릴수 있습니다 -_-;

 

 

오라클 9i를 설치하고 난 후에 8080를 점유하는 XDB HTTP 포트 변경하기

 

1. Enterprise Manager Console을 띄운다.

2. Oracle Enterprise Manager Console 창에서 '독립적으로 실행'을 선택하고

'확인'을 클릭한다.

3. Oracle Enterprise Manager Console, 독립형 창의 왼쪽 트리 구조에서 변경하고자 하는

데이터베이스를 선택한다.

4. 3번을 수행하면 뜨는 '데이터베이스 접속 정보'라는 창에서 사용자 이름 sys, 암호,

'다음으로접속'은 sysdba를 선택한 다음 '확인'을 클릭한다.

5. 로그인 하면 왼쪽 트리 구조의 데이터베이스 이름 밑으로 하위 메뉴가 나타나며 그 중

'XML 데이터베이스'를 선택해 준다.

6. 'XML 데이터베이스' 하위 메뉴 중 '구성'을 선택하면 내용창에 'XML 데이터베이스 매개변수' 목록들이 나타난다.

7. http-port 항목의 값을 바꾸려고 하는 적절한 값으로 변경한다.

8. 7번 수행후 다른 조치가 필요없이 바로 적용된다.

 

FROMhttp://cafe.naver.com/cmdir.cafe?iframe_url=/ArticleRead.nhn%3Farticleid=560

신고
Posted by The.민군

read / write lock

MYSQL 2007.01.27 21:52

- Lock설정은 특정 테이블을 사용하고 있는 상황에서 다른 접속자의 접근 차단하는 기능을 한다.
- READ Lock을 걸면 다른 사용자는 해당 테이블에 읽기만 할 수 있다.
- WRITE Lock을 걸면 다른 사용자는 테이블에 전혀 접근 할 수 없다.

-----------------------------------------------------------------------------
- 동시접속 실습을 위해서 도스창 2개를 열고 mysql을 같은 계정으로 실행 한다.

A 사용자 B 사용자

- Lock을 건다.
   LOCK TABLES customers READ;

 

- 다른 창에서 SELECT를 한다. 
   SELECT name FROM customers WHERE customers_id=1;

 

- 다른 창에서 update를 해본다.
   Lock 때문에 화면이 정지된 상태로 있는다.
   UPDATE customers SET name='허준2' WHERE customers_id=15;

 

- Lock을 푼다.
   UNLOCK TABLES;

 

- Lock이 풀리자마자 update가 실행된다.
   SELECT customers_id, name from customers;

 

- Lock을 건다.
   LOCK TABLES customers WRITE;

 

- 다른 창에서 SELECT를 한다. Lock 때문에 SELECT가 안된다.
   SELECT name FROM customers;

 

- Lock을 푼다.
   UNLOCK TABLES;

 

- Lock이 풀리자마자 바로 SELECT가 실행된다.

 

신고
Posted by The.민군

Mysql lock 해결기

MYSQL 2007.01.27 21:51

table lock 해결기

 

lock에 의한 too many connection 에러는 대부분 slow-query에 의해 발생 합니다

먼저 show processlist로 쿼리를 확인합니다 만약 존재하지 않는다면..

데이터 폴더에 **-slow.log 파일을 참고하여 slow-query들을 적절 히 튜닝합니다

 

만약 slow.log가 존재하지 않는다면

 

my.cnf

[mysqld]

log-slow-queries

long_query_time = 3

 

를 추가후 재시작 합니다

신고
Posted by The.민군


티스토리 툴바