eXtensible Markup Language
단순화된 데이터 기술 형식
Java는 코드가 한 글자라도 변환되면 다시 처음부터 전체 내용을 컴파일(이진 코드 번역)한다.
-> 비효율적
그런데, Java에 외부 파일을 읽어오는 변하지 않는 코드를 작성하면 컴파일을 다시 하지 않는다.
-> 컴파일을 다시 하지 않아도 외부 파일 내용이 변하면 자동으로 반영됨
-> 효율적
속성(데이터)
== Map<String, String>
ctrl + shift + /
properties XML 파일 설명
Map의 Key, 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 파일 생성
} catch (IOException e) {
e.printStackTrace();
}
}
}
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;
import oracle.jdbc.proxy.annotation.GetProxy;
public class LoadXML {
public static void main(String[] args) {
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());
}
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<!-- 마크업 언어 주석 -->
<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">ash_member</entry>
<entry key = "password">member1234</entry>
</properties>
-> 클래스 DB 연결, JDBC 자원 반환, 트랜잭션 제어 같은 반복적으로 사용되는 JDBC 관련 코드를 모아둔 클래스
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 관련 코드를 모아둔 클래스
*
* getConnection() 메소드
*
* close( Connection | Statement | ResultSet ) 메소드
* --> PreparedStatement는 Statement의 자식이므로
* 매개변수 다형성으로 한 번에 처리
*
* commit(Connection)
* rollback(Connection)
*
*
*/
// 필드
private static Connection conn; // 초기값 null
// private static Connection conn = null; // 초기값 null
// 메소드
// DB 연결 정보를 담고 있는 Connection 객체 반환 메소드
public static Connection getConnection() {
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()) {
conn.commit();
}
}catch(Exception e) {
e.printStackTrace();
}
}
// rollback 메소드
public static void rollback(Connection conn) {
try {
// 참조하는 Connection이 있으면서 닫혀 있지 않은 경우
if(conn != null && !conn.isClosed()) {
conn.rollback();
}
}catch(Exception e) {
e.printStackTrace();
}
}
}