MapStruct 라이브러리를 이용해서 Dto와 Entity간 변환하는 테스트가 성공했기 때문에 큰 이상을 느끼지 못하고 다음작업을 하고 있었는데 갑자기 잘되던 회원가입 로직이 동작하지 않았다.

 

 

 

 

에러내용 :

detached entity passed to persist: koo.project.matcheasy.domain.member.Member; nested exception is org.hibernate.PersistentObjectException: detached entity passed to persist:

"준영속 상태인 엔티티가 영속되기위해 전달되었다"

 

 

아직 복잡한 단계의 로직을 짜지 않았고 엔티티 준영속 상태가 될 이유가 없다고 생각했었다.. 뭔가 트랜잭션 설정에 문제가 있다고 판단했다.

 

 

 

 

의심1. 

MemberRepository는 클래스 레벨에서 @Transactional 애노테이션을 readOnly = true 옵션으로 지정하여 안의 메소드를 읽기전용으로 지정을 해주었다. save는 직접 DB에 접근하기 때문에 readOnly옵션을 풀어준 @Transactional 애노테이션만 붙여준 상황이었다. 

 

여기서 발견한 잘못된 점은 Service계층에서는 @Transactional 애노테이션을 붙여주지 않았다는 것이었다. 한개의 Request가 있고 난 후, 같은 트랜잭션 단위로 동작하기 위해서는 Service에서도 @Transactional을 붙여주어야 할 것 같았다. 

 

하지만, 변경 후에도 위와 똑같은 에러가 발생했다.

 

 

 

 

의심2.

 

참고 : 

http://credemol.blogspot.com/2011/01/spring-junit-transaction.html

 

Spring에서 JUnit 테스트 시 Transaction 처리

http://viralpatel.net/blogs/2010/11/spring3-mvc-hibernate-maven-tutorial-eclipse-example.html 위의 블로그에 방문하면 spring3 기반에서 hibernate를 이용해서 da...

credemol.blogspot.com

@Test annotation과 함께 설정된 @Transactional은 항상 rollback 된다고 한다. 테스트 환경에서 save로직이 실행되지 않았기에 테스트클래스에 @Rollback(value = false) 애노테이션을 붙여주어 롤백되지 않고 직접 데이터베이스에 저장되는 것을 확인하고자 하였다.

 

하지만 결과는 마찬가지였다.

 

 

 

 

save메서드에 직접 로그를 찍어서 잘 넘어오나 확인했는데.. 이상한점이 발견되었다.

save: member=Member(id=0, loginId=test, password=test!, name=테스트, age=20, email=aa@aa.com)

id값이 0...? 아차..

 

 

 

MapStruct의 Mapper 파일이다. toEntity메서드는 Dto를 Entity로 바꾸어주는 메서드이다. @Mapping을 이용하여 매핑속성을 지정할 수 있다.

target은 Entity의 field를 지정하고, constant는 그 field를 상수 0L로 지정하겠다는 의미이다.

Member엔티티는 DB와 매핑되는 필드를 가지고 있기 때문에 id값이 있지만, Dto는 id필드가 없다. 그러므로 toEntity를 할때 id필드의 값이 없어서 상수로 지정해준 것이다. (id값이 없어서 Error가 날 수도 있을 것 같아서 테스트를 진행할 때 constant로 박아놓고 잘 돌아가는군. 이라고 생각했다......)

 

그런데, Member엔티티의 id값은 @GeneratedValue의 default전략인 AUTO로 지정했기 때문에 기본키를 전략에 맞게 자동으로 증가시킨다. (H2데이터베이스로 로컬테스트를 하고 있기 때문에, 기본전략은 SEQUENCE전략이다)

처음 시퀀스값이 0인 상태에서 DB에 접근할 때마다 sequence값을 증가시켜서 id값을 지정해야하는데 0L 상수로 고정이 되어 있었기 때문에 에러가 발생한 것이었다.

 

매핑 애노테이션을 없앤 후 오류를 해결하였다.

+ Recent posts