【问题标题】:jpa em.persist insert previously deleted itemsjpa em.persist 插入以前删除的项目
【发布时间】:2013-12-10 08:29:05
【问题描述】:

当我在删除另一个项目后保留一个项目时,我的应用程序 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 映射

@实体 @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. 在数据库中使用 deletePortfolioItem 删除元素 A 只有 B
  3. 在数据库中使用 createPortfolioItem 创建元素 C 有 A、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();
        }

【问题讨论】:

  • 向我们展示这 3 个步骤的代码 + PortofolioItem 的代码。还有一个问题:为什么要从缓存中逐出所有内容?我怀疑你需要那个。
  • 我添加了 em.getEntityManagerFactory().getCache().evictAll();因为我认为这是一个缓存问题但不起作用

标签: java spring-mvc jpa entitymanager persist


【解决方案1】:

我认为错误不在此代码中,但也许您正在重新使用旧的 Profile/PortfolioItem 存储,也许是在某些 @SessionScoped/@ViewScoped bean 或等效项中。

另外两件事:

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

【讨论】:

  • 在控制器中,我从弹簧表单中获取对象并调用服务以进行持久化。我添加了 em.getEntityManagerFactory().getCache().evictAll();因为我认为这是一个缓存问题但不起作用。
【解决方案2】:

我认为问题在于删除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);

另外,您可以尝试拨打em.flush(),而不是使用cache.evictAll()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-03-27
    • 2019-12-22
    • 2018-11-25
    • 1970-01-01
    • 2013-11-11
    • 2019-05-25
    • 1970-01-01
    相关资源
    最近更新 更多