I have two api endpoints:
/api/posts
- Fetches list of paginated posts/api/countries/{country}/posts
- Fetches list of paginated posts by countrySo I have following entity:
@Data
@Entity
@Table(name = "posts")
@EntityListeners(AuditingEntityListener.class)
@NamedEntityGraph(
name = "Post.Resource",
attributeNodes = @NamedAttributeNode("country")
)
public class Post {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
private String title;
private String body;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "country_id")
private Country country;
@Column(name = "published_at")
private LocalDateTime publishedAt;
@CreatedDate
@Column(name = "created_at")
private LocalDateTime createdAt;
@LastModifiedDate
@Column(name = "updated_at")
private LocalDateTime updatedAt;
public boolean isPublished() {
return publishedAt != null;
}
public boolean isDraft() {
return !isPublished();
}
}
And I have defined following repository. Note that how I am defining entity graph for last two methods, and I need it that way, because I do not want to override findAll()
method, because in the future I will need to load posts without any relations. Also another thing I want it to be predicate, so that in various different services I can reuse method, and not create method for every single query...
@Repository
public interface PostRepository extends JpaRepository<Post, Long>,
JpaSpecificationExecutor<Post>,
QuerydslPredicateExecutor<Post>
{
@EntityGraph("Post.Resource")
Optional<Post> findPostResourceById(long id);
@Query("SELECT post FROM Post post")
@EntityGraph("Post.Resource")
Page<Post> findAllPostResources(Pageable pageable);
@Query("SELECT post FROM Post post")
@EntityGraph("Post.Resource")
Page<Post> findAllPostResources(Predicate predicate, Pageable pageable);
}
The problem is when I call findAllPostResources
with predicate and pageable arguments:
public Page<Post> getAllPostsByCountryPaginated(long countryId, Pageable pageable) {
return postRepository.findAllPostResources(QPost.post.country.id.eq(countryId), pageable);
}
It ignores predicate argument and execuites following query:
SELECT
post0_.id AS id1_13_0_,
country1_.id AS id1_3_1_,
post0_.body AS body2_13_0_,
post0_.country_id AS country_7_13_0_,
post0_.created_at AS created_3_13_0_,
post0_.published_at AS publishe4_13_0_,
post0_.title AS title5_13_0_,
post0_.updated_at AS updated_6_13_0_,
country1_.alpha2_code AS alpha2_3_1_,
country1_.alpha3_code AS alpha3_3_1_,
country1_.created_at AS created_4_3_1_,
country1_.name AS name5_3_1_,
country1_.updated_at AS updated_6_3_1_
FROM
posts post0_
LEFT OUTER JOIN countries country1_ ON
post0_.country_id = country1_.id
LIMIT ?
As you can see there is no WHERE caluse in SQL (WHERE country_id = ?
).
So, how to create findAll() method and define predicate, paging and also what entity graph to use inside JpaRepository? Or is this something that cannot be achieved this way and I will need to create custom repository implementation?
I have found solution for my problem: How to have methods with Predicate, Pageable and EntityGraph all at once and the answer is to use following library: