'oracle' 태그의 글 목록 :: 잡다한 프로그래밍
반응형

1. Transaction에서 rollback이 되지않는 경우는?

- checked exception은 트랜잭션에서 롤백되지않는다. (명시적인 예외처리가 필요한 것, try catch해야하는것 들)

- unchecked exception은 롤백대상 (예외처리를 하지 않아도 IDE에서 에러 뱉지 않음, Runtime Exception...)

 

2. checked exception 경우에도 rollback을 하고싶으면?

만약 B에서 에러가 발생했을때 A를 rollback시키고 싶다면? 이럴때 transaction을 이용한다

하지만 B의 exception이 checked exception이라면?

@Transactional
public void test() {
    A();
    B();
}

만약 아래처럼 try catch를 이용하면 에러를 catch에서 처리했기 때문에, rollback이 발생하지 않는다.

@Transactional
public void test() {
    A();
    try {
    	B(); // checked exception을 발생시키는 부분
    } catch {
    
    }
}

 

- @Transcational 어노테이션에 rollbackFor라는 옵션을 이용한다

해당 에러는 throw하고, rollbackFor옵션을 사용하면 checked exception도 확인할 수 있게 된다.

@Transactional(rollbackFor = {Exception.class})
public void test() {
    A();
    B(); // checked exception을 발생시키는 부분에서는 error throw
}

 

- checked 예외를 unchecked 예외로 변경하여 throw한다

public void B() {
    try {
    
    }catch(Exception e) {
    	throw new RuntimeException("예외");
    }
}


@Transactional
public void test() {
    A();
    B(); // unchecked exception으로 바꿈
}

 

3. 아래와 같은 경우에는 롤백이 일어날까 일어나지 않을까?

	// ATest 클래스
    @Transactional
    public void A() {
        try {
            test.B();
        } catch (RuntimeException e) {
            System.out.println("예외 처리");
        }
    }
    
    
    // BTest클래스
    @Transactional
    public void B() {
        //로직
        mapper.save();
        throw new RuntimeException("예외"); // unchecked exception
    }

 

해당 코드는 다음과 같이 동작한다.

1. A클래스의 트랜잭션이 실행된다.

2. B메소드가 실행되면서 1번의 트랜잭션에 참여한다 (기본 propagation 속성이 PROPAGATION_REQUIRED)

3. save를 실행하는 부분의 처리가 끝나고 트랜잭션의 완료처리 (completion)을 진행함

4. checked Exception이 일어나면서 트랜잭션이 완료처리 됨

5. checked Exception때문에 해당 트랜잭션을 롤백 규칙을 적용(기본 규칙적용), 해당 메소드에서 바로 롤백하지않고 rollback mark를 함 (해당 마크는 전역으로 관리함)

6. A의 로직 수행 > 1번에서 생성된 트랜잭션의 완료처리가 진행, 이때 rollback mark를 확인해서 값이 true라면 rollback진행

따라서 이경우에는 롤백되어버린다

 

해당 propagation 옵션을 변경할경우 해당 rollback mark 문제를 해결할 수 있다

 

PROPAGATION_REQUIRES_NEW 사용시 매번 새로운 트랜잭션 생성

- A와 B가 각각 트랜잭션을 생성하고, 매 번 commit하므로 서로의 rollback에 영향을 미치지 않음

하지만 오버헤드 발생할 수 있음 (매번 새로운 커넥션 생성)

반응형
반응형

1. 문법의 차이

#1) #을 이용한 경우

<select id="select" resultType="String" parameterType="Map">
    SELECT name FROM user WHERE id = #{id}
</select>

다음과 같은 SELECT문을 작성하였을경우 아래와 같이 ?에 파라미터가 바인딩 되어 수행된다 이렇게 파싱된 쿼리문은 재활용(캐싱)되므로 효율적이다.

SELECT name FROM user WHERE id = ?

 또한 변수에 작은 따옴표(')가 붙어 쿼리가 수행되므로 '#{id}'라고 쿼리문을 작성할 필요가 없다. 대신 다음과 같이 사용할 수 없다. 아래와 같이 사용할 경우 user_'tableName'이 되어버리므로 에러가 발생한다.

<select id="select" resultType="String" parameterType="Map">
    SELECT name FROM user_#{tableName} WHERE id = #{id}
</select>

 

#2) $를 이용한 경우

반면 $를 이용하게 되면 파라미터값이 바뀔 때마다 새로운 쿼리문의 파싱을 진행해야해서 성능상 단점이 존재한다.

또한 쿼리문에 #{}과 다르게 작은 따옴표(')가 붙지 않아서 테이블 이름이나 컬럼이름을 동적으로 결정할때 사용할 수 있다.

<select id="select" resultType="String" parameterType="Map">
    SELECT name FROM user_${tableName} WHERE id = #{id}
</select>

2. SQL Injection 차이

보안적으로 #과 $에는 차이가 존재한다. #은 $보다 보안에 안전하다 다음과 같은 예시를 보자

<select id="select" parameterType="Map" resultType="...">
    SELECT * FROM user WHERE id = '${id}' AND password = '${password}'
</select>

만약 이때 사용자가 id 값에 root' --를 입력했다고 가정하면 다음과 같은 결과를 초래한다.

SELECT * FROM user WHERE id = 'root' -- 'AND password = ''

사용자는 비밀번호를 입력하지 않았지만 뒷부분이 주석처리되어 로그인에 성공하게되어버린다 따라서 $는 #보다 SQL Injection에 취약하다

반응형
반응형

지난 #8 강의에 이어 MYSQL과 연동하여 Update, delete, insert 하는 방법을 설명하도록 한다.

 

1. INSERT

먼저 지난번 query와 달리 update메소드를 사용하며 다음과 같이 사용한다 update메서드 내부에는 insert sql문, new Object로 name, email, text를? 에 넣어주는 방식으로 사용하며 이때 반환하는 값이 1이면 true를 리턴한다.

	public boolean insert(Offer offer) {
		String sqlStatement = "insert into offers (name, email, text) values (?,?,?)";
		String name = offer.getName();
		String email = offer.getEmail();
		String text = offer.getText();
		
		return (jdbcTemplateObject.update(sqlStatement, new Object[]{name, email, text}) == 1);
	}

2. UPDATE

insert와 같이 update메소드를 사용하며 사용방법은 다음과 같다.

	public boolean update(Offer offer) {
		String sqlStatement = "update offers set name=?, email=?, text=? where id=?";
		String name = offer.getName();
		String email = offer.getEmail();
		String text = offer.getText();
		int id = offer.getId();
		
		return (jdbcTemplateObject.update(sqlStatement, new Object[]{name, email, text, id}) == 1);
	}

3. DELETE

마찬가지로 update 메소드를 사용하며 사용방법은 다음과 같다.

	public boolean delete(int id) {
		String sqlStatement = "delete from offers where id = ?";
		
		return (jdbcTemplateObject.update(sqlStatement, new Object[]{id}) == 1);
	}
반응형

+ Recent posts