0922 개발일지

Yesol Lee·2022년 9월 22일
0

개발일지 - 2022

목록 보기
140/187

오늘 목표

  • entityManager transactional 관련 에러 해결
  • mysql DB에서 crud 테스트
  • 개인 노트북에 mysql 설치하고 프로젝트 연결
  • 뉴스레터 회의 참석

오늘 한 일

homey: mysql 연동 후 crud 테스트 완료

entityManager tractional 에러 해결

javax.persistence.TransactionRequiredException: No EntityManager with actual transaction available for current thread - cannot reliably process 'persist' call

  • 서비스 인터페이스에 붙인 @Transational 어노테이션이 JpaRepository 메소드까지 적용되지 않아 발생한 오류

지난 며칠간 나를 괴롭혔던 에러이다. 해결책을 검색해보면 @Transactional 어노테이션을 붙이라고 하는데, 나는 서비스 인터페이스에 작성해두었으니 작동이 되어야 한다고 생각했다.

@TransactionalEntityManager가 작업할 때 적용되어야 할 속성인데, entityManager가 직접 작동하는 JpaRepository 메소드 단까지 해당 속성이 적용되지 않아 발생하는 문제인 것 같았다. (정확히 이해는 못함)

entityManager가 DB 데이터를 조작하는 경우 @Transactional이 붙어야 연결을 생성하고 쿼리를 실행한 후 커밋, 닫기까지 과정이 실행된다고 이해했다.

그런데 서비스 인터페이스-서비스 구현체-리포지토리 인터페이스-리포지토리 구현체의 과정을 거치며 해당 속성이 끝까지 적용되지 않아 문제가 되었다. 해당 메소드들이 JPA의 표준 네이밍과 다른 점도 영향을 미쳤을 수 있다.

Spring @Transactional Annotation

  • 해결 : JpaRepository (구현체)에서 데이터 생성, 수정, 삭제 메소드에 직접 @Transactional 어노테이션을 붙여주었다.
// JpaPostRepository.java
private final EntityManager em;

public JpaPostRepository(EntityManager em) {
	super();
	this.em = em;
}

@Override
@Transactional
public Post save(Post post) {
	// id, 생성일, 수정일 넣고 저장
	post.setPOST_DATE(LocalDateTime.now());
	post.setPOST_UPDATE(post.getPOST_DATE());
	em.persist(post);
	return post;
}

@Override
@Transactional
public Post update(Post post) {
	post.setPOST_UPDATE(LocalDateTime.now());
	em.merge(post);
	return post;
}

@Override
@Transactional
public void delete(Long postId) {
	em.createQuery("delete from Post p where p.POST_ID = :postId")
	.setParameter("postId", postId)
	.executeUpdate();
}

첨부파일 id 없는 에러

java.lang.IllegalArgumentException: id to load is required for loading
...
at com.ticktack.homey.repository.attach.JpaAttachRepository.findById(JpaAttachRepository.java:26) ~[main/:na]

  • JpaAttachRepository파일에서 첨부파일 id로 첨부파일 객체를 찾을 때 첨부파일 id가 null인 경우를 가정하지 않아 생긴 오류
  • 첨부파일의 경우 있을수도 있고 없을 수도 있는 정보라 기존 코드에서도 첨부파일 객체는 null일 수도 있음을 가정하고 있다. 하지만 첨부파일이 없으면 첨부파일id도 없어야 하는데 해당 값은 항상 있을 것처럼 작성되어 있어서 null 오류가 발생했다.
  • 첨부파일 id부터 null체크를 추가하자 에러가 해결되었다.
// 첨부파일 정보 가져오기
// 기존 코드 : 첨부파일 id를 받는 attachRepository.findById가 무조건 실행됨
Optional<Attach> attach = attachRepository.findById(form.getATTF_ID());
attach.ifPresent(f -> {
	form.setATTF_OBJ(f);
});

// 수정 코드 : id부터 없을 수 있다고 가정
Optional<Long> attfId = Optional.ofNullable(form.getATTF_ID());
attfId.ifPresent(id -> {
	form.setATTF_OBJ(attachRepository.findById(id).get());
});

post delete의 id 인식 못하는 오류

org.hibernate.QueryException: could not resolve property: postId of: com.ticktack.homey.domain.Post
...
at com.sun.proxy.$Proxy92.createQuery(Unknown Source) ~[na:na]
at com.ticktack.homey.repository.post.JpaPostRepository.delete(JpaPostRepository.java:52) ~[main/:na]

  • postRepository의 jpql 쿼리문 안 컬럼명을 잘못 작성해서 발생한 오류
  • :뒤에 오는 이름이 setParameter로 전달한 이름이어야 하고, where 바로 뒤는 DB 컬럼명이 와야 하는데 반대로 작성한 것을 발견해서 수정하였다.
// 작동하는 코드
@Override
@Transactional
public void delete(Long postId) {
	em.createQuery("delete from Post p where p.POST_ID = :postId")
	.setParameter("postId", postId)
	.executeUpdate();
}

첨부파일 정보 attach 삭제 쿼리 작성 오류

antlr.NoViableAltException: unexpected token: from
...
at com.sun.proxy.$Proxy92.createQuery(Unknown Source) ~[na:na]
at com.ticktack.homey.repository.attach.JpaAttachRepository.delete(JpaAttachRepository.java:35) ~[main/:na]

  • attachRepository의 jqpl 쿼리문을 잘못 작성해서 발생한 오류
  • 위의 post와 같이 DB 컬럼명과 파라미터 변수명 위치를 잘못 쓴 오류도 있었는데 쿼리문 문법을 틀리기도 했다.
  • delete from Attach~가 되어야 하는데 delete a from Attach~로 잘못 작성함. 기본적인 sql인데 헷갈린듯..ㅠㅠ
// 작동하는 코드
@Override
@Transactional
public void delete(Long attachId) {
	em.createQuery("delete from Attach a where a.ATTF_ID = :attachId")
	.setParameter("attachId", attachId)
	.executeUpdate();		
}
profile
문서화를 좋아하는 개발자

0개의 댓글