2013-12-10 2 views
0

Мое приложение j2ee + spring mvc + jpa (eclipselink, оракул базы данных) имеет проблему, когда я сохраняю элемент после удаления другого элемента. Если я удалю элемент или несколько элементов, следующая сохраняющая вставка в db элементы, которые были удалены ранее. В модели у меня есть это отображение для класса профиля:jpa em.persist insert Ранее удаленные элементы

@Entity 
@Table(name = "PROFILES") 

    Class Profile { 
     private Collection<PortfolioItem> portfolio; 
     ... 
     @OneToMany(orphanRemoval = true,cascade={PERSIST,MERGE,REFRESH,REMOVE}) 
     @JoinColumn(name = "PROFILE_FK", referencedColumnName = "PROFILE_ID") 
      public Collection<PortfolioItem> getPortfolio() { 
       return portfolio; 
     } 
    } 

Класс PortfolioItem является простой POJO сопоставляются йоту

@Entity @Table (имя = "PORTFOLIO_ITEMS")

В службе у меня есть два метода createPortfolioItem х deletePortfolioItem

@Transactional 
    @Override 
    public void create(PortfolioItem portfolioItem,Profile profile) 
throws BusinessException{ 

     em.persist(portfolioItem); 
     profile.portfolio.add(portfolioItem); 
     em.merge(profile); 
    } 

    @Transactional 
    @Override 
    public void deletePortfolioItem(int portfolioItemID) throws BusinessException { 
     PortfolioItem p = em.find(PortfolioItem.class, portfolioItemID); 
     em.remove(em.merge(p)); 
     em.getEntityManagerFactory().getCache().evictAll();  
    } 

Если я выполните следующие действия:

  1. создать элементы A и B с createPortfolioItem в БД есть являются А и В
  2. удаления элемента А с deletePortfolioItem в БД есть только Б
  3. создать элемент C с createPortfolioItem в БД есть , B и C

Пожалуйста, помогите!

Это PortfolioItem класс

@Entity 

@Table(name = "PORTFOLIO_ITEMS") 
public class PortfolioItem implements Serializable { 


    private int portfolioItemID; 
    private String title; 
    private String description; 
    private UploadedFile portfolioFile; 
    private static final long serialVersionUID = 1L; 

    public PortfolioItem() { 
     super(); 
    } 

    @Id  
    @Column(name = "PORTFOLIOITEM_ID") 
    @GeneratedValue(generator = "PortfolioItem_Gen") 
    @SequenceGenerator(name = "PortfolioItem_Gen", sequenceName = "PortfolioItem_Seq", initialValue=1, allocationSize=1) 
    public int getPortfolioItemID() { 
     return this.portfolioItemID; 
    } 

    public void setPortfolioItemID(int portfolioItemID) { 
     this.portfolioItemID = portfolioItemID; 
    } 
    public String getTitle() { 
     return this.title; 
    } 

    public void setTitle(String title) { 
     this.title = title; 
    } 
    public String getDescription() { 
     return this.description; 
    } 

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

Для создания объекта PortfolioItem я принимать данные из пружинной формы, как это в JSP странице

<form:form modelAttribute="portfolioItem" action="${pageContext.request.contextPath}/create" method="POST"> 

      <form:errors path="title"/> 
      <form:input path="title" id="title" placeholder="Title"/> 

      <form:errors path="description"/> 
      <form:input path="description" id="description" placeholder="Description"/> 

      <button type="submit" class="standard_button medium">Sumbit</button>    
      </form:form> 

В контроллере у меня есть эти методы:

@RequestMapping("/delete") 
    public String deletePortfolioItem(@RequestParam("portfolioItemID") int portfolioItemID) throws BusinessException{ 

     service.deletePortfolioItem(portfolioItemID); 
     return "redirect:/profiles/views?profileID="+profile.getID(); 
    } 

    @RequestMapping(value="/create",method=RequestMethod.GET) 
    public String createPortfolioStart(Model model){ 
     model.addAttribute("portfolioItem", new PortfolioItem()); 
     return "portfolio.createform"; 
    } 



@RequestMapping(value="/create",method=RequestMethod.POST) 
     public String createPortfolio(@ModelAttribute PortfolioItem portfolioItem, 
@RequestParam("profileID") int profileID, 
BindingResult bindingResult) throws BusinessException{ 

      portfolioValidator.validate(portfolioItem, bindingResult); 
       Profile profile = service.findProfileByID(profileID); 
      service.create(portfolioItem,profile); 

      return "redirect:/profiles/views?profileID="+profile.getID(); 
     } 
+0

Покажите нам код для этих 3 шагов + код для PortofolioItem. Также возникает вопрос: почему вы выселяете все из кеша? Я сомневаюсь, что вам это нужно. –

+0

Я добавил em.getEntityManagerFactory().getCache() evictAll(). потому что я думал, что это проблема с кешем, но не работает. – user3083618

ответ

0

Я не думаю, что ошибка кроется в этом коде, но, возможно, вы повторно используете старый Profile/PortfolioItem хранится, может быть, в некотором @SessionScoped/@ViewScoped компонентах или аналогичных.

еще 2 вещи:

1), так как getPortfolio() помечен cascade=PERSIST, вы можете просто сделать:

@Transactional 
@Override 
public void create(PortfolioItem portfolioItem,Profile profile) throws BusinessException 
{ 
    profile.getPortfolio().add(portfolioItem); 
    em.merge(profile); 
} 

2) Вам не нужно повторно объединить объект загружен внутри EJB транзакционных метод:

@Transactional 
@Override 
public void deletePortfolioItem(int portfolioItemID) throws BusinessException 
{ 
    PortfolioItem p = em.find(PortfolioItem.class, portfolioItemID); 
    em.remove(p); 
    em.getEntityManagerFactory().getCache().evictAll();  
} 
+0

В контроллере я беру объект из весенней формы и вызываю службу для сохранения. Я добавил em.getEntityManagerFactory(). GetCache(). EvictAll(); потому что я думал, что это проблема с кешем, но не работает. – user3083618

0

Я думаю, что проблема заключается в коде, когда вы удалите PortofolioItem. Перед удалением его em.remove(portofolioItem) вы должны удалить его из списка коллекции АНКЕТЫ:

TypedQuery<Profile> query = em.createQuery("SELECT profile FROM Profile profile JOIN profile.portfolio portofolio where portofolio.id = :portofolioId", Profile.class); 
query.setParameter("portofolioId", portofolioId); 
Profile profile = query.getSingleResult(); 
profile.getprotofolio().remove(portofolio); 

Кроме того, вместо того, чтобы играть с cache.evictAll() вы могли бы попытаться вызвать em.flush().