본문 바로가기

STUDY/국비과정

[JAVA 웹 개발 공부] 국비지원 44일차 - addBatch, Index, last_insert_id(), 세션변수, Stored Procedures

JDBC 대량 쿼리문 addBatch, executeBatch 실행

 

addBatch()를 사용하면 쿼리를 건별로 수행하지 않고, 여러 개의 쿼리들을 메모리에 올려놓고 모아둔 쿼리들을 한 번에 실행시켜 수행 속도를 개선할 수 있다.

 

1. Connection객체 설정 부분에 AutoCommit을 false로 설정

conn.setAutoCommit(false);

2. addBatch로 쿼리들을 메모리에 올리기

pstmt.addBatch();

3. executeBatch로 모아둔 쿼리들을 실행 (executeBatch는 처리결과로 int[] 타입의 값 반환)

int[] result = pstmt.executeBatch();

4. commit

conn.commit();

5. 예외발생시 rollback

catch (SQLException e) {
    e.printStackTrace();
    try {
        conn.rollback();
    } catch (SQLException e1) {
        e1.printStackTrace();
    }
}

 

*전체코드보기

public int[] createList(List<Restaurant> list) {
    String sql = "INSERT INTO restaurant (name, phoneNumber, address, score)" + " VALUES (?, ?, ?, ?)";
    Connection conn = ConnectionProvider.makeConnection();

    try (PreparedStatement pstmt = conn.prepareStatement(sql);) {
        conn.setAutoCommit(false);
        for (Restaurant r : list) {
            pstmt.setString(1, r.getName());
            pstmt.setString(2, r.getPhoneNumber());
            pstmt.setString(3, r.getAddress());
            pstmt.setDouble(4, r.getScore());

            pstmt.addBatch();
        }
        int[] result = pstmt.executeBatch();
        conn.commit();
        return result;
    } catch (SQLException e) {
        e.printStackTrace();
        try {
            conn.rollback();
        } catch (SQLException e1) {
            e1.printStackTrace();
        }
    } finally {
        ConnectionProvider.closeConnection(conn);
    }
    return null;
}

 

 

인덱스(Index)

 

1. 인덱스(Index)
인덱스는 데이터베이스 테이블에 대한 검색 성능의 속도를 높여주는 자료 구조이다.

2. 인덱스를 사용하는 이유 
테이블에 데이터들이 인덱스의 가장 큰 특징은 데이터들이 정렬이 되어있다는 점이다. 이 특징으로 인해 조건 검색이라는 영역에서 굉장한 장점이 된다.

*조건 검색 WHERE 절의 효율성
*정렬 Order by 절의 효율성

*특정 열을 고려 대상에서 빨리 없애 버리기 위해.
*조인 (join)을 실행할 때 다른 테이블에서 열을 추출하기 위해.
*특정하게 인덱스된 컬럼을 위한 MIN() 또는 MAX() 값을 찾기 위해.
*사용할 수 있는 키의 최 좌측 접두사(leftmost prefix)를 가지고 정렬 및 그룹화를 하기 위해.
*데이터 열을 참조하지 않는 상태로 값을 추출하기 위해서 쿼리를 최적화 하는 경우.


3. 인덱스의 단점 
인덱스의 가장 큰 문제점은 정렬된 상태를 계속 유지 시켜줘야 한다는 점이다. 그렇기에 레코드 내에 데이터값이 바뀌는 부분이라면 악영향을 미칩니다. INSERT, UPDATE, DELETE를 통해 데이터가 추가되거나 값이 바뀐다면 INDEX 테이블 내에 있는 값들을 다시 정렬을 해야된다. 그리고 INDEX 테이블, 원본 테이블 이렇게 두 군데에 데이터 수정 작업해줘야 한다는 단점도 있다.

 

4. 인덱스 생성

자주 사용하는 컬럼이라면 인덱스화 시켜주기
Schemas 테이블명 우클릭 > Alter Table... > Indexes 탭 > Index Name, Type(INDEX) 작성 > Index Columns에서 정렬기준 Column 체크 > Apply

 

 

Stored Procedures

 

Stored Procedures는 일련의 쿼리를 마치 하나의 함수처럼 실행하기 위한 쿼리의 집합이다. 

논리적인 모든 SQL문 가능, 모든 동작 가능 (insert, delete, 함수호출 등...)

 

*회원탈퇴는 추가와 삭제 모든 기능이 있어야한다. → 트랜잭션

create table userinfo_inactive like userinfo;
desc userinfo_inactive;
select * from userinfo_inactive;

select * from userinfo;
insert into userinfo_inactive (id, email, firstName, lastName) 
select id, email, firstName, lastName from userinfo where id = 7;

delete from userinfo where id = 7;

select * from userinfo_inactive;

 

*Stored Procedures - 회원탈퇴

CREATE PROCEDURE `userout`(IN userid INT)
BEGIN
	insert into userinfo_inactive (id, email, firstName, lastName) 
	select id, email, firstName, lastName from userinfo where id = userid;

	delete from userinfo where id = userid;
END

 

*Stored Procedures - 회원추가

CREATE PROCEDURE `usp_userin`
	(in email varchar(60), in firstName varchar(15), in lastName varchar(15), out id int)
BEGIN
	insert into userinfo (email, firstName, lastName) 
	values (email, firstName, lastName);

	set id := (select last_insert_id());
END

 

 

last_insert_id()

 

last_insert_id 함수는 테이블의 마지막 auto_increment 값을 리턴한다.

주의점) insert into 를 하는동작이 실패하더라도 auto_increment값은 증가

 

 

세션변수

 

MySQL에서 @붙은 변수는 세션 변수라고 하며, @붙은 변수는 세션이 종료될 때까지 사용이 가능하다.

SET @sessionvar := 44;
SELECT @sessionvar;

 

 

Unchecked Exception, Checked Exception

 

1. Unchecked Exception
명시적인 예외 처리를 강제하지 않기 때문에 Uncheked Exception이라고 한다. 명시적인 예외 처리란 try ~ catch로 예외를 잡거나 throw로 호출한 메소드에게 예외를 던지지 않는 행위를 말한다.

2. Checked Exception
명시적인 예외 처리를 강제하기 때문에 Checked Exception이라 한다. 반드시 try ~ catch로 예외를 잡거나 throw로 호출한 메소드에게 예외를 던져야 한다.

 

3. 정리

구분 Checked Exception Unchecked Exception
확인 시점 컴파일(Compile) 시점 런타임(Runtime) 시점
처리 여부 반드시 예외 처리해야 한다. 명시적으로 하지 않아도 된다.
트랜잭션 처리 예외 발생시 롤백(rollback)하지 않음 예외 발생시 롤백(rollback)해야 함
종류 IOException,
ClassNotFoundException 등
NullPointerException,
ClassCastException 등


*Checked Exception이 Rollback되지 않는 이유
기본적으로 Checked Exception은 복구가 가능하다는 메커니즘을 가지고 있다. 예를 들어, 특정 이미지 파일을 찾아서 전송해 주는 함수에서 이미지를 찾지 못 했을 경우 기본 이미지를 전송한다는 복구 전략을 가질 수 있다. 정리하자면, 복구가 가능하니 Rollback은 진행하지 않는다는 의미이다.

 

 

coupling

 

*coupling
의존성이 생겼다. → 해당객체가 동작하기 위해서 다른 객체가 필요하다.

의존성은 제거할 수 없으므로 느슨하게 만들려면 인터페이스로 미리 정의를 해놓고 
구현체만 다르게 해주면 조금더 느슨한 커플링을 만들수 있다.(교체가 쉬워진다.)

interface SmartPhone {
	void call();
	void message();
}

class IPhone implements SmartPhone {
	@Override
	public void call() {
	}
	@Override
	public void message() {
	}
}

class SamsungPhone implements SmartPhone {
	@Override
	public void call() {
	}
	@Override
	public void message() {
	}
}

class Parents {
	public static void main(String[] args) {
		People p = new People(new IPhone());
		People p2 = new People(new SamsungPhone());
	}
}

public class People {
	private SmartPhone phone;
	
	public People(SmartPhone phone) {
		this.phone = phone;
	}
	
	void call() {
		phone.call();
	}
	void message() {
		phone.message();
	}
}