it-source

@RestController 메서드는 기본적으로 트랜잭션인 것 같습니다. 왜죠?

criticalcode 2023. 7. 10. 22:27
반응형

@RestController 메서드는 기본적으로 트랜잭션인 것 같습니다. 왜죠?

스프링 부트 1.3.1 사용

@RestController가 기본적으로 Transactionnal인 이유를 이해할 수 없습니다.서류에서 그렇게 말하는 것을 발견하지 못했습니다.

아래 컨트롤러에서 메서드 findOne()이 Transactionnal이라는 사실을 강조하는 예:

@RestController
@RequestMapping("/books")
public class BookController {

    @RequestMapping("/{id}")
    public Book findOne(@PathVariable Long id) {
        Book book = this.bookDao.findOneBookById(id);
        // following line
        // => triggers a select author0_.id as id1_0_0_ etc... // where author0_.id=?
        System.out.println(book.getAuthor().getFirstname()); 
        return book;
    }
}

System.out.println(book.get)이 있는 줄작성자().getFirstname(); 레이지를 제기해야 합니다.Initialization Failure(초기화 실패) 그러나 여기서는 성공적이며 Author(작성자)의 선택을 트리거합니다.그래서 findOne이라는 메소드는 transactionnal로 보입니다.이클립스 디버거를 사용하면 보완 선택을 트리거하는 것이 정말 이 라인이라는 것을 확신할 수 있습니다.그런데 왜 그 방법은 거래에 유용한 것일까요?

@Configuration
@ComponentScan(basePackageClasses = _Controller.class)
@Import(BusinessConfig.class)
public class WebConfig extends WebMvcConfigurerAdapter {
   // ... here the conf to setup Jackson Hibernate4Module
}

@Configuration
@EnableAutoConfiguration
@EnableTransactionManagement
@EntityScan(basePackageClasses = _Model.class)
@ComponentScan(basePackageClasses = { _Dao.class })
public class BusinessConfig {
}

@SpringBootApplication
public class BookstoreStartForWebEmbedded {

    public static void main(String[] args) {
        SpringApplication.run(BookstoreStartForWebEmbedded.class, args);
    }

}

libs : 
spring-boot-starter 1.3.1.RELEASE
spring-boot-starter-test : 1.3.1.RELEASE
spring-boot-starter-valisation : 1.3.1.RELEASE
spring-boot-starter-web : 1.3.1.RELEASE
spring-boot-starter-data-jpa : 1.3.1.RELEASE
postgresql: 9.4-1206-jdbc41
querydsl-jps:3.7.0
jackson-annotations:2.6.4
jackson-datatype-hibernate4:2.6.4

감 잡히는 게 없어요?

기능인 경우에는 전원을 끄고 싶습니다.

MirMasej 답변 외에도 한 가지 더 있습니다. 스프링 부트는 자동으로 다음 정보를 등록합니다.OpenEntityManagerInViewInterceptor다음 조건이 참일 때:

  • 웹 애플리케이션이 있습니다.
  • 당신은 JPA를 사용합니다.

두 조건 모두 당신의 경우에 해당합니다.이 인터셉트는 요청의 전체 기간 동안 엔터티 관리자를 열어 둡니다.클래스에서 자동 구성이 발생합니다.JpaBaseConfiguration.

이러한 동작을 원하지 않는 경우 application.properties 파일에 다음 속성을 추가할 수 있습니다.

spring.jpa.open-in-view=false

그러나 이 동작은 트랜잭션과 완전히 독립적이며 엔티티 관리자의 라이프사이클에만 관련됩니다.여전히 두 개의 개별 트랜잭션을 수행할 수 있으며 Lazy는 없습니다.초기화두 트랜잭션 모두 기본 엔터티 관리자 인스턴스가 동일한 경우에는 예외입니다.

@dunni의 대답은 정말 훌륭하고 효과가 있습니다.제 경우에는 @Controller에서 @Transactional processing read-only JPA operations가 있는 @Servlet의 메서드를 호출하여 두 배 빠른 속도로 처리하는 등 성능을 저하시켰습니다.그러나 @Controller에서 spring.jpa.open-in-view=false설정하면 @WebServlet에서만큼 빠르게 처리됩니다.

그러나 이러한 의미에서 다음을 하나로 수행할 수 있으며 @Transactional을 사용하여 @Controller에서 호출된 메서드에 동일한 주석을 달 수 있습니다. 예:

@GetMapping("/test")
@Transactional(propagation = Propagation.NEVER, readOnly = true)
public void test()

일대일 관계는 항상 열심히 가져옵니다.하기 메드이으로판단름서단판.book.getAuthor().getFirstname()입니다.book->책->책->책->책의 관계입니다. LazyInitializationException게으른 수집에 대해서만 발생합니다.

언급URL : https://stackoverflow.com/questions/34641670/restcontroller-methods-seem-to-be-transactional-by-default-why

반응형