1. 程式人生 > >記: Spring Data Jpa @OneToMany 級聯查詢被動觸發的問題

記: Spring Data Jpa @OneToMany 級聯查詢被動觸發的問題

I have encountered a bug in using Spring Data Jpa. Specifically,when @OneToMany was used to maintain a one-to-many relationship, lazy loading was effective.However,it may passively trigger the cascading query without using the cascading property.

My development environment :

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

My User.class is as follows

My Paper.class is as follows

My PaperService.class is as follows

My UserController.class is as follows

I would like to use Jpa's @OneToMany default lazy loading mechanism when pagination queries was produced. Additionally, I don't need the collection of papers fields associated with the user.Nevertheless,I find that the papers attribute in the user is still populated with data in the returned results.

Therefore, I conducted the following debugging:**

send a request

Observe the execution of the code:

As you can see, although the lazy loading of Jpa was normal, I found the papers values that needed to be populated by cascading queries in the response data

I guess the user's papers field in Page must have been used by the framework before the data was written back to the browser, so I started with the UserController and continued to trace the source code

Then I was found the following call: Jackson called paper's getter through reflection while serializing the data . in the package com. Fasterxml. Jackson. Databind. Ser.

That's why I get a response in which the paper property is populated with a value, right

Look at it this way, even though lazy loading of Jpa is in effect, cascading queries are triggered passively

Lazy loading is in effect, but the cascading query is still triggered passively, which is not the result we want, I wonder what you think about it

  • solution 1:
    @RequestMapping(path = "/getUserByPage")
    public Page getUserByPage(@RequestParam Integer from, @RequestParam Integer limit, @RequestParam(required = false) String name) {
        Page<User> page = userService.getUserByPage(from, limit, name);
        page.getContent().forEach(user->{
            user.setPapers(null);
        });
        return page;
    }
  • solution 2: @JsonIgnore

@JsonIgnore can handle this pretty well, so why not let @onetomany have it?

    @JsonIgnore
    @OneToMany(mappedBy = "user", cascade = CascadeType.ALL,fetch = FetchType.LAZY)
    private Set<Paper> papers = new HashSet<>();
  • solution 3:

We can get rid of the getters (papers), but if we do that, we can't use the property by oursel