복붙노트

[SPRING] Spring, JPA, Hibernate - 동시성 문제없이 카운터를 증가시키는 방법

SPRING

Spring, JPA, Hibernate - 동시성 문제없이 카운터를 증가시키는 방법

나는 Spring과 JPA / Hibernate를 가지고 놀고 있는데 테이블의 카운터를 증가시키는 올바른 방법으로 혼란 스럽다.

내 REST API는 사용자 작업에 따라 데이터베이스에서 일부 값을 증가 및 감소시켜야합니다 (예 : 태그를 좋아하거나 싫어하면 태그가 증가하거나 감소합니다)

tagRepository는 JpaRepository (스프링 데이터) 이 같은 트랜잭션을 구성했습니다.

<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"/>

@Controller
public class TestController {

    @Autowired
    TagService tagService

    public void increaseTag() {
        tagService.increaseTagcount();
    }
    public void decreaseTag() {
        tagService.decreaseTagcount();

    }
}

@Transactional
@Service
public class TagServiceImpl implements TagService {


    public void decreaseTagcount() {
        Tag tag = tagRepository.findOne(tagId);
        decrement(tag)
    }

    public void increaseTagcount() {
        Tag tag = tagRepository.findOne(tagId);
        increment(tag)
    }

    private void increment(Tag tag) {
        tag.setCount(tag.getCount() + 1); 
        Thread.sleep(20000);
        tagRepository.save(tag);
    }

    private void decrement(Tag tag) {
        tag.setCount(tag.getCount() - 1); 
        tagRepository.save(tag);
    }
}

보시다시피 동시성 시나리오를 테스트 할 수 있으려면 .save () 전에 증분에 20 초의 수면을 취하십시오.

초기 태그 카운터 = 10;

데이터베이스를 확인할 때 태그의 값은 이제 11과 같습니다. 현실에서 (적어도 달성하고자하는 것) 10 일 때

이 행동이 정상입니까? 또는 @ Transactional 주석이 작동하지 않습니다?

해결법

  1. ==============================

    1.가장 간단한 해결책은 동시성을 데이터베이스에 위임하고 현재 수정 된 행에 대한 데이터베이스 격리 수준 잠금에만 의존하는 것입니다.

    가장 간단한 해결책은 동시성을 데이터베이스에 위임하고 현재 수정 된 행에 대한 데이터베이스 격리 수준 잠금에만 의존하는 것입니다.

    증분은 다음과 같이 간단합니다.

    UPDATE Tag t set t.count = t.count + 1 WHERE t.id = :id;
    

    감소 쿼리는 다음과 같습니다.

    UPDATE Tag t set t.count = t.count - 1 WHERE t.id = :id;
    

    UPDATE 쿼리는 수정 된 행을 잠 그어 현재 트랜잭션이 커밋되기 전에 다른 트랜잭션이 동일한 행을 수정하지 못하게합니다 (READ_UNCOMMITTED를 사용하지 않는 한).

  2. ==============================

    2.예를 들어 낙관적 잠금을 사용하십시오. 이것은 귀하의 문제를 해결하는 가장 쉬운 해결책입니다. 자세한 내용은 -> https://docs.jboss.org/hibernate/orm/4.0/devguide/en-US/html/ch05.html을 참조하십시오.

    예를 들어 낙관적 잠금을 사용하십시오. 이것은 귀하의 문제를 해결하는 가장 쉬운 해결책입니다. 자세한 내용은 -> https://docs.jboss.org/hibernate/orm/4.0/devguide/en-US/html/ch05.html을 참조하십시오.

  3. ==============================

    3.추가 할 수있는 또 다른 궁극적 인 솔루션 :

    추가 할 수있는 또 다른 궁극적 인 솔루션 :

    더:

  4. from https://stackoverflow.com/questions/30143594/spring-jpa-and-hibernate-how-to-increment-a-counter-without-concurrency-issu by cc-by-sa and MIT license