2015-08-15 3 views
2

Я попытался в какой-то момент обновить объект, используя Spring Boot + Spring Data JPA. Я возвращаю все правильные взгляды. Мое редактирование возвращает правильно сущности мне по ID. Все движется отлично .. пока я на самом деле не попытаюсь сохранить/слить/перенести объект. каждые один раз я возвращаю новый объект с новым ID. Я просто не знаю, почему. Я посмотрел примеры онлайн и ссылки на повторяющиеся вопросы, на которые вы, вероятно, собираетесь навестить меня. Так где же в этих частях кода я делаю ошибку?Spring Data JPA Merge Обновленный объект

package demo; 

    import javax.persistence.Column; 
    import javax.persistence.Entity; 
    import javax.persistence.GeneratedValue; 
    import javax.persistence.GenerationType; 
    import javax.persistence.Id; 
    import javax.persistence.Table; 

    @Entity 
    @Table(name = "ORDERS") 
    public class Order { 

     @Id 
     @GeneratedValue(strategy = GenerationType.AUTO) 
     private Integer id; 

     @Column(name = "ORDER_NAME") 
     private String name; 

     @Column(name = "ORDER_DESCRIPTION") 
     private String description; 

     @Column(name = "ORDER_CONTENT") 
     private String content; 

     public Order() {} 

     public Order(String name, String description, String content) { 
      this.name = name; 
      this.description = description; 
      this.content = content; 
     } 

     public String getContent() { 
      return content; 
     } 

     public String getDescription() { 
      return description; 
     } 

     public String getName() { 
      return name; 
     } 

     public Integer getId() { 
      return this.id; 
     } 

     public void setContent(String content) { 
      this.content = content; 
     } 

     public void setDescription(String description) { 
      this.description = description; 
     } 

     public void setName(String name) { 
      this.name = name; 
     } 

     @Override 
     public boolean equals(Object obj) { 
      if (this == obj) 
       return true; 
      if (obj == null) 
       return false; 
      if (getClass() != obj.getClass()) 
       return false; 
      Order other = (Order) obj; 
      if (content == null) { 
       if (other.content != null) 
        return false; 
      } else if (!content.equals(other.content)) 
       return false; 
      if (description == null) { 
       if (other.description != null) 
        return false; 
      } else if (!description.equals(other.description)) 
       return false; 
      if (id == null) { 
       if (other.id != null) 
        return false; 
      } else if (!id.equals(other.id)) 
       return false; 
      if (name == null) { 
       if (other.name != null) 
        return false; 
      } else if (!name.equals(other.name)) 
       return false; 
      return true; 
     } 

     @Override 
     public int hashCode() { 
      final int prime = 31; 
      int result = 1; 
      result = prime * result + ((content == null) ? 0 : content.hashCode()); 
      result = prime * result 
        + ((description == null) ? 0 : description.hashCode()); 
      result = prime * result + ((id == null) ? 0 : id.hashCode()); 
      result = prime * result + ((name == null) ? 0 : name.hashCode()); 
      return result; 
     } 

     @Override 
     public String toString() { 
      return "Order [id=" + id + ", name=" + name + ", description=" 
        + description + ", content=" + content + "]"; 
     } 

    } 





    package demo; 

    import org.springframework.data.jpa.repository.JpaRepository; 

    public interface OrderRepository extends JpaRepository<Order, Integer> { 

     public Order findByName(String name); 


    } 

package demo;

import javax.persistence.EntityManager; 
    import javax.persistence.PersistenceContext; 
    import javax.transaction.Transactional; 

    import org.springframework.stereotype.Service; 

    @Service("customJpaService") 
    public class CustomJpaServiceImpl implements CustomJpaService{ 

     @PersistenceContext 
     private EntityManager em; 

     @Transactional 
     public Order saveOrUpdateOrder(Order order) { 

      if (order.getId() == null) { 
       em.persist(order); 
      } else { 
       em.merge(order); 
      } 
      return order; 
     } 

    } 

Пакет demo;

import java.util.List; 

    import org.springframework.beans.factory.annotation.Autowired; 
    import org.springframework.stereotype.Controller; 
    import org.springframework.validation.BindingResult; 
    import org.springframework.web.bind.annotation.ModelAttribute; 
    import org.springframework.web.bind.annotation.PathVariable; 
    import org.springframework.web.bind.annotation.RequestMapping; 
    import org.springframework.web.bind.annotation.RequestMethod; 
    import org.springframework.web.servlet.ModelAndView; 
    import org.springframework.web.servlet.mvc.support.RedirectAttributes; 

    @Controller 
    public class OrderController { 

     //refactor to service with 
     //logging features 
     @Autowired 
     OrderRepository orderRepo; 

     @Autowired 
     CustomJpaService customJpaService; 

     @RequestMapping(value="/orders", method=RequestMethod.GET) 
     public ModelAndView listOrders() { 

      List<Order> orders = orderRepo.findAll(); 

      return new ModelAndView("orders", "orders", orders); 

     } 

     @RequestMapping(value="/orders/{id}", method=RequestMethod.GET) 
     public ModelAndView showOrder(@PathVariable Integer id, Order order) { 
      order = orderRepo.findOne(id); 
      return new ModelAndView("showOrder", "order", order); 
     } 

     @RequestMapping(value="/orders/edit/{id}", method=RequestMethod.GET) 
     public ModelAndView editForm(@PathVariable("id") Integer id) { 
      Order order = orderRepo.findOne(id); 
      return new ModelAndView("editOrder", "order", order); 
     } 

     @RequestMapping(value="/updateorder", method=RequestMethod.POST) 
     public String updateOrder(@ModelAttribute("order") Order order, BindingResult bindingResult, final RedirectAttributes redirectattributes) { 

      if (bindingResult.hasErrors()) { 
       return "redirect:/orders/edit/" + order.getId(); 
      } 

      customJpaService.saveOrUpdateOrder(order); 
      redirectattributes.addFlashAttribute("successAddNewOrderMessage", "Order updated successfully!"); 
      return "redirect:/orders/" + order.getId(); 
     } 


     @RequestMapping(value="/orders/new", method=RequestMethod.GET) 
     public ModelAndView orderForm() { 
      return new ModelAndView("newOrder", "order", new Order()); 
     } 

     @RequestMapping(value="/orders/new", method=RequestMethod.POST) 
     public String addOrder(Order order, final RedirectAttributes redirectAttributes) { 
      orderRepo.save(order); 
      redirectAttributes.addFlashAttribute("successAddNewOrderMessage", "Success! Order " + order.getName() + " added successfully!"); 
      return "redirect:/orders/" + order.getId(); 
     } 

    } 

После этого кода. Мой взгляд возвращает меня к правильному URL-адресу, но с идентификатором 4 < - это новый объект. Он должен сказать 3 с обновленными свойствами.

+0

Ну, я провел некоторое тестирование, и кажется, что в методе POST для обновления объекта объект заказа возвращает идентификатор нулевого значения. Я не знаю, почему атрибуты модели присутствуют в форме, и я использовал аннотацию @ModelAttribute. – DtechNet

ответ

2

Вам необходимо сохранить объект где-то между запросом GET и запросом POST. Ваши варианты:

  1. Reload объекта из базы данных в начале процедуры POST и скопировать его свойство из посланного объекта
  2. магазина инфо объекта в скрытом виде переменных
  3. Сохраните объект в сессии

3 - единственное правильное решение, так как оно позволяет оптимистично контролировать параллелизм и более безопасно, чем скрытые формы vars.

Добавить @SessionAttributes("modelAttributeName") в верхней части вашего контроллера и параметр SessionStatus в ваш метод POST-обработчика. Позвоните по телефону sessionStatus.setComplete() по завершении. См. Spring MVC: Validation, Post-Redirect-Get, Partial Updates, Optimistic Concurrency, Field Security для рабочего примера.

+0

Вы используете только метод method = RequestMethod.PUT для API? Потому что я заметил, что «PUT» не поддерживается тегами JSP и Spring. Поэтому, я думаю, вы все еще используете POST по методу «обновления». Фактическое обновление происходит на уровне данных. Кроме того, вам нужно использовать @Version для своей сущности? – DtechNet

+0

На самом деле это веб-браузеры, которые не помещают/удаляют из html-форм, а не только весны. Можно использовать put/delete w Ajax. Вам нужно только @version для оптимистической блокировки –

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