jpa em.persist插入以前删除的项目

时间:2013-12-10 08:29:05

标签: java spring-mvc jpa entitymanager persist

我的应用程序j2ee + spring mvc + jpa(eclipselink,database oracle)在删除另一个项目后保留项目时出现问题。如果我删除一个或多个项目,则下一个持久性数据库会在数据库中插入先前删除的项目。在模型中,我有类Profile的映射:

@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(name =“PORTFOLIO_ITEMS”)

在服务中我有两个方法createPortfolioItem e 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. 使用DB中的createPortfolioItem创建元素A和B. 是A和B
  2. 删除元素A,DB中的deletePortfolioItem只有B
  3. 在DB中使用createPortfolioItem创建元素C,有A,B和C
  4. 请帮帮我!

    这是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();
            }
    

2 个答案:

答案 0 :(得分:0)

我不认为错误在于此代码,但您可能正在重新使用旧的Profile / PortfolioItem存储,可能在某些@SessionScoped / {{1 bean或同等的。

另外两件事:

1)由于@ViewScoped被标记为getPortfolio(),您只需执行以下操作:

cascade=PERSIST

2)您不需要重新合并EJB事务方法中加载的实体:

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

答案 1 :(得分: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()