22일차(4)/java(33) : JDBC, DTO
MainClass06
- DB 관련 내용을 분리하지 않은 상태
package test.main;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
/*
* JDBC (Java DataBase Connectivity)
*
* DataBase에 연결해서 SELECT, INSERT, UPDATE, DELETE 작업하기
*
* Oracle에 연결하기 위해서는 드라이버 클래스가 들어있는 ojdbc6.jar 파일을
* 사용할 수 있도록 설정해야 한다.
*/
public class MainClass06 {
public static void main(String[] args) {
//DB 연결객체를 담을 지역 변수 만들기
Connection conn=null;
try {
//오라클 드라이버 로딩
Class.forName("oracle.jdbc.driver.OracleDriver");
//접속할 DB 의 정보 @아이피주소:port번호:db이름
String url="jdbc:oracle:thin:@localhost:1521:xe";
//계정 비밀번호를 이용해서 Connection 객체의 참조값 얻어오기
conn=DriverManager.getConnection(url, "scott", "tiger");
//예외가 발생하지 않고 여기까지 실행순서가 내려오면 접속 성공이다.
System.out.println("Oracle DB 접속 성공");
} catch (Exception e) {
e.printStackTrace();
}
//시퀀스(member_seq)를 이용해서 회원정보 추가
String name="바나나";
String addr="서울";
//INSERT 작업을 위해서 필요한 객체의 참조값을 담을 지역변수 미리 만들
PreparedStatement pstmt=null;
try {
//실행할 SQL문
String sql="INSERT INTO member"
+ " (num, name, addr)"
+ " VALUES(member_seq.NEXTVAL, ?, ?)";
//PreparedStatement 객체의 참조값 얻어오기
pstmt=conn.prepareStatement(sql);
pstmt.setString(1, name);
pstmt.setString(2, addr);
//sql문 실행하기
pstmt.executeUpdate();
System.out.println("회원 정보를 추가했습니다.");
}catch (Exception e){
e.printStackTrace();
}
}
}
- Primary key는 일반적으로 시퀀스를 이용한다.
- 시퀀스를 이용하면 숫자 관리가 쉽고, ? 의 수가 줄어든다!
test.util - DBConnect 클래스 생성
- MainClass06에서 DB 파트 분리!
package test.util;
import java.sql.Connection;
import java.sql.DriverManager;
public class DBConnect {
//필드
Connection conn;
//생성자
public DBConnect() {
//Connection 객체의 참조값을 얻어내서 필드에 저장하기
try {
//오라클 드라이버 로딩
Class.forName("oracle.jdbc.driver.OracleDriver");
//접속할 DB 의 정보 @아이피주소:port번호:db이름
String url="jdbc:oracle:thin:@localhost:1521:xe";
//계정 비밀번호를 이용해서 Connection 객체의 참조값 얻어오기
conn=DriverManager.getConnection(url, "scott", "tiger");
//예외가 발생하지 않고 여기까지 실행순서가 내려오면 접속 성공이다.
System.out.println("Oracle DB 접속 성공");
} catch (Exception e) {
e.printStackTrace();
}
}
//Connection 객체를 리턴해주는 메소드
public Connection getConn() {
//필드에 저장된 Connection 객체의 참조값을 리턴해주기
return conn;
}
}
MainClass06 (수정)
- DB 관련 내용을 따로 분리!
package test.main;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import test.util.DBConnect;
/*
* JDBC (Java DataBase Connectivity)
*
* DataBase에 연결해서 SELECT, INSERT, UPDATE, DELETE 작업하기
*
* Oracle에 연결하기 위해서는 드라이버 클래스가 들어있는 ojdbc6.jar 파일을
* 사용할 수 있도록 설정해야 한다.
*/
public class MainClass06 {
public static void main(String[] args) {
//시퀀스(member_seq)를 이용해서 회원정보 추가
String name="바나나";
String addr="서울";
//INSERT 작업을 위해서 필요한 객체의 참조값을 담을 지역변수 미리 만들
Connection conn=null;
PreparedStatement pstmt=null;
try {
//connection 객체의 참조값 얻어오기
conn=new DBConnect().getConn();
//실행할 SQL문
String sql="INSERT INTO member"
+ " (num, name, addr)"
+ " VALUES(member_seq.NEXTVAL, ?, ?)";
//PreparedStatement 객체의 참조값 얻어오기
pstmt=conn.prepareStatement(sql);
pstmt.setString(1, name);
pstmt.setString(2, addr);
//sql문 실행하기
pstmt.executeUpdate();
System.out.println("회원 정보를 추가했습니다.");
}catch (Exception e){
e.printStackTrace();
}finally {
try {
if(pstmt!=null)pstmt.close();
if(conn!=null)conn.close();
}catch(Exception e) {}
}
}
}
- Connection 객체를 얻어내야 하는데, 매번 복사하려니 불편하다.
→ Connection 객체만 리턴해주는 메소드가 있으면 좋겠다!
- 그런 별도의 클래스를 설계해보기!
Connection c = new DBConnect().getConn();
- DBConnect 클래스 안에 있는 getConn 메소드를 호출한다.
- 이 값을 미리 만들어져 있던 지역변수 안에 넣어서 사용.(여기서는 conn)
- new하면 필드에 들어가고(Connection 타입 참조값을 필드에 넣어두고) .getConn하면 꺼내와진다.
Member 클래스
package test.mypac;
public class Member {
public int num;
public String name;
public String addr;
}
- mypac 패키지에 새 Member class를 만들고 공개필드도 만들어둠
MainClass07
package test.main;
import java.sql.Connection;
import java.sql.PreparedStatement;
import test.mypac.Member;
import test.util.DBConnect;
public class MainClass07 {
public static void main(String[] args) {
//추가할 회원정보
String name="딸기";
String addr="부산";
//추가할 회원의 정보를 Member 객체에 담고
Member mem=new Member();
//객체의 필드가 public 공개필드이기 때문에 대입연산자로 직접 참조해서 필드에 값을 대입할 수 있다.
mem.name=name;
mem.addr=addr;
//insert()메소드 호출하면서 Member 객체 전달하기
insert(mem);
}
//회원 한명의 정보를 추가하는 메소드를 만들기
public static void insert(Member m) {
Connection conn=null;
PreparedStatement pstmt=null;
try {
//connection 객체의 참조값 얻어오기
conn=new DBConnect().getConn();
//실행할 SQL문
String sql="INSERT INTO member"
+ " (num, name, addr)"
+ " VALUES(member_seq.NEXTVAL, ?, ?)";
pstmt=conn.prepareStatement(sql);
pstmt.setString(1, m.name);
pstmt.setString(2, m.addr);
pstmt.executeUpdate();
System.out.println("회원 정보를 추가했습니다.");
} catch(Exception e){
e.printStackTrace();
}finally {
try {
if(pstmt!=null)pstmt.close();
if(conn!=null)conn.close();
}catch(Exception e) {}
}
}
}
- 이렇게 하나하나 넣으면 번거롭고 힘들다...
- '회원 한명의 정보를 저장하는 어떤 메소드'가 완성되어 있다면,
메인메소드에서 한번에 실행할 수 있다.
- 여러 개의 정보를 하나의 객체에 담아서 전달하기.(보통 단순나열해서 전달하지 않는다)
- 두개의 정보(name, addr)를 객체에 담고 그 참조값을 전달하는 방식으로 바꾸기.
- select, insert, update, ... 는 아예 다른 메소드로 분리할 예정!
- Member객체의 m.name이라는 필드 / m.addr이라는 필드 사용
- 필드에 넣은 뒤에 참조해서 가져온다!
MainClass08
- Map, HashMap사용
package test.main;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.util.HashMap;
import java.util.Map;
import test.mypac.Member;
import test.util.DBConnect;
public class MainClass08 {
public static void main(String[] args) {
//추가할 회원정보
String name="딸기";
String addr="부산";
//추가할 회원의 정보를 HashMap객체에 key:value의 쌍으로 저장한다음
Map<String, Object> map=new HashMap<>();
map.put("name", name);
map.put("addr", addr);
//insert()메소드 호출하면서 Map객체를 전달한다.
insert(map);
}
//회원 한명의 정보를 추가하는 메소드를 만들기
public static void insert(Map<String, Object> m) {
//Map에 저장된 회원의 이름과 주소를 읽어와서
String name=(String)m.get("name");
String addr=(String)m.get("addr");
//INSERT 작업을 위해서 필요한 객체의 참조값을 담을 지역변수 미리 만들기
Connection conn=null;
PreparedStatement pstmt=null;
try {
//connection 객체의 참조값 얻어오기
conn=new DBConnect().getConn();
//실행할 SQL문
String sql="INSERT INTO member"
+ " (num, name, addr)"
+ " VALUES(member_seq.NEXTVAL, ?, ?)";
pstmt=conn.prepareStatement(sql);
pstmt.setString(1, name);
pstmt.setString(2, addr);
pstmt.executeUpdate();
System.out.println("회원 정보를 추가했습니다.");
} catch(Exception e){
e.printStackTrace();
}finally {
try {
if(pstmt!=null)pstmt.close();
if(conn!=null)conn.close();
}catch(Exception e) {}
}
}
}
- member 객체를 사용하는대신 map을 사용한다. → key-value 가 쌍으로 있는 인터페이스!
- Map 객체의 값(묶음)을 매개변수 m에 전달하기!
- Map에 담아서 설계하면 member 클래스를 따로 만들지 않아도 된다.
여러 개의 정보를 하나의 묶음으로, 객체에 담아서 전달한 것.
String name=(String)m.get("name");
String addr=(String)m.get("addr");
- map을 사용하면 캐스팅하는 수고가 들어간다. object로 받기 때문에.
- 지금은 Member 클래스의 필드가 공개되어 있는데,
보통 java에서는 필드를 가려두고(private), 메소드를 통해서 접근하게끔 한다.
MemberDto 클래스
- 접근자 Accessor (etter, setter) 생성
package test.dto;
public class MemberDto {
//회원 한명의 정보를 저장할 필드(보통 테이블의 칼럼명과 일치시킨다)
private int num;
private String name;
private String addr;
//디폴트 생성자
public MemberDto() {}
public MemberDto(int num, String name, String addr) {
super();
this.num = num;
this.name = name;
this.addr = addr;
}
//private 필드를 위한 접근자accessor를 만들어야한다.
public int getNum() {
return num;
}
public void setNum(int num) {
this.num = num;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddr() {
return addr;
}
public void setAddr(String addr) {
this.addr = addr;
}
}
MainClass09
- MemberDto 클래스와 insert 메소드 활용
package test.main;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.util.HashMap;
import java.util.Map;
import test.dto.MemberDto;
import test.mypac.Member;
import test.util.DBConnect;
public class MainClass09 {
public static void main(String[] args) {
//추가할 회원정보
String name="딸기";
String addr="부산";
//추가할 회원의 정보를 MemberDto객체에 담아서
MemberDto dto=new MemberDto();
dto.setName(name);
dto.setAddr(addr);
//insert()메소드 호출하면서 Map객체를 전달한다.
insert(dto);
}
//회원 한명의 정보를 추가하는 메소드를 만들기
public static void insert(MemberDto dto) {
//INSERT 작업을 위해서 필요한 객체의 참조값을 담을 지역변수 미리 만들기
Connection conn=null;
PreparedStatement pstmt=null;
try {
//connection 객체의 참조값 얻어오기
conn=new DBConnect().getConn();
//실행할 SQL문
String sql="INSERT INTO member"
+ " (num, name, addr)"
+ " VALUES(member_seq.NEXTVAL, ?, ?)";
pstmt=conn.prepareStatement(sql);
pstmt.setString(1, dto.getName());
pstmt.setString(2, dto.getAddr());
pstmt.executeUpdate();
System.out.println("회원 정보를 추가했습니다.");
} catch(Exception e){
e.printStackTrace();
}finally {
try {
if(pstmt!=null)pstmt.close();
if(conn!=null)conn.close();
}catch(Exception e) {}
}
}
}
- DTO : Data Transfer Object
- 필드를 private으로 설정해두면 객체 안에서만 접근 가능하고, 외부에서는 해당 필드에 접근할 수 없다.
- 디폴트 생성자를 만들고, 이클립스 기능을 사용해서 필드를 사용하는 생성자를 generate 해준다.
- 우클릭-Source-Generate Constructor using Fields
- 전체 체크하고 Generate하면 num, name, addr을 인자로 받는
MemberDto 생성자가 자동으로 만들어진다.
- Setter : 값을 넣어주는 메소드
- Getter : 값을 가져오는 메소드
- 전체 체크하면 해당 이름으로 getter, setter가 만들어진다.
- 접근지정자가 public인 setter, getter가 만들어짐.
- 박스별로 각각 num, name, addr에 해당하는 각각의 accessor이다.
- 처음 생성되었을 때에는 0, null, null이 들어있다
dto.num=1; → X. 이렇게는 접근이 안된다.(필드 직접참조 불가)
dto.setNum(1); → O. 값을 넣어주고 싶으면 클래스의 setter 메소드를 사용한다.
dto.name="kim"; → X.
dto.setName="kim"; → O.
- dto에 저장된 이름을 불러오고(참조하고) 싶다면? getter메소드를 사용한다.
int num=dto.num; → X.
int num-dto.getNum(); → O.
- 모두 작성규약이 있어서 dto를 작성 규칙에 맞게 잘 만들어놓으면 자동화하여 처리할 수 있는 것이 많다.
그래서 이클립스의 generate를 사용한다.
- 메소드들은 필드명에 맞춰서 만들어진다. ex) 필드명이 price라면 setPrice, getPrice
setter 메소드를 통해 넣고, getter 메소드를 통해 읽어낸다.
MainClass10
- MemberDto 클래스와 update 메소드 활용
package test.main;
import java.sql.Connection;
import java.sql.PreparedStatement;
import test.dto.MemberDto;
import test.util.DBConnect;
public class MainClass10 {
public static void main(String[] args) {
//수정할 회원의 정보
int num=1;
String name="호빵";
String addr="분식집";
//MemberDto dto=new Member Dto(num, name, addr);
MemberDto dto=new MemberDto();
dto.setNum(num);
dto.setName(name);
dto.setAddr(addr);
update(dto);
}
public static void update(MemberDto dto) {
//INSERT 작업을 위해서 필요한 객체의 참조값을 담을 지역변수 미리 만들기
Connection conn=null;
PreparedStatement pstmt=null;
try {
//connection 객체의 참조값 얻어오기
conn=new DBConnect().getConn();
//실행할 SQL문
String sql="UPDATE member"
+ " SET name=?, addr=?"
+ " WHERE num=?";
//PreparedStatement 객체의 참조값 가져오기
pstmt=conn.prepareStatement(sql);
//?에 값 바인딩하기
pstmt.setString(1, dto.getName());
pstmt.setString(2, dto.getAddr());
pstmt.setInt(3, dto.getNum());
pstmt.executeUpdate();
System.out.println("회원 정보를 수정했습니다.");
}catch (Exception e) {
e.printStackTrace();
}finally {
try {
if(pstmt!=null)pstmt.close();
if(conn!=null)conn.close();
}catch(Exception e) {}
};
}
}
- 저 dto에 번호, 이름, 주소가 담겨 있을 것이라고 가정하고 먼저 코딩해두는 것.
- 메인메소드에서는: update 메소드가 만들어졌을 것이라고 가정하고 new MemberDto 객체를 생성한다.
update 메소드에서는: dto에 무슨 값이 들어갈 것인지는 모르지만 들어올 것이라 생각하고 메소드를 만들어 둔다.ㅎㅎ
MemberDto dto=new MemberDto();
dto.setNum(num);
dto.setName(name);
dto.setAddr(addr);
//
MemberDto dto=new Member Dto(num, name, addr);
- 위는 객체를 생성해두고 (0,null,null) 인 상태일 때 값을 하나씩 넣어주는 것.
아래는 처음부터 num, name, addr 인자를 가진 생성자를 호출하는 것!
- 생성자가 두개이기 때문에 둘 중 어느쪽을 쓰든 상관없다.
- run 하자 1행이 수정되었다!
- java에서는 이처럼 객체에 정보를 담아서 전달하고,
그 데이터를 받아서 DB에 저장하는 등 활용할 일이 매우 많다.
'국비교육(22-23)' 카테고리의 다른 글
23일차(2)/java(35) : JDBC 실습예제 (0) | 2022.11.08 |
---|---|
23일차(1)/java(34) : JDBC, DAO (0) | 2022.11.07 |
22일차(3)/java(32) : JDBC (0) | 2022.11.04 |
22일차(2)/java(31) : Input, Output(3) (1) | 2022.11.04 |
22일차(1)/java 퀴즈 : input, output 활용 예제 (0) | 2022.11.04 |