새로운 블로그로 이전하였습니다!
article thumbnail image
Published 2022. 8. 2. 17:10

Class.forName(“package.ClassName”);

  • 문자열로 전달되는 클래스가 method영역에 저장되어 있는 클래스를 메모리에 로드시키는 역할
  • 클래스가 처음 로드 되면 클래스 파일 내의 static 블록 안에 있는 로직이 실행되어 초기화한다.

DBMS Driver

  • DBMS Driver 클래스가 처음 로드 되면 클래스 파일 내의 static 블록 안에 있는 로직 (DriverManager.registerDriver(DBMS 드라이버))가 호출되면서 JDBC를 등록하고, 인스턴스를 생성한다.
  • JVM에 등록된 JDBC Driver는 Connection conn = DriverManager.getConnection(url, DB이름, ID, PW); 에서 DB를 처음 Connection 하는 시점에 사용하게 된다.
  • 일반적인 응용 어플리케이션에선 Class.forName()을 통해 등록하고, 실제 JDBC 드라이버를 만드는 경우가 아니라면 DriverManager를 제어하거나 사용할 일이 없기 때문에 DriverManager.registerDriver() 메서드는 드라이버를 구현하는 내부에서 사용된다.
  • Synchronized, CopyOnWirteList로 감싸서 위 데이터를 사용중인 스레드를 제외한 다른 스레드는 접근을 막음을 통해 Driver를 여러 번 로딩해도 JVM에 쌓이지 않고 getConnection 했을 때 로드한 드라이버가 호출된다.

DBMS Driver 등록 함수

DB Connection

package jdbc;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class DbConnect {

//	static final String MYSQLDRIVER = "com.mysql.jdbc.Driver"; //MySQL
	static final String ORACLEDRIVER = "oracle.jdbc.driver.OracleDriver"; //Oracle
	static final String ORACLE_URL = "jdbc:oracle:thin:@//아이피:포트/DB명";
	
	//
	public DbConnect() {
		try {
			Class.forName(ORACLEDRIVER);
			
		} catch (Exception se) {
			System.out.println("Oracle Driver Error : "+ se.getMessage());
		}
		
	}
	
	//Connection
	public Connection getConnection() {
		Connection conn=null;
		
		try {
			conn = DriverManager.getConnection(ORACLE_URL, "아이디", "패스워드");
		} catch (SQLException e) {
			System.out.println("Oracle Connection Error : " + e.getMessage());
		}
		return conn;
	}
	
	private void _dbClose( ResultSet rs, Statement stmt, PreparedStatement pstmt, Connection conn )
	{
		try {
			if(rs!=null) rs.close();
			if(stmt!=null) stmt.close();
			if(pstmt!=null) pstmt.close();
			if(!conn.isClosed()) conn.close();
		} catch (SQLException e) {
		}	
	}
	
	//Db Close
	public void dbClose(ResultSet rs, Statement stmt, Connection conn) {
		_dbClose( rs, stmt, null, conn );
	}
	
	public void dbClose(ResultSet rs, PreparedStatement pstmt, Connection conn) {
		_dbClose(rs, null, pstmt, conn);
	}
	
	public void dbClose(Statement stmt, Connection conn) {
		_dbClose(null, stmt, null, conn);
	}
	
	public void dbClose(PreparedStatement pstmt, Connection conn) {
		_dbClose(null, null, pstmt, conn);
	}
}

 

JDBC execute

execute()

  • 모든 유형의 SQL 문장과 실행 가능
  • return : Boolean // 업데이트 개수 or 결과 있으면 true | 없으면 false

executeUpdate()

  • Insert, Delete, Update SQL 문장을 실행
  • return : int // 영향받은 행의 수 (row count)

executeQuery()

  • Select SQL 문장을 실행
  • return : ResultSet 객체

executeBatch()

  • Insert, Delete, Update SQL 쿼리를 메모리에 올려뒀다가 실행 명령 시 한번에 DB로 쿼리를 전송
  • return : int[] // row영향을 받은 수 (-2 : 성공했으나 row count를 알 수 없음 | -3 : 실패)

배치 구현

// 랜덤값 대량 insert
	public int addRandomValue() {
		
		System.out.println("한글 테스트");
		System.out.println("abcd");
		
		long listAddStartTime = System.nanoTime();
		
		List<StringBuilder> valuelist = new ArrayList<>();
//		List<String> valuelist = new ArrayList<String>();
//		List<String> valuelist = new LinkedList<>();

		Random rnd = new Random();
		
//		int row = (int) (Math.random() * 1000000) + 100; // insert할 데이터 수
		int row = 1000000;

		// insert 할 값 생성
		for(int i = 0; i < row; i++) {
			int value_length = 20;
			
//			int value_length = (int) (Math.random() * 20) + 1;

			StringBuilder sb = new StringBuilder();
			
//			String value = "";
//			StringBuffer sb = new StringBuffer();
			
			for (int j = 0; j < value_length; j++) {
//				value += "a";
//				sb.append("a");
				if (rnd.nextBoolean())// true : 영문
					sb.append((char) ((int) (Math.random() * 26) + 97));
				else // false : 숫자 0 ~ 9
					sb.append((int) (Math.random() * 10)); 
			}
			valuelist.add(sb);
		}
		long listEndTime = System.nanoTime();
		System.out.println("List Add time : " + (listEndTime - listAddStartTime) + "ns");
		// String : 300938900ns
		// StringBuilder : 130211000ns
		// StringBuffer : 353035600ns


		long starttime = System.nanoTime();
		
		// pk
		Integer idx = getMaxIdx();
		if(idx == null)
			idx = 1;

		Connection conn = db.getConnection();
		PreparedStatement pstmt = null;

		int insertcnt = 0;
		
		String tableName = "que1";
		
		StringBuffer sql = new StringBuffer("INSERT ");
//		sql.append("/*+ APPEND PARALLEL(" + tableName + ", 4) */ ");
		sql.append("INTO ");
		sql.append(tableName + " VALUES(?, ?)");
		
		try {
//			oracleSetting.enableParallel(); // Oracle 힌트
			oracleSetting.noLogging(tableName); //nologging
			
			pstmt = conn.prepareStatement(sql.toString());
			conn.setAutoCommit(false);
			
//			ListIterator<StringBuilder> valueListItr = valuelist.listIterator();
//			while(valueListItr.hasNext()) {
			
			for (int i = 0; i < valuelist.size(); i++) {

//				pstmt.setObject(1, valuelist.get(i)); // 데이터 타입 지정이 불필요해서 유지보수에선 편리하나 PreparedStatment 클래스에서 형번환 후 DB에 반영되어서 더 느림
//				pstmt.setString(2, valueListItr.next().toString()); //iterator
				
				pstmt.setInt(1, idx++);
				pstmt.setString(2, valuelist.get(i).toString());

				// Batch 구현
				pstmt.addBatch(); // Batch 생성
				pstmt.clearParameters(); // pstmt 파라미터 비움 ( 기본적으로 새로운 파라미터를 씌우면 없어지긴 하나 대량작업 시 데이터 무결성 위해 명시 )
				
				final int batchSize = 5000;
				//Batch
				if(i%batchSize == 0) {
					
					int[] batchResult = pstmt.executeBatch();
					pstmt.clearBatch();
					conn.commit();
					for(int num : batchResult)
						if ( num > 0 )
							insertcnt += num;
					row -= batchSize;
				}
			}
			
			// 배치 결과 값 count
			int[] batchResult = pstmt.executeBatch();
			for (int num : batchResult) {
				if (num > 0)
					insertcnt += num;
			}
			pstmt.clearBatch();
			conn.commit();
			
//			oracleSetting.disableParallel();
			oracleSetting.Logging(tableName);
			
		} catch (SQLException e) {
			System.out.println("SQL Exception : " + e.getMessage());

		} finally {
			db.dbClose(pstmt, conn);
		}

		long endtime = System.nanoTime();
		System.out.println("insert time : " + (endtime - starttime) + "ns");
		// String : 1695457800ns
		// StringBuilder : 130211000ns
		// StringBuffer : 3677267200ns

		return insertcnt;
	}
복사했습니다!