Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.

Bug 335277

Summary: An aggregate Set is changed without making any changes -> forced an UpdateObjectQuery
Product: z_Archived Reporter: Thorsten Ruth <tr>
Component: EclipselinkAssignee: Project Inbox <eclipselink.orm-inbox>
Status: NEW --- QA Contact:
Severity: normal    
Priority: P2 CC: tom.ware, tr
Version: unspecified   
Target Milestone: ---   
Hardware: PC   
OS: Linux   
Whiteboard:

Description Thorsten Ruth CLA 2011-01-25 02:07:20 EST
Build Identifier: 20100617-1415

Assume an entity class A which contained an aggregate set of class B.

Classes:

class A {
    private Set<B> bees;

    public Set<B> getBees() {
		List<B> bList = new ArrayList<B>(bees);     //
		Collections.reverse(bList);                 // <- useless, but pictures the error
		return new HashSet<B>(bList);
    }

    public void setNicknames(final Set<B> bees) {
        this.bees = bees;
    }
}

class B {
    ...
}

orm.xml:

<entity-mappings>
	<entity class="A" access="PROPERTY">
		<table name="A"></table>
		<attributes>
			<element-collection name="bees" target-class="B">
				<collection-table name="B">
					<join-column name="a" />
				</collection-table>
			</element-collection>
		</attributes>
	</entity>
	<embeddable class="B">
		<attributes>
            ...
		</attributes>
	</embeddable>
</entity-mappings>

Test-Run:

entityManager.getTransaction().begin();
Query query = entityManager.createQuery("SELECT a FROM A a");
A a = query.getSingleResult();
entityManager.getTransaction().commit();


Enable full query logging (ALL) and you will see UpdateObjectQuerys for every element in Set<B>. This shouldn't happen, because nothing has changed.
Since sets have no explicid order, the set bees and its reversed version (see the getter of bee) have to be equal in mathematical sense.

After we debugging this issue, we found where the invalid set comparison take place. This comparison is valid for ordered collections but not for unordered collections.

org.eclipse.persistence.mappings.AggregateCollectionMapping.compareForChange(Object clone, Object backUp, ObjectChangeSet owner, AbstractSession session):
...
            while (cp.hasNext(cloneIterator)) {
                Object cloneObject = cp.next(cloneIterator, session);

                // For CR#2285 assume that if null is added the collection has changed.
                if (cloneObject == null) {
                    change = true;
                    break;
                }
                Object backUpObject = null;
                if (cp.hasNext(backUpIterator)) {
                    backUpObject = cp.next(backUpIterator, session);
                } else {
                    change = true;
                    break;
                }
                if (cloneObject.getClass().equals(backUpObject.getClass())) {
...



Reproducible: Always
Comment 1 Tom Ware CLA 2011-02-03 09:52:50 EST
Setting target and priority.  See the following page for the meanings of these fields:

http://wiki.eclipse.org/EclipseLink/Development/Bugs/Guidelines
Comment 2 Eclipse Webmaster CLA 2022-06-09 10:08:10 EDT
The Eclipselink project has moved to Github: https://github.com/eclipse-ee4j/eclipselink