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.

Reply via email to