Spring mvc 无法在一对一关系中使用JPA执行延迟提取操作

Spring mvc 无法在一对一关系中使用JPA执行延迟提取操作,spring-mvc,jpa,persistence,spring-orm,Spring Mvc,Jpa,Persistence,Spring Orm,我正在尝试使用JPA懒洋洋地获取PetDetails实体。但是,我得到了懒散初始化异常。我阅读了许多有关此异常的解决方案,并在JPQL中使用joinfetch找到了解决方案。人们还建议使用标准查询。但是,如果有一种方法可以按照我想要的方式获取PetDetails实体,而无需直接使用查询或依赖criteriaapi或不使用EAGER fetch,我将尝试寻找解决方案。我可能错过了什么。如果您能提供任何帮助或建议,我将不胜感激。以下是代码示例: 1. Controller class: @

我正在尝试使用JPA懒洋洋地获取
PetDetails
实体。但是,我得到了
懒散初始化异常
。我阅读了许多有关此异常的解决方案,并在
JPQL
中使用
joinfetch
找到了解决方案。人们还建议使用
标准
查询。但是,如果有一种方法可以按照我想要的方式获取
PetDetails
实体,而无需直接使用查询或依赖
criteriaapi
或不使用
EAGER fetch
,我将尝试寻找解决方案。我可能错过了什么。如果您能提供任何帮助或建议,我将不胜感激。以下是代码示例:

1. Controller class:

    @Controller
    public class PetController {
        private static Logger LOGGER = Logger.getLogger(PetController.class);

        @Autowired
        private PetService petService;

        @RequestMapping(value = "/", method = RequestMethod.GET)
        public void manageAndDisplayPet() {
            PetDetails petDetails = new PetDetails();
            petDetails.setName("DOG");
            Pet pet = new Pet(petDetails);
            // save
            petService.savePet(pet);

            // retrieve
            LOGGER.debug("**********************" + petService.getPet());
            LOGGER.debug("**********************" + pet.getPetDetails());
        }
    }

2. PetService class:

    @Service
    public class PetService {
        @Autowired
        private PetDAO petDAO;

        @Transactional
        public void savePet(Pet pet) {
            petDAO.savePet(pet);
        }

        @Transactional
        public Pet getPet() {
            return petDAO.getPet();
        }
    }

3. PetDAO class

    @Repository
    @EnableTransactionManagement
    public class PetDAO {
        @PersistenceContext(unitName = "petcontext")
        private EntityManager entityManagerFactory;

        public void savePet(Pet pet) {
            entityManagerFactory.persist(pet);
        }

        public Pet getPet() {
            Pet pet = (Pet) entityManagerFactory.find(Pet.class, 1);
            return pet;
        }

    }

4. Pet Entity:

@Entity
@Table(name = "t_pet")
public class Pet {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;
    @JoinColumn(name = "pet_details")
    @OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    private PetDetails petDetails;

    public Pet() {
    }

    public Pet(PetDetails petDetails) {
        this.petDetails = petDetails;
    }

    public int getId() {
        return id;
    }

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

    public PetDetails getPetDetails() {
        return petDetails;
    }

    public void setPetDetails(PetDetails petDetails) {
        this.petDetails = petDetails;
    }

    @Override
    public String toString() {
        return "Pet [id=" + id + ", petDetails=" + petDetails + "]";
    }

}

5. PetDetails Entity:

@Entity
@Table(name = "pet_details")
public class PetDetails {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;
    @Column(name = "pet_name")

    private String name;

    public int getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "PetDetails [id=" + id + ", name=" + name + "]";
    }

}

谢谢您的帮助。

您可以做的最简单的事情是在
PetService\getPet
内部调用
pet.getPetDetails()
。这个解决方案不是很清楚,但它也将迫使JPA获取实体。这是解决你问题的办法,但无论如何不是好办法


什么是好方法?

好方法可能取决于您的特定用例:

  • 如果您每次都需要此详细信息-您应该使用
    EAGER\u FETCH
  • 如果您有时需要它,而不是一个好的解决方案,那么您可以将JPQL与
    joinfetch
  • 但最好的方法不是选择实体,而是选择DTO,它将包含应用程序需要的全部信息,而不是更多。如前所述,可通过
    选择新的
    表达式来实现