JDBC
1. JDBC란 무엇인가?
자바 개발자인데 db를 사용하고 싶다면 jdbc를 알아야한다.
sql을 직접 사용하 할수잇엇고 오라클이나 mysql이 제공하는 프로그램으로 연결인증 문장실행 결과패치등을 햇엇다.
그러나 여기에 담을 수 없는 사람도 도구를 사용할 수없다면? ui로 간접적으로 db를 건들 수 잇다. 표현목록을 다라고 하면 ui를 통해서 달라고 한다.
자바 프로그래머는 사용자 요구를 위한 sql문을 작성할 수 잇다. 코드에서 db를 이요할 수잇는 api를 의미하는 것이다.
db마다 기능은 같지만 ui가 다르다. 오라클과 ms sql의 함수가 다르다. 완저 ㄴ동일하다고 해도 연결하고자 하는 api자체가 차이가 잇다. 코드에서 db에접속하는걸 고쳐야한다.
그런데 이것을 고치는게 맞느냐? 연결해서 하는데 매우 골치아프다. 그래서 등장한게 jdbc이다.
직접 사용하지 않고 가져다 사용하는 것이다. 조금씩 차이나는 것들을 가져다 쓰는것이다. 깡통이고 인터페이스이다. 차이를 알필요없고 그냥 함수를 가져다 쓰는 것이다.
직접 구동 코드를 가진게 driver이다.
무조건 이순서로 한다.
1.드라이버 로드하기
2.연결생성
3.문장실행
4.결과집합사용하기
2. DBMS와 JDBC Driver 준비하기
오라클 jdbc드라이버 다운로드
3. JDBC 기본 코드의 이해
1.Class.forName("oracle.jdbc.driver.OracleDriver"); 드라이버로드 객체생성
2.Connectionm con = DriverManager.getConnection(...);
3.Statement st = con.createStatement();
4.ResultSet rs = st.executeQuery(sql);
new연산자를 사용하지 않고 객체가 생성이 된다. 순차적으로 흐름을 가지게 하는 것이다.
실행이되면 메모리상에 driver가 올라간다. con하면 db와연결을 하고 쿼리를 st로 넣을 수잇다.
결과집합이 만들어지면 이것을 rs로 받아온다.
5.rs.next(); 하나씩 내려감
6.String title = rs.getString("title");
4. 쿼리 실행하기 실습
1.Class.forName("oracle.jdbc.driver.OracleDriver"); 드라이버로드 객체생성
2.Connection con = DriverManager.getConnection(url, "id" , "pwd");
3.Statement st = con.createStatement();
4.ResultSet rs = st.executeQuery(sql);
이것은 무조건 다들어간다.
사용한 리소스들을 닫아줘야한다. 닫는 것은 역순으로 닫는다.
rs.close();
st.close();
con.close();
항상기억하기 성능에 대한 부분이라 닫는게 좋다.
String url = "jdbc:oracle:thin:@localhost:1521/orcl";
String sql = "SELECT * FROM NOTICE";
5.rs.next();
String title = rs.getString("TITLE");
system.out.println(title);
if(rs.next()) {
String title = rs.getString("TITLE");
System.out.println(title);
}
만약 가져올 값이 없다면 예외가 발생한다. 그래서 if문으로 있다면 보여주게 해줘야한다.
5. 혼자 풀어보는 문제 #1
레코드의 모든 컬럼 출력하기 문자열이 아닌것들을 get?로할지
데이터 형식을 뭘로 할지
두번째 두번째 레코드 복붙? 하는건 말이안됨. 반복문 모든컬럼이 추가되도록 하기
while(rs.next()) {
int id = rs.getInt("ID");
String title = rs.getString("TITLE");
String writerId = rs.getString("WRITER_ID");
Date regdate = rs.getDate("REGDATE");
String content = rs.getString("CONTENT");
int hit = rs.getInt("HIT");
System.out.printf("id:%d, title:%s, wirterId:%s, regdate:%s, content:%s, hit:%d\n"
, id, title, writerId, regdate, content, hit);
}6. 문제 #1 풀이겸 문제 #2
풀이는 위에잇다.
또 다른 문제
조회수가 10이상인 게시글만 출력되게하기
7. 문제 #2 풀이와 SQL을 잘해야 하는 이유
while문에 if(hit > 10)으로 넣을수도잇지만
String sql = "SELECT * FROM NOTICE WHERE HIT > 10"; 로하면된다.
사용자가 볼때는 결과는 같다.
만약 게시글이 1억개가 있다고 생각해보자.
네트워크로 굳이 2개만 가져와도 될것을 1억개를 가져와서 동작을 한다면 비효율적이다.
데이터 필터링, 정렬, 그룹화 등의 모든 데이터 연산은 데이터베이스에서 처리한다.
자바는 UI레이아웃만 신경써야한다. 데이터 가공처리는 SQL이 한다. 자바가 하는 일이 훨씬 줄어들게 할 수 있다.
8. 데이터 입력을 위한 쿼리문 준비하기
먼저 developer에서 작성해보고 가져다 쓰는게 좋다. 입력할때는 어떤값인지 아는게 좋다.
developer에서 테이블을 드래그하면 sql문을 자동으로 만들 수있는 기능이잇다.
사용자가 입력하면 필요한 값만 넣어야한다.
id, regdate, hit, pub는 사용자가 입력하는 것으로 하지 않게 해야한다.
id는 서브쿼리를 넣거나 시퀀스로 알아서 늘어나게 할 수잇다.
INSERT INTO notice (title, writer_id,content, files
) VALUES (
'test',
'newlec',
'adf',
''
);9. 데이터 입력하기와 PreparedStatement
위에서 작성한 쿼리문을 통해 입력하도록 하자. select가 아닐때는 결과집합이 없다.
select문은 결과집합을 executeQuery로 얻지만 업데이트 인서트 등은 결과집합 resultset이 없기때문에 executeUpdate로 한다.
String title = "test2";
String writerId ="newlec";
String content = "hahaha";
String files = "";
이것들을 넣는다고 생각해보자. 마지막에 합쳐졋을때 온전한 sql문이 될 수잇도록 작성해야한다.
"VALUES( " + title + " )"; 이런식으로 넣을 수도잇다. 그런데 이럴때 양쪽에 ' ' 을 넣어야한다.
"VALUES( " + "'" + title + "'" + ")"; 그러면 이런식으로 매우 복잡해진다.
여기서 문자열을 하지 않고 값을꽃아넣는 방법이 있다. "VALUES(?, ?, ?, ?)";바로 ?로 꽃는것이다.
값을 사용하기 위해서 사용하기위해 이제 statement가아니라 PreparedStatement pstmt = con.prepareStatement(sql);이다.
이값을 채울 수잇도록 할 수잇는 쿼리문을 사용하면된다.
PreparedStatement st = con.prepareStatement(sql);
st.setString(1, title);
st.setString(2, writerId);
st.setString(3, content);
st.setString(4, files);
int result = st.executeUpdate();
System.out.println(result);
반환타입이 row count이다. 추가가됫다면 1을 반환할것이다.
10. 데이터 수정을 위한 쿼리 준비하기
수정하기 해보자. 간단한 쿼리 작성해보자.
UPDATE NOTICE
SET
TITLE ='TEST3',
CONTENT ='HAHA',
FILES=''
WHERE ID = 73;
WHERE절에 조건을 안달면 다 바뀌어버리니 주의하자.
11. 데이터 수정을 구현하기
String sql = "UPDATE NOTICE "
+ "SET "
+ "TITLE=?, "
+ "CONTENT= ?, "
+ "FILES=? "
+ "WHERE ID=?";
입력하고자 하는 부분은 다 ?로 바꾸어주면된다.
PreparedStatement st = con.prepareStatement(sql);
st.setString(1, title);
st.setString(2, content);
st.setString(3, files);
st.setInt(4, id);
12. 데이터 삭제하기
삭제쿼리는 단순하니 그냥 준비하자.
String sql = "DELETE NOTICE WHERE ID=?";
PreparedStatement st = con.prepareStatement(sql);
st.setInt(1, id);
잘 삭제 된게 보여진다.
13. CRUD를 담당하는 서비스 클래스 생성하기
select(retrieve반환받음) insert(create) update delete를 이작업을 줄여서 말하면 crud라고 한다.
각각 다른 프로그램으로 만들엇다. 이러면 재사용이 불가능하다. noticeservice만들어서 담아보자.
com.newlecture.app.service 패키지에 NoticeService를 담아보자.
public List<?> getList() {
return ?;
}
리스트로 받아서 getList 메소드로 불러오면 될것 같다.
담을수 있는 그릇은? 바로 Notice라는 객체를 만들어주자.
객체를 만들어서 list에 담아서 출력한다.
public List<Notice> getList() throws ClassNotFoundException, SQLException {
String sql = "SELECT * FROM NOTICE";
Class.forName(driver);
Connection con = DriverManager.getConnection(url, uid , pwd);
Statement st = con.createStatement();
ResultSet rs = st.executeQuery(sql);
List<Notice> list = new ArrayList<>();
while(rs.next()) {
int id = rs.getInt("ID");
String title = rs.getString("TITLE");
String writerId = rs.getString("WRITER_ID");
Date regdate = rs.getDate("REGDATE");
String content = rs.getString("CONTENT");
int hit = rs.getInt("HIT");
String files = rs.getString("FILES");
Notice notice = new Notice(
id,
title,
writerId,
regdate,
content,
hit,
files
);
list.add(notice);
}
rs.close();
st.close();
con.close();
return list;
}14. NoticeService 구현 마무리
나머지 기능들 추가해보자.
public int insert(Notice notice) {
return 0;
}
데이터는 Notice를 전달받아서 실행하는 것이다.
private String url = "jdbc:oracle:thin:@localhost:1521/orcl";
private String uid = "java";
private String pwd = "oracle";
private String driver ="oracle.jdbc.OracleDriver";
반복되는 부분들은 필드로 만들어주자.
public int insert(Notice notice) throws ClassNotFoundException, SQLException {
String title = notice.getTitle();
String writerId = notice.getWriterId();
String content = notice.getContent();
String files = notice.getFiles();
String sql = "INSERT INTO notice (title, writer_id,content, files) "
+ "VALUES(?, ?, ?, ?)";
Class.forName(driver);
Connection con = DriverManager.getConnection(url, uid , pwd);
//Statement st = con.createStatement();
PreparedStatement st = con.prepareStatement(sql);
st.setString(1, title);
st.setString(2, writerId);
st.setString(3, content);
st.setString(4, files);
int result = st.executeUpdate();
System.out.println(result);
st.close();
con.close();
return result;
}public int update(Notice notice) throws ClassNotFoundException, SQLException {
String title = notice.getTitle();
String content = notice.getContent();
String files = notice.getFiles();
int id = notice.getId();
String sql = "UPDATE NOTICE "
+ "SET "
+ "TITLE=?, "
+ "CONTENT= ?, "
+ "FILES=? "
+ "WHERE ID=?";
Class.forName(driver);
Connection con = DriverManager.getConnection(url, uid , pwd);
//Statement st = con.createStatement();
PreparedStatement st = con.prepareStatement(sql);
st.setString(1, title);
st.setString(2, content);
st.setString(3, files);
st.setInt(4, id);
int result = st.executeUpdate();
System.out.println(result);
st.close();
con.close();
return result;
}public int delete(Notice notice) throws ClassNotFoundException, SQLException {
int id = notice.getId();
String sql = "DELETE NOTICE WHERE ID=?";
Class.forName(driver);
Connection con = DriverManager.getConnection(url, uid , pwd);
//Statement st = con.createStatement();
PreparedStatement st = con.prepareStatement(sql);
st.setInt(1, id);
int result = st.executeUpdate();
System.out.println(result);
st.close();
con.close();
return result;
}15. 사용자 인터페이스 붙이기(공지사항 목록)
사용자에게 입력받고 사용자가 볼수잇도록 하는게 중요하다. 사용자 인터페이스란 웹, 자바콘솔등이잇을 것이다.
여기서는 자바 콘솔로 해보자. 페이징도 만들어볼것이다.
NoticeConsole을 만들어준다. 여기에 어떠한 기능 메소드를 추가할 것이냐? 그것은 program5에서하자.
.목록을 추가하는 부분과 입력받는 메뉴부분을 따로받아보자.
public class NoticeConsole {
private NoticeService service;
public NoticeConsole() {
service = new NoticeService();
}
public void printNoticeList() throws ClassNotFoundException, SQLException {
List<Notice> list = service.getList();
System.out.println("---------------------------------------------------------");
System.out.printf("<공지사항> 총 %d 게시글\n", 12);
System.out.println("---------------------------------------------------------");
for(Notice n : list) {
System.out.printf("%d. %s / %s / %s\n", n.getId() , n.getTitle(), n.getWriterId(), n.getRegdate());
}
System.out.println("---------------------------------------------------------");
System.out.printf(" %d/%d pages\n", 1, 2);
}
public int inputNoticeMenu() {
// TODO Auto-generated method stub
return 0;
}
} public class Program5 {
public static void main(String[] args) {
NoticeConsole console = new NoticeConsole();
try {
console.printNoticeList();
int menu = console.inputNoticeMenu();
switch(menu) {
case 1: //상세조회
break;
case 2: //이전
break;
case 3: //다음
break;
case 4: //글쓰기
break;
}
} catch (ClassNotFoundException | SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}}}2023.01.24 후기
스프링부트남은부분이 조금 있지만 하루만에 다 나가는것 보다 나눠 나가는게 낫다고 판단하였다.
마지막으로 다시 근본으로 돌아와서 자바프로그램으로만 작성하는 jdbc를 배우고 학원에 들어가고자 한다.
진짜 얼마남지 않았다. '좋은' 직장말고 '쓰레기'같지만 않은 직장을 다니고 싶다.
학원을 다니면서 복습을 위해 블로그를 작성하고 싶지만 솔직히 어떻게 될지 모른다. 최대한 적어보고 싶다.
본인 스스로 노력을 많이 해야된다고 하지만 솔직히 길을 잃는 느낌이다.
많이들 이런 학습용 블로그도 필요없다곤 하는데 복습용으로 사용하고자 사용하는 것이니 열심히 적고자 한다.
나중에 내가 어떤 일을 하고 있을지는 모르겠지만... 다시 이글을 보러왔을때 후회가 없으면 좋겠다.
그저 좋은 사람이 되고 싶을 뿐인데 정말 힘든 것임을 깨닫게 되었다.
설이 지나고 벌써 2023년이 한달이 지났는데 모든 사람이 좋은 일만 있으면 좋겠다.
'기초단계 > DB&JDBC' 카테고리의 다른 글
| 2023.03.06 DB (1) | 2023.03.06 |
|---|---|
| 2023.01.25-2 JDBC (0) | 2023.01.25 |
| 2023.01.11 DB (1) | 2023.01.11 |
| 2023.01.09 DB (1) | 2023.01.09 |
| 2023.01.08 DB (0) | 2023.01.09 |