@org.hibernate.annotations.Filter 可以标记在 Entity 或者 collections property 上。与 @Where 的不同是 @Filter 可以在运行时动态改变 filter clause
@Filter mapping usage
package org.example.demo.hibernate;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.Entity;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Persistence;
import org.hibernate.Session;
import org.hibernate.annotations.Filter;
import org.hibernate.annotations.FilterDef;
import org.hibernate.annotations.ParamDef;
public class Test {
public static void main(String[] args) throws Exception {
EntityManagerFactory factory = Persistence.createEntityManagerFactory("test");
EntityManager em = factory.createEntityManager();
Client client = new Client();
Account account1 = new Account();
account1.active = true;
account1.client = client;
client.accounts.add(account1);
Account account2 = new Account();
account2.active = false;
account2.client = client;
client.accounts.add(account2);
Account account3 = new Account();
account3.active = true;
account3.client = client;
client.accounts.add(account3);
em.getTransaction().begin();
em.persist(client);
em.persist(account1);
em.persist(account2);
em.persist(account3);
em.getTransaction().commit();
em.clear();
Client c = em.find(Client.class, client.id);
// [org.example.demo.hibernate.Test$Account@377c68c6, org.example.demo.hibernate.Test$Account@430fa4ef, org.example.demo.hibernate.Test$Account@1761de10]
System.out.println(c.accounts);
List<Account> accounts = em.createQuery("from Account", Account.class).getResultList();
// [org.example.demo.hibernate.Test$Account@377c68c6, org.example.demo.hibernate.Test$Account@430fa4ef, org.example.demo.hibernate.Test$Account@1761de10]
System.out.println(accounts);
em.clear();
em.unwrap(Session.class).enableFilter("activeAccount").setParameter("active", true);
c = em.find(Client.class, client.id);
// [org.example.demo.hibernate.Test$Account@14bae047, org.example.demo.hibernate.Test$Account@7ed9ae94]
System.out.println(c.accounts);
accounts = em.createQuery("from Account", Account.class).getResultList();
// [org.example.demo.hibernate.Test$Account@14bae047, org.example.demo.hibernate.Test$Account@7ed9ae94]
System.out.println(accounts);
Account a = em.find(Account.class, account2.id);
// org.example.demo.hibernate.Test$Account@5491f68b
System.out.println(a);
em.close();
factory.close();
}
@Entity(name = "Client")
public static class Client {
@Id
@GeneratedValue
private Long id;
@OneToMany(mappedBy = "client")
@Filter(name = "activeAccount", condition = "active = :active")
private List<Account> accounts = new ArrayList<>();
}
@Entity(name = "Account")
@FilterDef(name = "activeAccount", parameters = @ParamDef(name = "active", type = "boolean"))
@Filter(name = "activeAccount", condition = "active = :active")
public static class Account {
@Id
@GeneratedValue
private Long id;
@ManyToOne
private Client client;
boolean active;
}
}
生成的 SQL
alter table Account drop constraint FKpei4spdwejr1mbu98yngbojd8
drop table if exists Account cascade
drop table if exists Client cascade
drop sequence if exists hibernate_sequence
create sequence hibernate_sequence start 1 increment 1
create table Account (id int8 not null, active boolean not null, client_id int8, primary key (id))
create table Client (id int8 not null, primary key (id))
alter table Account add constraint FKpei4spdwejr1mbu98yngbojd8 foreign key (client_id) references Client
select nextval ('hibernate_sequence')
select nextval ('hibernate_sequence')
select nextval ('hibernate_sequence')
select nextval ('hibernate_sequence')
insert into Client (id) values (1)
insert into Account (active, client_id, id) values (true, 1, 2)
insert into Account (active, client_id, id) values (false, 1, 3)
insert into Account (active, client_id, id) values (true, 1, 4)
select test_clien0_.id as id1_1_0_ from Client test_clien0_ where test_clien0_.id=1
select accounts0_.client_id as client_i3_0_0_, accounts0_.id as id1_0_0_, accounts0_.id as id1_0_1_, accounts0_.active as active2_0_1_, accounts0_.client_id as client_i3_0_1_ from Account accounts0_ where accounts0_.client_id=1
select test_accou0_.id as id1_0_, test_accou0_.active as active2_0_, test_accou0_.client_id as client_i3_0_ from Account test_accou0_
select test_clien0_.id as id1_1_0_ from Client test_clien0_ where test_clien0_.id=1
select accounts0_.client_id as client_i3_0_0_, accounts0_.id as id1_0_0_, accounts0_.id as id1_0_1_, accounts0_.active as active2_0_1_, accounts0_.client_id as client_i3_0_1_ from Account accounts0_ where accounts0_.active = true and accounts0_.client_id=1
select test_accou0_.id as id1_0_, test_accou0_.active as active2_0_, test_accou0_.client_id as client_i3_0_ from Account test_accou0_ where test_accou0_.active = true
select test_accou0_.id as id1_0_0_, test_accou0_.active as active2_0_0_, test_accou0_.client_id as client_i3_0_0_, test_clien1_.id as id1_1_1_ from Account test_accou0_ left outer join Client test_clien1_ on test_accou0_.client_id=test_clien1_.id where test_accou0_.id=3
不能在 collection property 上同时使用 @Filter and @org.hibernate.annotations.Cache ,这是因为 filtering information 没有存储在 second-level cache 中。