[JPA] delete 사용 시 500 에러 해결

백승호·2022년 4월 6일
0

문제


우선 '좋아요' 기능을 구현할려고 했고, Heart 테이블에 @ManyToOne으로 User, Blog 테이블을 연관시켜놓은 상태입니다.

@NoArgsConstructor
@Data
@Entity
public class Heart {

    @GeneratedValue(strategy = GenerationType.AUTO)
    @Id
    private Long Id;

    @JoinColumn(name = "userId", nullable = false)
    @ManyToOne()
    private User user;

    @JoinColumn(name="blogId", nullable = false)
    @ManyToOne
    private Blog blog;

    public Heart(User user, Blog blog){
        this.user=user;
        this.blog=blog;
    }

}

JPA활용하여 USER 테이블과, BLOG 테이블을 저장 및 find할 때는 문제가 없었는데,
좋아요 취소를 위해 delete 메소드를 추가했을 때 에러가 발생했습니다..

문제의 코드👇

 public int addHeart(Long blogId, User user) {
 
        Blog blog=blogRepository.findById(blogId).orElseThrow(
                ()->new NullPointerException("해당 아이디가 없습니다")
        );

		//이상 없음
        List<Heart> heartList=heartRepository.findByUserAndBlog(user, blog);
 
        //size가 0이상이면 해당 user가 그 blog에 이미 좋아요를 눌렀다는 의미
        if(heartList.size()>0){
            heartRepository.deleteByUserAndBlog(user, blog);
            //@Formula로 가상 칼럼으로 좋아요 수 count한 것에서 -1
            return blog.getHeartCount()-1;
        }

        Heart heart=new Heart(user, blog);
        //좋아요 저장
        heartRepository.save(heart);

        //Formula로 좋아요 수 count한 것을 반환
        //1을 더한 이유는 좋아요 클릭해서 1이 늘어난 것을 반영하기 위함
        return blog.getHeartCount()+1;
    }
    

500에러(서버 에러)가 발생했습니다..

콘솔창의 에러메시지를 보니..

javax.persistence.TransactionRequiredException: No EntityManager with actual transaction available for current thread - cannot reliably process 'remove' call
	at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:295) ~[spring-orm-5.3.16.jar:5.3.16]
	at com.sun.proxy.$Proxy122.remove(Unknown Source) ~[na:na]
	at org.springframework.data.jpa.repository.query.JpaQueryExecution$DeleteExecution.doExecute(JpaQueryExecution.java:277) ~[spring-data-jpa-2.6.2.jar:2.6.2]
	at org.springframework.data.jpa.repository.query.JpaQueryExecution.execute(JpaQueryExecution.java:90) ~[spring-data-jpa-2.6.2.jar:2.6.2]
	at 
...
...

라 나와있는데 가만히보니 TransactionRequiredException 이라고 친히 나와있긴합니다.


해결

@Transactional 어노테이션은 하나의 트랜잭션 단위를 만들어서 db처리 시 하나라도 에러가 나면 전부 롤백시켜주는 기능으로 알고만 있었는데, 여기서는 왜 필요로 하는지 사실 아직 잘 모르겠습니다..
(다음번 포스팅은 transactional을 공부해보는 것으로!)

그래서 혹시나 하는 마음에 @Transactional 어노테이션을 메소드 위에 붙이니

Hibernate: select blog0_.id as id1_0_0_, blog0_.created_at as created_2_0_0_, blog0_.modified_at as modified3_0_0_, blog0_.contents as contents4_0_0_, blog0_.title as title5_0_0_, blog0_.writer as writer6_0_0_, (select count(1) from heart h where h.blog_id = blog0_.id) as formula1_0_ from blog blog0_ where blog0_.id=?
com.llave.mini_project.models.Blog@3e4a86d5
Hibernate: select heart0_.id as id1_1_, heart0_.blog_id as blog_id2_1_, heart0_.user_id as user_id3_1_ from heart heart0_ where heart0_.user_id=? and heart0_.blog_id=?
Hibernate: select user0_.id as id1_3_0_, user0_.created_at as created_2_3_0_, user0_.modified_at as modified3_3_0_, user0_.kakao_id as kakao_id4_3_0_, user0_.nickname as nickname5_3_0_, user0_.password as password6_3_0_ from user user0_ where user0_.id=?
Hibernate: select heart0_.id as id1_1_, heart0_.blog_id as blog_id2_1_, heart0_.user_id as user_id3_1_ from heart heart0_ where heart0_.user_id=? and heart0_.blog_id=?
Hibernate: delete from heart where id=?

에러 메시지 없이 맨 밑에 처럼 delete가 잘 된 것을 알수 있습니다.

다음번엔 트랜잭션에 대해 더 자세히 공부해보는 것으로..

profile
처음처럼

0개의 댓글