在 Hibernate 中使用延迟加载而不是急切加载
In Hibernate using Lazy loading instead of eager loading
我正在开发一个 Spring-MVC 应用程序,用户可以在其中注册产品和产品图像。现在有 3 个表,User、Product、ProductImages。并不总是需要拉取所有 productImages 直到并且除非用户明确进入产品,那里有一个模式,然后用户可以 select 要加载的图像。
所以我想到了使用 LazyLoading 而不是 EagerFetching。但是我得到了 lazyLoadException 。因此,我在 Product 和 ProductImages 中手动打开了一个会话,并且出现了 ObjectNotFound 异常。问题是,productImages 与产品有外键关系,所以我必须先保存产品,然后再保存其图像,这就是我遇到问题的地方。请建议我如何在这种情况下使用延迟加载。错误日志和代码如下:
错误日志:
org.hibernate.ObjectNotFoundException: No row with the given identifier exists: [com.WirTauschen.model.ProductImage#1150]
org.hibernate.internal.SessionFactoryImpl.handleEntityNotFound(SessionFactoryImpl.java:253)
com.WirTauschen.dao.ProductBasicDaoImpl.updateProduct(ProductBasicDaoImpl.java:50)
控制器:
@RequestMapping(value = "/product/addimages", method = RequestMethod.POST)
public @ResponseBody String addProductImages(@RequestParam("productImages") MultipartFile[] uploadedFiles){
if(uploadedFiles != null && uploadedFiles.length>0) {
for (MultipartFile uploadedFile : uploadedFiles) {
try {
if (!(uploadedFile.isEmpty())) {
imagesList.add(uploadedFile.getBytes());
}
} catch (IOException e) {
e.printStackTrace();
return "image failed to upload";
}
}
}
return "done";
}
@RequestMapping(value="/product/add",method = RequestMethod.POST)
public String addProduct(@ModelAttribute("product") ProductBasic productBasic,Model model){
model.addAttribute("product", new ProductBasic());
productBasic.setProductimage(productprofileimage);
int productid = productBasicService.addProduct(productBasic);
ProductBasic productBasic1 = this.productBasicService.getProductById(productid);
for (int index = 0; index < imagesList.size(); index++) {
if (index == 0) {
productBasic1.setProductimage(imagesList.get(0));
}
ProductImage productImage = new ProductImage();
productImage.setProductimage(imagesList.get(index));
this.productImageService.addProductImage(productBasic1, productImage);
}
productBasicService.updateProduct(productBasic1);
imagesList.clear();
productprofileimage =null;
return "redirect:/product/show";
}
ProductDAOImpl :
@Override
@Transactional
public int addProduct(User user, ProductBasic productBasic) {
// I was using getSessionBefore with Eager, it worked, thought of trying openSession
session = this.sessionFactory.openSession();
user.getProductBasics().add(productBasic);
productBasic.setUser1(user);
session.save(productBasic);
System.out.println("Returned product information is"+productBasic.getProductid());
session.flush();
//session.close();
return productBasic.getProductid();
}
@Override
@Transactional
public void updateProduct(User user,ProductBasic productBasic) {
logger.debug("Editing product information");
session = this.sessionFactory.getCurrentSession();
// User user1 = (User) session.get(User.class,id);
user.getProductBasics().add(productBasic);
productBasic.setUser1(user);
session.saveOrUpdate(productBasic);
session.flush();
}
ProductImageDAOImpl :
@Override
@Transactional
public boolean addProductImage(ProductBasic productBasic,ProductImage productImage) {
session = sessionFactory.openSession();
productBasic.getProductImageSet().add(productImage);
productImage.setProductimageupload(productBasic);
productBasic.setImagecount((productBasic.getImagecount()+1));
session.merge(productBasic);
session.saveOrUpdate(productImage);
return true;
}
控制器代码不应该包含那么多服务端信息,但这只是为了确保它能正常工作。我已经在模型中定义了 LazyLoading,如果需要,我可以 post 代码,请告诉我我做错了什么。欢迎任何指点。感谢您的时间。
扩展我的评论
- 去掉上面的saveOrUpdate。
- 将级联类型更改为
ALL
PS:您在 UpdateProduct 方法中遇到异常。但是您已经发布了 addProduct 的代码。
我正在开发一个 Spring-MVC 应用程序,用户可以在其中注册产品和产品图像。现在有 3 个表,User、Product、ProductImages。并不总是需要拉取所有 productImages 直到并且除非用户明确进入产品,那里有一个模式,然后用户可以 select 要加载的图像。
所以我想到了使用 LazyLoading 而不是 EagerFetching。但是我得到了 lazyLoadException 。因此,我在 Product 和 ProductImages 中手动打开了一个会话,并且出现了 ObjectNotFound 异常。问题是,productImages 与产品有外键关系,所以我必须先保存产品,然后再保存其图像,这就是我遇到问题的地方。请建议我如何在这种情况下使用延迟加载。错误日志和代码如下:
错误日志:
org.hibernate.ObjectNotFoundException: No row with the given identifier exists: [com.WirTauschen.model.ProductImage#1150]
org.hibernate.internal.SessionFactoryImpl.handleEntityNotFound(SessionFactoryImpl.java:253)
com.WirTauschen.dao.ProductBasicDaoImpl.updateProduct(ProductBasicDaoImpl.java:50)
控制器:
@RequestMapping(value = "/product/addimages", method = RequestMethod.POST)
public @ResponseBody String addProductImages(@RequestParam("productImages") MultipartFile[] uploadedFiles){
if(uploadedFiles != null && uploadedFiles.length>0) {
for (MultipartFile uploadedFile : uploadedFiles) {
try {
if (!(uploadedFile.isEmpty())) {
imagesList.add(uploadedFile.getBytes());
}
} catch (IOException e) {
e.printStackTrace();
return "image failed to upload";
}
}
}
return "done";
}
@RequestMapping(value="/product/add",method = RequestMethod.POST)
public String addProduct(@ModelAttribute("product") ProductBasic productBasic,Model model){
model.addAttribute("product", new ProductBasic());
productBasic.setProductimage(productprofileimage);
int productid = productBasicService.addProduct(productBasic);
ProductBasic productBasic1 = this.productBasicService.getProductById(productid);
for (int index = 0; index < imagesList.size(); index++) {
if (index == 0) {
productBasic1.setProductimage(imagesList.get(0));
}
ProductImage productImage = new ProductImage();
productImage.setProductimage(imagesList.get(index));
this.productImageService.addProductImage(productBasic1, productImage);
}
productBasicService.updateProduct(productBasic1);
imagesList.clear();
productprofileimage =null;
return "redirect:/product/show";
}
ProductDAOImpl :
@Override
@Transactional
public int addProduct(User user, ProductBasic productBasic) {
// I was using getSessionBefore with Eager, it worked, thought of trying openSession
session = this.sessionFactory.openSession();
user.getProductBasics().add(productBasic);
productBasic.setUser1(user);
session.save(productBasic);
System.out.println("Returned product information is"+productBasic.getProductid());
session.flush();
//session.close();
return productBasic.getProductid();
}
@Override
@Transactional
public void updateProduct(User user,ProductBasic productBasic) {
logger.debug("Editing product information");
session = this.sessionFactory.getCurrentSession();
// User user1 = (User) session.get(User.class,id);
user.getProductBasics().add(productBasic);
productBasic.setUser1(user);
session.saveOrUpdate(productBasic);
session.flush();
}
ProductImageDAOImpl :
@Override
@Transactional
public boolean addProductImage(ProductBasic productBasic,ProductImage productImage) {
session = sessionFactory.openSession();
productBasic.getProductImageSet().add(productImage);
productImage.setProductimageupload(productBasic);
productBasic.setImagecount((productBasic.getImagecount()+1));
session.merge(productBasic);
session.saveOrUpdate(productImage);
return true;
}
控制器代码不应该包含那么多服务端信息,但这只是为了确保它能正常工作。我已经在模型中定义了 LazyLoading,如果需要,我可以 post 代码,请告诉我我做错了什么。欢迎任何指点。感谢您的时间。
扩展我的评论
- 去掉上面的saveOrUpdate。
- 将级联类型更改为
ALL
PS:您在 UpdateProduct 方法中遇到异常。但是您已经发布了 addProduct 的代码。