-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 2 posts ] 
Author Message
 Post subject: How to persist Entity with assocation to persisted Entity
PostPosted: Sun Mar 09, 2008 1:57 pm 
Beginner
Beginner

Joined: Fri Jan 26, 2007 3:16 pm
Posts: 24
I have an Entity like this:

Code:
@Entity
@Table(name = "VIOLATION")
public final class Violation {

    @ManyToOne
    @ForeignKey(name = "FK_VIOLATION_TRANSACTION")
    @JoinColumn(name = "TRANSACTION_ID")
    private Transaction transaction;

    @ManyToOne(cascade = { CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH }, fetch = FetchType.EAGER)
    @ForeignKey(name = "FK_VIOLATION_OBJECT_REF", inverseName = "FK_OBJECT_REF_VIOLATION")
    @JoinColumn(name = "OBJECT_REF_ID")
    private ObjectRef objectRef;

}


Let's say I already have an ObjectRef persisted in the database in OBJECT_REF table like this row:

Code:
| ID | GEOM | REF_NAME | REF_ID |
| 1  | MDSYS.SDO_GEOM | ref name 1 | 1000001 |


Now, if create a new Violation object, like this:
Code:
// same as row in database
ObjectRef oRef = new ObjectRef("ref name", 1000001, new Geometry());

Violation v = new Violation("some text", oRef);

Transaction t; // already have instance of transaction
t.addViolation(v);
em.persist(v);


This triggers a unique constraint violation for me, since on ObjectRef entity I have this:

Code:
@Entity
@Table(name = "OBJECT_REF", uniqueConstraints = { @UniqueConstraint(columnNames = { "REF_NAME", "REF_ID" }) })
public final class ObjectRef {


So, I wrote some code instead, that does a Query to find if an ObjectRef entity is already persisted...if so, I override the detached instance that was set in the constructor...

Code:
Query q = getEntityManager().createQuery("from ObjectRef where name = :name and refId = :refId")
                    .setParameter("name", v.getObjectRef().getRefName())
                    .setParameter("refId", v.getObjectRef().getRefId());
ObjectRef oRef = (ObjectRef) q.getSingleResult();
if(oRef != null) { v.setObejctRef(oRef); }
em.persist(v);


This works, but I hit another problem. When the query is issued, all outstanding operations are flushed...and the Transaction entity now tries to get persisted, which cascades persisting the Violation, and then the ObjectRef -- which again hits my unique constraint violation.

I can get around this by do em.clear() to clear the cache, then finding the ObjectRef, setting it, persisting it, and then manually setting link again between the Transaction and the Violation, but this all seems so wrong...I feel like there must be a much easier and correct way to do this.

Can anyone offer some insight?

Thanks in advance,
Davis


Top
 Profile  
 
 Post subject:
PostPosted: Sun Mar 09, 2008 2:22 pm 
Beginner
Beginner

Joined: Fri Jan 26, 2007 3:16 pm
Posts: 24
I solved my own problem. I'm not sure if this is the best way to do this, but it apparently works. If it helps someone else...great. Or, if you see a problem with something I'm doing here, I'd like to hear about it.

This is the DAO save() method. Conversation() is an anonymous class that wraps exception handling and the logic around a transaction boundary. The issue is resolved by setting Flush Mode to COMMIT, so the Query.getResultList() will not force a flush operation. In addition, at the end, I do a merge() operation on the transaction (but not before persisting the Violation -- then I still get unique constraint violation).

Code:
public Violation save(final Violation v) {
               
        new Conversation() {
            @Override
            protected void conversation() {
               
                getEntityManager().setFlushMode(FlushModeType.COMMIT);             
                Query q = getEntityManager().createQuery("from ObjectRef where name = :name and refId = :refId")
                    .setParameter("name", v.getObjectRef().getRefName())
                    .setParameter("refId", v.getObjectRef().getRefId());
                List<ObjectRef> list = q.getResultList();
                if(list.isEmpty()) {
                    getEntityManager().persist(v);
                } else {
                    if(list.size() > 1) {
                        throw new RuntimeException("Duplicate Obejct Ref found in database "+list);
                    }
                    v.setObjectRef(list.iterator().next());
                    getEntityManager().persist(v);
                    getEntityManager().merge(v.getTransaction());
                }
            }       
        };
       
        return v;
    }


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 2 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.