HHH-12349 - User Guide documentation for @Filter is too verbose

This commit is contained in:
Vlad Mihalcea 2018-07-11 17:42:05 +03:00
parent b09fbb431d
commit 5e6298d2f9
12 changed files with 538 additions and 433 deletions

View File

@ -1829,19 +1829,40 @@ include::{sourcedir}/basic/WhereJoinTableTest.java[tags=mapping-where-join-table
[[mapping-column-filter]] [[mapping-column-filter]]
==== `@Filter` ==== `@Filter`
The `@Filter` annotation is another way to filter out entities or collections using custom SQL criteria, for both entities and collections. The `@Filter` annotation is another way to filter out entities or collections using custom SQL criteria.
Unlike the `@Where` annotation, `@Filter` allows you to parameterize the filter clause at runtime. Unlike the `@Where` annotation, `@Filter` allows you to parameterize the filter clause at runtime.
[[mapping-filter-example]] Now, considering we have the following `Account` entity:
.`@Filter` mapping usage
[[mapping-filter-account-example]]
.`@Filter` mapping entity-level usage
==== ====
[source, JAVA, indent=0] [source, JAVA, indent=0]
---- ----
include::{sourcedir}/basic/FilterTest.java[tags=mapping-filter-example] include::{sourcedir}/basic/FilterTest.java[tags=mapping-filter-Account-example]
---- ----
==== ====
If the database contains the following entities: [NOTE]
====
Notice that the `active` property is mapped to the `active_status` column.
This mapping was done to show you that the `@Filter` condition uses a SQL condition, and not a JPQL filtering criteria.
====
As already explained, we can also apply the `@Filter` annotation for collections as illustrated by the `Client` entity:
[[mapping-filter-client-example]]
.`@Filter` mapping collection-level usage
====
[source, JAVA, indent=0]
----
include::{sourcedir}/basic/FilterTest.java[tags=mapping-filter-Client-example]
----
====
If we persist a `Client` with three associated `Account` entities,
Hibernate will execute the following SQL statements:
[[mapping-filter-persistence-example]] [[mapping-filter-persistence-example]]
.Persisting and fetching entities with a `@Filter` mapping .Persisting and fetching entities with a `@Filter` mapping
@ -1858,6 +1879,21 @@ include::{extrasdir}/basic/mapping-filter-persistence-example.sql[]
==== ====
By default, without explicitly enabling the filter, Hibernate is going to fetch all `Account` entities. By default, without explicitly enabling the filter, Hibernate is going to fetch all `Account` entities.
[[mapping-no-filter-entity-query-example]]
.Query entities mapped without activating the `@Filter`
====
[source, JAVA, indent=0]
----
include::{sourcedir}/basic/FilterTest.java[tags=mapping-no-filter-entity-query-example]
----
[source, SQL, indent=0]
----
include::{extrasdir}/basic/mapping-no-filter-entity-query-example.sql[]
----
====
If the filter is enabled and the filter parameter value is provided, If the filter is enabled and the filter parameter value is provided,
then Hibernate is going to apply the filtering criteria to the associated `Account` entities. then Hibernate is going to apply the filtering criteria to the associated `Account` entities.
@ -1878,6 +1914,7 @@ include::{extrasdir}/basic/mapping-filter-entity-query-example.sql[]
[IMPORTANT] [IMPORTANT]
==== ====
Filters apply to entity queries, but not to direct fetching. Filters apply to entity queries, but not to direct fetching.
Therefore, in the following example, the filter is not taken into consideration when fetching an entity from the Persistence Context. Therefore, in the following example, the filter is not taken into consideration when fetching an entity from the Persistence Context.
[[mapping-filter-entity-example]] [[mapping-filter-entity-example]]
@ -1896,7 +1933,22 @@ As you can see from the example above, contrary to an entity query, the filter d
==== ====
Just like with entity queries, collections can be filtered as well, but only if the filter is explicitly enabled on the currently running Hibernate `Session`. Just like with entity queries, collections can be filtered as well, but only if the filter is explicitly enabled on the currently running Hibernate `Session`.
This way, when fetching the `accounts` collections, Hibernate is going to apply the `@Filter` clause filtering criteria to the associated collection entries.
[[mapping-no-filter-collection-query-example]]
.Traversing collections without activating the `@Filter`
====
[source, JAVA, indent=0]
----
include::{sourcedir}/basic/FilterTest.java[tags=mapping-no-filter-collection-query-example]
----
[source, SQL, indent=0]
----
include::{extrasdir}/basic/mapping-no-filter-collection-query-example.sql[]
----
====
When activating the `@Filter` and fetching the `accounts` collections, Hibernate is going to apply the filter condition to the associated collection entries.
[[mapping-filter-collection-query-example]] [[mapping-filter-collection-query-example]]
.Traversing collections mapped with `@Filter` .Traversing collections mapped with `@Filter`
@ -1922,7 +1974,7 @@ The main advantage of `@Filter` over the `@Where` clause is that the filtering c
It's not possible to combine the `@Filter` and `@Cache` collection annotations. It's not possible to combine the `@Filter` and `@Cache` collection annotations.
This limitation is due to ensuring consistency and because the filtering information is not stored in the second-level cache. This limitation is due to ensuring consistency and because the filtering information is not stored in the second-level cache.
If caching was allowed for a currently filtered collection, then the second-level cache would store only a subset of the whole collection. If caching were allowed for a currently filtered collection, then the second-level cache would store only a subset of the whole collection.
Afterward, every other Session will get the filtered collection from the cache, even if the Session-level filters have not been explicitly activated. Afterward, every other Session will get the filtered collection from the cache, even if the Session-level filters have not been explicitly activated.
For this reason, the second-level collection cache is limited to storing whole collections, and not subsets. For this reason, the second-level collection cache is limited to storing whole collections, and not subsets.
@ -1934,7 +1986,7 @@ For this reason, the second-level collection cache is limited to storing whole c
When using the `@Filter` annotation with collections, the filtering is done against the child entries (entities or embeddables). When using the `@Filter` annotation with collections, the filtering is done against the child entries (entities or embeddables).
However, if you have a link table between the parent entity and the child table, then you need to use the `@FilterJoinTable` to filter child entries according to some column contained in the join table. However, if you have a link table between the parent entity and the child table, then you need to use the `@FilterJoinTable` to filter child entries according to some column contained in the join table.
The `@FilterJoinTable` annotation can be, therefore, applied to a unidirectional `@OneToMany` collection as illustrate din the following mapping: The `@FilterJoinTable` annotation can be, therefore, applied to a unidirectional `@OneToMany` collection as illustrated in the following mapping:
[[mapping-filter-join-table-example]] [[mapping-filter-join-table-example]]
.`@FilterJoinTable` mapping usage .`@FilterJoinTable` mapping usage
@ -1945,7 +1997,11 @@ include::{sourcedir}/basic/FilterJoinTableTest.java[tags=mapping-filter-join-tab
---- ----
==== ====
If the database contains the following entities: The `firstAccounts` filter will allow us to get only the `Account` entities that have the `order_id`
(which tells the position of every entry inside the `accounts` collection)
less than a given number (e.g. `maxOrderId`).
Let's assume our database contains the following entities:
[[mapping-filter-join-table-persistence-example]] [[mapping-filter-join-table-persistence-example]]
.Persisting and fetching entities with a `@FilterJoinTable` mapping .Persisting and fetching entities with a `@FilterJoinTable` mapping
@ -1961,8 +2017,24 @@ include::{extrasdir}/basic/mapping-filter-join-table-persistence-example.sql[]
---- ----
==== ====
The collections can be filtered if the associated filter is enabled on the currently running Hibernate `Session`. The collections can be filtered only if the associated filter is enabled on the currently running Hibernate `Session`.
This way, when fetching the `accounts` collections, Hibernate is going to apply the `@FilterJoinTable` clause filtering criteria to the associated collection entries.
[[mapping-no-filter-join-table-collection-query-example]]
.Traversing collections mapped with `@FilterJoinTable` without enabling the filter
====
[source, JAVA, indent=0]
----
include::{sourcedir}/basic/FilterJoinTableTest.java[tags=mapping-no-filter-join-table-collection-query-example]
----
[source, SQL, indent=0]
----
include::{extrasdir}/basic/mapping-no-filter-join-table-collection-query-example.sql[]
----
====
If we enable the filter and set the `maxOrderId` to `1`, when fetching the `accounts` collections, Hibernate is going to apply the `@FilterJoinTable` clause filtering criteria, and we will get just
`2` `Account` entities, with the `order_id` values of `0` and `1`.
[[mapping-filter-join-table-collection-query-example]] [[mapping-filter-join-table-collection-query-example]]
.Traversing collections mapped with `@FilterJoinTable` .Traversing collections mapped with `@FilterJoinTable`

View File

@ -8,7 +8,7 @@ WHERE
SELECT SELECT
a.id as id1_0_, a.id as id1_0_,
a.active as active2_0_, a.active_status as active2_0_,
a.amount as amount3_0_, a.amount as amount3_0_,
a.client_id as client_i6_0_, a.client_id as client_i6_0_,
a.rate as rate4_0_, a.rate as rate4_0_,
@ -16,27 +16,5 @@ SELECT
FROM FROM
Account a Account a
WHERE WHERE
a.client_id = 1 accounts0_.active_status = true
-- Activate filter [activeAccount]
SELECT
c.id as id1_1_0_,
c.name as name2_1_0_
FROM
Client c
WHERE
c.id = 1
SELECT
a.id as id1_0_,
a.active as active2_0_,
a.amount as amount3_0_,
a.client_id as client_i6_0_,
a.rate as rate4_0_,
a.account_type as account_5_0_
FROM
Account a
WHERE
accounts0_.active = true
and a.client_id = 1 and a.client_id = 1

View File

@ -1,6 +1,6 @@
SELECT SELECT
a.id as id1_0_0_, a.id as id1_0_0_,
a.active as active2_0_0_, a.active_status as active2_0_0_,
a.amount as amount3_0_0_, a.amount as amount3_0_0_,
a.client_id as client_i6_0_0_, a.client_id as client_i6_0_0_,
a.rate as rate4_0_0_, a.rate as rate4_0_0_,
@ -9,8 +9,5 @@ SELECT
c.name as name2_1_1_ c.name as name2_1_1_
FROM FROM
Account a Account a
LEFT OUTER JOIN
Client c
ON a.client_id=c.id
WHERE WHERE
a.id = 2 a.id = 2

View File

@ -1,18 +1,6 @@
SELECT SELECT
a.id as id1_0_, a.id as id1_0_,
a.active as active2_0_, a.active_status as active2_0_,
a.amount as amount3_0_,
a.client_id as client_i6_0_,
a.rate as rate4_0_,
a.account_type as account_5_0_
FROM
Account a
-- Activate filter [activeAccount]
SELECT
a.id as id1_0_,
a.active as active2_0_,
a.amount as amount3_0_, a.amount as amount3_0_,
a.client_id as client_i6_0_, a.client_id as client_i6_0_,
a.rate as rate4_0_, a.rate as rate4_0_,
@ -20,4 +8,4 @@ SELECT
FROM FROM
Account a Account a
WHERE WHERE
a.active = true a.active_status = true

View File

@ -3,28 +3,6 @@ SELECT
ca.accounts_id as accounts2_2_0_, ca.accounts_id as accounts2_2_0_,
ca.order_id as order_id3_0_, ca.order_id as order_id3_0_,
a.id as id1_0_1_, a.id as id1_0_1_,
a.active as active2_0_1_,
a.amount as amount3_0_1_,
a.rate as rate4_0_1_,
a.account_type as account_5_0_1_
FROM
Client_Account ca
INNER JOIN
Account a
ON ca.accounts_id=a.id
WHERE
ca.Client_id = ?
-- binding parameter [1] as [BIGINT] - [1]
-- Activate filter [firstAccounts]
SELECT
ca.Client_id as Client_i1_2_0_,
ca.accounts_id as accounts2_2_0_,
ca.order_id as order_id3_0_,
a.id as id1_0_1_,
a.active as active2_0_1_,
a.amount as amount3_0_1_, a.amount as amount3_0_1_,
a.rate as rate4_0_1_, a.rate as rate4_0_1_,
a.account_type as account_5_0_1_ a.account_type as account_5_0_1_

View File

@ -1,14 +1,14 @@
INSERT INTO Client (name, id) INSERT INTO Client (name, id)
VALUES ('John Doe', 1) VALUES ('John Doe', 1)
INSERT INTO Account (active, amount, client_id, rate, account_type, id) INSERT INTO Account (amount, client_id, rate, account_type, id)
VALUES (true, 5000.0, 1, 0.0125, 'CREDIT', 1) VALUES (5000.0, 1, 0.0125, 'CREDIT', 1)
INSERT INTO Account (active, amount, client_id, rate, account_type, id) INSERT INTO Account (amount, client_id, rate, account_type, id)
VALUES (false, 0.0, 1, 0.0105, 'DEBIT', 2) VALUES (0.0, 1, 0.0105, 'DEBIT', 2)
INSERT INTO Account (active, amount, client_id, rate, account_type, id) INSERT INTO Account (amount, client_id, rate, account_type, id)
VALUES (true, 250.0, 1, 0.0105, 'DEBIT', 3) VALUES (250.0, 1, 0.0105, 'DEBIT', 3)
INSERT INTO Client_Account (Client_id, order_id, accounts_id) INSERT INTO Client_Account (Client_id, order_id, accounts_id)
VALUES (1, 0, 1) VALUES (1, 0, 1)

View File

@ -1,11 +1,11 @@
INSERT INTO Client (name, id) INSERT INTO Client (name, id)
VALUES ('John Doe', 1) VALUES ('John Doe', 1)
INSERT INTO Account (active, amount, client_id, rate, account_type, id) INSERT INTO Account (active_status, amount, client_id, rate, account_type, id)
VALUES (true, 5000.0, 1, 0.0125, 'CREDIT', 1) VALUES (true, 5000.0, 1, 0.0125, 'CREDIT', 1)
INSERT INTO Account (active, amount, client_id, rate, account_type, id) INSERT INTO Account (active_status, amount, client_id, rate, account_type, id)
VALUES (false, 0.0, 1, 0.0105, 'DEBIT', 2) VALUES (false, 0.0, 1, 0.0105, 'DEBIT', 2)
INSERT INTO Account (active, amount, client_id, rate, account_type, id) INSERT INTO Account (active_status, amount, client_id, rate, account_type, id)
VALUES (true, 250.0, 1, 0.0105, 'DEBIT', 3) VALUES (true, 250.0, 1, 0.0105, 'DEBIT', 3)

View File

@ -0,0 +1,19 @@
SELECT
c.id as id1_1_0_,
c.name as name2_1_0_
FROM
Client c
WHERE
c.id = 1
SELECT
a.id as id1_0_,
a.active_status as active2_0_,
a.amount as amount3_0_,
a.client_id as client_i6_0_,
a.rate as rate4_0_,
a.account_type as account_5_0_
FROM
Account a
WHERE
a.client_id = 1

View File

@ -0,0 +1,9 @@
SELECT
a.id as id1_0_,
a.active_status as active2_0_,
a.amount as amount3_0_,
a.client_id as client_i6_0_,
a.rate as rate4_0_,
a.account_type as account_5_0_
FROM
Account a

View File

@ -0,0 +1,17 @@
SELECT
ca.Client_id as Client_i1_2_0_,
ca.accounts_id as accounts2_2_0_,
ca.order_id as order_id3_0_,
a.id as id1_0_1_,
a.amount as amount3_0_1_,
a.rate as rate4_0_1_,
a.account_type as account_5_0_1_
FROM
Client_Account ca
INNER JOIN
Account a
ON ca.accounts_id=a.id
WHERE
ca.Client_id = ?
-- binding parameter [1] as [BIGINT] - [1]

View File

@ -8,6 +8,7 @@ package org.hibernate.userguide.mapping.basic;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Column; import javax.persistence.Column;
import javax.persistence.Entity; import javax.persistence.Entity;
import javax.persistence.EnumType; import javax.persistence.EnumType;
@ -35,180 +36,190 @@ import static org.junit.Assert.assertEquals;
*/ */
public class FilterJoinTableTest extends BaseEntityManagerFunctionalTestCase { public class FilterJoinTableTest extends BaseEntityManagerFunctionalTestCase {
@Override @Override
protected Class<?>[] getAnnotatedClasses() { protected Class<?>[] getAnnotatedClasses() {
return new Class<?>[] { return new Class<?>[] {
Client.class, Client.class,
Account.class Account.class
}; };
} }
@Test @Test
public void testLifecycle() { public void testLifecycle() {
//tag::mapping-filter-join-table-persistence-example[] doInJPA( this::entityManagerFactory, entityManager -> {
doInJPA( this::entityManagerFactory, entityManager -> { //tag::mapping-filter-join-table-persistence-example[]
Client client = new Client()
.setId( 1L )
.setName( "John Doe" );
Client client = new Client(); client.addAccount(
client.setId( 1L ); new Account()
client.setName( "John Doe" ); .setId( 1L )
entityManager.persist( client ); .setType( AccountType.CREDIT )
.setAmount( 5000d )
.setRate( 1.25 / 100 )
);
Account account1 = new Account( ); client.addAccount(
account1.setId( 1L ); new Account()
account1.setType( AccountType.CREDIT ); .setId( 2L )
account1.setAmount( 5000d ); .setType( AccountType.DEBIT )
account1.setRate( 1.25 / 100 ); .setAmount( 0d )
account1.setActive( true ); .setRate( 1.05 / 100 )
client.getAccounts().add( account1 ); );
entityManager.persist( account1 );
Account account2 = new Account( ); client.addAccount(
account2.setId( 2L ); new Account()
account2.setType( AccountType.DEBIT ); .setType( AccountType.DEBIT )
account2.setAmount( 0d ); .setId( 3L )
account2.setRate( 1.05 / 100 ); .setAmount( 250d )
account2.setActive( false ); .setRate( 1.05 / 100 )
client.getAccounts().add( account2 ); );
entityManager.persist( account2 );
Account account3 = new Account( ); entityManager.persist( client );
account3.setType( AccountType.DEBIT ); //end::mapping-filter-join-table-persistence-example[]
account3.setId( 3L ); } );
account3.setAmount( 250d );
account3.setRate( 1.05 / 100 );
account3.setActive( true );
client.getAccounts().add( account3 );
entityManager.persist( account3 );
} );
//end::mapping-filter-join-table-persistence-example[]
//tag::mapping-filter-join-table-collection-query-example[] doInJPA( this::entityManagerFactory, entityManager -> {
doInJPA( this::entityManagerFactory, entityManager -> { //tag::mapping-no-filter-join-table-collection-query-example[]
Client client = entityManager.find( Client.class, 1L ); Client client = entityManager.find( Client.class, 1L );
assertEquals( 3, client.getAccounts().size());
} );
doInJPA( this::entityManagerFactory, entityManager -> { assertEquals( 3, client.getAccounts().size());
log.infof( "Activate filter [%s]", "firstAccounts"); //end::mapping-no-filter-join-table-collection-query-example[]
} );
Client client = entityManager.find( Client.class, 1L ); doInJPA( this::entityManagerFactory, entityManager -> {
log.infof( "Activate filter [%s]", "firstAccounts");
entityManager //tag::mapping-filter-join-table-collection-query-example[]
.unwrap( Session.class ) Client client = entityManager.find( Client.class, 1L );
.enableFilter( "firstAccounts" )
.setParameter( "maxOrderId", 1);
assertEquals( 2, client.getAccounts().size()); entityManager
} ); .unwrap( Session.class )
//end::mapping-filter-join-table-collection-query-example[] .enableFilter( "firstAccounts" )
} .setParameter( "maxOrderId", 1);
//tag::mapping-filter-join-table-example[] assertEquals( 2, client.getAccounts().size());
public enum AccountType { //end::mapping-filter-join-table-collection-query-example[]
DEBIT, } );
CREDIT }
}
@Entity(name = "Client") public enum AccountType {
@FilterDef(name="firstAccounts", parameters=@ParamDef( name="maxOrderId", type="int" ) ) DEBIT,
@Filter(name="firstAccounts", condition="order_id <= :maxOrderId") CREDIT
public static class Client { }
@Id //tag::mapping-filter-join-table-example[]
private Long id; @Entity(name = "Client")
@FilterDef(
name="firstAccounts",
parameters=@ParamDef(
name="maxOrderId",
type="int"
)
)
@Filter(
name="firstAccounts",
condition="order_id <= :maxOrderId"
)
public static class Client {
private String name; @Id
private Long id;
@OneToMany private String name;
@OrderColumn(name = "order_id")
@FilterJoinTable(name="firstAccounts", condition="order_id <= :maxOrderId")
private List<Account> accounts = new ArrayList<>( );
//Getters and setters omitted for brevity @OneToMany(cascade = CascadeType.ALL)
@OrderColumn(name = "order_id")
@FilterJoinTable(
name="firstAccounts",
condition="order_id <= :maxOrderId"
)
private List<Account> accounts = new ArrayList<>( );
//end::mapping-filter-join-table-example[] //Getters and setters omitted for brevity
public Long getId() { //end::mapping-filter-join-table-example[]
return id; public Long getId() {
} return id;
}
public void setId(Long id) { public Client setId(Long id) {
this.id = id; this.id = id;
} return this;
}
public String getName() { public String getName() {
return name; return name;
} }
public void setName(String name) { public Client setName(String name) {
this.name = name; this.name = name;
} return this;
}
public List<Account> getAccounts() { public List<Account> getAccounts() {
return accounts; return accounts;
} }
//tag::mapping-filter-join-table-example[] //tag::mapping-filter-join-table-example[]
}
@Entity(name = "Account") public void addAccount(Account account) {
public static class Account { this.accounts.add( account );
}
}
@Id @Entity(name = "Account")
private Long id; public static class Account {
@Column(name = "account_type") @Id
@Enumerated(EnumType.STRING) private Long id;
private AccountType type;
private Double amount; @Column(name = "account_type")
@Enumerated(EnumType.STRING)
private AccountType type;
private Double rate; private Double amount;
private boolean active; private Double rate;
//Getters and setters omitted for brevity //Getters and setters omitted for brevity
//end::mapping-filter-join-table-example[]
public Long getId() {
return id;
}
//end::mapping-filter-join-table-example[] public Account setId(Long id) {
public Long getId() { this.id = id;
return id; return this;
} }
public void setId(Long id) { public AccountType getType() {
this.id = id; return type;
} }
public AccountType getType() { public Account setType(AccountType type) {
return type; this.type = type;
} return this;
}
public void setType(AccountType type) { public Double getAmount() {
this.type = type; return amount;
} }
public Double getAmount() { public Account setAmount(Double amount) {
return amount; this.amount = amount;
} return this;
}
public void setAmount(Double amount) { public Double getRate() {
this.amount = amount; return rate;
} }
public Double getRate() { public Account setRate(Double rate) {
return rate; this.rate = rate;
} return this;
}
public void setRate(Double rate) { //tag::mapping-filter-join-table-example[]
this.rate = rate; }
} //end::mapping-filter-join-table-example[]
public boolean isActive() {
return active;
}
public void setActive(boolean active) {
this.active = active;
}
//tag::mapping-filter-join-table-example[]
}
//end::mapping-filter-join-table-example[]
} }

View File

@ -8,10 +8,12 @@ package org.hibernate.userguide.mapping.basic;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Column; import javax.persistence.Column;
import javax.persistence.Entity; import javax.persistence.Entity;
import javax.persistence.EnumType; import javax.persistence.EnumType;
import javax.persistence.Enumerated; import javax.persistence.Enumerated;
import javax.persistence.FetchType;
import javax.persistence.Id; import javax.persistence.Id;
import javax.persistence.ManyToOne; import javax.persistence.ManyToOne;
import javax.persistence.NoResultException; import javax.persistence.NoResultException;
@ -39,267 +41,301 @@ import static org.junit.Assert.assertNull;
*/ */
public class FilterTest extends BaseEntityManagerFunctionalTestCase { public class FilterTest extends BaseEntityManagerFunctionalTestCase {
@Override @Override
protected Class<?>[] getAnnotatedClasses() { protected Class<?>[] getAnnotatedClasses() {
return new Class<?>[] { return new Class<?>[] {
Client.class, Client.class,
Account.class Account.class
}; };
} }
@Test @Test
public void testLifecycle() { public void testLifecycle() {
//tag::mapping-filter-persistence-example[] doInJPA( this::entityManagerFactory, entityManager -> {
doInJPA( this::entityManagerFactory, entityManager -> {
Client client = new Client(); //tag::mapping-filter-persistence-example[]
client.setId( 1L ); Client client = new Client()
client.setName( "John Doe" ); .setId( 1L )
entityManager.persist( client ); .setName( "John Doe" );
Account account1 = new Account( ); client.addAccount(
account1.setId( 1L ); new Account()
account1.setType( AccountType.CREDIT ); .setId( 1L )
account1.setAmount( 5000d ); .setType( AccountType.CREDIT )
account1.setRate( 1.25 / 100 ); .setAmount( 5000d )
account1.setActive( true ); .setRate( 1.25 / 100 )
account1.setClient( client ); .setActive( true )
client.getAccounts().add( account1 ); );
entityManager.persist( account1 );
Account account2 = new Account( ); client.addAccount(
account2.setId( 2L ); new Account()
account2.setType( AccountType.DEBIT ); .setId( 2L )
account2.setAmount( 0d ); .setType( AccountType.DEBIT )
account2.setRate( 1.05 / 100 ); .setAmount( 0d )
account2.setActive( false ); .setRate( 1.05 / 100 )
account2.setClient( client ); .setActive( false )
client.getAccounts().add( account2 ); );
entityManager.persist( account2 );
Account account3 = new Account( ); client.addAccount(
account3.setType( AccountType.DEBIT ); new Account()
account3.setId( 3L ); .setType( AccountType.DEBIT )
account3.setAmount( 250d ); .setId( 3L )
account3.setRate( 1.05 / 100 ); .setAmount( 250d )
account3.setActive( true ); .setRate( 1.05 / 100 )
account3.setClient( client ); .setActive( true )
client.getAccounts().add( account3 ); );
entityManager.persist( account3 );
} );
//end::mapping-filter-persistence-example[]
doInJPA( this::entityManagerFactory, entityManager -> { entityManager.persist( client );
log.infof( "Activate filter [%s]", "activeAccount"); //end::mapping-filter-persistence-example[]
} );
entityManager doInJPA( this::entityManagerFactory, entityManager -> {
.unwrap( Session.class ) log.infof( "Activate filter [%s]", "activeAccount");
.enableFilter( "activeAccount" )
.setParameter( "active", true);
Account account1 = entityManager.find( Account.class, 1L ); entityManager
Account account2 = entityManager.find( Account.class, 2L ); .unwrap( Session.class )
.enableFilter( "activeAccount" )
.setParameter( "active", true);
assertNotNull( account1 ); Account account1 = entityManager.find( Account.class, 1L );
assertNotNull( account2 ); Account account2 = entityManager.find( Account.class, 2L );
} );
doInJPA( this::entityManagerFactory, entityManager -> { assertNotNull( account1 );
log.infof( "Activate filter [%s]", "activeAccount"); assertNotNull( account2 );
} );
entityManager doInJPA( this::entityManagerFactory, entityManager -> {
.unwrap( Session.class ) log.infof( "Activate filter [%s]", "activeAccount");
.enableFilter( "activeAccount" )
.setParameter( "active", true);
Account account1 = entityManager.createQuery( entityManager
"select a from Account a where a.id = :id", Account.class) .unwrap( Session.class )
.setParameter( "id", 1L ) .enableFilter( "activeAccount" )
.getSingleResult(); .setParameter( "active", true);
assertNotNull( account1 );
try {
Account account2 = entityManager.createQuery(
"select a from Account a where a.id = :id", Account.class)
.setParameter( "id", 2L )
.getSingleResult();
}
catch (NoResultException expected) {
}
} );
//tag::mapping-filter-entity-example[] Account account1 = entityManager.createQuery(
doInJPA( this::entityManagerFactory, entityManager -> { "select a from Account a where a.id = :id", Account.class)
log.infof( "Activate filter [%s]", "activeAccount"); .setParameter( "id", 1L )
.getSingleResult();
assertNotNull( account1 );
try {
Account account2 = entityManager.createQuery(
"select a from Account a where a.id = :id", Account.class)
.setParameter( "id", 2L )
.getSingleResult();
}
catch (NoResultException expected) {
}
} );
entityManager doInJPA( this::entityManagerFactory, entityManager -> {
.unwrap( Session.class ) log.infof( "Activate filter [%s]", "activeAccount");
.enableFilter( "activeAccount" ) //tag::mapping-filter-entity-example[]
.setParameter( "active", true); entityManager
.unwrap( Session.class )
.enableFilter( "activeAccount" )
.setParameter( "active", true);
Account account = entityManager.find( Account.class, 2L ); Account account = entityManager.find( Account.class, 2L );
assertFalse( account.isActive() );
} );
//end::mapping-filter-entity-example[]
// tag::mapping-filter-entity-query-example[] assertFalse( account.isActive() );
doInJPA( this::entityManagerFactory, entityManager -> { //end::mapping-filter-entity-example[]
List<Account> accounts = entityManager.createQuery( } );
"select a from Account a", Account.class)
.getResultList();
assertEquals( 3, accounts.size());
} );
doInJPA( this::entityManagerFactory, entityManager -> { doInJPA( this::entityManagerFactory, entityManager -> {
log.infof( "Activate filter [%s]", "activeAccount"); //tag::mapping-no-filter-entity-query-example[]
List<Account> accounts = entityManager.createQuery(
"select a from Account a", Account.class)
.getResultList();
entityManager assertEquals( 3, accounts.size());
.unwrap( Session.class ) //end::mapping-no-filter-entity-query-example[]
.enableFilter( "activeAccount" ) } );
.setParameter( "active", true);
List<Account> accounts = entityManager.createQuery( doInJPA( this::entityManagerFactory, entityManager -> {
"select a from Account a", Account.class) log.infof( "Activate filter [%s]", "activeAccount");
.getResultList(); //tag::mapping-filter-entity-query-example[]
assertEquals( 2, accounts.size()); entityManager
} ); .unwrap( Session.class )
//end::mapping-filter-entity-query-example[] .enableFilter( "activeAccount" )
.setParameter( "active", true);
//tag::mapping-filter-collection-query-example[] List<Account> accounts = entityManager.createQuery(
doInJPA( this::entityManagerFactory, entityManager -> { "select a from Account a", Account.class)
Client client = entityManager.find( Client.class, 1L ); .getResultList();
assertEquals( 3, client.getAccounts().size() );
} );
doInJPA( this::entityManagerFactory, entityManager -> { assertEquals( 2, accounts.size());
log.infof( "Activate filter [%s]", "activeAccount"); //end::mapping-filter-entity-query-example[]
} );
entityManager doInJPA( this::entityManagerFactory, entityManager -> {
.unwrap( Session.class ) //tag::mapping-no-filter-collection-query-example[]
.enableFilter( "activeAccount" ) Client client = entityManager.find( Client.class, 1L );
.setParameter( "active", true);
Client client = entityManager.find( Client.class, 1L ); assertEquals( 3, client.getAccounts().size() );
assertEquals( 2, client.getAccounts().size() ); //end::mapping-no-filter-collection-query-example[]
} ); } );
//end::mapping-filter-collection-query-example[]
}
//tag::mapping-filter-example[] doInJPA( this::entityManagerFactory, entityManager -> {
public enum AccountType { log.infof( "Activate filter [%s]", "activeAccount");
DEBIT,
CREDIT
}
@Entity(name = "Client") //tag::mapping-filter-collection-query-example[]
public static class Client { entityManager
.unwrap( Session.class )
.enableFilter( "activeAccount" )
.setParameter( "active", true);
@Id Client client = entityManager.find( Client.class, 1L );
private Long id;
private String name; assertEquals( 2, client.getAccounts().size() );
//end::mapping-filter-collection-query-example[]
} );
}
@OneToMany(mappedBy = "client") public enum AccountType {
@Filter(name="activeAccount", condition="active = :active") DEBIT,
private List<Account> accounts = new ArrayList<>( ); CREDIT
}
//Getters and setters omitted for brevity //tag::mapping-filter-Client-example[]
@Entity(name = "Client")
public static class Client {
//end::mapping-filter-example[] @Id
public Long getId() { private Long id;
return id;
}
public void setId(Long id) { private String name;
this.id = id;
}
public String getName() { @OneToMany(
return name; mappedBy = "client",
} cascade = CascadeType.ALL
)
@Filter(
name="activeAccount",
condition="active_status = :active"
)
private List<Account> accounts = new ArrayList<>( );
public void setName(String name) { //Getters and setters omitted for brevity
this.name = name; //end::mapping-filter-Client-example[]
} public Long getId() {
return id;
}
public List<Account> getAccounts() { public Client setId(Long id) {
return accounts; this.id = id;
} return this;
//tag::mapping-filter-example[] }
}
@Entity(name = "Account") public String getName() {
@FilterDef(name="activeAccount", parameters=@ParamDef( name="active", type="boolean" ) ) return name;
@Filter(name="activeAccount", condition="active = :active") }
public static class Account {
@Id public Client setName(String name) {
private Long id; this.name = name;
return this;
}
@ManyToOne public List<Account> getAccounts() {
private Client client; return accounts;
}
//tag::mapping-filter-Client-example[]
@Column(name = "account_type") public void addAccount(Account account) {
@Enumerated(EnumType.STRING) account.setClient( this );
private AccountType type; this.accounts.add( account );
}
}
//end::mapping-filter-Client-example[]
private Double amount; //tag::mapping-filter-Account-example[]
@Entity(name = "Account")
@FilterDef(
name="activeAccount",
parameters = @ParamDef(
name="active",
type="boolean"
)
)
@Filter(
name="activeAccount",
condition="active_status = :active"
)
public static class Account {
private Double rate; @Id
private Long id;
private boolean active; @ManyToOne(fetch = FetchType.LAZY)
private Client client;
//Getters and setters omitted for brevity @Column(name = "account_type")
@Enumerated(EnumType.STRING)
private AccountType type;
//end::mapping-filter-example[] private Double amount;
public Long getId() {
return id;
}
public void setId(Long id) { private Double rate;
this.id = id;
}
public Client getClient() { @Column(name = "active_status")
return client; private boolean active;
}
public void setClient(Client client) { //Getters and setters omitted for brevity
this.client = client; //end::mapping-filter-Account-example[]
} public Long getId() {
return id;
}
public AccountType getType() { public Account setId(Long id) {
return type; this.id = id;
} return this;
}
public void setType(AccountType type) { public Client getClient() {
this.type = type; return client;
} }
public Double getAmount() { public Account setClient(Client client) {
return amount; this.client = client;
} return this;
}
public void setAmount(Double amount) { public AccountType getType() {
this.amount = amount; return type;
} }
public Double getRate() { public Account setType(AccountType type) {
return rate; this.type = type;
} return this;
}
public void setRate(Double rate) { public Double getAmount() {
this.rate = rate; return amount;
} }
public boolean isActive() { public Account setAmount(Double amount) {
return active; this.amount = amount;
} return this;
}
public void setActive(boolean active) { public Double getRate() {
this.active = active; return rate;
} }
//tag::mapping-filter-example[] public Account setRate(Double rate) {
} this.rate = rate;
//end::mapping-filter-example[] return this;
}
public boolean isActive() {
return active;
}
public Account setActive(boolean active) {
this.active = active;
return this;
}
//tag::mapping-filter-Account-example[]
}
//end::mapping-filter-Account-example[]
} }