2016-11-17 102 views
1

我新來休眠,我不是爲什麼我有這個錯誤。我評論了我的DAO代碼進行更新,並且hibernate仍在執行更新查詢。這是我的服務代碼。爲什麼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和休眠仍在執行查詢。

這是我的控制器的代碼。

@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: 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

當實體附加並且您更改其某個屬性,Hibernate會自動將您對數據庫中相應行進行的更改(在刷新/提交時)保存。 http://stackoverflow.com/questions/5260297/how-does-the-detached-object-work-in-hibernate – user3871754

+0

我該如何解決這個問題?這是我第一次遇到這個問題。我以前從未遇到更新問題。 – saluyotamazing

+0

[事務性保存而不調用更新方法]可能重複(http://stackoverflow.com/questions/8190926/transactional-saves-without-calling-update-method) – daredesm

回答

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有一個活動#逐出(),它有異曲同工之妙:

由於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); 
    } 
    ... 
} 
+0

投了票,因爲這是正確的答案。 JPA管理實體狀態,當您更改它時(就像您對「集合」所做的那樣),它將在下一次與該實體交互時持續存在。這就是視圖模型存在的原因。將您的DAO和實體與狀態更改分開以便查看。 –

相關問題