我刚接触休眠,但我不知道为什么会出现此错误。我注释掉了我的DAO代码进行更新,而hibernate仍在执行更新查询。这是我的服务代码。
@Override
@Transactional(readOnly = false)
public void updateProduct(Product productToUpdate) throws DuplicateProductException {
Product product = productDao.findByProductId(productToUpdate.getProductId());
if (productDao.findByName(productToUpdate.getName()) != null
&& !product.getName().equals(productToUpdate.getName())) {
throw new DuplicateProductException();
}
product.setName(productToUpdate.getName());
product.setCategory(productToUpdate.getCategory());
product.setPrice(productToUpdate.getPrice());
product.setImage(productToUpdate.getImage());
// productDao.updateProduct(product);
}
我评论了DAO,而hibernate仍在执行查询。
这是我的控制器的代码。
@RequestMapping(value = "/updateProduct", method = RequestMethod.POST)
public String updateProductPost(@Validated @ModelAttribute("product") ProductHelper productHelper,
BindingResult bindingResult, Model model) throws CategoryNotFoundException {
model.addAttribute("categories", categoryService.findAll());
model.addAttribute("activePage", AdminPage.UPDATE_PRODUCT);
updateProductValidator.validate(productHelper, bindingResult);
if (bindingResult.hasErrors()) {
return "admin_home";
}
Product product = productHelper.buildProductToUpdate(productService, categoryService);
try {
productService.updateProduct(product);
model.addAttribute("updatedProduct", product);
} catch (DuplicateProductException e) {
model.addAttribute("duplicateProduct", product);
}
return "admin_home";
}
奇怪的是,我已将整个DAO代码注释掉了:
// @Override
// public void updateProduct(Product product) {
//// sessionFactory.getCurrentSession().update(product);
// }
仍然是hibernate正在执行更新查询:
Hibernate: update PRODUCT set category_id=?, image=?, name=?, price=?, product_id=? where id=?
Hibernate: select product0_.id as id1_3_, product0_.category_id as category6_3_, product0_.image as image2_3_, product0_.name as name3_3_, product0_.price as price4_3_, product0_.product_id as product_5_3_ from PRODUCT product0_ where product0_.product_id=?
Hibernate: select product0_.id as id1_3_, product0_.category_id as category6_3_, product0_.image as image2_3_, product0_.name as name3_3_, product0_.price as price4_3_, product0_.product_id as product_5_3_ from PRODUCT product0_ where product0_.name=?
如果这是一些初学者的错误,我真的很抱歉,但我对hibernate相当新。谢谢。
答案 0 :(得分:1)
JPA使用托管实体。这意味着,当会话关闭或刷新时,您对会话中的托管实体所做的任何更改都会保留。
解决方法您可以按copy constructor创建新实例:
Product productDetached = new Product(productDao.findByProductId(productToUpdate.getProductId()))
//you can change and do not worry about sql query
productDetached.setName(productToUpdate.getName());
如果您不想要这种行为,则需要手动分离实体。
如果您使用的是JPA 2.0,则可以使用EntityManager#detach()从持久性上下文中分离单个实体。此外,Hibernate还有一个Session#evict(),其用途相同:
由于JpaRepository本身不提供此功能,您可以添加custom implementation,如下所示:
public interface UserRepositoryCustom {
...
void detachUser(User u);
...
}
public interface UserRepository extends JpaRepository<User, Long>, UserRepositoryCustom {
...
}
@Repository
public class UserRepositoryCustomImpl implements UserRepositoryCustom {
...
@PersistenceContext
private EntityManager entityManager;
@Override
public void detachUser(User u) {
entityManager.detach(u);
}
...
}