代码之家  ›  专栏  ›  技术社区  ›  Yogesh Ghimire

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

  •  1
  • Yogesh Ghimire  · 技术社区  · 7 年前

    我正试着懒洋洋地去拿 PetDetails 使用JPA的实体。然而,我得到 LazyInitialization Exception . 我阅读了许多有关此异常的解决方案,并使用 JOIN FETCH 在里面 JPQL . 还建议人们使用 Criteria 查询。然而,如果有办法获取 宠物详细信息 以我想要的方式创建实体,无需直接使用查询或依赖 Criteria API 或不使用 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 + "]";
        }
    
    }
    

    谢谢你的帮助。

    1 回复  |  直到 7 年前
        1
  •  1
  •   asm0dey    7 年前

    你能做的最简单的事就是打电话 pet.getPetDetails() 在…内 PetService#getPet . 这个解决方案不是很清楚,但它也将迫使JPA获取实体。这是你问题的解决方案,但无论如何都不是好办法。


    好的方法是什么?

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

    1. 如果您每次都需要此详细信息,您应该使用 EAGER_FETCH
    2. 如果您有时需要它,而不是好的解决方案,那么使用JPQL JOIN FETCH
    3. 但最好的方法不是选择实体,而是选择DTO,它将包含应用程序所需的全部信息,而不是更多。可通过以下方式实现 SELECT NEW 表达式如上所述 here
    推荐文章