XML(eXtensible Markup Language)
단순화된 데이터 기술 형식
XML 외부 파일을 이용해서 XML 내용을 바꿔도 Java에서 XML 파일을 읽어오는 코드는 변하지 않기 때문에 컴파일 작업을 따로 하지 않는다.
XML은 K : V 형식의 map, XML은 문자열만 저장
Properties
Map<String, String> == Properties
prop.getProperty("driver")
: XML에서 얻어온 값 중 key가 "driver"인 엔트리의 value를 얻어옴
package edu.kh.jdbc.common;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Properties;
public class CreateXML {
// XML(eXtensible Markup Language): 단순화된 데이터 기술 형식
// XML 사용하려는 이유
// - DB 연결, SQL같이 수정이 빈번한 내용을
// 코드에 직접 작성하면 좋지 않다.
//--> Java == 컴파일 언어 -> 코드가 조금만 수정되어도 전체 컴파일 다시 함
// --> 시간이 오래 걸림
// 그런데, XML 외부 파일을 이용해서 XML 내용을 바꿔도
// Java에서 XML 파일을 읽어오는 코드는 변하지 않음 --> 컴파일 X --> 시간 효율 상승
public static void main(String[] args) {
// XML은 K : V 형식의 map, XML은 문자열만 저장
// Map<String, String> == Properties
// * Properties 컬렉션 객체 *
// 1. <String, String> 으로 Key, Value가 타입 제한된 Map
// 2. XML 파일을 생성하고 읽어오는 데 특화
Properties prop = new Properties();
try {
FileOutputStream fos = new FileOutputStream("driver.xml");
// 파일 이름
// 주석
prop.storeToXML(fos, "DB Connection data"); // XML 파일 생성
// surround try catch
} catch (IOException e) {
e.printStackTrace();
}
// 실행 후 프로젝트 파일 새고하면 driver.xml 파일 생김
// 여러 번 실행하지 마세요. 내용 사라짐
}
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<!-- 마크업 언어 주석 ctrl shift / -->
<properties>
<!-- comment : properties XML 파일 설명 -->
<comment>DB Connection data</comment>
<!-- entry: Map의 Key, Value를 묶어서 부르는 명칭 -->
<entry key = "driver">oracle.jdbc.driver.OracleDriver</entry>
<!-- 각자 계정 -->
<entry key = "url">jdbc:oracle:thin:@localhost:1521:xe</entry>
<entry key = "user">khj_member</entry>
<entry key = "password">member1234</entry>
</properties>
package edu.kh.jdbc.common;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.InvalidPropertiesFormatException;
import java.util.Properties;
public class LoadXML {
public static void main(String[] args) {
// 외부 XML 파일 읽어오기 (Properties 사용)
Properties prop = new Properties();
// Key, Value가 String으로 제한된 Map
try {
prop.loadFromXML(new FileInputStream("driver.xml"));
// Property: 속성(데이터)
// prop.getProperty("driver"): XML에서 얻어온 값 중
// key가 "driver"인 엔트리의 value를 얻어옴
System.out.println("driver : " + prop.getProperty("driver"));
// 외부 파일 미사용
String str = "oracle.jdbc.driver.OracleDriver";
System.out.println(str);
// Java는 코드가 한 글자라도 변환되면
// 다시 처음부터 전체 내용을 컴파일(이진 코드 번역)한다 --> 비효율적
// 그런데, Java에 외부 파일을 읽어오는 변하지 않는 코드를 작성하면
// 컴파일을 다시 하지 않음 -> 효율적
// 컴파일을 다시 하지 않아도 외부 파일 내용이 변하면 자동으로 반영됨
// DB 연결 정보, SQL 내용은 빈번히 변화될 예정
// 1) Java 코드에 직접 작성 -> 다시 컴파일 -> 실행 (비효율적)
// 2) XML 작성 -> 바로 실행(다시 컴파일X, 효율적)
// + (추가효과) DB 정보, SQL 한 곳에 모아서 관리 -> 보기 좋고 관리 쉬움
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(JDBCTemplate.getConnection());
}
}
package edu.kh.jdbc.common;
import java.io.FileInputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Properties;
public class JDBCTemplate {
/* DB 연결, JDBC 자원 반환, 트랜잭션 제어 같은
* 반복적으로 사용되는 JDBC 관련 코드를 모아둔 클래스
*
* getConnectoin
*
* close(Connection | Statement | ResultSet) 메소드
* --> PreparedStatement는 Statement의 자식이므로
* 매개변수 다형성으로 한 번에 처리
*
* commit(Connection)
* rollback(Connection)
*
*
* */
// 필드
private static Connection conn; // 초기값 null
// private static Connection conn = null; // 초기값 null(위 코드와 동일)
// 메소드 반환형
public static Connection getConnection() {
// DB연결 정보를 담고 있는 Connection 객체 반환 메소드
try {
// 계속 공용으로 사용되는 conn 변수에
// 커넥션이 대입된 적이 없거나(null)
// 또는 이전 커넥션이 있었으나 닫힌 경우
// -> 새로운 커넥션이 필요한 상황
// 커넥션을 계속 닫고, 만들고, 닫고 만들고를 반복
// -> 프로그램 하나에 커넥션 1개만을 운용
if (conn == null || conn.isClosed()) {
Properties prop = new Properties();
// K,V 모두 String인 Map, XML 파일 입출력에 특화
// driver.xml 파일 읽어오기
prop.loadFromXML(new FileInputStream("driver.xml"));
// 커넥션 생성 준비
String driver = prop.getProperty("driver");
String url = prop.getProperty("url");
String user = prop.getProperty("user");
String password = prop.getProperty("password");
// 커넥션 생성
// 1) JDBC 드라이버 메모리 로드
Class.forName(driver);
// 2) DriverManager 통해 Connection 생성
conn = DriverManager.getConnection(url, user, password);
// 3) 트랜잭션 제어를 위한 자동 커밋 비활성화
conn.setAutoCommit(false);
}
} catch (Exception e) {
e.printStackTrace();
}
return conn;
}
// close() 메소드 작성
// Connection 반환 메소드
public static void close(Connection conn) {
try {
// 참조하는 Connection이 있으면서 닫혀있지 않은 경우
if (conn != null && !conn.isClosed()) {
// conn.isClosed(): 닫혀있으면 true 반환
conn.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
// Statement(부모), PreparedStatement(자식) 반환 메소드 (다형성 적용)
public static void close(Statement stmt) {
try {
// 참조하는 Statement이 있으면서 닫혀있지 않은 경우
if (stmt != null && !stmt.isClosed()) {
// stmt.isClosed(): 닫혀있으면 true 반환
stmt.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
// ResultSet 반환 메소드
public static void close(ResultSet rs) {
try {
// 참조하는 ResultSet이 있으면서 닫혀있지 않은 경우
if (rs != null && !rs.isClosed()) {
// rs.isClosed(): 닫혀있으면 true 반환
rs.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
// 트랜잭션 제어
// commit 반환 메소드
public static void commit(Connection conn) {
try {
// 참조하는 Connection이 있으면서 닫혀있지 않은 경우
if (conn != null && !conn.isClosed()) {
// rs.isClosed(): 닫혀있으면 true 반환
conn.commit();
}
} catch (Exception e) {
e.printStackTrace();
}
}
// rollback 메소드
public static void rollback(Connection conn) {
try {
// 참조하는 Connection이 있으면서 닫혀있지 않은 경우
if (conn != null && !conn.isClosed()) {
// rs.isClosed(): 닫혀있으면 true 반환
conn.rollback();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}