Search code examples
springhibernatespring-bootspring-data-jpaprojection

Retriving specific field of child collection using projection


   class Post {
  @Id
  Long id;
  String title;
 @ManyToMany(fetch = FetchType.LAZY,
                cascade = {
                    CascadeType.PERSIST,
                    CascadeType.MERGE,

                })
        @JoinTable(name = "post_tags",
                joinColumns = { @JoinColumn(name = "post_id") },
                inverseJoinColumns = { @JoinColumn(name = "tag_id") })

    Set<Tag> tags;
// constructor
// getters
// setters
}

class Tag{
   @Id
   Long id
   String name;
// getters, setter, constructor
}

interface PostProjection{
     Long getId();
     String getTitle();
 @Value("#{target.tags.size()}")
     int  getNumberOfTags();

}

In PostProjection I would like to retrive the name of each tags belong to this post. I am able to get the number of tags for a specific post but not the name of the tag. I don't want the tag id.I tried doing this:

 @Value("#{target.tags.name}")
         Set<String getTagsNanes();

But that doesn't work. How can retrieve the name of every tag belong enter to a specific post using projection? Thank you in advance!


Solution

  • My advice is to avoid using Open Projections unless you really need that. Remember that, according with docs, when using Open Projections, Spring will not optimize your query.

    Spring Data cannot apply query execution optimizations in this case, because the SpEL expression could use any attribute of the aggregate root.

    The solution above (Java 8) will get a Set of Tag names from your projection.

    import static java.util.stream.Collectors.toSet;
    
    public interface PostProjection {
        String getTitle();
    
        Set<Tag> getTags();
    
        default Set<String> getTagsNames() {
            return getTags().stream().map(Tag::getName).collect(toSet());
        }
    
    }