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

fix: @Query with projection and List<List> for Data JPA #1823

Open
wants to merge 1 commit into
base: 4.7.x
Choose a base branch
from

Conversation

sdelamo
Copy link
Contributor

@sdelamo sdelamo commented Nov 7, 2022

This PR contains two failing tests annotated with @PendingFeature.

Given these Entities with a ManyToOne Relationship

package io.micronaut.data.hibernate.entities;

import io.micronaut.data.hibernate.querygroupby.TaskStatus;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import java.time.LocalDate;
import java.util.Objects;
import java.util.UUID;

@Entity
public class MicronautTask {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    @Column(unique = true, nullable = false, updatable = false)
    private String uuid = UUID.randomUUID().toString();
    private String name;
    private String description;
    private LocalDate dueDate;

    private TaskStatus status;

    @ManyToOne(optional = false)
    private MicronautProject project;

...
}

and:

package io.micronaut.data.hibernate.entities;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;

@Entity
public class MicronautProject {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    @Column(unique = true, nullable = false, updatable = false)
    private String code;
    private String name;
    private String description;
    @OneToMany(mappedBy = "project", orphanRemoval = true, fetch = FetchType.EAGER, cascade = CascadeType.ALL)
    private Set<MicronautTask> tasks = new HashSet<>();
   ....
}

Both methods in this repository fail:

package io.micronaut.data.hibernate.querygroupby;

import io.micronaut.data.annotation.Query;
import io.micronaut.data.annotation.Repository;
import io.micronaut.data.hibernate.entities.MicronautTask;
import io.micronaut.data.repository.CrudRepository;

import java.util.List;
@Repository
public interface MicronautTaskRepository extends CrudRepository<MicronautTask, Long> {
    @Query("select count(*), year(t.dueDate) from MicronautTask t group by year(t.dueDate)")
    Iterable<TasksPerYear> countByDueYear();

    @Query("select count(*), year(t.dueDate) from MicronautTask t group by year(t.dueDate)")
    List<List<Integer>> countByDueYearReturnList();
}

TasksPerYear is a POJO:

package io.micronaut.data.hibernate.querygroupby;

import io.micronaut.core.annotation.Introspected;

@Introspected
public class TasksPerYear {
    private final String number;
    private final String year;

    public TasksPerYear(String number, String year) {
        this.number = number;
        this.year = year;
    }

    public String getNumber() {
        return number;
    }

    public String getYear() {
        return year;
    }
}

I expected both to pass.

@sdelamo sdelamo added the type: bug Something isn't working label Nov 7, 2022
@dstepanov
Copy link
Contributor

@radovanradic Can you please investigate the problem?

@radovanradic
Copy link
Contributor

@radovanradic Can you please investigate the problem?

I will

@sdelamo sdelamo force-pushed the issue-query-projection branch from 316d6c7 to bd33ddc Compare November 7, 2022 10:20
@sonarcloud
Copy link

sonarcloud bot commented Nov 7, 2022

Kudos, SonarCloud Quality Gate passed!    Quality Gate passed

Bug A 0 Bugs
Vulnerability A 0 Vulnerabilities
Security Hotspot A 0 Security Hotspots
Code Smell A 0 Code Smells

No Coverage information No Coverage information
0.0% 0.0% Duplication

import java.util.List;
@Repository
public interface MicronautTaskRepository extends CrudRepository<MicronautTask, Long> {
@Query("select count(*), year(t.dueDate) from MicronautTask t group by year(t.dueDate)")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This works when written as

@Query("select count(*) as number, year(t.dueDate) as year from MicronautTask t group by year(t.dueDate)")

because of this line of our code in AbstractHibernateRepository

Set<String> properties = tuple.getElements().stream().map(TupleElement::getAlias).collect(Collectors.toCollection(() -> new TreeSet<>(String.CASE_INSENSITIVE_ORDER)));

expects that TupleElement::getAlias is not null and is one of properties Set which is number, year in our case. Then query can be executed.

Iterable<TasksPerYear> countByDueYear();

@Query("select count(*), year(t.dueDate) from MicronautTask t group by year(t.dueDate)")
List<List<Integer>> countByDueYearReturnList();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And this fails with the error

Cannot create TypedQuery for query with more than one return using requested result type [java.util.List]

I tried to change it to List<Object[]> which I know Hibernate can return but does not work in our code and we probably can't support it now without some refactoring.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: bug Something isn't working
Projects
Status: No status
Development

Successfully merging this pull request may close these issues.

3 participants