728x90
JSP
- JavaServer Page: HTML 코드에 java코드를 넣어서 동적 웹페이지를 생성하는 웹어플리케이션 도구
- 사용자가 코드를 작성한 다음 컴파일 과정을 거치지 않고, 서버에서 실행
- 웹 서버에 의해 자동으로 서블릿으로 변환 된 다음 실행
2022.11.30 - [Server/JSP] - [JSP] JSP(태그), Servlet(서블릿)
Persistence Framework
- 영속성은 프로그램이 종료되더라도 사라지지 않는 데이터의 특성을 말함
- JDBC 프로그래밍의 복잡함이나 번거로움 없이 간단한 작업만으로 데이터베이스와 연동되는 시스템을 빠르게 개발할 수 있으며 안정적인 구동을 보장
SQL문을 실행하기 위한 방법
1. MyBatis (Spring에서 사용) - SQL 매핑
2. Hibernate (하이버네이트), JPA - ORM(객체) 매핑
SQL Mapper
- SQL을 명시하여 필드를 매핑 시킴
- 직접 데이터베이스를 다룸, 쿼리 직접 작성, 안정성
- MyBatis 사용
ORM
- Object Relation Mapping 객체 - 관계 매핑
- 객체와 관계형 데이터베이스의 데이터를 자동으로 매핑(연결) 해주는 것
- 객체 지향 프로그래밍은 클래스, 관계형 데이터베이스는 테이블을 사용하므로 ORM을 통해 불일치를 해결
- Hibernate, JPA 사용
JPA(Java Persistent API)
- ORM을 사용하기 위한 표준 인터페이스를 모아둔 것으로 JAVA에서 제공하는 API - 실제로 동작하는 것이 아
- 사용자가 원하는 JAP 구현체(ORM Framework)를 선택해서 사용가능
(Hibernate, EclipseLink, DataNucleus, OpenJPA, TopLink Essentials 등) - 통계나 동적 쿼리 같은 복잡한 쿼리를 처리하는 것이 어려우므로 QueryDSL을 함께 이용
https://gmlwjd9405.github.io/2019/08/04/what-is-jpa.html
JPA 실습
Hibernate
- JPA의 구현체 중 하나
- 아래 블로그 참고
https://gmlwjd9405.github.io/2018/12/25/difference-jdbc-jpa-mybatis.html
https://mangkyu.tistory.com/20
JDBC (ORM 사용X)
- Java Database Connectivity 프로그래밍
- 자바 프로그램에서 SQL문을 실행하여 데이터를 관리하기 위한 API
JDBC 사용법 (Oracle Database 실습)
-
- 드라이버 로드: Class.forName()
DriverManager: 로드된 드라이버를 통해서 Connectrion을 활성화해주는 객체 - Connection: DB 연결
- Statement: SQL 쿼리 실행: SQL을 실행하는 객체
ResultSet: SQL문 실행 후 데이터를 받는 객체 - excute(): 결괏값 처리
- close() DB 연결 해제
- 드라이버 로드: Class.forName()
JDBC 설치
1. Connector 다운로드
- 커넥터 다운 받는 방법은 多
- oracle connector - jdbc 검색 - 다운로드 - ojdbc8.jar 다운로드
jar: 자바 파일의 압축형
2. 라이브러리 추가
3. 드라이버 클래스 (암기x)
- MySQL: "com.mysql.jdbc.Driver"
- Oracle: "oracle.jdbc.driver.OracleDriver"
AuthDAO.java
//드라이버 로드
Class.forName("oracle.jdbc.driver.OracleDriver");
4. URL 패턴 (암기x)
- MySQL: "jdbc:mysql://호스트이름:포트번호/DB이름"
- Oracle: "jdbc:oracle:thin:호스트이름:포트번호:DB이름"
- PDB 경우: "jdbc:orcle:thin:호스트이름:포트번호/XEPDB1"
11ver 이상은 : 에서 / 로 바뀜
CDB(Container Database) 안에 여러 개의 PDB(Pluggable Database) 사용할 수 있음
- PDB 경우: "jdbc:orcle:thin:호스트이름:포트번호/XEPDB1"
MainClass.java
//상수 사용시 데이터베이스가 바뀌면 여기만 바뀌면 됨
public static final String URL = "jdbc:oracle:thin:@localhost:1521:xe";
//호스트 이름: IP주소 ▶ @localhost
//포트 번호 ▶ 1521
//DB 이름: 데이터베이스의 스키마명 ▶ xe
public static final String UID = "hr";
public static final String UPW = "hr";
JDBC 실행순서 (Statement)
Connection 객체
- 데이터베이스와 자바 연결
- 연결이 끝난 뒤에는 반드시 close() 메서드를 호출하여 Connection 객체가 사용한 시스템 자원을 반환해야 함
Statement = PreparedStatement 객체 (▼설명)
- Statement와 PreparedStatement 객체는 동일한 기능을 제공하나 업그레이드 된 PreparedStatement 사용하면 됨
- Connect 객체로부터 Statement를 생성하고 쿼리문 실행
setString (int parameterIndex, String x) | 지정된 매개변수를 x값으로 설정 | setString, setInt, setDate, setTimestamp 등 |
▲ sql문의 ?를 설정해주는 작업이라서 select에서 데이터를 가져올 때 필터링으로 사용 가능 | ||
executeUpdate() | Insert, Update, Delete 쿼리문 실행 | 데이터를 가져오는 작업, ResultSet객체 반환 |
executeQuery() | Select 쿼리문 실행 | 실행시키는 작업, int형 반환(성공 0, 실패 1) |
ResultSet 객체 - select 에서만 사용
- 위의 executeQuery() 메서드 안에 있는 객체로 select 쿼리문의 결과를 ResultSet 객체에 담아서 리
next() | 다음 값 확인 (하나씩 전진, 후진은 x) 다음 행이 있으면 true를 반환하고 전진 |
getString() | 지정한 컬럼 값을 String으로 읽음 |
getInt() | 지정한 컬럼 값을 int 타입으로 읽음 |
getDouble() | 지정한 컬럼 값을 double 타입으로 읽음 |
PrepareStatement 실행 순서
- Statement 객체를 대신하는 PreparedStatement 객체
- 값을 지정할 때 물음표(?)로 처리하기 때문에 값을 간단히 지정 가능
- 첫번째 물음표의 인덱스는 1이며, 이후 순서대로 인덱스 값이 1씩 증가
JDBC 실습
insert
package jdbc.ex;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
public class JDBCInsert {
public static void main(String[] args) {
//insert
String url = "jdbc:oracle:thin:@localhost:1521:xe"; //주소, @작성해야함
String uid = "hr"; //계정 아이디
String upw = "hr"; //비밀번호
String sql = "insert into auth values( seq_auth.nextval , ?, ?)"; //auth 컬럼 3개
Connection conn = null;
PreparedStatement pstmt = null;
// throws exception을 던지니까 try-catch
try {
//드라이버 로드
Class.forName("oracle.jdbc.driver.OracleDriver");
//connection - DB 연결
conn = DriverManager.getConnection(url, uid, upw);
//statement 객체 - sql문을 실행시키기 위한 query 전송 객체
pstmt = conn.prepareStatement(sql);
//?값 세팅 - 첫번째부터 1번 순서 (setString, setInt, setDate, setTimestamp)
pstmt.setString(1, "홍길동"); //1은 물음표를 나타냄, 물음표가 2개 이므로 1,2가 나옴
pstmt.setString(2, "프로그래머"); //직접 값을 적지 않고 변수화 가능
//sql 실행 (select문은 query 문장으로 실행, i, d, u문은 update 메서드로 실행) - i,d,u는 완전 똑같음 sql문만 바뀜
int result = pstmt.executeUpdate(); //업데이트문은 정수형 반환, 성공(1), 실패(0) 반환
// executeUpdate는 정수형 반환
if(result == 1) {
System.out.println("성공");
} else {
System.out.println("실패");
}
} catch(Exception e ) {
e.printStackTrace(); //에러 로그를 봐야 하니까
} finally {
try { //객체 계속 쌓여서 close 필수로 해줌
conn.close();
pstmt.close();
} catch (Exception e2) {
System.out.println("close 에러");
}
} //end try ~ catch ~ finally
} //end main
}
- Connection객체 - prepareStatement객체 - setString(index, x) 설정 - executeUpdate() 쿼리문 실행(업데이트)
select
package jdbc.ex;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
public class JDBCSelect {
public static void main(String[] args) {
//insert
String url = "jdbc:oracle:thin:@localhost:1521:xe"; //주소, @작성해야함
String uid = "hr"; //계정 아이디
String upw = "hr"; //비밀번호
String sql = "select * from auth order by auth_id desc"; //?가 없으니까 아래에서 딱히 할게 없음
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null; //결과 저장 객체, select 결과를 반환받을 객체
try {
//드라이버 로드
Class.forName("oracle.jdbc.driver.OracleDriver");
//conn
conn = DriverManager.getConnection(url, uid, upw);
//pstmt
pstmt = conn.prepareStatement(sql);
//?값에 대한 처리 x
//sql 실행 (select의 실행 - 데이터를 가져오는 작업)
rs = pstmt.executeQuery();
//executeQuery는 ResultSet형으로 반환
//그대로 실행된 결과가 rs에 담김
while (rs.next()) { //다음 row가 있다면 true
//한 행에 대한 처리(getInt, getString, getDouble, getTimestamp, getDate)
int auth_id = rs.getInt("auth_id");
String name = rs.getString("name"); //컬럼명
String job = rs.getString("job");
System.out.println("번호:" + auth_id + ", 이름:" + name + ",직업:" + job);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try { //객체 계속 쌓여서 close 필수로 해줌
conn.close();
pstmt.close();
} catch (Exception e2) {
System.out.println("close 에러");
}
} //end try ~ catch ~ finally
} //end main
}
- Connection객체 - prepareStatement객체 - executeQuery() 쿼리문 실행(데이터 가져오기) - next(), get()으로 한 행에 대한 처리
select2 - 조건O
package jdbc.ex;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.Scanner;
public class JDBCSelect2 {
public static void main(String[] args) {
/*
* 사원수를 입력받습니다.
* employees, departments 테이블에서 부서별 사원수가 입력받은 사원수보다 큰 데이터를 select
* 출력할 컬럼은 부서명, 사원수, 부서아이디
*/
Scanner scan = new Scanner(System.in);
System.out.println("사원수 입력>");
String tmp = scan.nextLine();
int c = Integer.parseInt(tmp);
//변수선언
String url = "jdbc:oracle:thin:@localhost:1521:xe"; //주소, @작성해야함
String uid = "hr"; //계정 아이디
String upw = "hr"; //비밀번호
String sql = "select d.department_name, a.total, d.department_id\r\n"
+ "from departments d\r\n"
+ "inner join (select department_id, count(*) as total\r\n"
+ " from employees e\r\n"
+ " group by department_id) a\r\n"
+ "on d.department_id = a.department_id\r\n"
+ "where total > ?";
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null; //select결과를 반환받을 객체
try {
Class.forName("oracle.jdbc.driver.OracleDriver");
conn = DriverManager.getConnection(url, uid, upw);
pstmt = conn.prepareStatement(sql);
pstmt.setInt(1, c); //물음표의 내용을 적어줌
//sql
rs = pstmt.executeQuery();
while(rs.next()) { //한줄이면 한번, 여러줄이면 여러번 실행
String department_name = rs.getString("department_name");
int total = rs.getInt("total");
int department_id = rs.getInt("department_id");
System.out.println("부서명:" + department_name + ", 사원수:" + total + ",부서아이디:" + department_id);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try { //객체 계속 쌓여서 close 필수로 해줌
conn.close();
pstmt.close();
} catch (Exception e2) {
System.out.println("close 에러");
}
} //end try ~ catch ~ finally
} //end main
}
select count(*) from employees ;
select department_id, count(*) total
from employees e
group by department_id;
select d.department_name, a.total, d.department_id
from departments d
inner join (select department_id, count(*) as total
from employees e
group by department_id) a -- null이 안나오면 좋겠어서 inner join
on d.department_id = a.department_id
where total > 1;
- Connection객체 - prepareStatement객체 - 특정 조건(?물음표에 대한) 설정 가능, set메서드 사용 - executeQuery() 쿼리문 실행(데이터 가져오기) - next(), get()으로 한 행에 대한 처리
update
package jdbc.ex;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.util.Scanner;
public class JDBCUpdate {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
System.out.println("auth_id 입력>");
String tmp = scan.nextLine();
int auth_id = Integer.parseInt(tmp);
System.out.println("name 입력>");
String name = scan.nextLine();
System.out.println("job 입력>");
String job = scan.nextLine();
//변수선언
String url = "jdbc:oracle:thin:@localhost:1521:xe"; //주소, @작성해야함
String uid = "hr"; //계정 아이디
String upw = "hr"; //비밀번호
//스캐너로 auth_id, name, job을 입력받아서 해당 auth_id의 name, job을 업데이트 하는 구문.
String sql = "update auth set name = ?, job = ? where auth_id = ?";
Connection conn = null;
PreparedStatement pstmt = null;
try {
//드라이버 로드
Class.forName("oracle.jdbc.driver.OracleDriver");
//connection
conn = DriverManager.getConnection(url, uid, upw);
//statement 객체
pstmt = conn.prepareStatement(sql);
pstmt.setString(1, name); //str
pstmt.setString(2, job); //str
pstmt.setInt(3, auth_id); //number
//sql 실행
int result = pstmt.executeUpdate(); // 1 or 0
if(result == 1) {
System.out.println("성공");
} else {
System.out.println("실패");
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try { //객체 계속 쌓여서 close 필수로 해줌
conn.close();
pstmt.close();
scan.close();
} catch (Exception e2) {
System.out.println("close 에러");
}
} //end try ~ catch ~ finally
} //end main
}
- 실행 과정은 insert와 같
- 변경 할 데이터 변수에 담기
- Connection객체 - prepareStatement객체 - setString(index, x) 설정 - executeUpdate() 쿼리문 실행(업데이트)
JDBC.Model 실습
AuthDAO.java
- DAO에서는 단순 연결
- URL 패턴으로 주소 적고, 아이디, 비밀번호 적고 사용
- 위에서 처럼 MainClass에 상수로 적어주면 AuthDAO.java 에서 MainClass.URL; 이런식으로 불러옴
//멤버변수
private String url = MainClass.URL; //주소, @작성해야함
private String uid = MainClass.UID; //계정 아이디
private String upw = MainClass.UPW; //비밀번호
삽입 - insertEx()
//메서드화 - 데이터베이스 작업(insert,select 등)만, 스캐너같은 작업은 main에서
//성공실패를 받기 위해서 int형 메서드, 매개변수는 MainClass의 스캐너값 받으려고
public int insertEx(String name, String job) {
int result = 0;
String sql = "insert into auth values( seq_auth.nextval , ?, ?)"; //auth 컬럼 3개임
Connection conn = null;
PreparedStatement pstmt = null;
// throws exception을 던지니까 try-catch
try {
//드라이버 로드
Class.forName("oracle.jdbc.driver.OracleDriver");
//connection
conn = DriverManager.getConnection(url, uid, upw);
//statement 객체
pstmt = conn.prepareStatement(sql);
//?값 세팅 - 첫번째부터 1번 순서 (setString, setInt, setDate, setTimestamp)
pstmt.setString(1, name); //1은 물음표를 나타냄, 물음표가 2개 이므로 1,2가 나옴
pstmt.setString(2, job); //직접 값을 적지 않고 변수화 가능
//sql 실행 (select문은 query 문장으로 실행, i, d, u문은 update 메서드로 실행) - i,d,u는 완전 똑같음 sql문만 바뀜
result = pstmt.executeUpdate(); //업데이트문은 정수형 반환, 성공(1), 실패(0) 반환
}catch(Exception e ) {
e.printStackTrace(); //에러 로그를 봐야 하니까
}finally {
try { //객체 계속 쌓여서 close 필수로 해줌
conn.close();
pstmt.close();
} catch (Exception e2) {
System.out.println("close 에러");
}
}
return result; //성공하면 sql값 반환, 실패하면 0 반환
}
검색 - selectEx()
//조회메서드
public ArrayList<AuthVO> selectEx() {
ArrayList<AuthVO> list = new ArrayList<>();
String sql = "select * from auth order by auth_id desc"; //?가 없으니까 아래에서 딱히 할게 없음
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null; //결과 저장 객체, select 결과를 반환받을 객체
try {
//드라이버 로드
Class.forName("oracle.jdbc.driver.OracleDriver");
//conn
conn = DriverManager.getConnection(url, uid, upw);
//stmt
pstmt = conn.prepareStatement(sql);
//?값에 대한 처리 x
//sql 실행 (select의 실행)
rs = pstmt.executeQuery();
//executeQuery는 ResultSet형으로 반환
//그대로 실행된 결과가 rs에 담김
while (rs.next()) { //다음 row가 있다면 true
//한 행에 대한 처리(getInt, getString, getDouble, getTimestamp, getDate)
int auth_id = rs.getInt("auth_id");
String name = rs.getString("name"); //컬럼명
String job = rs.getString("job");
//ORM 작업 = 데이터바인딩
//vo에 행 데이터 저장
//vo를 list에 저장
AuthVO vo = new AuthVO(auth_id, name, job);
list.add(vo);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try { //객체 계속 쌓여서 close 필수로 해줌
conn.close();
pstmt.close();
rs.close();
} catch (Exception e2) {
System.out.println("close 에러");
}
}
return list;
}
AuthVO.java
- 조회한 데이터를 저장할 클래스
- 변수는 은닉, 테이블이 가지고 있는 멤버변수를 그대로 사용
- getter & setter
package jdbc.model;
public class AuthVO {
//특별한 알고리즘을 가진 클래스가 아니라, 조회한 데이터를 저장할 클래스
//1. 변수는 은닉하고, 테이블이 가지고 있는 멤버변수를 그대로 사용합니다.
//2. getter, setter
private int auth_id;
private String name;
private String job; //테이블의 컬럼을 그대로 사용
//생성자 - 기본생성자, 매개변수 생성자(모든 멤버변수를 저장하는)
public AuthVO() { /* ctrl + shift + enter */ }
public AuthVO(int auth_id, String name, String job) {
super();
this.auth_id = auth_id;
this.name = name;
this.job = job;
}
//toString메서드 오버라이딩
@Override
public String toString() {
return "AuthVO [auth_id=" + auth_id + ", name=" + name + ", job=" + job + "]";
}
//getter, setter
public int getAuth_id() {
return auth_id;
}
public void setAuth_id(int auth_id) {
this.auth_id = auth_id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getJob() {
return job;
}
public void setJob(String job) {
this.job = job;
}
}
MainClass.java
package jdbc.model;
import java.util.ArrayList;
import java.util.Scanner;
public class MainClass {
//상수 사용시 데이터베이스가 바뀌면 여기만 바뀌면 됨
public static final String URL = "jdbc:oracle:thin:@localhost:1521:xe";
public static final String UID = "hr";
public static final String UPW = "hr";
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
//DAO 클래스 선언
AuthDAO authDAO = new AuthDAO();
String menu = "";
while(true) {
try {
System.out.println("메뉴 [ 1.저장, 2.조회 ] \n>");
menu = scan.nextLine();
} catch (Exception e) {
// TODO: handle exception
}
switch (menu) {
case "1" :
System.out.print("이름>");
String name = scan.nextLine();
System.out.print("직업>");
String job = scan.nextLine();
//이 아래부터 1끝까지 메서드화 되어 AuthDAO로 들어가야 함
int result = authDAO.insertEx(name, job);
if (result == 1) {
System.out.println("정상 값이 입력되었습니다");
} else {
System.out.println("입력 오류 발생");
}
break;
case "2":
ArrayList<AuthVO> list = authDAO.selectEx();
for(AuthVO vo : list) {
System.out.println(vo.toString());
}
break;
default:
break;
} //end switch
}
} //end main
}
2023.06.20 - [Server/Spring] - [Spring] DAO, VO, DTO
2023.02.02 - [Server/Spring] - [Spring] ??? MVC Controller, MVC 웹서비스 service, service 실습, DAO 구조
728x90
'Database > Oracle' 카테고리의 다른 글
[Oracle] 데이터베이스 모델링 (0) | 2022.11.18 |
---|