programing

@Transactional 주석은 어디에 속합니까?

sourcetip 2022. 7. 15. 23:26
반응형

@Transactional 주석은 어디에 속합니까?

를 배치해야 합니까?@Transactional DAO클래스 및/또는 그 메서드 또는 DAO 객체를 사용하여 호출하는 서비스 클래스에 주석을 다는 것이 더 나을까요?아니면 두 레이어 모두에 주석을 다는 것이 말이 됩니까?

거래는 서비스 계층에 속한다고 생각합니다.작업 단위와 사용 사례에 대해 잘 알고 있습니다.단일 트랜잭션에서 함께 작업해야 하는 서비스에 여러 DAO를 주입하는 것이 정답입니다.

일반적으로 트랜잭션은 일반적으로 서비스 수준에서 시작된다는 다른 설명에 동의합니다(물론 필요한 세분성에 따라 다름).

그 에 저는 '아까', '아까', '아까', '아까'도 붙이기 시작했어요.@Transactional(propagation = Propagation.MANDATORY)'' ('Da' : 'Da' : 'Da' : 'Da' : 'Da' : 'Da' : 'Da' : 'Da' : 'Da' : 'Da' : 'Da' : 'Da' 입니다.DAO에 필수 전파가 주석을 달면 메서드가 호출될 때 활성 트랜잭션이 없음을 나타내는 예외가 발생합니다.

, 이 콩 포스트 프로세서하고, 「빈 프로세서」가 는 불합격하는 테스트도 .@Transactional서비스 계층에 속하지 않는 빈에 필수 이외의 전파가 포함된 주석.이렇게 하면 잘못된 계층에서 트랜잭션을 시작하지 않도록 할 수 있습니다.

트랜잭션 주석은 분리할 수 없는 모든 작업 주위에 배치해야 합니다.

예를 들어, 콜은 「패스워드 변경」이라고 합니다.그것은 2개의 조작으로 구성되어 있습니다.

  1. 비밀번호를 변경합니다.
  2. 변경을 감사한다.
  3. 암호가 변경되었음을 클라이언트에 전자 메일로 보냅니다.

위의 경우 감사에 실패하면 패스워드 변경도 실패합니까?이 경우 트랜잭션은 약1과 2(서비스 레이어)가 됩니다.이메일이 실패했을 경우(아마도 실패하지 않도록 하기 위해 어떤 종류의 장애 안전장치가 있어야 합니다) 변경 비밀번호와 감사를 롤백해야 합니까?

은 어디에 때 꼭 이에요.@Transactional.

기존 Spring 아키텍처의 정답은 다른 사람들이 이미 설명한 이유로 트랜잭션 시멘틱스를 서비스 클래스에 배치하는 것입니다.

봄철에는 도메인 주도 설계(DDD)가 대두되고 있습니다.의 루는 유행을 잘 보여준다.이 아이디어는 도메인 객체 POJO를 일반적인 스프링 아키텍처(일반적으로 빈혈)보다 훨씬 풍부하게 만들고 특히 트랜잭션과 지속성 시멘틱스를 도메인 객체 자체에 추가하는 것입니다.간단한 CRUD 작업만 필요한 경우 웹 컨트롤러는 도메인 객체 POJO(이 컨텍스트에서는 엔티티로 기능)에서 직접 작동하며 서비스 계층은 없습니다.도메인 객체 간에 조정이 필요한 경우 서비스 빈 핸들을 사용하여@Transaction에 대한 도메인 오브젝트에 대한 트랜잭션 전파로 설정할 .REQUIRED따라서 도메인 객체는 서비스 빈에서 시작된 트랜잭션과 같은 기존 트랜잭션을 사용할 수 있습니다.

으로 이 및 Aspect를 합니다.<context:spring-configured />Roo는 AspectJ 유형의 정의를 사용하여 엔티티의 의미론(트랜잭션 및 지속성)을 도메인 오브젝트 내용(기본적으로 필드 및 비즈니스 방법)에서 분리합니다.

보통 서비스 레이어레벨에 주석을 달지만 실제로는 요건에 따라 달라집니다.

서비스 계층에 주석을 달면 DAO 수준에서 주석을 달 때보다 트랜잭션이 길어집니다.동시 트랜잭션은 에서 서로의 변경 사항을 볼 수 없으므로 문제를 발견할 수 있는 트랜잭션 분리 수준에 따라 달라집니다.반복 가능한 읽기

DAO에 주석을 달면 트랜잭션은 가능한 한 짧게 유지되지만 서비스 계층에서 제공하는 기능은 단일(롤백 가능) 트랜잭션에서 수행되지 않는다는 단점이 있습니다.

전파 모드가 기본값으로 설정된 경우 두 레이어에 모두 주석을 다는 것은 의미가 없습니다.

를 배치합니다.@Transactional에서@Service층과 세트rollbackFor예외는 없습니다.readOnly트랜잭션을 더욱 최적화합니다.

디폴트@Transactional찾을 뿐이다RuntimeException(체크되지 않은 예외), 롤백을 다음으로 설정Exception.class(체크된 예외) 모든 예외에 대해 롤백됩니다.

@Transactional(readOnly = false, rollbackFor = Exception.class)

'체크된 것'를 참조해 주세요. 선택되지 않은 예외.

데이터베이스 수준 트랜잭션의 경우

나는 주로 사용했다.@Transactional디폴트(필수)를 사용하여 설정할 수 있습니다.

  1. 데이터를 가져오는 DAO의 메서드(선택 .. ) - 필요 없음@Transactional트랜잭션 가로채기 / 및 실행이 필요한 AOP 프록시 때문에 약간의 오버헤드가 발생할 수 있습니다.

  2. 삽입/업데이트를 수행하는 DAO의 메서드는@Transactional

이행에 관한 매우 좋은 블로그

응용 프로그램 수준의 경우 -
비즈니스 로직을 트랜잭션으로 사용하고 있습니다.예기치 않은 오류가 발생했을 때 롤백할 수 있으면 좋겠습니다.

@Transactional(rollbackFor={MyApplicationException.class})
public void myMethod(){

    try {    
        //service logic here     
    } catch(Throwable e) {

        log.error(e)
        throw new MyApplicationException(..);
    }
}

또는 DAO에서 전파 "필수"를 사용하여 항상 서비스 계층에서 DAO 메서드를 호출(전파)하려면 서비스 계층과 DAO 계층 모두에 주석을 다는 것이 타당하지 않습니까?이로 인해 UI 계층(또는 컨트롤러)에서 DAO 메서드를 호출하는 데 몇 가지 제한이 있습니다.또한, 특히 유닛에서 DAO 계층을 테스트할 때 DAO에 주석을 달면 트랜잭션 기능 테스트도 완료됩니다.

또한 Spring에서는 인터페이스를 사용하지 않고 구체적인 클래스에서만 주석을 사용할 것을 권장합니다.

http://static.springsource.org/spring/docs/2.0.x/reference/transaction.html

@Transactional주석은 분리할 수 없는 모든 작업 주위에 배치해야 합니다.사용.@Transactional트랜잭션 전파가 자동으로 처리됩니다.이 경우 현재 메서드로 다른 메서드가 호출되면 해당 메서드는 진행 중인 트랜잭션에 참여할 수 있습니다.

예를 들어 보겠습니다.

두 가지 모델이 있습니다. Country그리고.City. 릴레이셔널 맵핑Country그리고.City모델은 하나와 같다Country여러 도시를 가질 수 있기 때문에 매핑은 다음과 같습니다.

@OneToMany(fetch = FetchType.LAZY, mappedBy="country")
private Set<City> cities;

여기서 국가는 여러 도시에 매핑되고 여러 도시를 가져옵니다.Lazily자, 이제 다음 역할로 넘어가겠습니다.@Transactinal데이터베이스에서 Country 객체를 검색할 때 Country 객체의 모든 데이터를 가져오지만 도시를 가져오기 때문에 도시 집합은 가져오지 않습니다.LAZILY.

//Without @Transactional
public Country getCountry(){
   Country country = countryRepository.getCountry();
   //After getting Country Object connection between countryRepository and database is Closed 
}

국가 개체에서 도시 집합에 액세스하려면 해당 집합에서 null 값을 얻습니다. 왜냐하면 이 집합만 만든 집합 개체는 우리가 사용하는 집합의 값을 얻기 위해 해당 데이터로 초기화되지 않기 때문입니다.@Transactional예.,

//with @Transactional
@Transactional
public Country getCountry(){
   Country country = countryRepository.getCountry();
   //below when we initialize cities using object country so that directly communicate with database and retrieve all cities from database this happens just because of @Transactinal
   Object object = country.getCities().size();   
}

그러니까 기본적으로는@Transactional서비스는 엔드포인트와의 접속을 종료하지 않고 단일 트랜잭션으로 여러 콜을 발신할 수 있습니다.

일반적으로 서비스 계층에 트랜잭션을 배치해야 합니다.

그러나 앞에서 설명한 바와 같이 운영의 원자성은 주석이 필요한 위치를 알려 줍니다.따라서 Hibernate와 같은 프레임워크를 사용하는 경우 오브젝트에 대한 단일 "save/update/delete/...modification" 조작이 여러 테이블에서 여러 행을 수정할 수 있습니다(오브젝트 그래프를 통한 계단식 때문에).물론 이 특정 DAO 방식에도 트랜잭션 관리가 필요합니다.

서비스 계층에 있는 것이 좋습니다!어제 우연히 본 기사 중 하나에 이런 내용이 명료하게 설명되어 있어요!확인하실 수 있는 링크입니다!

서비스 레이어를 추가하는 것이 최적@Transactional주석에는 상세 수준의 사용 사례 동작이 포함되어 있습니다.

DAO에 추가하여 서비스에서2개의 DAO 클래스를 호출한다고 가정합니다.이 경우, 1개는 실패, 1개는 기타 성공입니다.@Transactional한쪽 DB가 커밋되고 다른 한쪽 DB가 롤백됩니다.

따라서 이 주석을 현명하게 사용하여 서비스 계층에서만 사용할 것을 권장합니다.

Github 프로젝트 - java-algos

먼저 트랜잭션을 사용해야 할 위치를 정의해 봅시다.

내 생각에 정답은 - 일련의 행동들이 하나의 원자 작용으로 함께 끝나거나, 행동들 중 하나가 실패하더라도 변화가 일어나지 않도록 확실히 해야 할 때라고 생각한다.

서비스에 비즈니스 로직을 도입하는 것은 잘 알려진 관행입니다.따라서 서비스 방법에는 단일 논리 작업 단위로 수행해야 하는 여러 가지 작업이 포함될 수 있습니다.이 경우 해당 메서드는 트랜잭션으로 표시되어야 합니다.물론 모든 방법이 이러한 제한을 필요로 하는 것은 아니기 때문에 서비스 전체를 트랜잭션으로 표시할 필요는 없습니다.

게다가 @Transactional은 분명히 메서드의 퍼포먼스를 저하시킬 수 있습니다.전체 그림을 보려면 트랜잭션 분리 수준을 알아야 합니다.이 점을 알면 @Transactional을 사용하지 않아도 됩니다.

enter image description here

@Transactional는 비즈니스 로직이 포함되어 있기 때문에 서비스 계층에서 사용해야 합니다.DAO 계층에는 일반적으로 데이터베이스 CRUD 작업만 있습니다.

// the service class that we want to make transactional
@Transactional
public class DefaultFooService implements FooService {

    Foo getFoo(String fooName);

    Foo getFoo(String fooName, String barName);

    void insertFoo(Foo foo);

    void updateFoo(Foo foo);
}

봄철 문서 : https://docs.spring.io/spring/docs/4.2.x/spring-framework-reference/html/transaction.html

@Transactional은 DAO와 서비스 계층 사이의 별도의 중간 계층에 보관하는 것이 좋습니다.롤백은 매우 중요하므로 모든 DB 조작을 중간 계층에 배치하고 서비스 계층에 비즈니스 로직을 작성할 수 있습니다.중간 계층은 DAO 계층과 상호 작용합니다.

이는 ObjectOptimisticLockingFailure와 같은 많은 상황에서 도움이 됩니다.예외 - 이 예외는 트랜잭션이 종료된 후에만 발생합니다.따라서 중간 계층에서는 잡을 수 없지만 서비스 계층에서는 잡을 수 있습니다.서비스 계층에 @Transactional이 있는 경우 이 작업은 불가능합니다.컨트롤러에서 잡을 수 있지만 컨트롤러는 가능한 한 깨끗해야 합니다.

저장, 삭제 및 업데이트 옵션을 모두 완료한 후 별도의 스레드로 메일 또는 SMS를 보내는 경우 중간 계층에서 트랜잭션이 완료된 후 이 작업을 수행할 수 있습니다.다시 @Transactional in Service Layer를 언급하면 트랜잭션이 실패해도 메일이 발송됩니다.

따라서 중간 @Transaction 레이어를 갖는 것은 코드를 더 낫고 다루기 쉽게 만드는 데 도움이 됩니다.그렇지 않으면 DAO 계층에서 를 사용하는 경우 모든 작업을 롤백하지 못할 수 있습니다.서비스 계층에서 를 사용하는 경우 경우에 따라서는 AOP(Aspect Oriented Programming)를 사용해야 할 수 있습니다.

이상적으로는 서비스 계층(매니저)은 비즈니스 로직을 나타내므로 다음과 같이 주석을 달아야 합니다.@Transactional서비스 계층이 다른 DAO를 호출하여 DB 작업을 수행할 수 있습니다.서비스 방법에 DAO 작업이 N개 있는 경우를 가정해 보겠습니다.첫 번째 DAO 작업이 실패한 경우 다른 작업이 계속 통과되어 일관성 없는 DB 상태가 될 수 있습니다.서비스 계층에 주석을 달면 이러한 상황을 피할 수 있습니다.

사용하는 것을 선호합니다.@Transactional메서드 수준의 서비스 계층에 있습니다.

@Transactional는 컨트롤러 레이어를 사용하여 호출되는 서비스 레이어에서 사용합니다(@Controller및 DAO 레이어에 대한 서비스 레이어 콜(@Repository), 즉 데이터베이스 관련 작업.

언급URL : https://stackoverflow.com/questions/1079114/where-does-the-transactional-annotation-belong

반응형