FetchType.Lazy 在 Spring Boot 中无法在 JPA 中工作

Posted

技术标签:

【中文标题】FetchType.Lazy 在 Spring Boot 中无法在 JPA 中工作【英文标题】:FetchType.Lazy not working in JPA in spring boot 【发布时间】:2020-10-27 23:47:59 【问题描述】:

我有一个实体 Order.java 作为:

package in.ashwin.onlinebookstore.entity;

import java.util.Date;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToOne;
import javax.persistence.Table;

@Entity
@Table(name="tbl_order")
public class Order 
    
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long order_id;
    
    @OneToOne(cascade = CascadeType.MERGE,fetch = FetchType.LAZY)
    @JoinColumn(name = "user_id", nullable = false)
    private User user;
    
    @Column(name="today_date")
    private Date todayDate;
    
    @Column(name="status")
    private String status;
    
    public Order(User user, Date todayDate) 
        
        this.user = user;
        this.todayDate = todayDate;
        this.status="pending";
    

    public Long getOrder_id() 
        return order_id;
    

    public void setOrder_id(Long order_id) 
        this.order_id = order_id;
    

    public String getStatus() 
        return status;
    

    

    public User getUser() 
        return user;
    

    public void setUser(User user) 
        this.user = user;
    

    public Date getTodayDate() 
        return todayDate;
    

    public void setTodayDate(Date todayDate) 
        this.todayDate = todayDate;
    
    
    public Order() 
        
    


我在用户和订单之间包含了 Fetchtype 作为惰性。因为,我在获取订单时声明了 FetchType.LAZY,当我从邮递员测试时,我仍然看到用户对象被调用。根据我的理解,FetchType 的对象。 LAZY 只在需要时才被调用。如果没有调用,则忽略它。

 @OneToOne(cascade = CascadeType.MERGE,fetch = FetchType.LAZY)
        @JoinColumn(name = "user_id", nullable = false)
        private User user;

我获取所有订单的 api 是:

@GetMapping("/getAllPendingOrders")
    @PreAuthorize("hasRole('USER') or hasRole('MODERATOR') or hasRole('ADMIN')")
    public ResponseEntity<?> getOrders(Pageable pageable) 
        
        Authentication auth = SecurityContextHolder.getContext().getAuthentication();
        String user = auth.getName();
        UserDetailsImpl userDetails=(UserDetailsImpl)userdetailService.loadUserByUsername(user);
        
        Page<Order> orderList=orderRep.findByUserId(userDetails.getId(),pageable);
        if(orderList!=null) 
             return new ResponseEntity(orderList, HttpStatus.OK);
        
        else 
             return new ResponseEntity("Noorders", HttpStatus.OK);
        
       
        
    

我从 POSTMAN 收到的回复是:


    "content": [
        
            "order_id": 1,
            "user": 
                "id": 1,
                "username": "ashwin",
                "email": "ashwin@gmail.com",
                "password": "$2a$10$GoGUJh0Tzml5egBW5Wzbj.VLzfq4Z7YNCMnsOynLWufpQrWBdVLVi",
                "roles": [
                    
                        "id": 2,
                        "name": "ROLE_MODERATOR"
                    ,
                    
                        "id": 1,
                        "name": "ROLE_USER"
                    
                ]
            ,
            "todayDate": "2020-07-02T17:09:45.057+0000",
            "status": "pending"
        ,
        
            "order_id": 2,
            "user": 
                "id": 1,
                "username": "ashwin",
                "email": "ashwin@gmail.com",
                "password": "$2a$10$GoGUJh0Tzml5egBW5Wzbj.VLzfq4Z7YNCMnsOynLWufpQrWBdVLVi",
                "roles": [
                    
                        "id": 2,
                        "name": "ROLE_MODERATOR"
                    ,
                    
                        "id": 1,
                        "name": "ROLE_USER"
                    
                ]
            ,
            "todayDate": "2020-07-02T17:15:06.906+0000",
            "status": "pending"
        ,
        
            "order_id": 3,
            "user": 
                "id": 1,
                "username": "ashwin",
                "email": "ashwin@gmail.com",
                "password": "$2a$10$GoGUJh0Tzml5egBW5Wzbj.VLzfq4Z7YNCMnsOynLWufpQrWBdVLVi",
                "roles": [
                    
                        "id": 2,
                        "name": "ROLE_MODERATOR"
                    ,
                    
                        "id": 1,
                        "name": "ROLE_USER"
                    
                ]
            ,
            "todayDate": "2020-07-02T17:16:36.373+0000",
            "status": "pending"
        ,
        
            "order_id": 4,
            "user": 
                "id": 1,
                "username": "ashwin",
                "email": "ashwin@gmail.com",
                "password": "$2a$10$GoGUJh0Tzml5egBW5Wzbj.VLzfq4Z7YNCMnsOynLWufpQrWBdVLVi",
                "roles": [
                    
                        "id": 2,
                        "name": "ROLE_MODERATOR"
                    ,
                    
                        "id": 1,
                        "name": "ROLE_USER"
                    
                ]
            ,
            "todayDate": "2020-07-02T17:18:56.799+0000",
            "status": "pending"
        
       
    ],
    "pageable": 
        "sort": 
            "sorted": false,
            "unsorted": true,
            "empty": true
        ,
        "offset": 0,
        "pageNumber": 0,
        "pageSize": 20,
        "paged": true,
        "unpaged": false
    ,
    "totalPages": 2,
    "last": false,
    "totalElements": 39,
    "size": 20,
    "number": 0,
    "sort": 
        "sorted": false,
        "unsorted": true,
        "empty": true
    ,
    "numberOfElements": 20,
    "first": true,
    "empty": false

我仍然在我的 JSON.USing 中看到用户对象,@JSONIgnore 有效,但是由于我已将其声明为 Fetchtype.Lazy,为什么当我获取 Order 对象时会出现 USER 对象?我不知道当我获取 Order 对象时,希望 User 对象出现。

【问题讨论】:

Fetchtype.Lazy 只是表示,每当你调用一个订单时,用户不会同时来,只是在需要的时候,会再次查询数据库来获取这个信息。在这种情况下,您有您的存储库,这将调用所有的订单信息,因为它是创建 JSON 所必需的。 那么,这意味着存储库忽略了 FetchType.Laay? 【参考方案1】:

User 实体数据在显式调用之前不会被初始化并加载到内存中。您的 Order 实体包含 user 字段。因此,当序列化用户调用的订单数据获取器和使用另一个查询获取的用户数据时。

如果您不想使用@JsonIgnore,请为没有用户字段的订单创建响应类并映射您的数据。

【讨论】:

所以,假设如果我删除用户的 getter 并仍然放置 Fetchtype.lazy,那么如果我需要 order.getUser(),我该如何访问。如何访问用户对象?虽然可能有 getter,但如果我们声明 Fetchtype.Lazy 那么它会省略用户对象是吗?【参考方案2】:

对我来说添加 @JsonIgnore 注释有帮助

【讨论】:

正如目前所写,您的答案尚不清楚。请edit 添加其他详细信息,以帮助其他人了解这如何解决所提出的问题。你可以找到更多关于如何写好答案的信息in the help center。 这并没有提供问题的答案。一旦你有足够的reputation,你就可以comment on any post;相反,provide answers that don't require clarification from the asker。 - From Review

以上是关于FetchType.Lazy 在 Spring Boot 中无法在 JPA 中工作的主要内容,如果未能解决你的问题,请参考以下文章

Spring Boot 2. Jackson json 序列化或 Spring Data JPA FetchType.Lazy

没有会话的休眠 FetchType.LAZY

使用 FetchType.LAZY 休眠 ManyToOne 不会延迟获取

JPA fetchType.Lazy 不工作

FetchType.LAZY和FetchType.EAGER什么区别

Spring LazyInitializatoinException