JDBC
- 자바 프로그램내에서 SQL문을 실행하기 위한 자바 API
- JAVA는 표준 인터페이스인 JDBC API를 제공
- 데이터베이스 벤더, 또는 기타 써드파티에서는 JDBC 인터페이스를 구현한 드라이버 (driver)를 제공
- java.sql패키지를 보면 대부분이 interface로 되어 있음
- 이를 실제로 구현하는 것은 DBMS를 만든 회사
JDBC 드라이버 설치-build.gradle
dependencies {
implementation group: 'com.mysql', name: 'mysql-connector-j', version: '8.3.0'
}
maven,gradle이 없었으면 드라이버(라이브러리)를 하나 씩 찾아서 다운로드 해서 사용해야 함
JDBC 사용
import java.sql.*;
//드라이버 로드 (예전 버전은 필요. 8 버전에선 필요없다.)
Class.forName( "com.mysql.cj.jdbc.Driver" );
//Connection 얻기
String dburl = "jdbc:mysql://localhost/dbName";
Connection con = DriverManager.getConnection ( dburl, ID, PWD );
insert
public class InsertTest {
public static void main(String[] args) {
//1.선언
Connection conn =null;
PreparedStatement ps =null;
//Statement객체와 다르게 값을 바인딩 해줌 , 값이 바뀔 때마다 문장을 새로 번역 할 필요가 없어 성능이 좋음
try {
String url="jdbc:mysql://localhost:3306/socott";
String user="like";
String password="lion";
int deptno=90;
String sql="insert into dept(deptno,dname,loc) values (?,?,?)";
try {
//Class.forName("com.mysql.cj.jdbc.Driver"); //드라이버 로딩(객체 생성)
//3.접속 (Connection)
conn= DriverManager.getConnection(url, user, password);
//4.sql작성(Statement 객체 이용)
ps=conn.prepareStatement(sql);
//?에 해당하는 값을 바인딩 해줄 필요가 있다
ps.setInt(1, deptno);
ps.setString(2,"교육부");
ps.setString(3, "일산");
//5.실행
int count=ps.executeUpdate();
//6.결과 얻기
System.out.println(count+"건 입력했습니다");
}catch (Exception e){
System.out.println(e);
}finally {
//2.닫는다
if(ps != null){
try {
ps.close();
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
if ((conn!=null)){
try {
conn.close();
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
}
}
}
update
public class UpdateTest {
public static void main(String[] args) {
Connection conn =null;
PreparedStatement ps =null;
String url="jdbc:mysql://localhost:3306/socott";
String user="like";
String password="lion";
String sql="update dept set dname=? where deptno=?";
try {
conn = DriverManager.getConnection(url, user, password);
ps=conn.prepareStatement(sql);
ps.setString(1, "마케팅");
ps.setInt(2, 90);
int count=ps.executeUpdate();
System.out.println(count+"건 수정했어요");
} catch (SQLException e) {
System.out.println(e);
}
}
}
delete
public class DeleteTest {
public static void main(String[] args) {
String url= "jdbc:mysql://localhost:3306/socott";
String user = "like";
String password = "lion";
String sql = "delete from dept where deptno=?";
try(
//1.접속
Connection conn = DriverManager.getConnection(url,user,password);
//2. sql문작성
PreparedStatement ps = conn.prepareStatement(sql);
){
ps.setInt(1, 80);
//3. 실행!!
int count = ps.executeUpdate();
System.out.println(count + " 건 삭제했습니다.");
}catch (Exception e){
e.printStackTrace();
}
}
}
select
//기본키 검색으로 한 행만 조회 할 때
public class SelectTest {
public static void main(String[] args) {
//1. 선언
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null; //결과를 얻어오는 객체
//조건에 맞는 데이터 1권조회 와 여러건 조회 !!
String sql = "select deptno, dname, loc from dept where deptno=?";
try{
//3. 접속
conn = DBUtil.getConnection();
//4. 쿼리 작성
ps = conn.prepareStatement(sql);
ps.setInt(1,200);
//5. 쿼리실행
rs = ps.executeQuery();
//6. 결과 얻어오기!!
if(rs.next()){ // 실행할 행 있다면(한줄 씩 행을 가져옴)
System.out.println(rs.getInt(1));
System.out.println(rs.getString("dname"));
System.out.println(rs.getString(3));
}
} catch (Exception e) {
throw new RuntimeException(e);
}finally {
//2.닫는코드
DBUtil.close(conn,ps,rs);
}
}
}
//전체 테이블을 조회할 때
public class SelectManyTest {
public static void main(String[] args) {
//1. 선언
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
//조건에 맞는 데이터 1권조회 와 여러건 조회 !!
String sql = "select deptno, dname, loc from dept";
try{
//3. 접속
conn = DBUtil.getConnection();
//4. 쿼리 작성
ps = conn.prepareStatement(sql);
//5. 쿼리실행
rs = ps.executeQuery();
//6. 결과 얻어오기!!
while(rs.next()){ //행이 있을 때까지
System.out.println(rs.getInt(1));
System.out.println(rs.getString("dname"));
System.out.println(rs.getString(3));
}
} catch (Exception e) {
throw new RuntimeException(e);
}finally {
//2.닫는코드
DBUtil.close(conn,ps,rs);
}
}
}
| 기능 | Statement | PreparedStatement | CallableStatement |
| SQL 매개변수화 | 없음 | 예 (? 플레이스홀더) | 예 (입력 및 출력 매개변수) |
| 사전 컴파일 | 없음 | 예 | 예 |
| 보안 | 적절히 처리하지 않으면 SQL 인젝션에 취약 | SQL 인젝션 방지 | SQL 인젝션 방지 |
| 사용 사례 | 단순하고 정적인 SQL 쿼리 | 매개변수가 있는 반복 쿼리 | 저장 프로시저 실행 |
| 성능 | 반복 실행 시 비효율적 | 반복 실행 시 효율적 | 저장 프로시저 복잡도에 따라 다름 |
| 유연성 | 동적 쿼리에 덜 유연 | 동적 매개변수에 더 유연 | 저장 프로시저에 특화됨 |
DAO (Data Access Object)
- 데이터베이스와 같은 영속성 저장소에 접근하는 로직을 캡슐화하여 비즈니스 로직과 분리하는 디자인 패턴
public class DeptDAO {
// 기본 CRUD
//insert -- c
//dept 테이블에 데이터를 한건 입력하는 메소드
public boolean addDept(DeptDTO deptDTO){
//1.객체 선언
Connection connection=null;
PreparedStatement preparedStatement=null;
String sql="insert into dept(deptno,dname,loc) values (?,?,?)";
try {
connection=DBUtil.getConnection();
preparedStatement=connection.prepareStatement(sql);
preparedStatement.setInt(1,deptDTO.getDeptno());
preparedStatement.setString(2, deptDTO.getDname());
preparedStatement.setString(3, deptDTO.getLoc());
int count=preparedStatement.executeUpdate();
if(count==1){
return true;
}else {
return false;
}
} catch (SQLException e) {
throw new RuntimeException(e);
}finally {
//2. 선언한 객체 닫기
DBUtil.close(connection,preparedStatement);
}
}
//update -- u
public int updateDept(DeptDTO deptDTO){
//1.객체 선언
Connection connection=null;
PreparedStatement preparedStatement=null;
String sql="update dept set dname=? where deptno=?";
try {
connection=DBUtil.getConnection();
preparedStatement=connection.prepareStatement(sql);
preparedStatement.setString(1, deptDTO.getDname());
preparedStatement.setInt(2, deptDTO.getDeptno());
int count=preparedStatement.executeUpdate();
return count;
} catch (SQLException e) {
throw new RuntimeException(e);
}finally {
//2. 선언한 객체 닫기
DBUtil.close(connection,preparedStatement);
}
}
//delete -- d
public void deleteDept(int deptno){
//1.객체 선언
Connection connection=null;
PreparedStatement preparedStatement=null;
String sql="delete from dept where deptno=?";
try {
connection=DBUtil.getConnection();
preparedStatement=connection.prepareStatement(sql);
preparedStatement.setInt(1,deptno);
int count=preparedStatement.executeUpdate();
System.out.println(count + " 건 삭제했습니다.");
} catch (SQLException e) {
throw new RuntimeException(e);
}finally {
//2. 선언한 객체 닫기
DBUtil.close(connection,preparedStatement);
}
}
//여러건 조회
public List<DeptDTO> getDeptList(){
List<DeptDTO> deptList = new ArrayList<>();
//선언
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try{
conn = DBUtil.getConnection();
ps = conn.prepareStatement("select deptno,dname,loc from dept");
rs = ps.executeQuery();
while (rs.next()){
DeptDTO deptDTO = new DeptDTO();
deptDTO.setDeptno(rs.getInt(1));
deptDTO.setDname(rs.getString(2));
deptDTO.setLoc(rs.getString(3));
deptList.add(deptDTO);
}
} catch (Exception e) {
throw new RuntimeException(e);
}finally {
DBUtil.close(conn,ps,rs);
}
return deptList;
}
//1건 조회
public DeptDTO getDept(int deptno){
DeptDTO deptDTO = new DeptDTO();
//선언
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
String sql = "select deptno, dname, loc from dept where deptno=?";
try{
conn = DBUtil.getConnection();
ps = conn.prepareStatement(sql);
ps.setInt(1, deptno);
rs = ps.executeQuery();
if(rs.next()){
deptDTO.setDeptno(rs.getInt("deptno"));
deptDTO.setDname(rs.getString("dname"));
deptDTO.setLoc(rs.getString("loc"));
}
} catch (Exception e) {
throw new RuntimeException(e);
}finally {
DBUtil.close(conn,ps,rs);
}
return deptDTO;
}
}
DTO (Data Transfer Object)
- 계층 간에 데이터를 전송하기 위해 사용하는 객체로, 주로 네트워크를 통해 데이터를 전송하거나, 애플리케이션의 여러 계층 간에 데이터를 전달할 때 사용
- 값을 가지고 다닐 목적을 사용하는 객체
public class DeptDTO {
private int deptno;
private String dname;
private String loc;
public DeptDTO() {
}
public DeptDTO(int deptno, String dname, String loc) {
this.deptno=deptno;
this.dname=dname;
this.loc=loc;
}
public int getDeptno() {
return deptno;
}
public void setDeptno(int deptno) {
this.deptno = deptno;
}
public String getDname() {
return dname;
}
public void setDname(String dname) {
this.dname = dname;
}
public String getLoc() {
return loc;
}
public void setLoc(String loc) {
this.loc = loc;
}
@Override
public String toString() {
return "DeptDTO{" +
"deptno=" + deptno +
", dname='" + dname + '\\'' +
", loc='" + loc + '\\'' +
'}';
}
}
DBUtil
DB접속과 종료 메서드를 static으로 호출하여 간편하게 쓸 수 있음
public class DBUtil {
//DB 접속
public static Connection getConnection() throws SQLException {
String url="jdbc:mysql://localhost:3306/socott";
String user="like";
String password="lion";
Connection conn = DriverManager.getConnection(url, user, password);
return conn;
}
public static Connection getConnection(String user,String password) throws SQLException {
String url="jdbc:mysql://localhost:3306/socott";
Connection conn = DriverManager.getConnection(url, user, password);
return conn;
}
//close
public static void close(Connection connection) {
if(connection!=null)
try {
connection.close();
} catch (SQLException e) {
System.out.println(e);
}
}
public static void close(Connection connection, PreparedStatement preparedStatement) {
if(preparedStatement!=null)
try {
preparedStatement.close();
} catch (SQLException e) {
System.out.println(e);
}
close(connection);
}
public static void close(Connection conn, PreparedStatement ps, ResultSet rs){
if(rs != null){
try {
rs.close();
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
close(conn,ps);
}
}
사용예제
public class DeptDaoUser {
public static void main(String[] args) {
DeptDAO deptDAO=new DeptDAO();
DeptDTO deptDTO=new DeptDTO();
deptDTO.setDeptno(110);
deptDTO.setDname("Test 부서");
deptDTO.setLoc("판교");
//Insert
boolean result=deptDAO.addDept(deptDTO);
if(result=true){
System.out.println("성공");
}else{
System.out.println("실패");
}
deptDTO.setDeptno(110);
deptDTO.setDname("그냥 부서");
//update
int count=deptDAO.updateDept(deptDTO);
System.out.println(count+"건을 업데이트 했습니다");*/
//delete
deptDAO.deleteDept(110);
//select
List<DeptDTO> list = deptDAO.getDeptList();
for(DeptDTO dto : list){
System.out.println(dto);
}
}
}
try-with-resources
- 자원을 자동으로 관리하고 닫아주는 기능을 제공
- finally안에서 접속을 close해줄 필요 없음
try (자원 선언) {
// 자원을 사용하는 코드
} catch (예외 처리) {
// 예외 처리 코드
}
MYSQL 락
- 트랜잭션이 데이터를 처리할 때 다른 트랜잭션의 접근을 제어하기 위해 사용
- 쿼리 문을 처리(커밋&롤백) 할 때 까지 같은 쿼리 문을 실행 할 수 없음
- 데이터 무결성 유지
-- 트랜잭션 1
START TRANSACTION;
SELECT * FROM users WHERE id = 1 FOR UPDATE;
-- 트랜잭션 2
START TRANSACTION;
SELECT * FROM users WHERE id = 1 FOR UPDATE;
-- 트랜잭션 2는 트랜잭션 1이 커밋하거나 롤백할 때까지 대기
'TIL' 카테고리의 다른 글
| 241223 TIL (6) | 2024.12.24 |
|---|---|
| 241224 TIL (3) | 2024.12.24 |
| 241219 TIL (1) | 2024.12.19 |
| 241218 [멋쟁이사자처럼 부트캠프 TIL 회고] Back-End school (2) | 2024.12.18 |
| 241217 [멋쟁이사자처럼 부트캠프 TIL 회고] Back-End school (1) | 2024.12.17 |