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 했을 때 로드한 드라이버가 호출된다.
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;
}
'Back-End > Java & Spring' 카테고리의 다른 글
[JAVA] JVM 메모리 구조와 라이프 사이클 (0) | 2022.08.02 |
---|---|
[JAVA] Java Framework 종류 (0) | 2022.08.02 |
[JAVA] Collection Framework 정의/성능 비교 (0) | 2022.08.02 |
[JAVA] 문자열 String (0) | 2022.08.02 |
[JAVA] int / Integer 차이 (0) | 2022.08.02 |