Ashes Duong
Ashes Duong

Reputation: 13

Disable Fetch association mapping with JPA/Hibernate

I have trouble with JPA/Hibernate, no matter what I set fetch = FetchType.Lazy or fetch = FetchType.Eager.

My custom method not working (when debug, I see answers collection is PersistentBag and whenever I call getter, the answer is actually created and some condition with WITH in my custom was not applied). That's what I dont want, I want it will be set at my custom method.

Question is :

1, Am I doing right, disable fetch type and set association at hql query ?

2, If I am doing right, why it's not working, association only when call getter ?

3, If I am wrong, Please tell me how to implement this.

Thanks for reading .

My Parent class :

@Entity
@NamedQuery(name="Question.findAll", query="SELECT q FROM Question q")
public class Question implements Serializable {

    //bi-directional many-to-one association to Answer
    @OneToMany(mappedBy="question",fetch=FetchType.LAZY)
    @JsonManagedReference
    private List<Answer> answers;

  ...
}

And Child class :

@Entity
@NamedQuery(name="Answer.findAll", query="SELECT a FROM Answer a")
public class Answer implements Serializable {

    //bi-directional many-to-one association to Question
    @ManyToOne
    @JoinColumn(name="question_id")
    @JsonBackReference
    private Question question;

  ...

}

In My custom method , I'm using HQL as :

    public List<Question> search() {

        String sql = "SELECT distinct(question)"
                + " FROM Question as question "
                + " LEFT JOIN question.answers as answer with answer.isDeleted = true";

        List<Question> result = query.getResultList();

        return result;
    }

PS. I found I have very similar issue with this post https://stackoverflow.com/a/1372725 but I dont know how to follow his instruction.

Upvotes: 1

Views: 4210

Answers (2)

v.ladynev
v.ladynev

Reputation: 19976

This query

SELECT distinct(question)
  FROM Question as question
  LEFT JOIN question.answers as answer with answer.isDeleted = true

means the same as

SELECT distinct(question)
  FROM Question

This query

SELECT distinct(question)
  FROM Question as question
  INNER JOIN question.answers as answer with answer.isDeleted = true

means get questions that have at least one answer with isDeleted = true.

To fetch a lazy association join fetch can be used

 SELECT distinct(question)
      FROM Question as question
      LEFT JOIN FETCH question.answers

But, I think, it is impossible to fetch an association with a condition. There is an example using EclipseLink:

http://java-persistence-performance.blogspot.com.by/2012/04/objects-vs-data-and-filtering-join.html#Filtering

You can try something similar with Hibernate. I think, it will not work.

Other option is use @Where

@OneToMany(mappedBy="question",fetch=FetchType.LAZY)
@Where(clause = "is_deleted = 0")
private List<Answer> answers;

But, probably, it doesn't suitable to you, because of it is impossible to disable @Where clause. You will never have all answers with fetching.

So better to load answers with condition with a separate query.

Upvotes: 0

Vũ L&#234;
Vũ L&#234;

Reputation: 11

JPA doesn't provide any specification on mapping annotations to select fetch strategy. In general, related entities can be fetched in any one of the ways given below

  • SELECT => one query for root entities + one query for related mapped entity/collection of each root entity = (n+1) queries
  • SUBSELECT => one query for root entities + second query for related mapped entity/collection of all root entities retrieved in first query = 2 queries
  • JOIN => one query to fetch both root entities and all of their mapped entity/collection = 1 query

Set your @OneToMany with fetch=FetchType.LAZY and add @Fetch(FetchMode.SELECT) Then your query will working fine.

Upvotes: 1

Related Questions