Thanks for the thorough description of the problem! The problem here is that you're merging a new instance of ToBeMerged, which has a relationship to a detached RelatedObject. The merge operation isn't cascaded by default, so the rules become a little muddy.
Adding CascadeType.MERGE will also solve the problem, is that an acceptable solution for you? -mike On Sun, Jun 19, 2011 at 9:17 PM, twelveeighty <[email protected]>wrote: > Since this sounds like a basic operation that fails for me, I'm inclined to > think I'm doing something wrong, but I can't find anything similar in the > FAQ or online, so please tell me what I am missing here. > > If I use merge() to insert a new entity that has a many-to-one relationship > to another entity, it gets created OK, but the *returned* object from > merge() has the related record defined with ONLY its primary key filled in, > all other attributes on the related record are null. To make it even > weirder: if I call "get<RelatedObject>()" while the object is still > attached, everything is fine. > > Here are the details: > > OpenJPA version 2.1.1 > > @Entity > RelatedObject { > @Id > private int relatedObjectId; > > @Column(nullable=false, length=255) > private String shouldNeverBeNull; > } > > @Entity > ToBeMergedObject { > @Id > private int toBeMergedObjectId; > > // @ManyToOne(optional=false, cascade=CascadeType.REFRESH) - tried both, > didn't make a difference > @ManyToOne(optional=false) > @JoinColumn(name="relatedObjectId", nullable=false, updatable=false) > private RelatedObject relatedObject; > } > > In the database, there is an existing row for RelatedObject with values (1, > 'Some String'). An corresponding instance has been preloaded and has been > detached at some point, let's call this detached instance: > preloadedRelatedObject. > > Now, create a new ToBeMergedObject (still outside an EntityManager's > context) > > ToBeMergedObject toBeMerged = new ToBeMergedObject(); > > toBeMerged.setRelatedObject(preloadedRelatedObject); > > CASE 1: Create a context and merge the new entity: > > EntityManager em = [...] > > em.getTransaction().begin(); > ToBeMergedObject afterMerge = em.merge(toBeMerged); > em.getTransaction().commit(); > em.close(); > if (afterMerge.getRelatedObject().getShouldNeverBeNull()==null) { > log.error("HOW IS THIS POSSIBLE?"); > } > > CASE 2: Create a context and merge the new entity, but make a (useless) > call > to getRelatedObject() before the em.close(); > > EntityManager em = [...] > > em.getTransaction().begin(); > ToBeMergedObject afterMerge = em.merge(toBeMerged); > em.getTransaction().commit(); > logger.debug("Some useless call: " + > afterMerge.getRelatedObject().getShouldNeverBeNull()); > em.close(); > if (afterMerge.getRelatedObject().getShouldNeverBeNull()==null) { > log("doesn't happen"); > } else { > log("NOW IT IS AS EXPECTED - getShouldNeverBeNull() returns a value"); > } > > As I mention in the definition of the many-to-one pseudo code, I have tried > with cascade=CascadeType.REFRESH but that makes no difference. > > Why is it that with a call to the getShouldNeverBeNull() INSIDE the "scope" > of the EntitiyManager that the object gets returned "fully loaded", but > without it, it doesn't? > > I appreciate any help you folks can give me on this one. > > -- > View this message in context: > http://openjpa.208410.n2.nabble.com/merge-doesn-t-refresh-many-to-one-members-unless-attribute-is-called-explicitly-tp6494445p6494445.html > Sent from the OpenJPA Users mailing list archive at Nabble.com. >
