Thanks for clarifying this. Yes, when I use CascadeType.MERGE it returns a "proper" ToBeMerged object.
However, your suggestion made be reconsider my design. Since I really only need to make sure the returned (and eventually detached) toBeMerged instance is a completely valid object, I could probably just call em.refresh(toBeMerged) to generate a "proper" object. Which of the following two would be more "expensive" in terms of database access, assuming that the RelatedObject is guaranteed to be always the same? CASE 1: @ManyToOne(optional=false, cascade=CascadeType.MERGE) @JoinColumn(name="relatedObjectId", nullable=false, updatable=false) private RelatedObject relatedObject; and then: EntityManager em = [...] em.getTransaction().begin(); ToBeMergedObject afterMerge = em.merge(toBeMerged); em.getTransaction().commit(); em.close(); return afterMerge; CASE 2: @ManyToOne(optional=false, cascade=CascadeType.REFRESH) @JoinColumn(name="relatedObjectId", nullable=false, updatable=false) private RelatedObject relatedObject; and then: EntityManager em = [...] em.getTransaction().begin(); ToBeMergedObject afterMerge = em.merge(toBeMerged); em.getTransaction().commit(); em.refresh(afterMerge); em.close(); return afterMerge; Michael Dick wrote: > > 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 > <twelve.eig...@gmail.com>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. >> > -- View this message in context: http://openjpa.208410.n2.nabble.com/merge-doesn-t-refresh-many-to-one-members-unless-attribute-is-called-explicitly-tp6494445p6498536.html Sent from the OpenJPA Users mailing list archive at Nabble.com.