Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Hibernate @Filter does not work in JPA?

I'm using JPA with Hibernate as a JPA provider. I cannot figure out how to configure my entities to apply a hibernate filter to a One-to-Many association.

I have a Master with a collection of Details. Here are my entity definitions:

@Entity
public class Master extends Base {
    private List<Detail> details;

    @OneToMany
    @OrderColumn
    @JoinTable(name = "master_details")
    @Filter(name = "notDeleted")
//    @Where(clause = "deleted = 'false'")
    public List<Detail> getDetails() {
        return details;
    }

    public void setDetails(List<Detail> details) {
        this.details = details;
    }
}

@Entity
@FilterDef(name = "notDeleted", defaultCondition = "deleted = false")
public class Detail extends Base {
    private Boolean deleted = false;

    public Boolean getDeleted() {
        return deleted;
    }

    public void setDeleted(Boolean deleted) {
        this.deleted = deleted;
    }
}

The Base is nothing special but a simple MappedSuperClass:

@MappedSuperclass
public class Base {
    private Long id;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }
}

When loading a Master by entityManager.find(Master.class, mid), the filter should prvent all Details from loading but I checked the sql queries generated by hibernate (by show_sql=true) and no where clause is added when loading details of the master !!! A sample query generated by hibernate is:

select
    details0_.Master_id as Master1_6_1_,
    details0_.details_id as details2_1_,
    details0_.details_ORDER as details3_1_,
    detail1_.id as id7_0_,
    detail1_.deleted as deleted7_0_,
from
    master_details details0_ 
inner join
    Detail detail1_ 
        on details0_.details_id=detail1_.id 
where
    details0_.Master_id=?

After some search there was some hints that "loading by id will not use filters, use queries" so I tried the following but no gain :(

entityManager.createQuery("from Master where id=" + mid).getSingleResult();

But just if the @Where above getDetails is uncommented (instead of @Filter), its clause is added to the query generated by hibernate (but I cannot use @Where)

like image 690
rabolfazl Avatar asked May 25 '14 20:05

rabolfazl


1 Answers

The Hibernate @Filter needs to be manually activated via enableFilter method:

session.enableFilter("myFilter").setParameter("myFilterParam", "some-value");

However, filters are useful when you need to parameterize the filtering condition. And, you don't seem to need a dynamic filtering clause.

For this reason, you could use the Hibernate @Where filter, like this:

@org.hibernate.annotations.Where(clause="deleted=false")        
public List<Detail> getDetails() {
    return details;
}

This way, you should get the list of non-deleted Detail entities.

like image 144
Vlad Mihalcea Avatar answered Oct 24 '22 01:10

Vlad Mihalcea