简体   繁体   English

SpringBoot + Hibernate JPA Lazy fetching 模式仍然查询实体中的列表

[英]SpringBoot + Hibernate JPA Lazy fetching mode still queries lists in an entity

I am doing a REST API using springboot and JPA.我正在使用 springboot 和 JPA 做一个 REST API。 I am trying to lazy fetching an entity in a One to Many relationship.我试图在一对多关系中懒惰地获取一个实体。 Teacher to courses.老师上课。 I can see the sql statements done by JPA as I have the debuging option on.我可以看到 JPA 完成的 sql 语句,因为我打开了调试选项。

In the controller, when calling a path all works great, but I can see that JPA is executing two queries.在控制器中,调用路径时一切正常,但我可以看到 JPA 正在执行两个查询。 One for the teacher and another one for its courses.一份给老师,另一份给课程。 As I know, the lazy loading does not query until the data is required and I am not requiring it.据我所知,直到需要数据并且我不需要它时,延迟加载才会查询。

I have checked and conirmed that in the controller, when I retrieve the teacher data JPA does not query for the courses, but AFTER the return statement of the controller, somewhere, the courses are required and it loads everything when I call the teacher info from postman with a GET call.我已经检查并确认在控制器中,当我检索教师数据时 JPA 不会查询课程,但是在控制器的返回语句之后,某处需要课程并且当我从带有 GET 调用的邮递员。

It seems as if the LAZY loading is working correctly, but after the controller JPA loads the course list.似乎 LAZY 加载工作正常,但是在控制器 JPA 加载课程列表之后。 If I do the EAGER fetching everything is loaded before the return statemnt.如果我执行 EAGER 获取所有内容,则在返回语句之前加载。

I am not writing any code as I guess the question is more theorical than practical.我没有写任何代码,因为我猜这个问题比实际更理论。

Does anyone know how this works?有谁知道这是如何工作的?

Thank you so much!!!!非常感谢!!!!

EDIT:编辑:

Teacher table教师桌

@Entity
@Table(name="profesores")
public class Profesor implements Serializable{

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

    @Column(name="nombre")
    private String nombre;

    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    @JoinColumn(name = "profesor_id", referencedColumnName = "id")
    private List<Curso> cursos = new ArrayList<>();

}

Course Table课程表

@Entity
@Table(name = "curso")
public class Curso implements Serializable {

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

    private String nombre;

    @Column(name="profesor_id")
    private Long profesorId;
}

Controller控制器

    @GetMapping("/profesor/{id}")
    public ResponseEntity<?> getProfesor(@PathVariable(value = "id") Long id){
        Profesor p = profesorService.findById(id);
        if(p!=null) {
            ResponseEntity<?> re = new ResponseEntity<>(p, HttpStatus.OK);
            //Just one query executed. I don't know the courses yet
            return re;
        }
        else {
            return new ResponseEntity<Void>(HttpStatus.NOT_FOUND);
        }
    }

After the return re;返回后重新; statement, somewhere, the courses are retrieved and JPA queries for them.声明,在某处,检索课程并为它们查询 JPA。 I don't know what does the controller call, as I do directly from PostMan.我不知道控制器调用什么,就像我直接从 PostMan 做的那样。

After returned Entity Profesor is serialized for response when serializer try to access courses to serialized for response then JPA load courses also.在返回的 Entity Profesor被序列化以进行响应后,当序列化程序尝试访问courses以进行序列化以进行响应时,JPA 也会加载courses To solve this issue, You can create a response class for response (without courses field)为了解决这个问题,您可以为响应创建一个响应类(没有courses字段)

public class ProfesorResponse {
    private Long id;
    private String number;
    ...constructor
}

then map your entity in response object and return it.然后将您的实体映射到响应对象中并返回它。

Profesor p = profesorService.findById(id);
ProfesorResponse response = new ProfesorResponse(p.getId(), p.getNumber());

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM