Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.
Bug 330914 - Incomplete query results with specific mappings and orderings
Summary: Incomplete query results with specific mappings and orderings
Status: NEW
Alias: None
Product: z_Archived
Classification: Eclipse Foundation
Component: Eclipselink (show other bugs)
Version: unspecified   Edit
Hardware: PC Windows XP
: P3 enhancement with 2 votes (vote)
Target Milestone: ---   Edit
Assignee: Nobody - feel free to take it CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2010-11-23 08:16 EST by Piotr Szarański CLA
Modified: 2022-06-09 10:34 EDT (History)
0 users

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
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