Skip to content

Commit

Permalink
fix: @query with projection and List<List>
Browse files Browse the repository at this point in the history
  • Loading branch information
sdelamo committed Nov 7, 2022
1 parent 89e588b commit bd33ddc
Show file tree
Hide file tree
Showing 7 changed files with 392 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
package io.micronaut.data.hibernate.querygroupby

import io.micronaut.context.annotation.Property
import io.micronaut.data.hibernate.entities.MicronautProject
import io.micronaut.data.hibernate.entities.MicronautTask
import io.micronaut.test.extensions.spock.annotation.MicronautTest
import jakarta.inject.Inject
import spock.lang.PendingFeature
import spock.lang.Specification

import java.time.LocalDate

@MicronautTest(startApplication = false, packages = "io.micronaut.data.hibernate.entities")
@Property(name = "datasources.default.name", value = "mydb")
@Property(name = 'jpa.default.properties.hibernate.hbm2ddl.auto', value = 'create-drop')
class TaskRepositorySpec extends Specification {

@Inject
MicronautProjectRepository projectRepository

@Inject
MicronautTaskRepository taskRepository

@PendingFeature
void "@Query projecting to a POJO"() {
given:
MicronautProject p1 = projectRepository.save(new MicronautProject("P1", "Project 1", "Description of Project 1"))
MicronautProject p2 = projectRepository.save(new MicronautProject("P2", "Project 2", "Description of Project 2"))
MicronautProject p3 = projectRepository.save(new MicronautProject("P3", "Project 3", "Description of Project 3"))
MicronautTask t1 = taskRepository.save(new MicronautTask("Task 1", "Task 1 Description", LocalDate.of(2025, 1, 12), p1, TaskStatus.TO_DO))
MicronautTask t2 = taskRepository.save(new MicronautTask("Task 2", "Task 2 Description", LocalDate.of(2025, 2, 10), p1, TaskStatus.TO_DO))
MicronautTask t3 = taskRepository.save(new MicronautTask("Task 3", "Task 3 Description", LocalDate.of(2025, 3, 16), p1, TaskStatus.TO_DO))
MicronautTask t4 = taskRepository.save(new MicronautTask("Task 4", "Task 4 Description", LocalDate.of(2025, 6, 25), p1, TaskStatus.IN_PROGRESS))

expect:
3 == countIterableElements(projectRepository.findAll())

4 == countIterableElements(taskRepository.findAll())

when:
Iterable<TasksPerYear> tasks = taskRepository.countByDueYear()

then:
2 == countIterableElements(tasks)

cleanup:
taskRepository.delete(t4)
taskRepository.delete(t3)
taskRepository.delete(t2)
taskRepository.delete(t1)
projectRepository.delete(p3)
projectRepository.delete(p2)
projectRepository.delete(p1)
}

@PendingFeature
void "@Query returning List of List"() {
given:
MicronautProject p1 = projectRepository.save(new MicronautProject("P1", "Project 1", "Description of Project 1"))
MicronautProject p2 = projectRepository.save(new MicronautProject("P2", "Project 2", "Description of Project 2"))
MicronautProject p3 = projectRepository.save(new MicronautProject("P3", "Project 3", "Description of Project 3"))
MicronautTask t1 = taskRepository.save(new MicronautTask("Task 1", "Task 1 Description", LocalDate.of(2025, 1, 12), p1, TaskStatus.TO_DO))
MicronautTask t2 = taskRepository.save(new MicronautTask("Task 2", "Task 2 Description", LocalDate.of(2025, 2, 10), p1, TaskStatus.TO_DO))
MicronautTask t3 = taskRepository.save(new MicronautTask("Task 3", "Task 3 Description", LocalDate.of(2025, 3, 16), p1, TaskStatus.TO_DO))
MicronautTask t4 = taskRepository.save(new MicronautTask("Task 4", "Task 4 Description", LocalDate.of(2025, 6, 25), p1, TaskStatus.IN_PROGRESS))

expect:
3 == countIterableElements(projectRepository.findAll())

4 == countIterableElements(taskRepository.findAll())
when:
List<List<Integer>> tasks = taskRepository.countByDueYearReturnList()

then:
2 == tasks.size()
tasks.every { it.size() == 2 }

cleanup:
taskRepository.delete(t4)
taskRepository.delete(t3)
taskRepository.delete(t2)
taskRepository.delete(t1)
projectRepository.delete(p3)
projectRepository.delete(p2)
projectRepository.delete(p1)
}

static int countIterableElements(Iterable<?> iterable) {
int count = 0
Iterator<?> iterator = iterable.iterator()
if (iterator.hasNext()) {
do {
iterator.next()
count++
} while (iterator.hasNext())
}
count
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
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<>();
public MicronautProject() {
}

public MicronautProject(String code, String name, String description) {
this.code = code;
this.name = name;
this.description = description;
}

@Override
public int hashCode() {
return Objects.hashCode(code);
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
MicronautProject other = (MicronautProject) obj;
if (code == null) {
if (other.code != null)
return false;
} else if (!code.equals(other.code))
return false;
return true;
}

public Long getId() {
return id;
}

public void setId(Long id) {
this.id = id;
}

public String getCode() {
return code;
}

public void setCode(String code) {
this.code = code;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getDescription() {
return description;
}

public void setDescription(String description) {
this.description = description;
}

public Set<MicronautTask> getTasks() {
return tasks;
}

public void setTasks(Set<MicronautTask> tasks) {
this.tasks = tasks;
}

@Override
public String toString() {
return "Project [id=" + id + ", code=" + code + ", name=" + name + ", description=" + description + "]";
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
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;


public MicronautTask() {
}
public MicronautTask(String name, String description, LocalDate dueDate, MicronautProject project) {
this(name, description, dueDate, project, TaskStatus.TO_DO);
}

public MicronautTask(String name, String description, LocalDate dueDate, MicronautProject project, TaskStatus status) {
this.name = name;
this.description = description;
this.dueDate = dueDate;
this.status = status;
this.project = project;
}

@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
MicronautTask other = (MicronautTask) obj;
if (uuid == null) {
if (other.uuid != null)
return false;
} else if (!uuid.equals(other.uuid))
return false;
return true;
}
@Override
public int hashCode() {
return Objects.hash(uuid);
}


public Long getId() {
return id;
}

public void setId(Long id) {
this.id = id;
}

public String getUuid() {
return uuid;
}

public void setUuid(String uuid) {
this.uuid = uuid;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getDescription() {
return description;
}

public void setDescription(String description) {
this.description = description;
}

public LocalDate getDueDate() {
return dueDate;
}

public void setDueDate(LocalDate dueDate) {
this.dueDate = dueDate;
}

public TaskStatus getStatus() {
return status;
}

public void setStatus(TaskStatus status) {
this.status = status;
}

public MicronautProject getProject() {
return project;
}

public void setProject(MicronautProject project) {
this.project = project;
}


@Override
public String toString() {
return "Task [id=" + id + ", name=" + name + ", description=" + description + ", dueDate=" + dueDate + ", status=" + status + ", project=" + project + "]";
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package io.micronaut.data.hibernate.querygroupby;

import io.micronaut.data.annotation.Repository;
import io.micronaut.data.hibernate.entities.MicronautProject;
import io.micronaut.data.repository.CrudRepository;
@Repository
public interface MicronautProjectRepository extends CrudRepository<MicronautProject, Long> {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
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();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package io.micronaut.data.hibernate.querygroupby;

public enum TaskStatus {
TO_DO("To Do"),
IN_PROGRESS("In Progress"),
ON_HOLD("On Hold"),
DONE("Done");
private final String label;

private TaskStatus(String label) {
this.label = label;
}
public String getLabel() {
return label;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
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;
}
}

0 comments on commit bd33ddc

Please sign in to comment.