[
Date Prev][
Date Next][
Thread Prev][
Thread Next][
Date Index][
Thread Index]
[
List Home]
[eclipselink-users] Tree hieararchy and @PrivateOwned problems
|
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