【问题标题】:Spring Boot with Spring Data JPASpring Boot 与 Spring Data JPA
【发布时间】:2017-05-09 18:15:06
【问题描述】:

环境:

Spring boot 1.4.0.RELEASE

代码:

我有一个简单的 Spring REST 网络服务设置如下:

Spring Data JPA 道层:

public interface UserDao extends JpaRepository<User,Long>{

}

Spring 服务层:

@Service
public class UserServiceImpl implements UserService{

    @Autowired
    private UserDao userDao;

    @Override
    public void saveUser(User user){        
        userDao.save(user);     
    }
}

弹簧控制器:

@RestController
public class UserController {

    @Autowired
    private UserService userService; 


    @RequestMapping(value = "/user", method = RequestMethod.POST)
    @ResponseStatus(HttpStatus.CREATED)
    public void saveUser(@RequestBody User user){

        this.userService.saveUser(user);
    }
}

pom.xml 提取:

<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.4.3.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-tomcat</artifactId>
        <scope>provided</scope>
    </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>


        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

问题/查询:

当我调用 UserController.saveUser 时,通过上述设置,一切正常,数据被保存到数据库。我在内存中使用 H2 db。

所以我的问题是:

1)我的服务层没有标记@Transactional,我也没有使用任何 AOP 配置?
那么谁在这里创建/管理事务呢?

调试应用程序后,Spring Data JPA Repository 类似乎具有AOPProxy CGLIB 语义? 这意味着这个类在事务内部运行。 如果我们不将 Spring Service 设为 @Transactional,这是默认行为吗?

2)当使用 Spring Boot 时,以下所有内容都会根据类路径自动为您配置:

1)DataSource

2)Transaction Manager

如果是这种情况,我看过一些教程,其中持久性配置包含以下内容: 为什么这需要呢? Spring boot 不应该自动为您配置以下所有内容吗?

   @Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
        final LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
        em.setDataSource(dataSource());
        em.setPackagesToScan(new String[] { "com.atul.domain" });
        final HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
        em.setJpaVendorAdapter(vendorAdapter);
        em.setJpaProperties(additionalProperties());
        return em;
    }

    @Bean
    public DataSource dataSource() {
        final DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName(env.getProperty("jdbc.driverClassName"));
        dataSource.setUrl(env.getProperty("jdbc.url"));
        dataSource.setUsername(env.getProperty("jdbc.username"));
        dataSource.setPassword(env.getProperty("jdbc.password"));
        return dataSource;
    }

    @Bean
    public JpaTransactionManager transactionManager() {
        final JpaTransactionManager transactionManager = new JpaTransactionManager();
        transactionManager.setEntityManagerFactory(entityManagerFactory().getObject());
        return transactionManager;
    }

【问题讨论】:

    标签: spring-boot spring-data-jpa spring-transactions


    【解决方案1】:

    1) 默认情况下,Spring Data 会围绕对存储库方法的调用创建事务(请参阅http://docs.spring.io/spring-data/jpa/docs/current/reference/html/#transactions)。因此,如果您的服务层未标记@Transactional,则默认情况下,每个存储库调用都会有自己的事务(这在许多情况下是不可取的)。

    2) 仅当默认值不能满足您的需要时,才需要此额外的配置代码。在您的代码示例中,我没有看到您无法使用 Spring Boot 功能配置的任何内容,因此实际上不需要这些额外的代码。

    【讨论】:

    • 感谢您的回答。有用 。我还有一个查询,我已将我的服务层设置为 Transactional,它将服务层包裹在事务代理周围。但道层也在代理周围。什么时候删除 Dao 类的代理?只有一个事务运行,应该从服务层启动
    • 如果你的意思是存储库与 DAO 层的接口,它总是有一个代理,因为这就是 Spring 即时创建接口实现的方式。
    • Spring Data 存储库默认事务类型为 REQUIRED,这意味着它们将在服务层中已经打开的事务中运行,如果没有找到,它们将打开一个新事务.
    猜你喜欢
    • 2017-09-22
    • 2017-11-29
    • 2014-10-21
    • 2021-01-18
    • 2021-02-09
    • 2014-07-21
    • 1970-01-01
    • 2020-07-04
    • 2020-08-18
    相关资源
    最近更新 更多