Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [eclipselink-users] Caching problem? when persisting a ManyToOne entity

The if statement seems to suggest the part is not in the bin's list of parts.  If not, then the cached version of bin will only ever show the new part when it is refreshed or the cache cleared.  Bin has an addPartComplete method which probably should be used, and merge called on bin if it isn't managed.  This will pick up new parts in the list without the need to call persist on then directly.

Best regards
Chris

On 2012-09-01, at 9:25 PM, Oldguy <nospamgarb@xxxxxxxxx> wrote:

> Bin class has a bidirectional OneToMany relationship with Part class.
>  1) A new Part is added to an existing Bin, (also setting its Bin pointer)
> and persisted<br/>
>  2) The new Part appears in the list (and appears in a separate DB
> check)<br/>
>  3) The Bin is re-fetched from the DB (cache?) and the Part no longer
> appears<br/>
>  4) The container is restarted and the Part again appears in the Bins list
> This is a JSF Web application produced on NetBeans with Glassfish
> I have duplicated this problem using (3-year old?) NetBeans 6.8 and current
> Netbeans 7.2
> 7,2 reports: "EclipseLink, version: Eclipse Persistence Services -
> 2.3.2.v20111125-r10461"
> 
> A workaround appears in comments in the Facade file, but I would rather not
> have to visit
> the Controller and Facade for the Bin every time a Part is created. I saw a
> post by jamesssss
> which seemed to say that when merging(or persisting?) objects into the
> cache, any relationships in
> the object will also be merged into the cache. Does anyone here know what is
> happening here?
> Thank you in advance for any light someone can shed on this.
> 
> The following simplified but complete code demonstrates the problem:
> 
> ====== Bin class ======
> /* Bin.java - Created on Aug 6, 2012, 4:23:22 PM */
> package test;
> import java.util.List;
> import javax.persistence.CascadeType;
> import javax.persistence.Entity;
> import javax.persistence.Id;
> import javax.persistence.OneToMany;
> 
> @Entity
> public class Bin {
>    @Id
>    private Long id;
>    public Long getId()         {   return id;  }
>    public void setId(Long id)  {   this.id = id;  }
> 
>    @OneToMany(mappedBy="bin", cascade=CascadeType.ALL)
>    private List<Part> partsList;
> 
>    public List<Part> getPartsList()
>    {   return partsList;  }
>    public void addPartComplete(Part part)
>    {   partsList.add(part);
>        part.setBin(this);
>    }
>    public void addPartSimple(Part part)
>    {   partsList.add(part);
>    }
> }
> 
> ====== Part class ======
> /* Part.java - Created on Aug 6, 2012, 4:26:39 PM */
> package test;
> import javax.persistence.Entity;
> import javax.persistence.Id;
> import javax.persistence.ManyToOne;
> 
> @Entity
> public class Part {
>    @Id
>    private Long id;
>    public Long getId()         {   return id;  }
>    public void setId(Long id)  {   this.id = id;  }
> 
>    @ManyToOne
>    private Bin bin;
> 
>    public Bin getBin()
>    {   return bin;  }
>    public void setBin(Bin bin)
>    {   this.bin = bin;  }
> }
> 
> ====== Combined Facade for both Entities ======
> /* BinPartTestFacade.java - Created on Aug 6, 2012, 4:39:09 PM */
> package test;
> import javax.ejb.Stateless;
> import javax.persistence.EntityManager;
> import javax.persistence.PersistenceContext;
> 
> @Stateless
> public class BinPartTestFacade {
>    @PersistenceContext(unitName = "HomeFoodWebAppPU")
>    private EntityManager em;
> 
>    public void createBin(Bin bin)
>    {   em.persist(bin);  }
> 
>    public Bin findBinById(Object id)
>    {   return em.find(Bin.class, id);  }
> 
>    public void createPart(Part part)
>    {   em.persist(part);  }
> 
> // **Replacing the createPart() call above with the following code works
> around the problem
> //    public void createPart(Part part)
> //    {   Bin bin = part.getBin();
> //        if (bin != null)
> //        {   if (!bin.getPartsList().contains(part))
> //            {   // moving the adds to AFTER the merge dropped an SQL
> queried rebuild of the part list
> //                em.merge(bin).getPartsList().add(part);
> //                bin.getPartsList().add(part);       // adds to current
> in-use bin
> //            }
> //        }
> //        em.persist(part);
> //    }
> 
>    public Part findPartById(Object id)
>    {   return em.find(Part.class, id);  }
> 
>    public boolean isManaged(Object entity)
>    {   return em.contains(entity);  }
> }
> 
> ====== Combined Controller for both Entities ======
> /* BinPartTestController.java - Created on Aug 6, 2012, 4:39:41 PM */
> package test;
> import javax.ejb.EJB;
> import javax.faces.bean.ManagedBean;
> import javax.faces.bean.SessionScoped;
> 
> @ManagedBean(name="binPartTestController")
> @SessionScoped
> public class BinPartTestController {
>    @EJB private test.BinPartTestFacade ejbFacade;
> 
>    public BinPartTestController()
>    {}
> 
>    public String test()
>    {
>        Bin bin = ejbFacade.findBinById(1L);
>        int startCount = bin.getPartsList().size();
> 
>        Part part = new Part();
>        Long newPartId = 11L + startCount;
>        part.setId(newPartId);
>        bin.addPartComplete(part);      //also does part.setBin(bin);
>        ejbFacade.createPart(part);
>        int postAddCount = bin.getPartsList().size();
> 
>        bin = ejbFacade.findBinById(1L);
>        int refoundBinCount = bin.getPartsList().size();
> 
>        return "test results:" +
>                        "<br/>Starting Parts List Count = " + startCount +
>                        "<br/> => Count After adding New Part =" +
> postAddCount +
>                        "<br/> => Count after re-querying Bin" +
> refoundBinCount;
>    }
> }
> 
> ====== JSF page to launch and display results (binPartTest.xhtml) ======
> 
> <?xml version='1.0' encoding='UTF-8' ?>
> <!DOCTYPE html PUBLIC &quot;-//W3C//DTD XHTML 1.0 Transitional//EN&quot;
> &quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd&quot;>
> <html xmlns="http://www.w3.org/1999/xhtml";
>      xmlns:h="http://java.sun.com/jsf/html";>
>    <h:head>
>        <title>Bin-Part Test 1</title>
>    </h:head>
>    <h:body>
>        A minimalised demonstration of the @OneToMany problem<br/>
>        1) A new Part is added to an existing Bin, (also setting its Bin
> pointer) and persisted<br/>
>        2) The new Part appears in the list (and appears in a separate DB
> check)<br/>
>        3) The Bin is re-fetched from the DB (cache?) and the Part no longer
> appears<br/>
>        4) The container is restarted and the Part again appears in the Bins
> list<br/>
>        5) Note that restarting the browser (new session?) did NOT make the
> Part reappear<br/>
>        <br/>
>        <h:form>
>            <h:outputText value="#{binPartTestController.test()}"
> escape="false"/>
>        </h:form>
>    </h:body>
> </html>
> 
> 
> 
> 
> --
> View this message in context: http://eclipse.1072660.n5.nabble.com/Caching-problem-when-persisting-a-ManyToOne-entity-tp154123.html
> Sent from the EclipseLink - Users mailing list archive at Nabble.com.
> _______________________________________________
> eclipselink-users mailing list
> eclipselink-users@xxxxxxxxxxx
> https://dev.eclipse.org/mailman/listinfo/eclipselink-users


Back to the top