[211215] 교육 45일차
DAO Pattern
class Bang01VO { private Integer no = null; public Integer getNo(){ return this.no; } public void setNo( Integer i ){ this.no = i; } // private String content = null; public String getContent(){ return this.content; } public void setContent( String i ){ this.content = i; } // private String theTime = null; public String getTheTime(){ return this.theTime; } public void setTheTime( String i ){ this.theTime = i; } // private String author = null; public String getAuthor(){ return this.author; } public void setAuthor( String i ){ this.author = i; } } // class BangDAO { public List<Bang01VO> findAll() throws Exception { List<Bang01VO> ls = new ArrayList<Bang01VO>(); // 어떤 상황에서도 close() 가 실행되도록 예외처리 & 에러가 나면 받고 다시 던지는 형태 포함 Connection conn = null; Statement stmt = null; ResultSet rs = null; try { Class.forName("org.mariadb.jdbc.Driver"); conn = DriverManager.getConnection( "jdbc:mariadb://...", "...", "..." ); stmt = conn.createStatement(); rs = stmt.executeQuery("SELECT * FROM bang01_T"); while( rs.next() ) { Bang01VO vo = new Bang01VO(); vo.setNo( rs.getInt("no") ); vo.setContent( rs.getString("content") ); vo.setTheTime( rs.getString("the_time") ); vo.setAuthor( rs.getString("author") ); ls.add( vo ); } } catch( Exception e ) { throw e; } finally { if( rs != null ) rs.close(); if( stmt != null ) stmt.close(); if( conn != null ) conn.close(); } return ls; } // public void add( Bang01VO pvo ) throws Exception { Connection conn = null; Statement stmt = null; try { Class.forName("org.mariadb.jdbc.Driver"); conn = DriverManager.getConnection("jdbc:mariadb://...", "...", "..."); stmt = conn.createStatement(); String sql = "INSERT INTO bang01_T VALUES ( default, '"+ pvo.getContent() + "', NOW() , '" + pvo.getAuthor() + "')"; stmt.executeUpdate( sql ); } catch ( Exception e ) { throw e; } finally { if( stmt != null ) stmt.close(); if( conn != null ) conn.close(); } } } // public class Test296 { public static void main( String[] args ) { BangDAO dao = new BangDAO(); try { Bang01VO pvo = new Bang01VO(); pvo.setContent("DAO Content"); pvo.setAuthor("daoAuthor"); // dao.add( pvo ); // SELECT 결과를 List<Bang01VO> 담아서 리턴하는 형태로 동작하는 함수 List<Bang01VO> ls = dao.findAll(); for( Bang01VO vo : ls ) { System.out.println( vo.getNo() + "," + vo.getContent() ); } } catch( Exception e ) { System.out.println( e.toString() ); } } }
DAO Pattern
실전에서는 data 를 읽고/쓰고/수정/삭제 하는 역할을 하는 함수는 DAO 라는 클래스에 모아서 함수 형태로 만들어 준다. ( Data Access Object )
DAO 패턴의 원칙
- DAO 안에는 DB 또는 데이터와 관련된 코드로만 채운다
O-R Mapping
개념을 적용한다
(테이블 : 클래스/ 필드 : 프로퍼티/ 레코드 : 인스턴스 )- 예외처리를 꼼꼼하게 하고, 발생시에 다시 던져주는 형태로 구현 ( 에러가 나도 close() 필수 )
SELECT
문은find / select / sel
등의 접두어를 붙여서 이름만 보고 그 의미를 알 수 있어야 한다.
( 예 : findByPK , findByOrderNo , findByClassName ... )INSERT
는add / insert / ins
등의 접두어DELETE
는del / remove
등의 접두어
( 예 : delByPK , removeByName , delByOrderNo ... )UPDATE
는mod / update / up
등의 접두어
( 예 : modNickNameByPK , modTheTimeByPK ... )
interface BangDAO { public List<Bang01VO> findAll() throws Exception ; public void add( Bang01VO pvo ) throws Exception ; } // class BangDAO_MariaImpl implements BangDAO{ ublic List<Bang01VO> findAll() throws Exception {} public void add( Bang01VO pvo ) throws Exception {} }
DAO Pattern 의 결정적인 핵심 개념
- IA a = new A() 개념을 적용한다.
- 클래스 이름에 사용하는 DB 타입을 명시한다.
BangDAO dao = new BangDAO(); 코드를
BangDAO dao = new BangDAO_MariaImpl(); 로 인스턴스만 바꾼다.
가짜로 하나 인터페이스를 상속하여 돌아가게 만들고 이걸로 일단 BackEnd 를 구현하고 테스트 한 뒤에 DB 담당이 BangDAO_MariaImpl 을 가져오면 인스턴스만 교체하면 된다
( 동시 진행 가능 )
PreparedStatement
String data = null; String sql = "INSERT INTO temp09_T VALUES ('"+ data +"')" : stmt.executeUpdate( sql );
INSERT INTO temp09_T VALUES ('null');
'null' 은 NULL 값이 아니라 4글자 문자열이다.
String data = null; String sql = ( data != null ) ? "INSERT INTO temp09_T VALUES ('"+ data +"')" : "INSERT INTO temp09_T VALUES ( NULL )"; stmt.executeUpdate( sql );
String sql = "INSERT INTO temp09_T VALUES ( ? )"; PreparedStatement stmt = conn.prepareStatement( sql ); // stmt.setString( 1, null ); // stmt.setString( 1, "XY" ); stmt.executeUpdate();
int no = 10101; String data = "YZ"; // String sql = "INSERT INTO temp10_T VALUES ( ?, ? )"; PreparedStatement stmt = conn.prepareStatement( sql ); stmt.setInt( 1, no ); stmt.setString( 2, data ); stmt.executeUpdate();
Statement 는 conn 에 달려있는 바구니. 이때 바구니에 SQL 문을 아예 새겨넣은 바구니가 PreparedStatement
이다.
해당 SQL 에는 ?
라는 빈 공간을 만들어 넣을 수 있다.
stmt.setString( 1, "XY"); -- ?
로 비워놓은 공간에 데이터를 채워 넣는다. 이 때는 executeUpdate 시에 매개변수가 존재하지 않는다.
다른 이유도 있지만, NULL
에 대한 처리가 PreparedStatement 를 쓰면 훨씬 깔끔하다.
PROCEDURE 프로시저
그냥 SQL 문을 실행시키는 것과 프로시저를 만들어서 실행시키는 것은 속도
에서 차이가 난다.
CREATE TABLE temp11_T ( no INT NULL, data VARCHAR(10) NULL ); INSERT INTO temp11_T VALUES ( 100 , 'HelloWorld' );
프로시저 생성
DELIMITER // CREATE PROCEDURE proc_apple() BEGIN INSERT INTO temp11_T VALUES ( 100 , 'HelloWorld' ); END; // DELIMITER ;
프로시저를 생성만 했을때는 INSERT 동작하지 않는다.
프로시저 호출
CALL proc_apple();
INSERT 동작
만약 프로시저가 존재한다면 삭제
DROP PROCEDURE IF EXISTS proc_apple;
프로시저 생성
DELIMITER // CREATE PROCEDURE proc_apple ( IN v_no INT, IN v_data VARCHAR(10) ) BEGIN INSERT INTO temp11_T VALUES ( v_no , v_data ); // DELIMITER ;
매개변수를 사용한 프로시저 호출
CALL proc_apple( 300, 'AppleKiwi' );
프로시저 생성
DELIMITER // CREATE PROCEDURE proc_apple2( IN v_no INT, IN v_data VARCHAR(10), OUT v_uc INT ) BEGIN DECLARE v_count INT; SELECT COUNT(*) INTO v_count FROM temp11_T; IF v_count < 5 THEN INSERT INTO temp11_T VALUES ( v_no, v_data ); SET v_uc = 1; ELSE SET v_uc = 0; END IF; END; // DELIMITER ;
DECLARE v_count INT;
: 변수 선언
SELECT COUNT(*) INTO v_count FROM temp11_T;
: SELECT 결과를 이용한 변수 대입
프로시저 호출
CALL proc_apple2(600,'Hello600',@abcd);
OUT 파라미터 확인
SELECT @abcd;
IN/OUT 파라미터
CallableStatement
jdbc 프로시저 호출
String sql = "CALL proc_apple(?,?)"; CallableStatement stmt = conn.prepareCall( sql ); // proc_apple ( IN v_no INT, IN v_data VARCHAR(10) ) stmt.setInt( 1, 401 ); stmt.setString( 2, "WorldHello" ); stmt.execute();
OUT 파라미터 받아오기
String sql = "CALL proc_apple2(?,?,?)"; CallableStatement stmt = conn.prepareCall( sql ); // proc_apple2( IN v_no INT, IN v_data VARCHAR(10), OUT v_uc INT ) stmt.setInt( 1, 401 ); stmt.setString( 2, "WorldHello" ); stmt.registerOutParameter( 3, Types.INTEGER ); stmt.execute(); // int abcd = stmt.getInt( 3 ); System.out.println( abcd );
registerOutParameter
를 사용하여 OUT 파라미터를 받아올 수 있다.
SELECT 결과 받아오기
DELIMITER // CREATE PROCEDURE proc_banana () BEGIN SELECT no, data FROM temp11_T; -- SELECT * FROM temp10_T; END; // DELIMITER ;
프로시저는 주석을 쓸 때 -- 을 사용한다.
CALL proc_banana();
CallableStatement stmt = conn.prepareCall("CALL proc_banana()"); stmt.execute(); ResultSet rs = stmt.getResultSet(); while( rs.next() ) { Integer no = rs.getInt("no"); String data = rs.getString("data"); System.out.println( no + "," + data ); }
프로시저에서 SELECT 결과를 발생시키는 경우 getResultSet
으로 ResultSet
을 추출할 수 있다.
Author And Source
이 문제에 관하여([211215] 교육 45일차), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@choiyezz/211215-교육-45일차저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)