2022년 1월 9일 일요일

[자바스프링동영상]스프링 JPA로깅, Log4J, Logback-spring, 오라클교육/오라클학원/자바학원/스프링학원/자바교육/스프링교육

 [자바스프링동영상]스프링 JPA로깅, Log4J, Logback-spring, 오라클교육/오라클학원/자바학원/스프링학원/자바교육/스프링교육


https://www.youtube.com/watch?v=3HzIvCF7miQ&list=PLxU-iZCqT52AlV-Y7UlwSQp8N6pMjijFX&index=10http://ojc.asia/bbs/board.php?bo_table=LecJpa&wr_id=362 

https://www.youtube.com/watch?v=2Ct32nlhBzA&list=PLxU-iZCqT52AlV-Y7UlwSQp8N6pMjijFX&index=1 


스프링 JPA로깅, Log4J, Logback-spring

스프링 JPA로깅, Log4J, Logback-springLoggingSQL을 대신 작성해 주는 JPA 기술을 사용하다 보면 과연 적합한 SQL을 사용하는지 궁금해지기 마련입니다. 특히나 테이블 크기가 크고 복잡한 조인 쿼리를 사

ojc.asia

https://www.youtube.com/watch?v=poDicowrj_Y&list=PLxU-iZCqT52AlV-Y7UlwSQp8N6pMjijFX&index=11 



 Logging

SQL을 대신 작성해 주는 JPA 기술을 사용하다 보면 과연 적합한 SQL을 사용하는지 궁금해지기 마련입니다. 특히나 테이블 크기가 크고 복잡한 조인 쿼리를 사용해서 여러 테이블의 데이터를 구해야 하는 경우 JPA가 최적의 SQL을 작성해서 사용하는지 검토해 볼 필요가 있습니다. 


오랜 역사의 오라클데이터베이스도 때때로 최적의 쿼리를 사용하지 않고 있는 모습을 볼 수 있습니다. 그럴 때 힌트를 사용해서 개발자가 직접 쿼리의 실행계획을 조정할 필요가 있습니다. 이와 마찬가지로 JPA가 작성해서 사용하는 쿼리도 최적의 쿼리가 아닐 수 있습니다. 어떤 SQL 쿼리를 사용하느냐에 따라 성능의 차이가 날 수 있기 때문에 개발자가 직접 확인 해야 합니다. 이를 위해 프로젝트에 로깅기술을 적용해서 사용된 쿼리를 살펴보기 쉽도록 만들 필요가 있습니다.


     프로젝트 생성

앞서 작업한 프로젝트 chapter1-4를 선택한 상태에서 ctrl+c, ctrl+v 키를 연속으로 눌러서 소스 전체를 복사해 chapter1-5라고 명명하면서 프로젝트를 추가합니다.




 디펜던시 설정

pom.xml 파일에 다음 설정을 추가합니다.

<dependency>

<groupId>org.bgee.log4jdbc-log4j2</groupId>

<artifactId>log4jdbc-log4j2-jdbc4.1</artifactId>

<version>1.16</version>

</dependency>

    로깅 환경설정

환경설정파일에 로깅을 위한 설정을 추가합니다.

application.properties

# DATASOURCE

#spring.datasource.url=jdbc:mysql://localhost:3306/testdb?createDatabaseIfNotExist=true

spring.datasource.url=jdbc:log4jdbc:mysql://localhost:3306/testdb?createDatabaseIfNotExist=true

#spring.datasource.driver-class-name=com.mysql.jdbc.Driver

spring.datasource.driver-class-name=net.sf.log4jdbc.sql.jdbcapi.DriverSpy


# Logging

logging.config=classpath:logback-spring.xml

기존 드라이버 설정은 # 주석으로 막고 드라이버 스파이를 사용하도록 변경합니다. 로깅설정의 상세한 내용은 logback-spring.xml에 작성합니다. logback은 log4j를 업그레이드 한 기술입니다.


logback-spring.xml

<?xml version="1.0" encoding="UTF-8"?>

<!--  

jdbc.sqlonly    : Logs only SQL

jdbc.sqltiming  : Logs the SQL, post-execution, including timing execution statistics

jdbc.audit      : Logs ALL JDBC calls except for ResultSets

jdbc.resultset  : all calls to ResultSet objects are logged

jdbc.connection : Logs connection open and close events

-->

<configuration>

<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">

<!-- By default, encoders are assigned 

the type ch.qos.logback.classic.encoder.PatternLayoutEncoder -->

<encoder>

<pattern>

%d{yyyyMMdd HH:mm:ss.SSS} [%thread] %-3level %logger{5} -%msg %n

</pattern>

</encoder>

</appender>


<logger name="jdbc" level="OFF" />

<logger name="jdbc.sqlonly" level="DEBUG" additivity="false">

<appender-ref ref="STDOUT" />

</logger>

<logger name="jdbc.resultsettable" level="DEBUG" additivity="false">

<appender-ref ref="STDOUT" />

</logger>


<include resource="org/springframework/boot/logging/logback/base.xml"/>


<appender name="dailyRollingFileAppender" 

class="ch.qos.logback.core.rolling.RollingFileAppender">

<prudent>true</prudent>

<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">

<fileNamePattern>applicatoin.%d{yyyy-MM-dd}.log</fileNamePattern>

<maxHistory>30</maxHistory>

</rollingPolicy>

<filter class="ch.qos.logback.classic.filter.ThresholdFilter">

<level>INFO</level>

</filter>

<encoder>

<pattern>

%d{yyyy:MM:dd HH:mm:ss.SSS} %-5level --- [%thread] %logger{35} : %msg %n

</pattern>

</encoder>

</appender>


<logger name="org.springframework.web" level="INFO"/>

<logger name="org.thymeleaf" level="INFO"/>

<logger name="org.hibernate.SQL" level="INFO"/>

<logger name="org.quartz.core" level="INFO"/>

<logger name="org.h2.server.web" level="INFO"/>


<root level="INFO">

<appender-ref ref="STDOUT" />

<!-- 프로젝트 루트 폴더에서 파일생성을 확인 (applicatoin.20YY-MM-DD.log) -->

<appender-ref ref="dailyRollingFileAppender" />

</root>

</configuration>

 "STDOUT" 설정으로 로깅정보가 콘솔에 출력됩니다.

 "dailyRollingFileAppender" 설정으로 로깅 정보가 프로젝트 루트에 파일로 기록됩니다.


log4jdbc.log4j2.properties

로깅을 처리할 때 로거가 참조하는 설정정보를 알려줍니다.

log4jdbc.spylogdelegator.name=net.sf.log4jdbc.log.slf4j.Slf4jSpyLogDelegator

# multi-line query display

log4jdbc.dump.sql.maxlinelength=0


    테스트

스프링 기동 로그 살펴보기

application.properties 파일에 spring.jpa.hibernate.ddl-auto=create 설정으로 프로젝트가 기동 시 기존 테이블을 삭제하고 다시 생성할 것입니다. 로그 정보에서 관련 로그내역을 찾아보세요.

drop table if exists employee
 

create table employee (empno bigint not null, ename varchar(255), job varchar(255), primary key (empno)) ENGINE=InnoDB


data.sql에 작성된 쿼리를 처리하는지 확인합니다.

INSERT IGNORE INTO EMPLOYEE(empno, ename, job) VALUES(7839,'KING','PRESIDENT');

INSERT IGNORE INTO EMPLOYEE(empno, ename, job) VALUES(7566,'JONES','MANAGER');

INSERT IGNORE INTO EMPLOYEE(empno, ename, job) VALUES(7698,'BLAKE','MANAGER');

INSERT IGNORE INTO EMPLOYEE(empno, ename, job) VALUES(7782,'CLARK','MANAGER');


브라우저로 접근해서 데이터를 요청하여 테스트 합니다.


질의 관련 로그 살펴보기

드라이버스파이는 조회쿼리인 경우 결과를 보기 좋게 테이블로 표시해 줍니다.

select employee0_.empno as empno1_0_, employee0_.ename as ename2_0_, employee0_.job as job3_0_ from employee employee0_


쿼리의 퍼포먼스를 판단할 수 있는 실행계획까지는 보여주지 않으므로 로그에 표시된 쿼리를 데이터베이스 전용 프로그램에서 실행하여 실행계획을 살펴 보시기 바랍니다.


https://www.youtube.com/watch?v=w6XoZ3Luzus&list=PLxU-iZCqT52AlV-Y7UlwSQp8N6pMjijFX&index=4 

 

#JPA, #로깅, #스프링로깅, #Log4J, #스프링교육, #자바교육, #오라클교육,#스프링학원, #자바학원, #SQL학원, #오라클학원, JPA, 로깅, 스프링로깅, Log4J, 스프링교육, 자바교육, 오라클교육,스프링학원, 자바학원, SQL학원, 오라클학원

2022년 1월 8일 토요일

오라클,PLSQL,DBMS_SQL,컬럼값을 가로행으로 출력,Unpivot, DESCRIBE_COLUMNS, DEFINE_COLUMN, COLUMN_VALUE, 자바학원, 오라클학원, SQL학원, 닷넷학원

 오라클,PLSQL,DBMS_SQL,컬럼값을 가로행으로 출력,Unpivot, DESCRIBE_COLUMNS, DEFINE_COLUMN, COLUMN_VALUE, 자바학원, 오라클학원, SQL학원, 닷넷학원


http://ojc.asia/bbs/board.php?bo_table=LecSQLnPlSql&wr_id=731 

오라클,PLSQL,DBMS_SQL.DESCRIBE_COLUMNS, 컬럼정보출력, DESC_TAB, DESC_REC, 오라클교육, SQL교육, 자바교육, 오

오라클,PLSQL,DBMS_SQL.DESCRIBE_COLUMNS, 컬럼정보출력, DESC_TAB, DESC_REC, 오라클교육, SQL교육, 자바교육, 오라클학원, SQL학원, 자바학원오라클 PL/SQLDBMS_SQL.DESCRIBE_COLUMNS(컬럼정보 출력)실습DBMS_SQL.DESCRIBE_COLUM

ojc.asia



https://www.youtube.com/watch?v=6Dj4un2o9bQ&list=PLxU-iZCqT52CfP98Y4gCDKIm52tKvgy36&index=44 


컬럼값을 가로행으로 출력

(Unpivot)


https://www.youtube.com/watch?v=0CYrvAWrBjk&list=PLxU-iZCqT52CfP98Y4gCDKIm52tKvgy36&index=43





먼저 예제에서 사용되는 몇가지 프로시저에 대해 이해를 하고 실습을 하겠습니다.


DBMS_SQL.DESCRIBE_COLUMNS 프로시저 : 컬럼의 정보를 DESC_REC 레코드 타입의 배열 형태인 DESC_TAB(OUT 타입) 변수에 담아두면 호출한 쪽에서 꺼내서 사용한다.


DBMS_SQL.DESCRIBE_COLUMNS ( 
   c                  IN     INTEGER, 
   col_cnt        OUT  INTEGER, 
   desc_t         OUT  DESC_TAB);
OPEN되고 파싱되는 커서의 컬럼을 정의. 컬럼의 정보를 배열에 담는다.

c : 커서, col_cnt : 컬럼 개수
desc_r : 컬럼의 정의를 담을 배열

DESC_TAB 타입은 DESC_REC를 담고 있는 오라클 테이블 타입(배열)

DESC_REC 에는 col_type, col_maxlen, col_name, col_name_len, col_schema_name, col_schema_name_len, col_precision, col_scale 등의 속성이 있다.


https://www.youtube.com/watch?v=oR_UKxk_HO4&list=PLxU-iZCqT52CfP98Y4gCDKIm52tKvgy36&index=39 



DBMS_SQL.DEFINE_COLUMN


[컬럼값의 타입이 문자열인 경우]
DBMS_SQL.DEFINE_COLUMN (
   c              IN INTEGER,
   position       IN INTEGER,
   column         IN VARCHAR2   
               CHARACTER SET ANY_CS,
   column_size    IN INTEGER);

[컬럼값의 타입이 문자열이 아닌 경우]
DBMS_SQL.DEFINE_COLUMN (
         c        IN INTEGER,
         position IN INTEGER,
         column   IN <datatype>);

커서에서 추출되는 컬럼 값을 담을 변수를 정의. 컬럼의 위치는 SELECT 목록에서 상대적 위치로 구별된다.

c : 커서ID
position : 컬럼의 상태위치
column : 커서의 SELECT되는 컬럼값을 받을 변수
column_size : 컬럼 길이
DBMS_SQL.COLUMN_VALUE (
   c                 IN  INTEGER,
   position          IN  INTEGER,
   value             OUT <datatype> 
 [,column_error      OUT NUMBER] 
 [,actual_length     OUT INTEGER]);

주어진 컬럼의 값을 리턴. FETCH_ROWS를 호출하여 가져온 데이터에 접근하는 데 사용된다.

c : 커서ID
position : 컬럼의 상태위치
value : 컬럼값을 담을 OUT 변수

[실습 : SELECT쿼리문을 입력 받아 DBMS_SQL을 이용하여 행만큼 루프를 돌면서 컬럼값을 가로행으로 출력]


CREATE OR REPLACE PROCEDURE unpivottable( p_sql IN VARCHAR2 )
AUTHID CURRENT_USER  --프로시저 실행시 컴파일 사용자가 아닌 현재 접속사용자로 실행, 기본은 AUTHID DEFINER
IS
    v_cursor        INTEGER;
    v_columnvalue   VARCHAR2(500);
    v_return        INTEGER;
    v_descrectable  dbms_sql.desc_tab;
    v_colcnt        NUMBER;
BEGIN
    -- SQL 실행을 위한 커서를 오픈, 커서ID 리턴
    v_cursor := dbms_sql.open_cursor;
    
    -- SQL문장 파싱
    dbms_sql.parse(v_cursor, p_sql, dbms_sql.NATIVE);
    
    -- 커서에 대한 컬럼정보를 DBMS_SQL.DESC_TAB 배열변수에 넣는다.
    -- DBMS_SQL.DESC_TAB은 DESC_REC 레코드 타입의 배열이다.
    dbms_sql.describe_columns ( v_cursor, v_colcnt, v_descrectable );
    
    -- v_colCnt의 컬럼 개수만큼 루프를 돌며 컬럼을 정의.
    -- 커서에서 추출되는 컬럼값을 담을 변수를 정의
    FOR I IN 1..v_colcnt
    LOOP
        dbms_sql.define_column (v_cursor, I, v_columnvalue, 500);
    END LOOP;
    
    -- SQL실행, INSERT, UPDATE, DELETE의 경우 처리된 건수를 리턴받는다. 그 외는 무시
    v_return := dbms_sql.EXECUTE(v_cursor);
    
    -- 읽어들인 행의 수만큼 반복
    WHILE ( dbms_sql.fetch_rows (v_cursor) > 0 )
      LOOP
        -- 컬럼 개수만큼 다시 루프를 돌면서 컬럼 값을 v_columnvalue 변수에 담는다
        -- DBMS_SQL.DESC_TABdms DESC_REC 레코드 타입의 배열이고, DESC_REC 타입의 col_name은 컬럼 명칭 이다. 
        FOR I IN 1..v_colcnt
        LOOP
          -- FETCH후 컬럼값을 받아 옴
          dbms_sql.COLUMN_VALUE ( v_cursor, I, v_columnvalue );
          dbms_output.put_line  ( rpad( v_descrectable(I).col_name, 20 ) || ': ' || v_columnvalue );
        END LOOP;
        -- 한행이 끝날때마다 출력
        dbms_output.put_line( '--------------------------------------------' );
    END LOOP;

    dbms_sql.close_cursor (v_cursor);
END;


EXEC UNPIVOTTABLE('select ename, sal, deptno from emp where deptno = 20');


ENAME               : SMITH
SAL                 : 1100
DEPTNO              : 20
--------------------------------------------
ENAME               : JONES
SAL                 : 2975
DEPTNO              : 20
--------------------------------------------
ENAME               : SCOTT
SAL                 : 3000
DEPTNO              : 20
--------------------------------------------
ENAME               : ADAMS
SAL                 : 1100
DEPTNO              : 20
--------------------------------------------
ENAME               : FORD
SAL                 : 3000
DEPTNO              : 20
--------------------------------------------


https://www.youtube.com/watch?v=XJOkRPZYSYo&list=PLxU-iZCqT52CfP98Y4gCDKIm52tKvgy36&index=42
#오라클,#PLSQL,#DBMS_SQL,#Unpivot,#DESCRIBE_COLUMNS,#DEFINE_COLUMN, #COLUMN_VALUE, #ORACLE교육, #ORACLE학원, #SQL교육, #SQL학원, #JAVA교육, #JAVA학원, 오라클,PLSQL,DBMS_SQL,Unpivot,DESCRIBE_COLUMNS,DEFINE_COLUMN, COLUMN_VALUE, ORACLE교육, ORACLE학원, SQL교육, SQL학원, JAVA교육, JAVA학원


https://www.youtube.com/watch?v=XbRQfXxbyng&list=PLxU-iZCqT52CfP98Y4gCDKIm52tKvgy36&index=41 

https://www.youtube.com/watch?v=tO4rkJAC7FM&list=PLxU-iZCqT52CfP98Y4gCDKIm52tKvgy36&index=40 


오라클,PLSQL,DBMS_SQL.DESCRIBE_COLUMNS, 컬럼정보출력, DESC_TAB, DESC_REC, 오라클교육, SQL교육, 자바교육, 오라클학원, SQL학원, 자바학원

 오라클,PLSQL,DBMS_SQL.DESCRIBE_COLUMNS, 컬럼정보출력, DESC_TAB, DESC_REC, 오라클교육, SQL교육, 자바교육, 오라클학원, SQL학원, 자바학원


http://ojc.asia/bbs/board.php?bo_table=LecSQLnPlSql&wr_id=730 

오라클,PL/SQL,DBMS_SQL,동적SQL실습 테이블 생성, 멀티행 입력,BIND_ARRAY, EXECUTE, 오라클교육, 오라클학

오라클,PL/SQL,DBMS_SQL,동적SQL실습 테이블 생성, 멀티행 입력,BIND_ARRAY, EXECUTE, 오라클교육, 오라클학원, 오라클동영상,자바교육,자바학원,SQL교육, SQL학원오라클 PL/SQLDBMS_SQL동적SQL실습테이블 생성,

ojc.asia


https://www.youtube.com/watch?v=0CYrvAWrBjk&list=PLxU-iZCqT52CfP98Y4gCDKIm52tKvgy36&index=43 


http://ojc.asia/bbs/board.php?bo_table=LecSQLnPlSql&wr_id=731 


오라클,PLSQL,DBMS_SQL.DESCRIBE_COLUMNS, 컬럼정보출력, DESC_TAB, DESC_REC, 오라클교육, SQL교육, 자바교육, 오

오라클,PLSQL,DBMS_SQL.DESCRIBE_COLUMNS, 컬럼정보출력, DESC_TAB, DESC_REC, 오라클교육, SQL교육, 자바교육, 오라클학원, SQL학원, 자바학원오라클 PL/SQLDBMS_SQL.DESCRIBE_COLUMNS(컬럼정보 출력)실습DBMS_SQL.DESCRIBE_COLUM

ojc.asia

https://www.youtube.com/watch?v=XJOkRPZYSYo&list=PLxU-iZCqT52CfP98Y4gCDKIm52tKvgy36&index=42 

https://www.youtube.com/watch?v=tO4rkJAC7FM&list=PLxU-iZCqT52CfP98Y4gCDKIm52tKvgy36&index=40 


오라클 PL/SQL




DBMS_SQL.DESCRIBE_COLUMNS

(컬럼정보 출력)


실습








DBMS_SQL.DESCRIBE_COLUMNS 프로시저 : 컬럼의 정보를 DESC_REC 레코드 타입의 배열 형태인 DESC_TAB(OUT 타입) 변수에 담아두면 호출한 쪽에서 꺼내서 사용한다.


DBMS_SQL.DESCRIBE_COLUMNS ( 
   c                  IN     INTEGER, 
   col_cnt        OUT  INTEGER, 
   desc_t         OUT  DESC_TAB);
OPEN되고 파싱되는 커서의 컬럼을 정의. 컬럼의 정보를 배열에 담는다.

c : 커서, col_cnt : 컬럼 개수
desc_r : 컬럼의 정의를 담을 배열

DESC_TAB 타입은 DESC_REC를 담고 있는 오라클 테이블 타입(배열)

DESC_REC 에는 col_type, col_maxlen, col_name, col_name_len, col_schema_name, col_schema_name_len, col_precision, col_scale 등의 속성이 있다.





[실습 : DBMS_SQL.DECRIBE_COLUMNS 실습]

CREATE OR REPLACE PROCEDURE  desc_query( p_sql IN VARCHAR2 )
AUTHID CURRENT_USER  --프로시저 실행시 컴파일 사용자가 아닌 현재 접속사용자로 실행, 기본은 AUTHID DEFINER
IS
    v_cursor        INTEGER;
    v_colcnt        NUMBER DEFAULT 0;
    v_cnt           NUMBER DEFAULT 0;
    v_descrectable  dbms_sql.desc_tab;
BEGIN
   -- SQL실행을 위한 커서 오픈ㅡ 커서ID 리턴
   v_cursor := dbms_sql.open_cursor;
   dbms_sql.parse(  v_cursor,  p_sql, dbms_sql.NATIVE );
   -- 커서 SQL의 컬럼정보 셋팅, v_colcnt에 컬럼개수 셋팅, v_descrectable 배열에 컬럼정보셋팅
   dbms_sql.describe_columns(v_cursor, v_colcnt, v_descrectable );
   -- 컬럼개수만큼 반복하면서 정보 출력
   FOR I IN 1 .. v_colcnt
   LOOP
       dbms_output.put_line( 'Column Type:' || v_descrectable(I).col_type );
       dbms_output.put_line( 'Max Length:' || v_descrectable(I).col_max_len );
       dbms_output.put_line( 'Name:' || v_descrectable(I).col_name );
       dbms_output.put_line( 'Name Length:' || v_descrectable(I).col_name_len );
       dbms_output.put_line( 'Precision:' || v_descrectable(I).col_precision );  –전체
       dbms_output.put_line( 'Scale:' || v_descrectable(I).col_scale );  –소수자리
       IF ( v_descrectable(I).col_null_ok ) THEN
           dbms_output.put_line( 'Null허용:Y' );
       ELSE
           dbms_output.put_line( 'Null허용:N' );
       END IF;
       dbms_output.put_line( '-------------------------------');
   END LOOP;
   -- 커서 CLOSE
   dbms_sql.close_cursor(v_cursor);
EXCEPTION
   WHEN OTHERS THEN
      dbms_output.put_line(sqlerrm);
    IF dbms_sql.is_open(v_cursor) THEN
       dbms_sql.close_cursor(v_cursor);
    END IF;
END desc_query;

exec desc_query('select empno, ename, sal from emp');

Column Type:2
Max Length:22
Name:EMPNO
Name Length:5
Precision:4
Scale:0
Null허용:N
-------------------------------
Column Type:1
Max Length:10
Name:ENAME
Name Length:5
Precision:0
Scale:0
Null허용:Y
-------------------------------
Column Type:2
Max Length:22
Name:SAL
Name Length:3
Precision:7
Scale:2
Null허용:Y
-------------------------------




#오라클,#PLSQL,#DBMS_SQL.#DESCRIBE_COLUMNS, #DESC_TAB, #DESC_REC, #오라클교육, #SQL교육, #자바교육, #오라클학원, #SQL학원, #자바학원, 오라클,PLSQL,DBMS_SQL.DESCRIBE_COLUMNS, DESC_TAB, DESC_REC, 오라클교육, SQL교육, 자바교육, 오라클학원, SQL학원, 자바학원, 

(C#교육동영상)C# ADO.NET 실습 ODP.NET/ODAC 설치 오라클 함수 호출 실습, C#학원, WPF학원, 닷넷학원, 자바학원

  (C#교육동영상)C# ADO.NET 실습  ODP.NET/ODAC 설치  오라클 함수 호출 실습, C#학원, WPF학원, 닷넷학원, 자바학원 https://www.youtube.com/watch?v=qIPU85yAlzc&list=PLxU-i...