【问题标题】:Spring Boot JPA ignores lazy loading for OneToMany BidirectionalSpring Boot JPA 忽略 OneToMany 双向的延迟加载
【发布时间】:2021-05-06 15:33:44
【问题描述】:

我正在使用 springboot(spring-boot-starter-parent 2.3.0 版本)和 Jpa。我有 User 类,它是父类,UserEmails 是子实体。

用户实体

@Entity
@Table(name = "user")
public class User extends BaseEntity {

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

    @NotEmpty(message = "Name cannot be empty")
    @Column(name = "name")
    private String name;

    @OneToMany(mappedBy = "user",fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    @JsonManagedReference
    private List<UserEmails> userEmails = new ArrayList<UserEmails>();
 
    //setters and getters

     public void setUserEmails(List<UserEmails> userEmails) {
       this.userEmails= userEmails;
       this.userEmails.forEach(userEmail->{
         userEmail.setUser(this);
       });
}
}

UserRoles 实体

@Entity
@Table(name = "user_emails")
public class UserEmails extends BaseEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;
    
    @Column(name="email")
    private String email;

    @JsonBackReference
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "user_id" , referencedColumnName = "id", nullable=true)
    private User user;

    //getters and setters
}

问题是,即使我在关系的双方都使用 fetch 类型作为惰性,但当我调用 getUserById 或 getAllUsers 时,jpa 也会加载用户电子邮件。

用户服务实现

@Service
public class UserServiceImpl extends BaseServiceImpl implements UserService {

    private static final Logger logger = LoggerFactory.getLogger(UserServiceImpl.class);

    @Autowired
    UserDAO userDAO;

   @Override
    public User getUserById(int id) {
        logger.info("Executing getUserById() in user service");
        User user = null;
        
        try {
            user = userDAO.findById(id);
        } catch (DataAccessException e) {
            String message = "Some message"
            throw new Exception(message, e);
        }

        if (user == null) {
              String message = "Some message"
              throw new ResourceNotFoundException(message);
        }
        return user;
    }
} 

用户DAO

@Repository
public interface UserDAO extends JpaRepository<User, Long>{
    

    public User findById(int id);

}

【问题讨论】:

    标签: spring-boot jpa


    【解决方案1】:

    是的,它可能会发生,如果您使用持久对象(在您的实例中为 User 的对象)作为控制器之一中的返回值(例如 REST URL /user/{id} 处的 ResponseEntity&lt;User&gt; getUser(Long id)),就会发生这种情况 如果您有类似的 REST 控制器,则会发生 UserEmails 的延迟获取。 这种惰性获取基本上会发生在控制器的返回语句中。

    你有两种可能:

    1. 定义DTO对象,例如UserDTO,mapper在User和UserDTO之间进行映射 的

    2. User 类中使用@JsonIgnoreProperties 和@JsonProperty 等其他注解:

           @Entity 
           @Table(name = "user") 
           @JsonIgnoreProperties({"userEmails"})
           public class User extends BaseEntity {
      
           @Id
           @GeneratedValue(strategy = GenerationType.IDENTITY)
           private int id;
      
           @NotEmpty(message = "Name cannot be empty")
           @Column(name = "name")
           private String name;
      
           @OneToMany(mappedBy = "user",fetch = FetchType.LAZY, cascade = CascadeType.ALL)
           @JsonManagedReference
           @JsonProperty("userEmails")
           private List<UserEmails> userEmails = new ArrayList<UserEmails>();
      
           //setters and getters
      
            public void setUserEmails(List<UserEmails> userEmails) {
              this.userEmails= userEmails;
              this.userEmails.forEach(userEmail->{
                userEmail.setUser(this);
              });
            }}
      

      .

    【讨论】:

    • 谢谢!期待你的答复。我按照您的建议进行了尝试,但我仍然可以看到用户电子邮件正在热切地加载。基本上,我尝试在服务类本身中打印用户对象,我也可以看到正在执行查询日志以获取用户电子邮件。似乎延迟加载不是从控制器的返回语句中获取,而是从服务或 dao 本身(user = userDAO.findById(id))获取。
    • 你是如何打印用户对象的?因为每次触摸都会发生 getUserEmails 提取。其次,我希望你使用 log4jm 如果是这样添加` ` 确定发生延迟获取的确切位置。每次我遇到类似的问题时,都是我的错误,通常是匆忙做出的。对不起,我没有帮助你。
    • 我刚刚使用了 system.out.println(user)。我也在使用 sl4j 进行日志记录。我从下面的链接中得到了一个解决方案,stackoverflow.com/questions/57169361/… 他们建议使用 HttpMessageConverter ,如果没有数据,它可以防止延迟加载的对象的 Serializable
    猜你喜欢
    • 2016-01-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-01
    • 1970-01-01
    相关资源
    最近更新 更多