2019년 6월 20일 목요일

spring boot mybatis 에서 rollback 이 안되는 문제, 해결 한 결과


기본 base가 되는 table이 있고, 그 테이블에 대한 이력을 저장하는 history테이블이 있을 경우, base가 insert가 성공하고, history에서 에러가 발생할 경우 rollback이 되지 않는 문제가 있어서 여러가지 테스트를 해 본 결과이다.


1. 컨트롤러에서 base와 history 두개의 service를 가져와서 처리하는 경우 rollback이 되지 않는다.
서비스단에서 @Transactional 를 주고 처리를 해야 rollback이 된다.

2.Transactional 어노테이션은 클래스에 줘도 적용된다.


3. 이 부분 때문에 고생했다.
아래와 같이 강제로 익셉션을 발생시키면서 try catch로 잡으면 rollback이 안된다.
아래와 같이 메소드에서 throws Exception을 해 줘야 한다.
이 때 강제로 발생시키는 익셉션은 (rollbackFor = Exception.class) 옵션을 줘야 rollback이 된다.

@Transactional(rollbackFor = Exception.class)
public class CompanyRoleService extends GenericService<CompanyRole, CompanyRoleRequest> {

...
    public int saveWithHistory(CompanyRole object) throws Exception {
        AddBaseEntity.addCreatedBy(object);
        object.setUseYn("Y");
        object.setDeleteYn("N");
        int baseSuccessCount = baseMapper.insert(object);
        if(baseSuccessCount>0){
            throw new Exception("test");
        }
...


2019.07.26 추가.
4. try catch로 롤백 하는 방법
https://stackoverflow.com/questions/25738883/spring-transactional-annotation-when-using-try-catch-block


메소드에 선언.
@Transactional(rollbackFor={MyException1.class, MyException2.class, ....})
public Result doStuff(){
   ...
}

or

프로그램 방식으로 rollback
public Result doStuff(){
  try {
    // business logic...
  } catch (Exception ex) {
    // trigger rollback programmatically
    TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
  }
}


2019년 6월 19일 수요일

queryDsl로 groupBy having 사용시 에러 발생.

queryDsl로 groupBy having을 사용할 때 아래와 같은 에러가 발생한다.
nested exception is java.lang.IllegalArgumentException: org.hibernate.hql.internal.ast.QuerySyntaxException: unexpected token: having near line 3, column 1 [select count(distinct multiLangInfo.languageCode)\nfrom com.charzin.cems.api.model.multiLang.MultiLangInfo multiLangInfo\nhaving multiLangInfo.languageType = ?1]


문제의 원인은  fetchCount()라는 전체 개수를 가져오는 함수를 사용하는 데, 이 함수가 만들어 주는 sql 쿼리문이 잘못 되었다. 위에 오류내용에 나와 있듯이 그냥 groupby를 없애버리는 쿼리를 만든다.

할 수 없이 전체 개수를 구해오는 쿼리를 따로 만들었다.

보통 group by 카운트를 가져오는 from 절 subquery는 queryDsl에서 지원하지 않는다.
여기서 확인.

할 수 없이 네이티브를 사용했다.