https://tomcat.apache.org/download-90.cgi
CTRL+SHIFT+ +/-
: 글씨 커지고 작아짐
CTRL + F11
: 실행 ==> JAVA Application
선택
ALT + SHIFT + T
==> Extract interface
클라이언트에 따라 코드를 계속 수정할 것인가?
인터페이스를 상속한 자식은 반드시 메소드를 재정의해야 함
자동형변환 : promotion (ex-LgTV=>TV)
오래 살아남는 시스템 = 유지보수가 편한 것
CTRL + SPACE
: 자동완성 ==> IMPORT해서 사용
CTRL + Click
: 어떠한 Exception을 던지는 지 알 수 있음
// new org.h2.Driver에서 에러 발생
DriverManager의 registerDriver에 에러 발생
try {
// JDBC 1단계 : 드라이버 객체 등록
DriverManager.registerDriver(new org.h2.Driver());
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Connection : 고속도로라고 이해
DriverManager.getConnection
의 3가지의 parameter가 필요하게 됩니다.
위 사진처럼, 3개의 정보를 복사해서 가져온다.
1) JDBC URL, 2) ID, 3) PW
syso + CTRL + ENTER
: 자동완성
그 후에...
// JDBC 1단계 : 드라이버 객체 등록
DriverManager.registerDriver(new org.h2.Driver());
// JDBC 2단계 : Connection 연결
Connection conn = DriverManager.getConnection("jdbc:h2:tcp://localhost/~/test", "sa", "");
if(conn != null)
System.out.println("연결 성공 : " + conn.toString());
else
System.out.println("연결 실패");
// JDBC 3단계 => Statement : 고속버스 연결
Statement stmt = conn.createStatement();
// JDBC 4단계 => SQL(승객) 전송
String sql = "INSERT INTO board(seq, title, writer, content) " +
"VALUES((SELECT NVL(MAX(seq),0)+1 FROM board), " +
"'임시 제목', '테스터', '임시 내용....')";
int count = stmt.executeUpdate(sql); // sql을 DBMS에 전송해주는 명령
CTRL + SHIFT + O
: 자동 IMPORT, 쓸데없는 IMPORT를 제거해주기도 합니다.
CTRL + SHIFT + F
: 들여쓰기
CTRL + /
: 주석 설정 및 해제
// JDBC 관련 변수 선언
Connection conn = null;
Statement stmt = null;
try {
// JDBC 1단계 : 드라이버 객체 등록
DriverManager.registerDriver(new org.h2.Driver());
// JDBC 2단계 : Connection 연결 (고속도로 연결)
conn = DriverManager.getConnection("jdbc:h2:tcp://localhost/~/test", "sa", "");
// if(conn != null)
// System.out.println("연결 성공 : " + conn.toString());
// else
// System.out.println("연결 실패");
// JDBC 3단계 : Statement(고속버스) 생성
stmt = conn.createStatement();
// JDBC 4단계 : SQL(승객) 전송
String sql = "INSERT INTO board(seq, title, writer, content) " +
"VALUES((SELECT NVL(MAX(seq),0)+1 FROM board), " +
"'임시 제목', '테스터', '임시 내용....')";
int count = stmt.executeUpdate(sql);
System.out.println(count + "데이터 처리 성공");
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.out.println("연결 실패");
}
왜 바깥으로 빼는가?
- 자원 해제
stmt.close();
conn.close();
고속버스를 없애고 나서, 고속도로를 없애야 함
finally {
// JDBC 5단계 : 자원 해제
stmt.close();
conn.close();
}
try {
stmt.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
conn.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
그래서 위처럼 나누어서 해주어야 합니다.
DriverManager.register~~ 부분을 대체 가능
- Class.forName("org.h2.Driver");로 가능
Connection conn = null;
Statement stmt = null;
try{
Class.forName("org.h2.Driver");
conn = DriverManager.getConnection("jdbc:h2:tcp://localhost/~/test", "sa", "");
stmt = conn.createStatement();
String sql = "UPDATE board SET title = 'JAVA 어려움', content = '오늘도 놀자' WHERE seq = 2";
int count = stmt.executeUpdate(sql);
System.out.println(count + "데이터 처리 성공");
} catch (Exception e) {
e.printStackTrace();
System.out.println("연결 실패");
} finally {
try {
stmt.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
conn.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
고속버스를 더 빠르게 하자 : Statement ==> PreparedStatement
String sql = "INSERT INTO board(seq, title, writer, content) " +
"VALUES((SELECT NVL(MAX(seq),0)+1 FROM board), " +
"?, ?, ?)";
stmt = conn.prepareStatement(sql);
String sql = "INSERT INTO board(seq, title, writer, content) " +
"VALUES((SELECT NVL(MAX(seq),0)+1 FROM board), " +
"?, ?, ?)";
stmt = conn.prepareStatement(sql);
// SQL을 전송하기 전에 ?(파라미터)를 세팅한다.
// 주의 : ? 갯수만큼 값을 설정해야 한다. (물론 타입도 일치해야한다.)
stmt.setString(1, "PreparedStatement 적용");
stmt.setString(2, "ㅎㅎㅎ");
stmt.setString(3, "PreparedStatement 테스트.....");
int count = stmt.executeUpdate();
conn.preparedStatement ~~~
왜 preparedStatement가 Statement가 더 빠를까?
다 문자 타입의 Column이라 setString 메서드를 사용함
데이터 별로 다 존재함
ex) 정수 : setInt, 실수 : setDouble, 문자 : setString, 날짜 : setDate
stmt.executeUpdate() : INSERT, UPDATE, DELETE 전용 메서드
stmt.executeQuery() : SELECT 전용 메소드
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
try{
Class.forName("org.h2.Driver");
conn = DriverManager.getConnection("jdbc:h2:tcp://localhost/~/test", "sa", "");
String sql = "SELECT * FROM board ORDER BY seq DESC";
stmt = conn.prepareStatement(sql);
// stmt.executeUpdate() : INSERT, UPDATE, DELETE 전용 메서드
// stmt.executeQuery() : SELECT 전용 메소드
rs = stmt.executeQuery();
rs.next();
rs = stmt.executeQuery();
// JDBC 5단계 : 검색 결과 처리
System.out.println("[ 게시글 목록 ]");
rs.next(); // ResultSet 객체의 커서를 밑으로 한 칸 내려준다.
System.out.print(rs.getInt("SEQ"));
System.out.print(rs.getString("TITLE"));
System.out.print(rs.getString("WRITER"));
System.out.print(rs.getString("CONTENT"));
System.out.print(rs.getDate("REGDATE"));
System.out.print(rs.getInt("CNT"));
} catch (Exception e) {
e.printStackTrace();
System.out.println("연결 실패");
} finally {
try {
stmt.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
conn.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
rs.next의 시작은 Before First에서 시작이기 때문에 rs.next를 한 번 실행하고 출력 후, while 루프를 계속해서 진행합니다.
주의! 컬럼 이름은 대소문자를 구분하지 않습니다.
대문자
로 쓰기로 약속을 했습니다. 또한, 컬럼의 위치를 기반으로 SELECT를 해도 결과가 같지만, 작성한 나만 알 수 있기 때문에
+) 데이터 타입을 항상 신경써야 합니다.
나머지 코드는 그대로 ==> JDBC의 장점
하지만, 반복되는 정보가 흩어져 있다면?
public class JDBCUtil {
public static Connection getConnection() {
Connection conn = null;
try {
Class.forName("org.h2.Driver");
conn = DriverManager.getConnection("jdbc:h2:tcp://localhost/~/test", "sa", "");
} catch (Exception e) {
e.printStackTrace();
}
return conn;
}
public static void close(ResultSet rs, PreparedStatement stmt, Connection conn) {
try {
rs.close();
} catch (SQLException e1) {
e1.printStackTrace();
}
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
public static void close(PreparedStatement stmt, Connection conn) {
try {
stmt.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
conn.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
DAO
글 목록을 보고 싶으면 위와 같은 정말 많은 코드가 필요합니다.
insert 후에, 글 목록을 바로 보고 싶다??
직접 코드를 뒤에 추가하는 것은? 너무 지저분합니다.
가독성이 엄청나게 떨어짐
ex) 삭제 후, 목록 보여주기 : 로직 자체는 되게 심플한테, 과정이 너무 복잡해질 수 있어
비즈니스 로직 자체가 도드라지지 않아
일단 수정하고 나서, 또 수정하려면?
이러한 문제를 한 방에 해결할 수 있는 것이 DAO 패턴
DAO 클래스
: 실질적인 DB 연동을 담당하는 클래스이다.
관련된 SQL을 찾아서 수정도 가능 => DB 연동 로직이 편함
뭔가를 추가한다거나, 수정한다고 할 때 DAO를 찾아보자