Search code examples
javajpacriteria

JPA Criteria API join


Help me plz with one moment. I read about 10 articles already, but don't understand join moment. I have 2 tables:

public class News implements Serializable {
@Id
@GeneratedValue (generator = "increment")
@GenericGenerator (name = "increment", strategy = "increment")
private int id;
@Column
private String name;
@Column
private Date created;
@Column
private String data;
@ManyToOne (cascade = CascadeType.ALL, fetch = FetchType.LAZY)
@JoinColumn (name = "category_id")
private NewsCategoryDict category;
// getters, setters
}

and

public class NewsCategoryDict implements Serializable {
@Id
@GeneratedValue (generator = "increment")
@GenericGenerator (name = "increment", strategy = "increment")
private int id;
@Column
private String name;
@OneToMany (mappedBy = "category", cascade = CascadeType.ALL)
private List<News> news = new ArrayList<>();
}

I want a query works like

SELECT * FROM news, categorynews WHERE news.category_id = categorynews.id;

And then get the result in jsp with

    <div id="list_news">
        <c:forEach items="${news}" var="news">
            <h5>${news.id} : ${news.name} - ${news.created} ; ${news.data} (${news.category.name})</h5>
        </c:forEach>
    </div>

And I just can't understand this JOIN with Criteria API. Can you help me ? Try to use this snippet, but get a error

public List<News> getAll() {
    CriteriaBuilder cb = em.getCriteriaBuilder();
    CriteriaQuery<News> cq = cb.createQuery(News.class);
    Root<News> rootFromNews = cq.from(News.class);
    Join<NewsCategoryDict, News> join = rootFromNews.join("category");
    cq.select(join);

    return em.createQuery(cq).getResultList();
}

PropertyNotFoundException: Property 'created' not found on type ru.r1k0.spring.model.NewsCategoryDict


Solution

  • Assuming you want to return an instance of News associated to an instance of NewsCategoryDict, your criteria query should look as follows:

    public List<News> getAll() {
        CriteriaBuilder cb = em.getCriteriaBuilder();
        CriteriaQuery<News> cq = cb.createQuery(News.class);
        Root<News> rootFromNews = cq.from(News.class);
        Join<News, NewsCategoryDict> join = rootFromNews.join("category"); // #1
        cq.select(rootFromNews);  // #2
    
        return em.createQuery(cq).getResultList();
    }
    

    The modified lines are marked with #1 and #2 comments.

    The query should return all News which have a matching NewsCategoryDict; but News records which are not associated to aNewsCategoryDict record will not be returned.