java - 在 Fetchtype Lazy 和 Eager 上获得相同的值

标签 java spring hibernate spring-boot jpa

我是 Jpa 的新手,我在我的 spring boot 中添加了 spring boot jpa 用于一对一映射。所以,

package com.jpa.onetoone.onetoonejpa.model;

import org.hibernate.annotations.GeneratorType;

import javax.persistence.*;

@Entity
public class User {

   @Id
   @GeneratedValue
   private Long id;

   private String username;

   private String password;

   @OneToOne(cascade=CascadeType.ALL,mappedBy = "user",fetch = FetchType.LAZY)
   private Address address;

    public User(String username, String password) {

        this.username = username;
        this.password = password;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public Address getAddress() {
        return address;
    }

    public void setAddress(Address address) {
        this.address = address;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                '}';
    }

    public User() {
    }
}

Address.java文件是

package com.jpa.onetoone.onetoonejpa.model;

import com.fasterxml.jackson.annotation.JsonIgnore;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToOne;

@Entity
public class Address {

    @Id
    @GeneratedValue
    private Long id;

    private String homeAddress;

    private int homeNumber;

    @OneToOne
    @JsonIgnore
    private User user;


    public Address(String homeAddress, int homeNumber) {
        this.homeAddress = homeAddress;
        this.homeNumber = homeNumber;
    }

    public User getUser() {
        return user;
    }

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

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getHomeAddress() {
        return homeAddress;
    }

    public void setHomeAddress(String homeAddress) {
        this.homeAddress = homeAddress;
    }

    public int getHomeNumber() {
        return homeNumber;
    }

    public void setHomeNumber(int homeNumber) {
        this.homeNumber = homeNumber;
    }

    public Address() {
    }
}

我在 User 和 Address 之间添加了一对一的关系。我已经将数据插入数据库并希望通过 RestController 获取数据。所以,我只是在 User 类中使用 FetchType.Lazy 和 FetchType.Eager 测试我的应用程序但是我得到相同的 Json。使用 FetchType 的 JSOn 没有变化。

当我点击 URL 时:http://localhost:8080/users在 fetchtype.lazy 和 fetchtype.eager 中,我得到了相同的 JSON,因为我在地址字段中使用 fetchtype.lazy 时需要删除地址字段。

 @OneToOne(cascade=CascadeType.ALL,mappedBy = "user",fetch = FetchType.LAZY)
   private Address address;

我在这两种情况下得到的 JSON 是:

[  
   {  
      "id":3,
      "username":"ashwin",
      "password":"karki",
      "address":{  
         "id":4,
         "homeAddress":"kapan",
         "homeNumber":71444
      }
   }
]

我想问的另一个问题是,当我尝试访问 http://localhost:8080/address 时,我还想要与地址关联的用户对象。循环进入无限期,我添加了 JsonIgnore,然后 Json 打印如下。有什么办法,我们可以在点击这两个 URL 时从地址访问用户和从用户访问地址?

[  
   {  
      "id":4,
      "homeAddress":"kapan",
      "homeNumber":71444
   }
]

默认 Controller .java

package com.jpa.onetoone.onetoonejpa.controller;


import com.jpa.onetoone.onetoonejpa.model.Address;
import com.jpa.onetoone.onetoonejpa.model.User;
import com.jpa.onetoone.onetoonejpa.repository.AddressRepository;
import com.jpa.onetoone.onetoonejpa.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

@RestController
public class DefaultController {


    @Autowired
    private UserRepository userRepository;

    @Autowired
    private AddressRepository addressRepository;


    @GetMapping(value = "/users")
    public List<User> getUsers() {

        List<User> users = userRepository.findAll();
       return users;
    }

    @GetMapping(value = "/address")
    public List<Address> getAddress() {

        List<Address> address = addressRepository.findAll();
        return address;
    }

}

最佳答案

使用 FetchType 的 JSON 没有变化——也不应该。 fetch 类型是一种从数据库加载数据的策略。

通过一个 SQL 调用同时加载 EAGER 用户和地址:

@GetMapping(value = "/users")
public List<User> getUsers() {

   List<User> users = userRepository.findAll(); // users and addresses was loaded
   return users;
}

使用 LAZY,当您不阅读地址时,不会加载地址。但是,当您从 Controller 返回用户时,JSON 映射器读取地址属性,因此它将通过每个用户一个 SQL 调用加载:

@GetMapping(value = "/users")
public List<User> getUsers() {

   List<User> users = userRepository.findAll(); // users was loaded
   return users; // addresses was loaded for each user one by one
}

第二个问题。有很多方法。参见 JsonView ,例如。

关于java - 在 Fetchtype Lazy 和 Eager 上获得相同的值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57351892/

相关文章:

java - 我的 servlet 不工作 我收到错误 HTTP404-not found 但我的 jsp +html 文件工作正常

java - 如何以编程方式动态创建 WSDL 并在没有生成代码或 Java stub 的情况下解析请求?

Java 可能的有损转换 Double 到 Int

java - 上下文初始化失败 - NoSuchMethodError : AntPathMatcher. setCaseSensitive()

java - Session.get 在 hibernate 中工作,同时逐步调试,但在 eclipse 中运行时不工作

c# - 如何在 NHibernate 中映射多对多对多的三元关系?

ArrayList 的 java.lang.IndexOutOfBoundsException

java - Spring AOP - ProceedingJoinpoint - MethodSignature 向下转型

java - 在 bean 上使用 @PostConstruct 对 @SqlGroup 进行 Spring 测试

java - 使用 Hibernate 执行 Oracle 存储过程