Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [eclipselink-users] Tree hieararchy and @PrivateOwned problems

If something is @PrivateOwned, it must be treated as a privately owned
dependent object, it cannot be moved to another owner.

If you want to be able to move it to a different category, then do not mark
it as @PrivateOwned.  Or you can create a copy/clone of the child, null out
its id, and add this new child to its new category.


jandam wrote:
> 
> Please can you tell me what I'm doing wrong. Or I there is bug in
> eclipselink version (stable 2.1.1 - nightly 2.2.0.v20101002-r8292).
> 
> I store categories with entity list in tree hierarchy. (stripped code
> attached).
> I want move one category to another so only category parent should be
> changed (= 1x UPDATE sql statement)
> 
> Category_1
>   +- Category_2
>   +- Category_3
> 
> Action: move Category_2 to Category_3
> 
> EclipseLink steps:
> *) remove Category_2 from Category_1
>    - delete Category_2
>    - cascade delete all entities from Category_2 (@PrivateOwned)
> *) add Category_2 to Category_3
>    - undelete Category_2
>    - cascade undelete all entities from Category_2 (@PrivateOwned)  ---
> here is problem !!!
>    - record modify Category_2 parent, Category_3 children
>  
> 
> 2 different cases for @PrivateOwned entities
> 
> 1)  @OneToMany(mappedBy = "category", cascade = {})
> When I want to move Category_2 to Category_3 (should one generate SQL
> UPDATE statement) entities from Category 2 are ALWAYS deleted.
> 
> 2) @OneToMany(mappedBy = "category", cascade = {CascadeType.MERGE,
> CascadeType.REFRESH, CascadeType.PERSIST})
>         or
>    @OneToMany(mappedBy = "category", cascade = CascadeType.ALL)
> 
> Is non deterministic. Sometimes it deletes all entities from Category_2.
> (generates 1x UPDATE, 2x DELETE) sometimes only 1x UPDATE that is supposed
> to be correct behaviour.
> 
> ----
> 
> I think that there is bug in @PrivateOwned implementation. Non determinism
> in case 2) is due to using Map for storing modifications in UOW. Map uses
> hashCode and identityHashCode - so the order of modifications in UOW is
> changing.
> Sometimes it uses "cascade" and sometimes it uses "@PrivateOwned" part of
> implementation.
> 
> In @PrivateOwned case 1) Category_2 is undeleted from UOW
> (UnitOfWorkImpl:4171) bud entities remain in deleted collection.
> 
> https://fisheye2.atlassian.com/browse/eclipselink/trunk/foundation/org.eclipse.persistence.core/src/org/eclipse/persistence/internal/sessions/UnitOfWorkImpl.java?r=HEAD#l4171
> 
>       Thank you very much for reply
>      Martin
> 
> ---------------------------------------------------------------------------------------
> CODE: entities
> @Entity
> @Table(name = "CATEGORY")
> public class GeoCategory implements Serializable {
> 
>     ...
> 
>     @Id
>     @GeneratedValue(strategy = GenerationType.TABLE, generator =
> "SEQ_CATEGORY")
>     @Column(name = "ID_CATEGORY", nullable = false)
>     private long idCategory;
> 
>     @ManyToOne
>     @JoinColumn(name = "parent", referencedColumnName = "ID_CATEGORY")
>     private GeoCategory parent;
> 
>     @OneToMany(mappedBy = "parent", cascade = {CascadeType.MERGE,
> CascadeType.REFRESH, CascadeType.PERSIST})
>     @PrivateOwned
>     private List<GeoCategory> children;
> 
>     @OneToMany(mappedBy = "category", cascade = {})
> //    @OneToMany(mappedBy = "category", cascade = {CascadeType.MERGE,
> CascadeType.REFRESH, CascadeType.PERSIST})
> //    @OneToMany(mappedBy = "category", cascade = CascadeType.ALL)
>     @PrivateOwned
>     private List<GeoEntity>   entities;
> 
>     ...
> 
>     public void addCategory(int index, final GeoCategory category) {
>         if(category == null) throw new IllegalArgumentException("category
> is null");
>         if(children == null) children = new ArrayList<GeoCategory>();
>         if(category.getParent() != null) {
>             if(equals(category.getParent())) {
>                 int baseIndex = children.indexOf(category);
>                 if(baseIndex >=0 && baseIndex < index) index--;
>                 children.remove(category);
>             } else
>                 category.getParent().removeCategory(category);
>         }
>         if(index >= children.size())
>             children.add(category);
>         else
>             children.add(index, category);
>         category.setParent(this);
>     }
> 
>     public void removeCategory(final GeoCategory category) {
>         if(category == null) throw new IllegalArgumentException("category
> is null");
>         if(children != null &&  children.remove(category)) {
>             category.setParent(null);
>         }
>     }
> }
> 
> @Entity
> @Inheritance(strategy = InheritanceType.SINGLE_TABLE)
> @DiscriminatorColumn(name = "TYPE", discriminatorType =
> DiscriminatorType.STRING, length = 2)
> @Table(name = "ENTITY")
> @DefTranslation
> public abstract class GeoEntity implements Serializable {
> 
>     ...
> 
>     @Id
>     @GeneratedValue(strategy = GenerationType.TABLE, generator =
> "SEQ_ENTITY")
>     @Column(name = "ID_ENTITY", nullable = false)
>     private long idEntity;
> 
>     @JoinColumn(name = "CATEGORY_ID", referencedColumnName =
> "ID_CATEGORY", nullable = false)
>     @ManyToOne(optional = false)
>     private GeoCategory     category;
> 
>     ...
> }
> 
> 
> ---------------------------------------------------------------------------------------
> CODE: init tables
> 
>     private static void init() {
>         EntityManager em = null;
>         try {
>             em = entityManagerBegin();
> 
>             GeoCategory category = new GeoCategory();
>             category.setCategoryName("Name 1");
> 
>             GeoCategory category2 = new GeoCategory();
>             category2.setCategoryName("Name 2");
>             category2.setParent(category);
>             category.getChildren().add(category2);
> 
>             addEntities(category2, 2);
> 
>             GeoCategory category3 = new GeoCategory();
>             category3.setCategoryName("Name 3");
>             category3.setParent(category);
>             category.getChildren().add(category3);
> 
>             addEntities(category3, 1);
> 
>             em.persist(category);
>             em.persist(category2);
>             em.persist(category3);
> 
>             entityManagerCommit(em);  // transaction commit
>         } finally {
>             entityManagerClose(em);  // rollback active transaction and
> close EM
>         }
>     }
> 
>     private static void addEntities(final GeoCategory category, final int
> count) {
>         String prefix = category.getCategoryName() + " - entity: ";
>         for(int index = 0; index < count; index++) {
>             GeoEntity entity = new GeoEntity(prefix + index);
>             category.addEntity(entity);
>         }
>     }
> 
> ---------------------------------------------------------------------------------------
> CODE: method move
> 
>     public void move(final GeoCategory dstCategory, final GeoCategory
> srcCategory, final int index) throws Exception {
>         if(dstCategory == null) throw new
> IllegalArgumentException("dstCategory is null");
>         if(srcCategory == null) throw new
> IllegalArgumentException("srcCategory is null");
> 
>         EntityManager em = null;
>         try {
>             em = entityManagerBegin();  // create EM and begin transaction
>             em.setFlushMode(FlushModeType.COMMIT);
> 
>             GeoCategory dc = em.merge(dstCategory);
>             GeoCategory sc = em.merge(srcCategory);
>             
>             dc.addCategory(index, sc);
> 
>             entityManagerCommit(em);  // transaction commit
>         } finally {
>             entityManagerClose(em);  // rollback active transaction and
> close EM
>         }
>     }
> 
> ---------------------------------------------------------------------------------------
> CODE: test
>             em = emf.createEntityManager();
>             GeoCategory dst = em.find(GeoCategory.class, 3L);
>             GeoCategory src = em.find(GeoCategory.class, 2L);
>             entityManagerClose(em);  // rollback active transaction and
> close EM
>             em = null;
> 
>             move(dst, src, 1);
> 
> ---------------------------------------------------------------------------------------
> LOGGING_LEVEL: FINE
> 
> [EL Info]: 2010-10-05
> 09:59:46.51--ServerSession(27891041)--Thread(Thread[main,5,main])--EclipseLink,
> version: Eclipse Persistence Services - 2.2.0.v20101002-r8292
> [EL Fine]: 2010-10-05 09:59:47.641--Thread(Thread[main,5,main])--Detected
> Vendor platform: org.eclipse.persistence.platform.database.JavaDBPlatform
> [EL Config]: 2010-10-05
> 09:59:47.663--ServerSession(27891041)--Connection(17743384)--Thread(Thread[main,5,main])--connecting(DatabaseLogin(
> 	platform=>JavaDBPlatform
> 	user name=> ""
> 	datasource URL=> "jdbc:derby:/home/jandam/ddl/geobase;create=true"
> ))
> [EL Config]: 2010-10-05
> 09:59:47.665--ServerSession(27891041)--Connection(24749215)--Thread(Thread[main,5,main])--Connected:
> jdbc:derby:/home/jandam/ddl/geobase
> 	User: APP
> 	Database: Apache Derby  Version: 10.5.3.0 - (802917)
> 	Driver: Apache Derby Embedded JDBC Driver  Version: 10.5.3.0 - (802917)
> [EL Config]: 2010-10-05
> 09:59:47.665--ServerSession(27891041)--Connection(19333383)--Thread(Thread[main,5,main])--connecting(DatabaseLogin(
> 	platform=>JavaDBPlatform
> 	user name=> ""
> 	datasource URL=> "jdbc:derby:/home/jandam/ddl/geobase;create=true"
> ))
> [EL Config]: 2010-10-05
> 09:59:47.666--ServerSession(27891041)--Connection(26873835)--Thread(Thread[main,5,main])--Connected:
> jdbc:derby:/home/jandam/ddl/geobase
> 	User: APP
> 	Database: Apache Derby  Version: 10.5.3.0 - (802917)
> 	Driver: Apache Derby Embedded JDBC Driver  Version: 10.5.3.0 - (802917)
> [EL Info]: 2010-10-05
> 09:59:47.728--ServerSession(27891041)--Thread(Thread[main,5,main])--file:/home/jandam/java/projects/RadioLab
> App/RL GeoBase/RL GeoBase
> Base/classes/_rl-geobase-1-0_url=jdbc:derby:/home/jandam/ddl/geobase;create=true
> login successful
> [EL Fine]: 2010-10-05
> 09:59:47.794--ServerSession(27891041)--Connection(24749215)--Thread(Thread[main,5,main])--SELECT
> ID_CATEGORY, CAT_NAME, CAT_NOTE, parent FROM CATEGORY WHERE (ID_CATEGORY =
> ?)
> 	bind => [3]
> [EL Fine]: 2010-10-05
> 09:59:48.044--ServerSession(27891041)--Connection(24749215)--Thread(Thread[main,5,main])--SELECT
> ID_CATEGORY, CAT_NAME, CAT_NOTE, parent FROM CATEGORY WHERE (ID_CATEGORY =
> ?)
> 	bind => [1]
> [EL Fine]: 2010-10-05
> 09:59:48.05--ServerSession(27891041)--Connection(24749215)--Thread(Thread[main,5,main])--SELECT
> ID_CATEGORY, CAT_NAME, CAT_NOTE, parent FROM CATEGORY WHERE (ID_CATEGORY =
> ?)
> 	bind => [2]
> TEST move
> [EL Fine]: 2010-10-05
> 09:59:48.055--ServerSession(27891041)--Connection(24749215)--Thread(Thread[main,5,main])--SELECT
> ID_CATEGORY, CAT_NAME, CAT_NOTE, parent FROM CATEGORY WHERE (parent = ?)
> 	bind => [1]
> [EL Fine]: 2010-10-05
> 09:59:48.066--ServerSession(27891041)--Connection(24749215)--Thread(Thread[main,5,main])--SELECT
> ID_CATEGORY, CAT_NAME, CAT_NOTE, parent FROM CATEGORY WHERE (parent = ?)
> 	bind => [3]
> [EL Fine]: 2010-10-05
> 09:59:48.071--ServerSession(27891041)--Connection(24749215)--Thread(Thread[main,5,main])--SELECT
> ID_CATEGORY, CAT_NAME, CAT_NOTE, parent FROM CATEGORY WHERE (parent = ?)
> 	bind => [2]
> [EL Fine]: 2010-10-05
> 09:59:48.072--ServerSession(27891041)--Connection(24749215)--Thread(Thread[main,5,main])--SELECT
> ID_ENTITY, TYPE, ENTITY_NAME, CATEGORY_ID, ATTR_ID, DATA, LON_MIN,
> LAT_MIN, LON_MAX, LAT_MAX, VALUE_ASL, VALUE, LON, LAT FROM ENTITY WHERE
> (CATEGORY_ID = ?)
> 	bind => [2]
> [EL Fine]: 2010-10-05
> 09:59:48.096--ClientSession(30476335)--Connection(26873835)--Thread(Thread[main,5,main])--UPDATE
> CATEGORY SET parent = ? WHERE (ID_CATEGORY = ?)
> 	bind => [3, 2]
> [EL Fine]: 2010-10-05
> 09:59:48.144--ClientSession(30476335)--Connection(26873835)--Thread(Thread[main,5,main])--DELETE
> FROM ENTITY WHERE (ID_ENTITY = ?)
> 	bind => [2]
> [EL Fine]: 2010-10-05
> 09:59:48.159--ClientSession(30476335)--Connection(26873835)--Thread(Thread[main,5,main])--DELETE
> FROM ENTITY WHERE (ID_ENTITY = ?)
> 	bind => [1]
> TEST move - DONE
> [EL Config]: 2010-10-05
> 09:59:48.163--ServerSession(27891041)--Connection(24749215)--Thread(Thread[main,5,main])--disconnect
> [EL Info]: 2010-10-05
> 09:59:48.163--ServerSession(27891041)--Thread(Thread[main,5,main])--file:/home/jandam/java/projects/RadioLab
> App/RL GeoBase/RL GeoBase
> Base/classes/_rl-geobase-1-0_url=jdbc:derby:/home/jandam/ddl/geobase;create=true
> logout successful
> [EL Config]: 2010-10-05
> 09:59:48.164--ServerSession(27891041)--Connection(17743384)--Thread(Thread[main,5,main])--disconnect
> [EL Config]: 2010-10-05
> 09:59:48.164--ServerSession(27891041)--Connection(26873835)--Thread(Thread[main,5,main])--disconnect
> 
> 


-----
http://wiki.eclipse.org/User:James.sutherland.oracle.com James Sutherland 
http://www.eclipse.org/eclipselink/
 EclipseLink ,  http://www.oracle.com/technology/products/ias/toplink/
TopLink 
Wiki:  http://wiki.eclipse.org/EclipseLink EclipseLink , 
http://wiki.oracle.com/page/TopLink TopLink 
Forums:  http://forums.oracle.com/forums/forum.jspa?forumID=48 TopLink , 
http://www.nabble.com/EclipseLink-f26430.html EclipseLink 
Book:  http://en.wikibooks.org/wiki/Java_Persistence Java Persistence 
-- 
View this message in context: http://old.nabble.com/Tree-hieararchy-and-%40PrivateOwned-problems-tp29885352p30000816.html
Sent from the EclipseLink - Users mailing list archive at Nabble.com.



Back to the top