hibernate란 JPA 구현체 중 하나라고 생각을 하면 된다. 여기서 JPA 는 ORM 기술을 명세한 인터페이스라고 한다.
기존에 Mybatis 에서 SQL 구문을 DB에 날리는 형식이지만 JPA의 경우 메소드를 사용을 하여 쿼리를 날리기 때문에 JDBC API를 사용을 안한다는 것은 아니다.
메소드의 내부에서 JDBC API를 이용한 쿼리를 날려주기 때문에 JAVA 개발자로써는 비지니스 로직에 대한 집중을 할 수 있다는 장점이 있다.
트랜잭션이란 데이터 베이스에서 상태 변화를 이르키는 한 단위로 커밋 과 롤백 이 존재한다.
여기서 상태란 select,delete,update,insert (DML)을 이용해서 상태에 대한 변화를 이르키는 것을 말하는데 이때 에러 혹은 이슈가 발생이 되면 롤백을 하게 된다.
하지만 정상적인 작업이 진행이 되면 커밋을 하게 된다. 커밋의 경우 optional이 있는데 auto, off, on , true, false 가 존재한다.
spring 에서 @transaction 를 이용을 해서 트랜잭션 처리를 한다. 트랜잭선은 기본적으로 aop이다, 그리고 aop 이면서 프록시 패턴으로 이루어 져있다. 메소드를 선언후 트랜잭션을 사용하기 위해서 @transaction을 선언을 해주는데 아래의 그림 처럼 작동을 한다.
아래의 그림 처럼 unable to commit agient JDBC 라는 에러가 발생이 되었다.
상황은 이렇다 로그인 하는 유저가 있는데 로그인이 되지 않고 있었다.
디버그를 해본뒤 하나하나 따라가 보았다.
DaoAuthenticationProvider
라는 객체가 존재를 하는데 기본적으로 스프링 시큐리티를 사용을 하면 제공을 해주는 클래스 이다
이 클래스의 경우 시큐리티를 통해서 로그인을 할 경우 유저에 대한 정보를 로드 해주는 기능이 포함 되어 있다.
유저의 정보를 로드 해주는 메소드 가 retrieveUser
라는 메소드 이다.
UserDetailService 에서 loadUserByUsername() 을 호출을 한다. username이라는 변수의 경우 우리가 form login 을 통해서 넘겨주는 아이디 값 (eamil , username) 등등 값이라고 생각을 하면된다.
UserDetails 라는 객체를 반환을 해준는데 여기서는 기본적으로 db 에서 있는 유저를 넣는다.
로드유저가 null 이 아니면 반환을 하는데 여기서 맨 아래 Exception 부분에서 에러가 나게 되는 상황이 였다.
지금 연동이 되어 있는 RDBMS 의 경우 Auto-Commit 이 off 가 기본값으로 되어 있어서 JPA 트랜잭션이 걸리면 자동으로 auto commit 이 세팅이 되는 상황이다.
설정파일 (yml)에서 위와 같이 hibernate.connection.provider_disables_autocommit 을 false 로 설정을 하면 에러 없이 진행이 가능하다.