I try to select the Article list by Tag which join by foreign key:
@Repository
public interface ArticleRepository extends JpaRepository<Article, Long>, JpaSpecificationExecutor<Article> {}
// Service call
public List<Article> findAllArticlesWithTag(String tag) {
return articleRepository
.findAll(articleSpecificationFactory.allArticlesWithTag(tag));
}
The problem in Specification factory method allArticlesWithTag(String tag)
public Specification<Article> allArticlesWithTag(String tag) {
return new Specification<Article>() {
@Override
public Predicate toPredicate(Root<Article> root,
CriteriaQuery<?> query,
CriteriaBuilder builder) {
Predicate predicate = builder.conjunction();
if (Objects.nonNull(tag) && !tag.isBlank()) {
predicate.getExpressions().add(
builder.in(builder.equal(root.get("tags"), tag))); // problem here
}
return predicate;
}
};
}
How can I implement toPredicate for correct selection articles by tag?
SQL scheme:
CREATE TABLE IF NOT EXISTS articles
(
id BIGSERIAL PRIMARY KEY,
title VARCHAR(255) UNIQUE
);
CREATE TABLE IF NOT EXISTS tags
(
article_id BIGINT REFERENCES articles (id),
tag VARCHAR(255)
);
But Tag entity no has its own java entity and represent as @ElementCollection:
@Getter
@Setter
@Entity
@ToString
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "articles")
public class Article {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ElementCollection(targetClass = String.class,
fetch = FetchType.EAGER)
@CollectionTable(name = "tags",
joinColumns = @JoinColumn(name = "article_id"))
@Column(name = "tag")
private List<String> tags = new ArrayList<>();
}
I think it's should be a combination of CriteriaBuilder builder calls but how exactly? builder.in(builder.equal(root.get("tags"), tag)) is wrong.