zerkenn
zerkenn

Reputation: 37

JPA @OneToMany cast collection to its size

I have a piece of code with School entity that contains a list of its students (List<Student> schoolStudents). Is it possible to map this list to its size and have Integer numberOfStudents; entity instead? I tried to use @JoinColumnsOrFormulas with selecting count of students query but I'm always getting this exception:

org.hibernate.AnnotationException: Illegal attempt to map a non collection as a @OneToMany, @ManyToMany or @CollectionOfElements: com.xyz.School.numberOfStudents

Here is an example of code:

School.java

@OneToMany(mappedBy = "school")
    private List<Student> schoolStudents = new ArrayList<Student>(); //desired: private Integer numberOfStudents;

Student.java

@JoinColumn(name = "schoolId")
private School school;

SchoolMapper.java

@Mapping(target = "students", source = "schoolStudents")
    SchoolDto schoolToSchoolDto(School school);

@Mapping(target = "schoolId", source = "school")
    StudentDto studentToStudentDto(Student source);

SchoolDto.java

public class SchoolDto {
    private String name;
    private List<Student> students; //desired: private Integer students;
}

StudentDto.java

public class StudentDto {
    private School school;
    private String studentName;
}

Upvotes: 1

Views: 406

Answers (1)

Aleksandr Semyannikov
Aleksandr Semyannikov

Reputation: 1442

You cant make field with count of related objects inside your entity.

What you can is to map it's size using expressions:

  1. Create method returning size of students list

    @OneToMany(mappedBy = "school", fetch = FetchType.LAZY)
    private List<Student> schoolStudents = new ArrayList<Student>();
    
    public int getStudentsCount() {
        return schoolStudents.size();
    }
    
  2. Modify your DTO

    public class SchoolDto {
        private String name;
        private int students;
    }
    
  3. Use expression inside your mapper

    @Mapping(target = "students", expression = "java(school.getStudentsCount())")
    SchoolDto schoolToSchoolDto(School school);
    

If your collection of students is large and you are concerned about performance\memory you can use annotation @LazyCollection(LazyCollectionOption.EXTRA) but be careful because it may increase number of queries.

Upvotes: 2

Related Questions