250x250
반응형
arkhyeon
arkhyeon
arkhyeon
전체 방문자
오늘
어제
  • 분류 전체보기 (88)
    • Spring (5)
    • Java (4)
    • React (25)
      • TypeScript (6)
      • JavaScript (1)
      • Jest (9)
    • NEXT (8)
    • SQL (1)
    • React native (1)
    • CSS (3)
    • Web (1)
    • Git (3)
    • ETC (6)
    • 빅데이터DB (8)
    • Docker (4)
    • Tool (1)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • Spring WebSocket
  • react usetransition
  • react
  • websocket
  • HIVE
  • javasciprt websocket
  • react spring websocket
  • react jest
  • react websocket
  • usetransition
  • javascript wss
  • WSS
  • react19
  • react typescript
  • docker tomcat
  • react loading
  • jest
  • kudu
  • node WebSocket
  • websocket server

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
arkhyeon

arkhyeon

ETC

JDBC Select문만 실행하는 방법

2024. 5. 27. 10:57
728x90
반응형

ORACLE, POSTGRESQL, TIBERO, MYSQL DB 테스트 완료되었으며 총 4가지의 방법이 있다.

  1. executeQuery() + Connection Rollback + 정규식 검사 ✅
  2. Explain 실행 후 Select 확인
  3. executeQuery(Select) / executeUpdate(CRUD)
  4. Connection setReadOnly Option True
💡 선행 
executeQuery는 Select 조회 지원을 우선적으로 하고 리턴 값은 ResultSet 이고 
executeUpdate는 CRUD를 우선적으로 지원하고 리턴 값은 int 입니다. (Oracle 제외)

1. executeQuery() + Connection Rollback + 정규식 검사

  • executeQuery로 CRUD 분기
  • ORACLE의 CRUD문 통과 시 Rollback 진행
  • CREATE 문은 실행과 동시에 Commit 되기에 정규식 검사를 통해 CRUD 분기
//DB Connection 및 화면에서 SQL 받아오기

if(isNotSelectSql(strQuery)) {
	Log.getLog().error("CREATE, INSERT, UPDATE, DELETE statements are not allowed.");
	return new ResponseEntity<String>("CRUD statements are not allowed.", HttpStatus.INTERNAL_SERVER_ERROR);
}

try {
	Conn.setAutoCommit(false);
	Log.getLog().info("[Separate Query Start] Query : " + strQuery);
	PreparedStatement userQueryPstmt = Conn.prepareStatement(strQuery);
	ResultSet userRsSet = userQueryPstmt.executeQuery();
	ResultSetMetaData rsMeta = userRsSet.getMetaData();
	
} catch (Exception e) {
	if (Conn != null) {
		try {
			Conn.rollback();
		} catch (SQLException e1) {
			Log.getLog().error(e1.getMessage());
		}
	}
	Log.getLog().error(e.getMessage());
	return new ResponseEntity<String>(e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR);
}

// Connection, pstmt, reSet 종료

public boolean isNotSelectSql(String sql) {
    Pattern pattern = Pattern.compile("^\\\\s*(\\\\w+)", Pattern.MULTILINE);
    Matcher matcher = pattern.matcher(sql.trim());
    
    boolean isFirstWordDml = matcher.find() && Arrays.asList("CREATE", "UPDATE", "DELETE", "INSERT").contains(matcher.group().toUpperCase());
    
    return isFirstWordDml;
}

2. Explain 실행 후 Select 확인

실행 계획을 조회하여 해당 쿼리의 어떻게 동작하는지 알아내 분별한다. 하지만 모든 쿼리의 Explain 구문이 달라 하나의 DB만 사용하는게 아니라면 실질적 사용이 어렵다.

//Oracle
EXPLAIN PLAN FOR 'YOUR_SQL';
SELECT * FROM TABLE(dbms_xplan.display);

//PostgreSQL
PREPARE PLAN AS 'YOUR_SQL';
EXPLAIN EXECUTE PLAN;

//Tibero
SELECT SUBSTRB(TO_CHAR(ID), 1, 3) || LPAD(' ', LEVEL * 2) || UPPER(OPERATION) ||
       DECODE(OBJECT_NAME, NULL, NULL, ': '||OBJECT_NAME) || ' (Cost:' || COST ||
       ', %%CPU:' || DECODE(COST, 0, 0, TRUNC((COST-IO_COST)/COST * 100))|| ', Rows:'
       || CARDINALITY || ') ' || DECODE(PSTART, '', '', '(PS:' || PSTART || ', PE:' ||
       PEND || ')') AS "Execution Plan"
FROM (SELECT * FROM V$SQL_PLAN WHERE SQL_ID = 'your_sql_id_here')
START WITH DEPTH = 1
CONNECT BY PRIOR ID = PARENT_ID AND PRIOR SQL_ID = SQL_ID
ORDER SIBLINGS BY POSITION;

//MYSQL
explain 'YOUR_SQL';

3. executeQuery(Select) / executeUpdate(CRUD)

둘 다 쿼리를 실행하지만 서로 실행하는 쿼리 종류와 반환값이 다릅니다.

executeQuery 는 Select 조회 지원을 우선적으로 하고 리턴 값은 ResultSet 이고 executeUpdate 는 CRUD를 우선적으로 지원하고 리턴 값은 int 입니다.

그러나 Oracle은 예외적으로 executeQuery 에서 오류가 나지 않고 CRUD를 지원합니다.

 

PreparedStatement (Java Platform SE 8 )

Sets the designated parameter to SQL NULL. This version of the method setNull should be used for user-defined types and REF type parameters. Examples of user-defined types include: STRUCT, DISTINCT, JAVA_OBJECT, and named array types. Note: To be portable,

docs.oracle.com

4. Connection setReadOnly Option True

해당 옵션은 DB 최적화를 위해 드라이버 힌트로 연결을 읽기 전용 모드로 설정합니다. 하지만 CRUD를 막는 것은 아닙니다.

 

Connection (Java Platform SE 6)

 PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability)           Creates a PreparedStatement object that will generate ResultSet objects with the given type, concurrency, and ho

docs.oracle.com

Connection Conn = 'YOUR_TABLE_CONNECTION'

Conn.setAutoCommit(false);
Conn.setReadOnly(true);

How to run JDBC Select statements only

728x90
반응형

'ETC' 카테고리의 다른 글

HTTP-SERVER  (0) 2023.05.23
View Transitions API  (0) 2023.05.22
NPM ERR_INVALID_AUTH 오류 해결  (0) 2023.02.24
SVN - Eclipse  (0) 2022.12.27
Eclipse jar 배포 및 Linux Character Set, ClassPath, Lib 설정  (0) 2022.06.15
    'ETC' 카테고리의 다른 글
    • HTTP-SERVER
    • View Transitions API
    • NPM ERR_INVALID_AUTH 오류 해결
    • SVN - Eclipse
    arkhyeon
    arkhyeon

    티스토리툴바