Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pagination in queries that join on an @OneToMany or @ManyToMany attribute return duplicate results #1914

Open
rybandrei2014 opened this issue Jun 21, 2024 · 1 comment

Comments

@rybandrei2014
Copy link

Description

I need to retrieve paginated result with fetch and I am also getting duplicates in result. It happens when I am getting entities that have more than one attribute bound by @manytoone relation. Here is the pseudocode:

public class Entity {
    @Id
    private Long id;

    @OneToMany(fetch = FetchType.LAZY, mappedBy = "entity")
    private Set<EntityAttribute> attributes;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(nullable = false, insertable = false, updatable = false)
    private EntityType entityType;
}

public class EntityAttribute {
    @Id
    private Long id;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(nullable = false, insertable = false, updatable = false)
    private Entity entity;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(nullable = false, insertable = false, updatable = false)
    private Attribute attribute;
}

@Override
public PagedList<Entity> search(SearchByCodeRequest request) {
        var date = Optional.ofNullable(request.getDate()).orElse(new Date());
        var pageSize = request.getPageSize();
        var firstResult = request.getPage() * pageSize;

        var cb = criteriaBuilderFactory.create(entityManager, Entity.class)
                .fetch("entityType", "attributes", "attributes.attribute")
                .orderByAsc("id")
                .page(firstResult, pageSize)
                .withCountQuery(true)
                .where("validFrom").le(date)
                .where("validTo").ge(date);

        var code = request.getCode();

        if (code != null) {
            cb.where("entityType.code").eq(code);
        }

        var r = cb.getResultList();

        return r;
}

Here is pseudo result I am getting:

{
    "data": [
        {
            "id": 3,
            "entityType": {
                "code": "REGISTER"
            },
            "attributes": [
                {
                    "id": 4,
                    "attribute": {
                        "id": 4
                    }
                },
                {
                    "id": 7,
                    "attribute": {
                        "id": 8
                    }
                },
                {
                    "id": 5,
                    "attribute": {
                        "id": 6
                    }
                },
                {
                    "id": 6,
                    "attribute": {
                        "id": 7
                    }
                }
            ]
        },
        {
            "id": 3,
            "entityType": {
                "code": "REGISTER"
            },
            "attributes": [
                {
                    "id": 4,
                    "attribute": {
                        "id": 4
                    }
                },
                {
                    "id": 7,
                    "attribute": {
                        "id": 8
                    }
                },
                {
                    "id": 5,
                    "attribute": {
                        "id": 6
                    }
                },
                {
                    "id": 6,
                    "attribute": {
                        "id": 7
                    }
                }
            ]
        },
        {
            "id": 3,
            "entityType": {
                "code": "REGISTER"
            },
            "attributes": [
                {
                    "id": 4,
                    "attribute": {
                        "id": 4
                    }
                },
                {
                    "id": 7,
                    "attribute": {
                        "id": 8
                    }
                },
                {
                    "id": 5,
                    "attribute": {
                        "id": 6
                    }
                },
                {
                    "id": 6,
                    "attribute": {
                        "id": 7
                    }
                }
            ]
        },
        {
            "id": 3,
            "entityType": {
                "code": "REGISTER"
            },
            "attributes": [
                {
                    "id": 4,
                    "attribute": {
                        "id": 4
                    }
                },
                {
                    "id": 7,
                    "attribute": {
                        "id": 8
                    }
                },
                {
                    "id": 5,
                    "attribute": {
                        "id": 6
                    }
                },
                {
                    "id": 6,
                    "attribute": {
                        "id": 7
                    }
                }
            ]
        }
    ],
    "page": 1,
    "pageSize": 4,
    "total": 4
}

As you can see I get the same entity with Id = 3 4 times in the result set, due to 4 attributes bound to that entity. How can I remove such duplicates in result set? Thank you in advance

Expected behavior

No duplicates are returned in result

Actual behavior

Duplicates are returned when entity has several @onetomany or @manytomany bonds fetched

Environment

Version: 1.6.11
JPA-Provider: Hibernate 6.4.4.Final
DBMS: PostgreSQL 16

@beikov
Copy link
Member

beikov commented Jul 5, 2024

Please share the generated SQL queries.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants