2016-11-17 2 views
1

Я новичок в спящем режиме, и я не понимаю, почему у меня такая ошибка. Я прокомментировал, что мой код 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: 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=? 

Если это какой-то новичок ошибка, мне очень жаль, но я довольно новичок в спячке. Спасибо.

+0

Когда юридическое лицо и вы меняете одно из своих свойств, Hibernate автоматически сохраняет изменения, внесенные вами в соответствующую строку в базе данных (время флеша/фиксации). http://stackoverflow.com/questions/5260297/how-does-the-detached-object-work-in-hibernate – user3871754

+0

Как это исправить? Это моя первая встреча с этой проблемой. Раньше у меня никогда не было проблем с обновлениями. – saluyotamazing

+0

Возможный дубликат [Transactional сохраняет без вызова метода обновления] (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 имеет Session # выселить(), который служит той же цели:

Поскольку 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 и сущности от изменения состояния для целей просмотра. –

Смежные вопросы