@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 中。

results matching ""

    No results matching ""