Spring Boot - 事务管理不起作用

Posted

技术标签:

【中文标题】Spring Boot - 事务管理不起作用【英文标题】:Spring Boot - Transaction Management is not working 【发布时间】:2016-11-07 14:13:07 【问题描述】:

期望 - 延迟加载不应该超出事务范围(例如在休息控制器中),但它可以工作。

问题出在@Transactional中的,我的配置中的spring应用程序没有使用它。我该如何解决?

...Rest 控制器没有任何事务方法,它仅使用指定的服务来加载实体。未在服务中加载的依赖集合应为空。

应用程序启动类:

@SpringBootApplication
@EntityScan("com.vl.pmanager.domain.model")
@EnableJpaRepositories("com.vl.pmanager.domain.repository")
@EnableTransactionManagement
public class ProjectManagerApplication 

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

我知道 Spring Boot 会自动配置存储库并扫描实体,但我希望添加...

@EntityScan("com.vl.pmanager.domain.model")
@EnableJpaRepositories("com.vl.pmanager.domain.repository")

我也尝试将 @Transactional 添加到存储库接口,但它对我不起作用

package com.vl.pmanager.domain.repository;

import com.vl.pmanager.domain.model.Tag;
import org.springframework.data.repository.PagingAndSortingRepository;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

@Repository
@Transactional
public interface TagRepository extends PagingAndSortingRepository<Tag, Long> 

所以我从存储库中删除了 @Transactional,创建了其他服务层来使用注释对其进行管理并将服务注入控制器:

package com.vl.pmanager.domain.db.service.api;

import com.vl.pmanager.domain.model.Tag;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;

public interface ITagManager 
    Page<Tag> findAll(Pageable pageable);
    Tag findOne(Long id);

// ======================== TAG SERVICE WRAPPED WITH TRANSACTION ==========================
package com.vl.pmanager.domain.db.service;

import com.vl.pmanager.domain.db.service.api.ITagManager;
import com.vl.pmanager.domain.model.Tag;
import com.vl.pmanager.domain.repository.TagRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@Transactional
public class TagManager implements ITagManager 
    @Autowired
    private TagRepository tagRepository;

    @Override
    public Page<Tag> findAll(Pageable pageable) 
        return tagRepository.findAll(pageable);
    

    @Override
    public Tag findOne(Long id) 
        return tagRepository.findOne(id);
    

// ====================== REST CONTROLLER ============================
package com.vl.pmanager.web;

import com.vl.pmanager.domain.db.service.api.ITagManager;
import com.vl.pmanager.domain.model.Tag;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.web.PageableDefault;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping(value = "/tags")
public class TagController 
    private static final int DEFAULT_PAGE_SIZE = 50;

    @Autowired
    private ITagManager tagManager;

    @RequestMapping(method = RequestMethod.GET, consumes = MediaType.ALL_VALUE)
    public Page<Tag> getTags(@PageableDefault(size = DEFAULT_PAGE_SIZE) Pageable pageable) 
        return tagManager.findAll(pageable);
    

    @RequestMapping(value = "/id", method = RequestMethod.GET, consumes = MediaType.ALL_VALUE)
    public Tag getTag(@PathVariable("id") Long id) 
        return tagManager.findOne(id);
    

标签实体有一个字段 Set projectInfo 映射到具有 @ManyToMany 关系的其他实体 FetchType fetch() default LAZY; 所以返回结果不能包含依赖实体,但它是。

我还监控了数据库日志:

// make request - load data using db service to controller level
Hibernate: select count(tag0_.id) as col_0_0_ from tag tag0_
Hibernate: select tag0_.id as id1_6_, tag0_.description as descript2_6_, tag0_.name as name3_6_ from tag tag0_ limit ?
// converting data to JSON automatically
Hibernate: select projectinf0_.tags as tags1_6_0_, projectinf0_.project_info as project_2_7_0_, projectinf1_.id as id1_4_1_, projectinf1_.description as descript2_4_1_, projectinf1_.name as name3_4_1_ from tag_project_info projectinf0_ inner join project_info projectinf1_ on projectinf0_.project_info=projectinf1_.id where projectinf0_.tags=?
Hibernate: select projectinf0_.tags as tags1_6_0_, projectinf0_.project_info as project_2_7_0_, projectinf1_.id as id1_4_1_, projectinf1_.description as descript2_4_1_, projectinf1_.name as name3_4_1_ from tag_project_info projectinf0_ inner join project_info projectinf1_ on projectinf0_.project_info=projectinf1_.id where projectinf0_.tags=?
Hibernate: select projectinf0_.tags as tags1_6_0_, projectinf0_.project_info as project_2_7_0_, projectinf1_.id as id1_4_1_, projectinf1_.description as descript2_4_1_, projectinf1_.name as name3_4_1_ from tag_project_info projectinf0_ inner join project_info projectinf1_ on projectinf0_.project_info=projectinf1_.id where projectinf0_.tags=?
Hibernate: select projectinf0_.tags as tags1_6_0_, projectinf0_.project_info as project_2_7_0_, projectinf1_.id as id1_4_1_, projectinf1_.description as descript2_4_1_, projectinf1_.name as name3_4_1_ from tag_project_info projectinf0_ inner join project_info projectinf1_ on projectinf0_.project_info=projectinf1_.id where projectinf0_.tags=?
Hibernate: select projectinf0_.tags as tags1_6_0_, projectinf0_.project_info as project_2_7_0_, projectinf1_.id as id1_4_1_, projectinf1_.description as descript2_4_1_, projectinf1_.name as name3_4_1_ from tag_project_info projectinf0_ inner join project_info projectinf1_ on projectinf0_.project_info=projectinf1_.id where projectinf0_.tags=?

而且我知道只有 5 个额外的请求,因为我只有 5 个依赖于 tag project_info。 因此,作为结论,我的事务级别不管理事务。 ...我检查了注入 bean 的数据源和 transactionManager - 创建了一个。 没有错误,启动时间或运行时间没有警告......

【问题讨论】:

您的问题太长,不清楚。你正在执行什么代码,你期望它做什么,它会做什么? 期望 - 延迟加载不应超出事务范围。但它适用于控制器级别。似乎@Transactional 注释在我的配置中不起作用.... 不是交易问题。在文档中查找属性 spring.jpa.open-in-view ,如果您不想要它,请将其设置为 false。 请注意,集合不会像您想象的那样为空。它不会被初始化,尝试访问它的元素会抛出异常 是的:)。感谢您的帮助。它现在对我有用,因为它应该可以工作。 【参考方案1】:

@JBNizet

这不是交易问题。在文档中查找属性 spring.jpa.open-in-view ,如果您不想要它,请将其设置为 false

我已添加此答案以将问题标记为已关闭。如果我关闭 jpa open in view,交易就会像我预期的那样工作。

版主请将作者答案更改为@JBNizet

【讨论】:

以上是关于Spring Boot - 事务管理不起作用的主要内容,如果未能解决你的问题,请参考以下文章

事务注释在 Spring Boot 2.1.3 中不起作用

Spring Boot Security - Thymeleaf sec:授权不起作用

指定端口时,Spring Boot Actuator 端点的单元测试不起作用

Spring Boot WebFlux NettyServerCustomizer 不起作用

spring-boot-devtools 自动重启不起作用

Spring Boot 安全配置不起作用