2015년 7월 22일 수요일

[JAVA TreeSet예제, Comparator, compare]

[JAVA TreeSet예제, Comparator, compare]


package day6;

import java.util.*;

class AddrBook {
String name;
String addr;

AddrBook(String name, String addr) {
this.name = name;
this.addr = addr;
}

public String toString() {
return name + " / " + addr;
}
}

public class TreeSetTest2 implements Comparator {
Set treeset;

public TreeSetTest2() {
// Comparable을구현않은객체를add 하므로/TreeSet의생성자에
// Comparator 객체를전달하여다른비교메소드를이용하라고알림
treeset = new TreeSet(this);
}

public void test() {
treeset.add(new AddrBook("나길동", "서울"));
treeset.add(new AddrBook("하길동", "부산"));
treeset.add(new AddrBook("김길동", "대구"));
treeset.add(new AddrBook("최길동", "광주"));
printAll();
}

public int compare(Object o1, Object o2) {
return (((AddrBook) o1).name).compareTo(((AddrBook) o2).name);
}

public void printAll() {
Iterator iter = treeset.iterator();
while (iter.hasNext())
System.out.println(iter.next());
}

public static void main(String[] args) {
TreeSetTest2 tst = new TreeSetTest2();
tst.test();
}
}


[결과]
김길동 / 대구
나길동 / 서울
최길동 / 광주
하길동 / 부산

[자바 컬렉션,람다식,forEach,더블콜론, TreeSet예제,Comparable,compareTo,iterator]

[자바 컬렉션,람다식,forEach,더블콜론, TreeSet예제,Comparable,compareTo,iterator]

package day6;
import java.util.Iterator;
import java.util.Set;
import java.util.TreeSet;
import java.util.function.Consumer;
class AddrBook2 implements Comparable{
String name;
String addr;
AddrBook2(String name, String addr) {
this.name = name;
this.addr = addr;
}
public String toString() {
return name + " / " + addr;
}
@Override
public int compareTo(Object o) {
return this.name.compareTo(((AddrBook2)o).name);
}
}
public class TreeSetTest3 {
Set treeset;
public TreeSetTest3() {
// Comparable을구현한객체를add 하므로/TreeSet의생성자에 this를 넣지 않음
treeset = new TreeSet();
}
public void test() {
treeset.add(new AddrBook2("나길동", "서울"));
treeset.add(new AddrBook2("하길동", "부산"));
treeset.add(new AddrBook2("김길동", "대구"));
treeset.add(new AddrBook2("최길동", "광주"));
printAll();
}
public void printAll() {
Iterator iter = treeset.iterator();
while (iter.hasNext())
System.out.println(iter.next());
treeset.forEach(new Consumer<AddrBook2>() { 
            public void accept(AddrBook2 addr) {
                System.out.println("forEach s :: " + addr );
            } 
        });
//이번에는 forEach 람다식으로...
System.out.println("--------------------");
treeset.forEach( (addr) -> System.out.println("람다식 Addr ::" + addr ) );        
        //이번에는 forEach 더블콜론 연산자로...
        System.out.println("--------------");
        treeset.forEach(System.out::println);
        
      //이번에는 forEach 더블콜론 연산자, 람다식으로...
        System.out.println("--------------");
        treeset.forEach((addr) -> System.out.println(addr)); 
}
public static void main(String[] args) {
TreeSetTest3 tst = new TreeSetTest3();
tst.test();
}
}

[결과]
김길동 / 대구
나길동 / 서울
최길동 / 광주
하길동 / 부산
forEach s :: 김길동 / 대구
forEach s :: 나길동 / 서울
forEach s :: 최길동 / 광주
forEach s :: 하길동 / 부산
--------------------
람다식 Addr ::김길동 / 대구
람다식 Addr ::나길동 / 서울
람다식 Addr ::최길동 / 광주
람다식 Addr ::하길동 / 부산
--------------------
--------------
김길동 / 대구
나길동 / 서울
최길동 / 광주
하길동 / 부산


2015년 7월 14일 화요일

스프링 자바빈로딩방법2가지(Lazy-Loading, Pre-Loading, BeanFactory,ApplicationContext )

스프링 자바빈로딩방법2가지(Lazy-Loading, Pre-Loading, BeanFactory,ApplicationContext )

스프링프레임워크에서는 자바빈을 인스턴스로 만든 후 로딩하는 하는 방법이 두가지 이다. BeanFactory를 사용하느냐 ApplicationContext containers를 사용하느냐에 따라서...

1. Lazy-Loading

메소드나 클래스가 요청을 받는 시점에 자바빈의 인스턴스를 만들고 로딩하는 방법이다.

BeanFactory factory = new XmlBeanFactory(
                        new InputStreamResource(
                        new FileInputStream("oraclejavacommunity.xml"))); // 1
OracleJavaComm ojc = (OracleJavaComm) factory.getBean("oracleJavaBean"); // 2

1번에서 BeanFactory 컨테이너에 의해 oraclejavacommunity.xml 파일이 로드되더라도 어떠한 빈도 인스턴스화 되지 않고 2번에서 oracleJavaBean이 요청을 받는시점에 인스턴스화 되고 로드된다. 즉 getBean메소드 호출시 빈이 로드되는 것이다.

2. Pre-loading

모든 빈들이 스프링 설정파일이 ApplicationContext 컨테이너에 의해 로드될 때 인스턴스로 만들어지고 로드된다.

ApplicationContext context =
            new ClassPathXmlApplicationContext("oraclejavacommunity.xml"); // 1 
OracleJavaComm ojc = (OracleJavaComm) factory.getBean("oracleJavaBean"); // 2

1번에서 모든 싱글톤 빈들이 인스턴스화 된다. 그러므로 빈이 여러개라면 시간이 소요될 것이다. 2번에서는 미리 컨테이너에서 만들어진 빈들이 클라이언트로 리턴된다.

[결론]
스프링 설정파일에 여러개의 자바빈이 정의되었다고 모두 자주 사용되는 것은 아닐 수 있다. 모두 자주 사용되지 않을수도 있으니 이러한 경우라면 요청이 있을 때 자바빈을 인스턴스로 만드는 것이 좋을 것이다. 물론 모두 자주 사용되는 빈이라면 한번에 로드하는 것도 좋은 방법이다.

Spring AOP를 이용한 SQL로깅(?를파라미터로 치환하여 DML로그출력),Spring JDBC로깅,Spring Framework의 JdbcOperations을 포인트컷으로 해서 모든 SQL에 대해 로깅 충고

Spring AOP를 이용한 SQL로깅(?를파라미터로 치환하여 DML로그출력),Spring JDBC로깅,Spring Framework의 JdbcOperations을 포인트컷으로 해서 모든 SQL에 대해 로깅 충고


1. 로깅을 위한 Aspcet 작성

package onj.board.aop;

import org.slf4j.Logger;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.beans.factory.annotation.Autowired;
import org.slf4j.LoggerFactory;

@Aspect
public class LoggingAspect {
private final Logger logger = LoggerFactory.getLogger(LoggingAspect.class);

// 사전충고
// Spring Framework의 JdbcOperations을 포인트컷으로 해서 모든 SQL에 대해 로깅 충고가 적용
@Before("execution(* org.springframework.jdbc.core.JdbcOperations.*(String, ..))")    
public void logBefore(JoinPoint joinPoint) {
logger.info("<<<<<<<<<<<<<<<<< DAO 로깅 충고 실행");

Object[] methodArgs = joinPoint.getArgs(), sqlArgs = null;
// 실행시킨 SQL 문장
String statement = methodArgs[0].toString();   // ? 가 포함된 SQL문

// find the SQL arguments (parameters)
for (int i = 1, n = methodArgs.length; i < n; i++) {
Object arg = methodArgs[i];
if (arg instanceof Object[]) {
sqlArgs = (Object[]) arg;
break;
}
}
// '?' 대신 파라미터로 대체
   String completedStatement = (sqlArgs == null ? 
    statement : fillParameters(statement, sqlArgs));
   
   logger.info(completedStatement);
}
//SQL문장의 ?를 넘겨주는 파라미터로 대체해서 최종SQL문을 리턴
private String fillParameters(String statement, Object[] sqlArgs) {
   // initialize a StringBuilder with a guesstimated final length
   StringBuilder completedSqlBuilder = new StringBuilder(Math.round(statement.length() * 1.2f));
   int index, // will hold the index of the next ?
   prevIndex = 0; // will hold the index of the previous ? + 1
 
   // loop through each SQL argument
   for (Object arg : sqlArgs) {
       index = statement.indexOf("?", prevIndex);
       if (index == -1)
           break; // bail out if there's a mismatch in # of args vs. ?'s
 
       // append the chunk of SQL coming before this ?
       completedSqlBuilder.append(statement.substring(prevIndex, index));
       // append the replacement for the ?
       if (arg == null)
           completedSqlBuilder.append("NULL");
       else
           completedSqlBuilder.append(":"+arg.toString());
 
       prevIndex = index + 1;
   }
 
   // add the rest of the SQL if any
   if (prevIndex != statement.length())
       completedSqlBuilder.append(statement.substring(prevIndex));
 
   return completedSqlBuilder.toString();
}
}


2. XML 설정파일에서

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xmlns:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop" 
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
<aop:aspectj-autoproxy />
<context:component-scan base-package="onj.board.dao" />
<context:component-scan base-package="onj.board.service" />

<!-- JdbcTemplate -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"
p:dataSource-ref="dataSource" />

<!-- wire the JdbcTemplate into your DAO (Alternatively, you could use autowiring) -->
    <bean id="boardDAO" class="onj.board.dao.BoardDAOImpl"/>

<!-- AOP를 적용하여 DML처리시 로깅을 위한 것 -->
<bean id="myLogger" class="onj.board.aop.LoggingAspect" />

</beans>


3. DAO 파일에서는 jdbcTemplate을 어노테이션을 이용하여 주입받자.

@Repository("boardDAO")
public class BoardDAOImpl implements BoardDAO {
@Autowired
private JdbcOperations jdbcTemplate;

        .............................
}

이제 Spring JDBC를 통하여 실행되는 모든 SQL문은 로깅이 된다.


jdbcTemplate을 스프링 빈으로 주입하기(jdbcTemplate Autowiredd 시키기)

참고하세요~


1. XML 설정 파일에서

<!-- JdbcTemplate -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"
p:dataSource-ref="dataSource" />

<!-- wire the JdbcTemplate into your DAO (Alternatively, you could use autowiring) -->
    <bean id="boardDAO" class="onj.board.dao.BoardDAOImpl"/>

<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:@192.168.0.17:1521:onj</value>
</property>
<property name="username">
<value>scott</value>
</property>
<property name="password">
<value>tiger</value>
</property>
</bean>
    

2. DAO 자바파일에서

@Repository("boardDAO")
public class BoardDAOImpl implements BoardDAO {
@Autowired
private JdbcOperations jdbcTemplate; 
  
        또는

      @Autowired
private JdbcTemplate jdbcTemplate;

        .................................


또는 아래처럼 setter를 만들어서... 세터주입으로


       //아래 두개의 어떤 타입으로 받아도 된다.
//private JdbcOperations jdbcTemplate;
private JdbcTemplate jdbcTemplate;

public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}

2015년 7월 6일 월요일

PL/SQL 블록에서 다른 프러시저, 함수 호출하기

PL/SQL 블록에서 다른 프러시저, 함수 호출하기

SQL> CREATE OR REPLACE PROCEDURE create_dept (
  2    p_deptno IN dept2.deptno%TYPE,
  3    p_dname  IN dept2.dname%TYPE,
  4    p_loc    IN dept2.loc%TYPE
  5  )
  6  IS
  7  BEGIN
  8
  9    INSERT INTO dept2 values (
 10      p_deptno,
 11      p_dname,
 12      p_loc);
 13  END;
 14  /
프로시저가 생성되었습니다.

SQL> DECLARE
  2    plsql_block VARCHAR2(500);
  3    new_deptno  dept2.deptno%TYPE := 99;
  4    new_dname  dept2.dname%TYPE := 'SALES';
  5    new_loc  dept2.loc%TYPE := 'GURODIGITAL';
  6  BEGIN
  7    -- PL/SQL 프로그램 호출
  8    plsql_block := 'BEGIN create_dept(:a, :b, :c); END;';
  9
 10    EXECUTE IMMEDIATE plsql_block
 11      USING new_deptno, new_dname, new_loc;
 12  END;
 13  /

SQL> SELECT * FROM DEPT2;

    DEPTNO  DNAME          LOC
----------  --------------  -------------
        10 ACCOUNTING    GURODIGITAL
        20 RESEARCH        DALLAS
        30 SALES            CHICAGO
        40 OPERATIONS      BOSTON
        99 SALES            GURODIGITAL 

패키지,프러시저,함수 전위적 선언(Forward Declaration)

패키지,프러시저,함수 전위적 선언(Forward Declaration)

 동일한 PL/SQL블록에 여러 개의 Sub Program들이 올 수 있는데, 패키지내 함수, 프러시저는 서로 호출을 하거나 호출당하는 입장이다.
 어떤 프로시저/함수에서 다른 프로시저/함수를 호출할 때 호출당하는 프로시저/함수는 먼저 선언 되어야 한다.(구현부가 뒤쪽에 있는 경우)

SQL> DECLARE
          -- proc2 선언 및 구현
          PROCEDURE proc2(num NUMBER) IS
          BEGIN
            proc1();
          END;
        -- proc1 구현
        PROCEDURE proc1 IS
        BEGIN
          proc2(8514790) ;
        END;
      BEGIN
        NULL;
      END;
  /

        proc1();
        *
5행에 오류:
ORA-06550: 줄 5, 열9:PLS-00313: 범위 내에 'PROC1'(이)가 선언되지 않았습니다
ORA-06550: 줄 5, 열9:PL/SQL: Statement ignored

SQL> DECLARE
      -- proc1 선언
      PROCEDURE proc1;
 
      -- proc2 선언 및 구현
      PROCEDURE proc2(num NUMBER) IS
      BEGIN
        proc1();
      END;
 
    -- proc1 구현
    PROCEDURE proc1 IS
    BEGIN
      proc2(8514790) ;
    END;
 
  BEGIN
    NULL;
  END;
  /
PL/SQL 처리가 정상적으로 완료되었습니다.

SQL> DECLARE
  2    -- proc1 구현
  3    PROCEDURE proc1 IS
  4    BEGIN
  5      NULL;
  6    END;
  7    -- proc2 선언 및 구현
  8    PROCEDURE proc2(num NUMBER) IS
  9    BEGIN
 10      proc1();
 11    END;
 12  BEGIN
 13    NULL;
 14  END;
 15  /

PL/SQL 처리가 정상적으로 완료되었습니다.