@RestController 方法似乎默认是事务性的,为什么? [英] @RestController methods seem to be Transactional by default, Why?

查看:21
本文介绍了@RestController 方法似乎默认是事务性的,为什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用 Spring Boot 1.3.1

Using Spring boot 1.3.1

我不明白为什么@RestController 默认是事务性的.我在文档中没有发现任何这样的说法.

I don't understand why @RestController are Transactionnal by default. I haven't found anything saying so in the docs.

这个例子说明了下面控制器中的 findOne() 方法是 Transactionnal:

Example which pushes this fact that the method findOne() in the controller below is 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.getAuthor().getFirstname());应该引发 LazyInitiaizationFailure但是在这里它成功并触发了作者的选择.所以 findOne 方法似乎是事务性的.使用 Eclipse 调试器,我可以确定正是这一行触发了互补选择.但为什么这种方法是事务性的?

The line with the System.out.println(book.getAuthor().getFirstname()); should raise a LazyInitiaizationFailure BUT here it is successful and trigger the select of an an Author. So the method findOne seems to be transactionnal. With the eclipse debugger I can be sure that it is really this line that triggers the complementary select. But Why is that method 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

有什么想法吗?

如果它是一个功能,我想关闭它...

If it is a feature, i would like to switch it off...

推荐答案

除了 MirMasej 的回答之外,还有一件事:Spring Boot 会在满足以下条件时自动注册一个 OpenEntityManagerInViewInterceptor:

In addition to MirMasej answers, there is one more thing: Spring Boot will automatically register an OpenEntityManagerInViewInterceptor when the following conditions are true:

  • 您有一个网络应用程序
  • 您使用 JPA

在您的情况下,这两个条件都成立.这个拦截器在请求的整个持续时间内保持实体管理器打开.自动配置发生在 JpaBaseConfiguration 类中.

Both conditions are true in your case. This interceptor holds the entity manager open for the whole duration of a request. The auto configuration occurs in the class JpaBaseConfiguration.

如果您不想要这种行为,您可以将以下属性添加到您的 application.properties 文件中:

If you don't want that behaviour, you can add the following property to your application.properties file:

spring.jpa.open-in-view=false

顺便说一句.这种行为完全独立于事务,只与实体管理器的生命周期有关.如果两个事务具有相同的底层实体管理器实例,您仍然可以有两个单独的事务并且没有 LazyInitializationException.

Btw. this behaviour is completely independent of transactions, it's only related to the lifecycle of the entity manager. You can still have two separate transactions and no LazyInitializationException, if both transactions have the same underlying entity manager instance.

这篇关于@RestController 方法似乎默认是事务性的,为什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆