Spring 使用 Spring 数据 JPA 启动

Spring Boot with Spring Data JPA

环境:

Spring 引导 1.4.0.RELEASE

代码:

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

Spring 数据 JPA Dao 层:

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);     
    }
}

Spring 控制器:

@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>

Issue/Queries :

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

所以我的问题是:

1)我的服务层没有标记 @Transactional 也没有使用任何 AOP 配置?
那么creating/managing这里的交易是谁?

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

2)当使用 Spring 引导时,以下所有内容都会根据 classpath 自动为您配置:

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;
    }

1) Spring 默认情况下,数据会围绕对存储库方法的调用创建事务(参见 http://docs.spring.io/spring-data/jpa/docs/current/reference/html/#transactions)。所以,如果你的服务层没有标记@Transactional,默认情况下每个存储库调用都会有自己的事务(这在很多情况下是不可取的)。

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