简体   繁体   English

将 @Transactional 方法结果从 Service 传递到 Controller 层 Spring Boot

[英]Pass @Transactional method result from Service to Controller Layer Spring Boot

I'm trying to lazily fetch a ManyToMany relationship (Courses - Students) from the Service and pass the result to the Controller. While i'm in the Service, no LazyInitializationException is thrown, thanks to the @Transactional annotation.我试图从服务中懒惰地获取 ManyToMany 关系(课程 - 学生)并将结果传递给 Controller。当我在服务中时,没有抛出LazyInitializationException ,这要归功于@Transactional注释。 However, while i'm in the Controller the LazyInitializationException is thrown (while getting Course.students ), because the Session was closed.但是,当我在 Controller 时,会抛出LazyInitializationException (在获取Course.students ),因为 Session 已关闭。 How can i resolve this issue, without eagerly fetch the Collection?如果不急切地获取集合,我该如何解决这个问题?

That's my code:那是我的代码:

Couse Model辅导员 Model

@Entity
@Getter
@Setter
public class Course {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column
    private String name;

    @ManyToMany
    @JoinTable(name = "COURSES_STUDENTS",
            joinColumns = {@JoinColumn(name = "COURSE_ID")},
            inverseJoinColumns = {@JoinColumn(name = "STUDENT_ID")})
    private Set<Student> students;

    public Course() {
        this.students = new HashSet<>();
    }

Student Model学生 Model

@Entity
@Getter
@Setter
public class Student {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column
    private String name;

    @ManyToMany(mappedBy = "students")
    private Set<Course> courses;

    public Student() {
        this.courses = new HashSet<>();
    }
}

Course Repository课程资料库

@Repository
public interface CourseRepository extends JpaRepository<Course, Long> {
}

Course Service课程服务

@Service
public class CourseService {

    private final CourseRepository courseRepository;

    @Autowired
    public CourseService(CourseRepository courseRepository) {
        this.courseRepository = courseRepository;
    }

    @Transactional
    public ResponseEntity<List<Course>> findAll() {
        return this.courseRepository.findAll().isEmpty() ? ResponseEntity.noContent().build()
                : ResponseEntity.ok(this.courseRepository.findAll());
    }
}

Course Controller课程 Controller

@Controller
@RequestMapping("/")
public class CourseController {

    private final CourseService courseService;

    @Autowired
    public CourseController(CourseService courseService) {
        this.courseService = courseService;
    }

    @GetMapping
    public ResponseEntity<List<Course>> index() {
        return this.courseService.findAll();
    }
}

application.properties应用程序.properties

spring.datasource.url=jdbc:h2:~/database;AUTO_SERVER=TRUE
spring.datasource.username=sa
spring.datasource.password=
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.H2Dialect
spring.jpa.hibernate.ddl-auto=create-drop
spring.h2.console.enabled=true
spring.h2.console.path=/h2
spring.jpa.open-in-view=false
spring.mvc.hiddenmethod.filter.enabled=true
logging.level.org.springframework.web=DEBUG
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.format_sql=true

Thanks in advance.提前致谢。

So there are 2 approaches:所以有两种方法:

  1. What is this spring.jpa.open-in-view=true property in Spring Boot? Spring Boot 中的这个 spring.jpa.open-in-view=true 属性是什么?

This is bad for performance and must be avoided at all costs.这对性能不利,必须不惜一切代价避免。

  1. use jpql queries to join fetch lazy collections needed in DAO layer so they are available in the controller when you need them to be.使用 jpql 查询加入 DAO 层所需的 fetch lazy collections,以便在需要时可以在 controller 中使用它们。

All in all, do not use transactional to keep the db session open to fetch lazy collections. Just join fetch lazy collections in db / dao layer to have the data needed for each endpoint available.总而言之,不要使用事务来保持 db session 打开以获取惰性 collections。只需在 db/dao 层中加入 fetch lazy collections 即可获得每个端点所需的数据。

If you want have a look here for how to use join fetch How to fetch FetchType.LAZY associations with JPA and Hibernate in a Spring Controller如果你想看看这里如何使用 join fetch How to fetch FetchType.LAZY associations with JPA and Hibernate in a Spring Controller

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何从spring boot服务层调用java类方法 - How to call a java class method from spring boot service layer 服务层和spring事务中的验证 - Validation in service layer and spring transactional 使用Spring从控制器层调用存储库和服务 - Call repository and service from controller layer with Spring 如何通过自动装配服务在 spring-boot 上测试控制器层? - How to test controller layer on spring-boot by autowiring service? Spring Boot结构:是否在控制器或服务层中验证图像大小? - Spring Boot Structure: Validation of image size in controller or service layer? 从Spring Boot测试调用的@Caching方法[注有@Transactional]无法正常工作 - @Caching method called from spring boot test [annotated with @Transactional] not working JPA 和 Spring 的手动事务服务和 DAO 层 - Manual Transactional Service and DAO layer for JPA with Spring 服务层在春季总是必须是事务性的吗? - Do service layer always must be transactional in spring? Spring Boot-从非事务性原因更新中校准事务性方法 - Spring Boot - caling transactional method from non-transactional cause update 弹簧靴。 @Transactional 方法调用 @Transactional(readonly=true) 方法 - Spring Boot. @Transactional method calling a @Transactional(readonly=true) method
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM