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

Bug 330914

Summary: Incomplete query results with specific mappings and orderings
Product: z_Archived Reporter: Piotr Szarański <szaranski.piotr>
Component: EclipselinkAssignee: Nobody - feel free to take it <nobody>
Status: NEW --- QA Contact:
Severity: enhancement    
Priority: P3    
Version: unspecified   
Target Milestone: ---   
Hardware: PC   
OS: Windows XP   
Whiteboard:

Description Piotr Szarański CLA 2010-11-23 08:16:31 EST
During development I have found an area, where some performance tuning would be considered appropriate.

Consider these mappings:
====================================================
1. MainEntity:
@Access(AccessType.FIELD)
@Entity(name="MainEntity")
@Table(name = "business_entities")
public class MainEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "mainentity_seq")
    @SequenceGenerator(name = "mainentity_seq", sequenceName = "mainentity_seq", allocationSize = 1)
    @Column(name = "id")
    private Long id;
    
    @OneToOne(targetEntity = AssociatedEntity.class, fetch = FetchType.LAZY)
    @JoinColumn(name = "associatedentity_id", nullable = true)
    private AssociatedEntity associatedEntity;
    
    @OneToOne(targetEntity = MainEntity.class, fetch = FetchType.EAGER)
    @JoinColumn(name = "related_entity_id", nullable = true)
    private MainEntity relatedEntity;

// constructors, getters, setters...

@StaticMetamodel(MainEntity.class)
    public static class Model extends BaseEntity.Model {
        public static volatile SingularAttribute<MainEntity, Long> id;
        public static volatile SingularAttribute<MainEntity, String> someField;
        public static volatile SingularAttribute<MainEntity, AssociatedEntity> associatedEntity;
        public static volatile SingularAttribute<MainEntity, MainEntity> relatedEntity;
    }
}

2. AssociatedEntity

@Access(AccessType.FIELD)
@Entity(name="AssociatedEntity")
@Table(name="associated_entities")
public class AssociatedEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "associatedentity_seq")
    @SequenceGenerator(name = "associatedentity_seq", sequenceName = "associatedentity_seq", allocationSize = 1)
    @Column(name = "id")
    private Long id;
    
    @Column(name = "some_field", nullable = false)
    private String someField;

// constructors, getters, setters...

@StaticMetamodel(AssociatedEntity.class)
    public static class Model extends InstrumentFinansowyPochodnyEntity.Model {
        public static volatile SingularAttribute<AssociatedEntity, Long> id;
        public static volatile SingularAttribute<AssociatedEntity, String> someField;
    }
}
========================================================================

Remember that MainEntity has a NONLAZY reference to MainEntity.


Here we have database dump (PostgreSQL used):

associated_entities:
INSERT INTO associated_entities (id, some_field) VALUES (1, 'test1');
INSERT INTO associated_entities (id, some_field) VALUES (2, 'test2');
INSERT INTO associated_entities (id, some_field) VALUES (3, 'test2');

business_entities:
INSERT INTO business_entities (id, associatedentity_id, related_entity_id) VALUES (1, 1, NULL);
INSERT INTO business_entities (id, associatedentity_id, related_entity_id) VALUES (2, 2, 1);
INSERT INTO business_entities (id, associatedentity_id, related_entity_id) VALUES (3, 3, 2);



And here's some "business" EJB logic:
====================================================
public List<MainEntity> showMeYourBug(boolean asc) {
        CriteriaBuilder criteriaBuilder = em.getCriteriaBuilder();
        CriteriaQuery<MainEntity> mainCriteriaQuery = criteriaBuilder.createQuery(MainEntity.class);
        
        Root<MainEntity> mainRoot = mainCriteriaQuery.from(MainEntity.class);
        mainRoot.fetch(MainEntity.Model.associatedEntity);
        
        if (asc) {
            mainCriteriaQuery.orderBy(criteriaBuilder.asc(mainRoot.get(MainEntity.Model.id)));
        } else {
            mainCriteriaQuery.orderBy(criteriaBuilder.desc(mainRoot.get(MainEntity.Model.id)));
        }
        
        TypedQuery<MainEntity> typedMainQuery = em.createQuery(mainCriteriaQuery);
        
        return typedMainQuery.getResultList();
    }
====================================================

When invoking:
List<MainEntity> fetchItForMe = testDao.showMeYourBug(true);
I get results just as expected.

Unfortunately, this one:
List<MainEntity> fetchItForMe = testDao.showMeYourBug(false);
returns MainEntities but their AssociatedEntities are set to NULL (they are fetched later when accessing the field).

It would be cool, if the AssociatedEntities were build from already fetched AbstractRecords rather than using additional database roundtrips.
Comment 1 Piotr Szarański CLA 2010-11-25 05:24:19 EST
There is a bug in code snippet (AssociatedEntity), here is correct:


@StaticMetamodel(AssociatedEntity.class)
    public static class Model {
        public static volatile SingularAttribute<AssociatedEntity, Long> id;
        public static volatile SingularAttribute<AssociatedEntity, String>
someField;
    }


Cheers :)
Comment 2 Eclipse Webmaster CLA 2022-06-09 10:34:00 EDT
The Eclipselink project has moved to Github: https://github.com/eclipse-ee4j/eclipselink