Excuse me Tom for intervening in the discussion, but I suppose what
Mike says is quite correct!
1. when em.remove(object-of-B); is called, shouldn't it remove that
entity instance from the cache as well?
2. when A is fetched from a new transaction, shouldn't the
object-of-A.getChildren() be a fresh list of objects of B?
3. So, where does the "developer maintaining the relationship" come
into picture?
4. do you mean the developer should also remove the association
between A and B?
5. I believe this should have been handled automatically with
@ManyToOne annotation on the child side of the relation ship
6. It would be better if eclipselink checks for existence of the
enitiy before loading the relationship in case if the relation has not
been cleaned up.
7. Further, it would interesting to see if the
A.getChildren().get(0).getB() is returning the complete details of the
object or just the priomary key of the object.
I suspect, it is only retuning the primary key and hence a bug in
the way eclipselink is constructing objects from references.
Regards,
Samba
On Tue, Sep 1, 2009 at 8:49 PM, Tom Ware <tom.ware@xxxxxxxxxx
<mailto:tom.ware@xxxxxxxxxx>> wrote:
There may be an enhancement request in there somewhere. Please
feel free to enter one.
At the moment the JPA specification requires that you maintain
your relationships and does not mandate any automatic relationship
maintenance by the provider.
-Tom
Mike Traum wrote:
Sure. Here's a snippet:
EntityManager em = emf.createEntityManager();
Query q = em.createQuery("select a FROM A a");
List<A> as = q.getResultList();
em.clear();
em.close();
B b = as.get(0).getChildren().get(0);
System.out.println(b.getId()); // prints '2'
em = emf.createEntityManager();
em.getTransaction().begin();
B bm = em.merge(b);
em.remove(bm);
em.getTransaction().commit(); // successfully removes b with
id '2' from database
em.clear();
em.close();
em = emf.createEntityManager();
q = em.createQuery("select a FROM A a");
as = q.getResultList();
b = as.get(0).getChildren().get(0);
System.out.println(b.getId()); // prints '2'
boolean contains = em.contains(b);
System.out.println(contains); // prints 'true'
em.clear();
em.close();
mike
Tom Ware wrote:
I am not sure I follow. Can you provide a code sample?
Mike Traum wrote:
Tom,
I see where you're coming from. The spec references
that you gave do seem to support this behavior
(unfortunate, but that's an issue for a different
list). But, I think you then run into other conflicts
with the spec. For example, contains on that the
removed entity will return true after retrieving it
with the query.
Section 3.2.5
The contains method returns true:
• If the entity has been retrieved from the database,
and has not been removed or detached.
• If the entity instance is new, and the persist
method has been called on the entity or the persist
operation has been cascaded to it.
The contains method returns false:
• If the instance is detached.
• If the remove method has been called on the entity,
or the remove operation has been cascaded
to it.
• If the instance is new, and the persist method
mike
mike
Tom Ware wrote:
The spec references I have found are in section
3.2.3 of the JPA 1.0 specification:
Reference 1:
---
Bidirectional relationships between managed
entities will be persisted based on references
held by the
owning side of the relationship. It is the
developer’s responsibility to keep the in-memory
references
held on the owning side and those held on the
inverse side consistent with each other when they
change.
---
Reference 2: (for flushing)
----
The semantics of the flush operation, applied to
an entity X are as follows:
<snip>
- If X is a removed entity, it is removed from the
database. No cascade options are relevant.
----
Is there something I am missing in the spec that
you can point me to?
-Tom
Mike Traum wrote:
Maybe I've been defining my entities
strangely, but if you define a @OneToMany on A
and then a @ManyToOne on B (pointing to A),
the schema generated by eclipselink will have
the foreign key in B pointing to A. So, this
will not be enforced by the database. I can
drop in some code to illustrate if desired.
If the above is not funky, I think, by the JPA
spec, the DB delete should not occur.
Otherwise, the relationship 'magic' will occur
between app restarts but not within app queries.
mike
Tom Ware wrote:
EclipseLink relies on your DB
foreign-key-contstraints to enforce this.
i.e. You should get a SQL exception on the
remove if a foreign-key-constraint exists
for this relationship.
Mike Traum wrote:
Yes, I thought that might be the
answer. But, the implementation seems
odd. JPA doesn't provide magic for
this, but it is deleted from the
database, however the cache is
maintained in a stale state. It seems
to me that either it should not be
deleted from the database or it should
be removed from the cache.
mike
Tom Ware wrote:
Hi Mike,
You need to sever the
relationship between an A and a B
before you remove B. JPA does not
provide any magic for this.
-Tom
Mike Traum wrote:
I have the following enitiy map:
A->B->C (where -> represents a
OneToMany relationship)
If I do a EntityManager.remove
on a B, a following Query
(select all) will still return
that entity, even though it
has been removed from the
database.
Any ideas on the proper way to
handle this?
Here's some code illustrating
the issue:
EntityManager em =
emf.createEntityManager();
Query q =
em.createQuery("select a FROM
A a");
List<A> as = q.getResultList();
em.clear();
em.close();
System.out.println(as.get(0).getChildren().size());
// output is 2
B b =
as.get(0).getChildren().get(0);
em =
emf.createEntityManager();
em.getTransaction().begin();
B bm = em.merge(b);
em.remove(bm);
em.getTransaction().commit();
// successfully removes B and
children from database
em.clear();
em.close();
em = emf.createEntityManager();
q = em.createQuery("select a
FROM A a");
as = q.getResultList();
em.clear();
em.close();
System.out.println(as.get(0).getChildren().size());
// output is 2
em =
emf.createEntityManager();
q = em.createQuery("select a
FROM A a");
((ReadAllQuery)((EJBQueryImpl)q).getDatabaseQuery()).refreshIdentityMapResult();
as = q.getResultList();
em.clear();
em.close();
System.out.println(as.get(0).getChildren().size());
// output is 1
Thanks,
Mike
_______________________________________________
eclipselink-users mailing list
eclipselink-users@xxxxxxxxxxx
<mailto:eclipselink-users@xxxxxxxxxxx>
https://dev.eclipse.org/mailman/listinfo/eclipselink-users
_______________________________________________
eclipselink-users mailing list
eclipselink-users@xxxxxxxxxxx
<mailto:eclipselink-users@xxxxxxxxxxx>
https://dev.eclipse.org/mailman/listinfo/eclipselink-users
_______________________________________________
eclipselink-users mailing list
eclipselink-users@xxxxxxxxxxx
<mailto:eclipselink-users@xxxxxxxxxxx>
https://dev.eclipse.org/mailman/listinfo/eclipselink-users
_______________________________________________
eclipselink-users mailing list
eclipselink-users@xxxxxxxxxxx
<mailto:eclipselink-users@xxxxxxxxxxx>
https://dev.eclipse.org/mailman/listinfo/eclipselink-users
_______________________________________________
eclipselink-users mailing list
eclipselink-users@xxxxxxxxxxx
<mailto:eclipselink-users@xxxxxxxxxxx>
https://dev.eclipse.org/mailman/listinfo/eclipselink-users
_______________________________________________
eclipselink-users mailing list
eclipselink-users@xxxxxxxxxxx
<mailto:eclipselink-users@xxxxxxxxxxx>
https://dev.eclipse.org/mailman/listinfo/eclipselink-users
_______________________________________________
eclipselink-users mailing list
eclipselink-users@xxxxxxxxxxx
<mailto:eclipselink-users@xxxxxxxxxxx>
https://dev.eclipse.org/mailman/listinfo/eclipselink-users
_______________________________________________
eclipselink-users mailing list
eclipselink-users@xxxxxxxxxxx
<mailto:eclipselink-users@xxxxxxxxxxx>
https://dev.eclipse.org/mailman/listinfo/eclipselink-users
_______________________________________________
eclipselink-users mailing list
eclipselink-users@xxxxxxxxxxx
<mailto:eclipselink-users@xxxxxxxxxxx>
https://dev.eclipse.org/mailman/listinfo/eclipselink-users
_______________________________________________
eclipselink-users mailing list
eclipselink-users@xxxxxxxxxxx <mailto:eclipselink-users@xxxxxxxxxxx>
https://dev.eclipse.org/mailman/listinfo/eclipselink-users
------------------------------------------------------------------------
_______________________________________________
eclipselink-users mailing list
eclipselink-users@xxxxxxxxxxx
https://dev.eclipse.org/mailman/listinfo/eclipselink-users