HHH-16830: apply filters to find() method
This commit is contained in:
parent
84f2f3535f
commit
e721a37691
|
@ -558,9 +558,11 @@ include::{example-dir-pc}/FilterTest.java[tags=pc-filter-resolver-Account-exampl
|
||||||
|
|
||||||
[IMPORTANT]
|
[IMPORTANT]
|
||||||
====
|
====
|
||||||
Filters apply to entity queries, but not to direct fetching.
|
Filters apply to entity queries, but not to direct fetching, unless otherwise configured using the `applyToLoadByKey` flag
|
||||||
|
on the `@FilterDef`, that should be set to `true` in order to activate the filter with 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 `activeAccount` filter is not taken into consideration when fetching an entity from the Persistence Context.
|
||||||
|
On the other hand, the `minimumAmount` filter is taken into consideration, because its `applyToLoadByKey` flag is set to `true`.
|
||||||
|
|
||||||
[[pc-filter-entity-example]]
|
[[pc-filter-entity-example]]
|
||||||
.Fetching entities mapped with `@Filter`
|
.Fetching entities mapped with `@Filter`
|
||||||
|
@ -574,7 +576,13 @@ include::{example-dir-pc}/FilterTest.java[tags=pc-filter-entity-example]
|
||||||
include::{extrasdir}/pc-filter-entity-example.sql[]
|
include::{extrasdir}/pc-filter-entity-example.sql[]
|
||||||
----
|
----
|
||||||
|
|
||||||
As you can see from the example above, contrary to an entity query, the filter does not prevent the entity from being loaded.
|
[source, SQL, indent=0]
|
||||||
|
----
|
||||||
|
include::{extrasdir}/pc-filter-entity-find-example.sql[]
|
||||||
|
----
|
||||||
|
|
||||||
|
As you can see from the example above, contrary to an entity query, the `activeAccount` filter does not prevent the entity from being loaded,
|
||||||
|
but the `minimumAmount` filter limits the results to the ones with an amount that is greater than the specified one.
|
||||||
====
|
====
|
||||||
|
|
||||||
Just like with entity queries, collections can be filtered as well, but only if the filter is enabled on the currently running Hibernate `Session`,
|
Just like with entity queries, collections can be filtered as well, but only if the filter is enabled on the currently running Hibernate `Session`,
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
SELECT
|
||||||
|
a.id as id1_0_0_,
|
||||||
|
a.active_status as active2_0_0_,
|
||||||
|
a.amount as amount3_0_0_,
|
||||||
|
a.client_id as client_i6_0_0_,
|
||||||
|
a.rate as rate4_0_0_,
|
||||||
|
a.account_type as account_5_0_0_,
|
||||||
|
c.id as id1_1_1_,
|
||||||
|
c.name as name2_1_1_
|
||||||
|
FROM
|
||||||
|
Account a
|
||||||
|
WHERE
|
||||||
|
a.id = 1
|
||||||
|
AND a.amount > 9000
|
|
@ -95,4 +95,12 @@ public interface Filter {
|
||||||
* @return The flag value
|
* @return The flag value
|
||||||
*/
|
*/
|
||||||
boolean isAutoEnabled();
|
boolean isAutoEnabled();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the associated {@link FilterDefinition applyToLoadByKey} of this
|
||||||
|
* named filter.
|
||||||
|
*
|
||||||
|
* @return The flag value
|
||||||
|
*/
|
||||||
|
boolean isApplyToLoadByKey();
|
||||||
}
|
}
|
||||||
|
|
|
@ -95,4 +95,13 @@ public @interface FilterDef {
|
||||||
* The flag used to auto-enable the filter on the session.
|
* The flag used to auto-enable the filter on the session.
|
||||||
*/
|
*/
|
||||||
boolean autoEnabled() default false;
|
boolean autoEnabled() default false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The flag used to decide if the filter will
|
||||||
|
* be applied on direct fetches or not.
|
||||||
|
* <p>
|
||||||
|
* If the flag is true, the filter will be
|
||||||
|
* applied on direct fetches, such as findById().
|
||||||
|
*/
|
||||||
|
boolean applyToLoadByKey() default false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,7 +59,8 @@ public class TenantIdBinder implements AttributeBinder<TenantId> {
|
||||||
"",
|
"",
|
||||||
singletonMap( PARAMETER_NAME, tenantIdType ),
|
singletonMap( PARAMETER_NAME, tenantIdType ),
|
||||||
Collections.emptyMap(),
|
Collections.emptyMap(),
|
||||||
false
|
true,
|
||||||
|
true
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -416,11 +416,11 @@ public final class AnnotationBinder {
|
||||||
//@Entity and @MappedSuperclass on the same class leads to a NPE down the road
|
//@Entity and @MappedSuperclass on the same class leads to a NPE down the road
|
||||||
if ( annotatedClass.isAnnotationPresent( Entity.class ) ) {
|
if ( annotatedClass.isAnnotationPresent( Entity.class ) ) {
|
||||||
throw new AnnotationException( "Type '" + annotatedClass.getName()
|
throw new AnnotationException( "Type '" + annotatedClass.getName()
|
||||||
+ "' is annotated both '@Entity' and '@MappedSuperclass'" );
|
+ "' is annotated both '@Entity' and '@MappedSuperclass'" );
|
||||||
}
|
}
|
||||||
if ( annotatedClass.isAnnotationPresent( Table.class ) ) {
|
if ( annotatedClass.isAnnotationPresent( Table.class ) ) {
|
||||||
throw new AnnotationException( "Mapped superclass '" + annotatedClass.getName()
|
throw new AnnotationException( "Mapped superclass '" + annotatedClass.getName()
|
||||||
+ "' may not specify a '@Table'" );
|
+ "' may not specify a '@Table'" );
|
||||||
}
|
}
|
||||||
if ( annotatedClass.isAnnotationPresent( Inheritance.class ) ) {
|
if ( annotatedClass.isAnnotationPresent( Inheritance.class ) ) {
|
||||||
throw new AnnotationException( "Mapped superclass '" + annotatedClass.getName()
|
throw new AnnotationException( "Mapped superclass '" + annotatedClass.getName()
|
||||||
|
@ -651,8 +651,8 @@ public final class AnnotationBinder {
|
||||||
for ( FetchOverride fetch : fetchProfile.fetchOverrides() ) {
|
for ( FetchOverride fetch : fetchProfile.fetchOverrides() ) {
|
||||||
if ( fetch.fetch() == FetchType.LAZY && fetch.mode() == FetchMode.JOIN ) {
|
if ( fetch.fetch() == FetchType.LAZY && fetch.mode() == FetchMode.JOIN ) {
|
||||||
throw new AnnotationException( "Fetch profile '" + name
|
throw new AnnotationException( "Fetch profile '" + name
|
||||||
+ "' has a '@FetchOverride' with 'fetch=LAZY' and 'mode=JOIN'"
|
+ "' has a '@FetchOverride' with 'fetch=LAZY' and 'mode=JOIN'"
|
||||||
+ " (join fetching is eager by nature)");
|
+ " (join fetching is eager by nature)");
|
||||||
}
|
}
|
||||||
context.getMetadataCollector()
|
context.getMetadataCollector()
|
||||||
.addSecondPass( new FetchOverrideSecondPass( name, fetch, context ) );
|
.addSecondPass( new FetchOverrideSecondPass( name, fetch, context ) );
|
||||||
|
|
|
@ -92,7 +92,8 @@ class FilterDefBinder {
|
||||||
filterDef.defaultCondition(),
|
filterDef.defaultCondition(),
|
||||||
explicitParamJaMappings,
|
explicitParamJaMappings,
|
||||||
parameterResolvers,
|
parameterResolvers,
|
||||||
filterDef.autoEnabled()
|
filterDef.autoEnabled(),
|
||||||
|
filterDef.applyToLoadByKey()
|
||||||
);
|
);
|
||||||
LOG.debugf( "Binding filter definition: %s", filterDefinition.getFilterName() );
|
LOG.debugf( "Binding filter definition: %s", filterDefinition.getFilterName() );
|
||||||
context.getMetadataCollector().addFilterDefinition( filterDefinition );
|
context.getMetadataCollector().addFilterDefinition( filterDefinition );
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
package org.hibernate.boot.model.source.internal.hbm;
|
package org.hibernate.boot.model.source.internal.hbm;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
|
|
@ -37,6 +37,7 @@ public class FilterDefinition implements Serializable {
|
||||||
private final Map<String, JdbcMapping> explicitParamJaMappings = new HashMap<>();
|
private final Map<String, JdbcMapping> explicitParamJaMappings = new HashMap<>();
|
||||||
private final Map<String, ManagedBean<? extends Supplier<?>>> parameterResolverMap = new HashMap<>();
|
private final Map<String, ManagedBean<? extends Supplier<?>>> parameterResolverMap = new HashMap<>();
|
||||||
private final boolean autoEnabled;
|
private final boolean autoEnabled;
|
||||||
|
private final boolean applyToLoadByKey;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct a new FilterDefinition instance.
|
* Construct a new FilterDefinition instance.
|
||||||
|
@ -44,17 +45,18 @@ public class FilterDefinition implements Serializable {
|
||||||
* @param name The name of the filter for which this configuration is in effect.
|
* @param name The name of the filter for which this configuration is in effect.
|
||||||
*/
|
*/
|
||||||
public FilterDefinition(String name, String defaultCondition, @Nullable Map<String, JdbcMapping> explicitParamJaMappings) {
|
public FilterDefinition(String name, String defaultCondition, @Nullable Map<String, JdbcMapping> explicitParamJaMappings) {
|
||||||
this( name, defaultCondition, explicitParamJaMappings, Collections.emptyMap(), false);
|
this( name, defaultCondition, explicitParamJaMappings, Collections.emptyMap(), false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public FilterDefinition(
|
public FilterDefinition(
|
||||||
String name, String defaultCondition, @Nullable Map<String, JdbcMapping> explicitParamJaMappings,
|
String name, String defaultCondition, @Nullable Map<String, JdbcMapping> explicitParamJaMappings,
|
||||||
Map<String, ManagedBean<? extends Supplier<?>>> parameterResolverMap, boolean autoEnabled) {
|
Map<String, ManagedBean<? extends Supplier<?>>> parameterResolverMap, boolean autoEnabled, boolean applyToLoadByKey) {
|
||||||
this.filterName = name;
|
this.filterName = name;
|
||||||
this.defaultFilterCondition = defaultCondition;
|
this.defaultFilterCondition = defaultCondition;
|
||||||
if ( explicitParamJaMappings != null ) {
|
if ( explicitParamJaMappings != null ) {
|
||||||
this.explicitParamJaMappings.putAll( explicitParamJaMappings );
|
this.explicitParamJaMappings.putAll( explicitParamJaMappings );
|
||||||
}
|
}
|
||||||
|
this.applyToLoadByKey = applyToLoadByKey;
|
||||||
if ( parameterResolverMap != null ) {
|
if ( parameterResolverMap != null ) {
|
||||||
this.parameterResolverMap.putAll( parameterResolverMap );
|
this.parameterResolverMap.putAll( parameterResolverMap );
|
||||||
}
|
}
|
||||||
|
@ -101,6 +103,16 @@ public class FilterDefinition implements Serializable {
|
||||||
return defaultFilterCondition;
|
return defaultFilterCondition;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a flag that defines if the filter should be applied
|
||||||
|
* on direct fetches or not.
|
||||||
|
*
|
||||||
|
* @return The flag value.
|
||||||
|
*/
|
||||||
|
public boolean isApplyToLoadByKey() {
|
||||||
|
return applyToLoadByKey;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called before binding a JDBC parameter
|
* Called before binding a JDBC parameter
|
||||||
*
|
*
|
||||||
|
|
|
@ -13,6 +13,7 @@ import java.util.HashSet;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import org.hibernate.Filter;
|
import org.hibernate.Filter;
|
||||||
import org.hibernate.Internal;
|
import org.hibernate.Internal;
|
||||||
|
@ -168,6 +169,20 @@ public class LoadQueryInfluencers implements Serializable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a Map of enabled filters that have the applyToLoadByKey
|
||||||
|
* flag set to true
|
||||||
|
* @return a Map of enabled filters that have the applyToLoadByKey
|
||||||
|
* flag set to true
|
||||||
|
*/
|
||||||
|
public Map<String, Filter> getEnabledFiltersForFind() {
|
||||||
|
return getEnabledFilters()
|
||||||
|
.entrySet()
|
||||||
|
.stream()
|
||||||
|
.filter(f -> f.getValue().isApplyToLoadByKey())
|
||||||
|
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns an unmodifiable Set of enabled filter names.
|
* Returns an unmodifiable Set of enabled filter names.
|
||||||
* @return an unmodifiable Set of enabled filter names.
|
* @return an unmodifiable Set of enabled filter names.
|
||||||
|
|
|
@ -32,7 +32,8 @@ public class FilterImpl implements Filter, Serializable {
|
||||||
private final String filterName;
|
private final String filterName;
|
||||||
private final Map<String,Object> parameters = new HashMap<>();
|
private final Map<String,Object> parameters = new HashMap<>();
|
||||||
private final boolean autoEnabled;
|
private final boolean autoEnabled;
|
||||||
|
private final boolean applyToLoadByKey;
|
||||||
|
|
||||||
void afterDeserialize(SessionFactoryImplementor factory) {
|
void afterDeserialize(SessionFactoryImplementor factory) {
|
||||||
definition = factory.getFilterDefinition( filterName );
|
definition = factory.getFilterDefinition( filterName );
|
||||||
validate();
|
validate();
|
||||||
|
@ -47,6 +48,7 @@ public class FilterImpl implements Filter, Serializable {
|
||||||
this.definition = configuration;
|
this.definition = configuration;
|
||||||
filterName = definition.getFilterName();
|
filterName = definition.getFilterName();
|
||||||
this.autoEnabled = definition.isAutoEnabled();
|
this.autoEnabled = definition.isAutoEnabled();
|
||||||
|
this.applyToLoadByKey = definition.isApplyToLoadByKey();
|
||||||
}
|
}
|
||||||
|
|
||||||
public FilterDefinition getFilterDefinition() {
|
public FilterDefinition getFilterDefinition() {
|
||||||
|
@ -70,7 +72,18 @@ public class FilterImpl implements Filter, Serializable {
|
||||||
public boolean isAutoEnabled() {
|
public boolean isAutoEnabled() {
|
||||||
return autoEnabled;
|
return autoEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a flag that defines if the filter should be applied
|
||||||
|
* on direct fetches or not.
|
||||||
|
*
|
||||||
|
* @return The flag value.
|
||||||
|
*/
|
||||||
|
public boolean isApplyToLoadByKey() {
|
||||||
|
return applyToLoadByKey;
|
||||||
|
}
|
||||||
|
|
||||||
public Map<String,?> getParameters() {
|
public Map<String,?> getParameters() {
|
||||||
return parameters;
|
return parameters;
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,6 @@
|
||||||
package org.hibernate.loader.ast.internal;
|
package org.hibernate.loader.ast.internal;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
@ -717,8 +716,8 @@ public class LoaderSelectBuilder {
|
||||||
querySpec::applyPredicate,
|
querySpec::applyPredicate,
|
||||||
tableGroup,
|
tableGroup,
|
||||||
true,
|
true,
|
||||||
// HHH-16179 Session.find should not apply filters
|
// HHH-16830 Session.find should apply filters only if specified on the filter definition
|
||||||
Collections.emptyMap(),//loadQueryInfluencers.getEnabledFilters(),
|
loadQueryInfluencers.getEnabledFiltersForFind(),
|
||||||
null,
|
null,
|
||||||
astCreationState
|
astCreationState
|
||||||
);
|
);
|
||||||
|
|
|
@ -2281,6 +2281,7 @@
|
||||||
</xsd:complexType>
|
</xsd:complexType>
|
||||||
</xsd:element>
|
</xsd:element>
|
||||||
<xsd:element name="condition" type="xsd:string" minOccurs="0"/>
|
<xsd:element name="condition" type="xsd:string" minOccurs="0"/>
|
||||||
|
<xsd:element name="apply-to-load-by-key" type="xsd:boolean" default="false"/>
|
||||||
</xsd:sequence>
|
</xsd:sequence>
|
||||||
|
|
||||||
<xsd:attribute name="name" use="required" type="xsd:string"/>
|
<xsd:attribute name="name" use="required" type="xsd:string"/>
|
||||||
|
|
|
@ -177,6 +177,50 @@ public class FilterTest extends BaseEntityManagerFunctionalTestCase {
|
||||||
//end::pc-filter-entity-query-example[]
|
//end::pc-filter-entity-query-example[]
|
||||||
});
|
});
|
||||||
|
|
||||||
|
doInJPA(this::entityManagerFactory, entityManager -> {
|
||||||
|
log.infof("Activate filter [%s]", "minimumAmount");
|
||||||
|
//tag::pc-filter-entity-example[]
|
||||||
|
entityManager
|
||||||
|
.unwrap(Session.class)
|
||||||
|
.enableFilter("minimumAmount")
|
||||||
|
.setParameter("amount", 9000d);
|
||||||
|
|
||||||
|
Account account = entityManager.find(Account.class, 1L);
|
||||||
|
|
||||||
|
assertNull( account );
|
||||||
|
//end::pc-filter-entity-example[]
|
||||||
|
});
|
||||||
|
|
||||||
|
doInJPA(this::entityManagerFactory, entityManager -> {
|
||||||
|
log.infof("Activate filter [%s]", "minimumAmount");
|
||||||
|
//tag::pc-filter-entity-example[]
|
||||||
|
entityManager
|
||||||
|
.unwrap(Session.class)
|
||||||
|
.enableFilter("minimumAmount")
|
||||||
|
.setParameter("amount", 100d);
|
||||||
|
|
||||||
|
Account account = entityManager.find(Account.class, 1L);
|
||||||
|
|
||||||
|
assertNotNull( account );
|
||||||
|
//end::pc-filter-entity-example[]
|
||||||
|
});
|
||||||
|
|
||||||
|
doInJPA(this::entityManagerFactory, entityManager -> {
|
||||||
|
log.infof("Activate filter [%s]", "minimumAmount");
|
||||||
|
//tag::pc-filter-entity-query-example[]
|
||||||
|
entityManager
|
||||||
|
.unwrap(Session.class)
|
||||||
|
.enableFilter("minimumAmount")
|
||||||
|
.setParameter("amount", 500d);
|
||||||
|
|
||||||
|
List<Account> accounts = entityManager.createQuery(
|
||||||
|
"select a from Account a", Account.class)
|
||||||
|
.getResultList();
|
||||||
|
|
||||||
|
assertEquals(1, accounts.size());
|
||||||
|
//end::pc-filter-entity-query-example[]
|
||||||
|
});
|
||||||
|
|
||||||
doInJPA(this::entityManagerFactory, entityManager -> {
|
doInJPA(this::entityManagerFactory, entityManager -> {
|
||||||
//tag::pc-no-filter-collection-query-example[]
|
//tag::pc-no-filter-collection-query-example[]
|
||||||
Client client = entityManager.find(Client.class, 1L);
|
Client client = entityManager.find(Client.class, 1L);
|
||||||
|
@ -280,9 +324,22 @@ public class FilterTest extends BaseEntityManagerFunctionalTestCase {
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@Filter(
|
@Filter(
|
||||||
name="activeAccount",
|
name="activeAccount",
|
||||||
condition="active_status = :active"
|
condition="active_status = :active"
|
||||||
)
|
)
|
||||||
|
@FilterDef(
|
||||||
|
name="minimumAmount",
|
||||||
|
parameters = @ParamDef(
|
||||||
|
name="amount",
|
||||||
|
type=Double.class
|
||||||
|
),
|
||||||
|
applyToLoadByKey = true
|
||||||
|
)
|
||||||
|
@Filter(
|
||||||
|
name="minimumAmount",
|
||||||
|
condition="amount > :amount"
|
||||||
|
)
|
||||||
|
|
||||||
public static class Account {
|
public static class Account {
|
||||||
|
|
||||||
@Id
|
@Id
|
||||||
|
|
|
@ -40,6 +40,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||||
import static org.hibernate.cfg.AvailableSettings.JAKARTA_HBM2DDL_DATABASE_ACTION;
|
import static org.hibernate.cfg.AvailableSettings.JAKARTA_HBM2DDL_DATABASE_ACTION;
|
||||||
import static org.hibernate.internal.util.collections.CollectionHelper.toMap;
|
import static org.hibernate.internal.util.collections.CollectionHelper.toMap;
|
||||||
import static org.hibernate.jpa.HibernateHints.HINT_TENANT_ID;
|
import static org.hibernate.jpa.HibernateHints.HINT_TENANT_ID;
|
||||||
|
import static org.junit.Assert.assertNull;
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
import static org.junit.jupiter.api.Assertions.assertNotEquals;
|
import static org.junit.jupiter.api.Assertions.assertNotEquals;
|
||||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||||
|
@ -110,7 +111,8 @@ public class TenantIdTest implements SessionFactoryProducer {
|
||||||
|
|
||||||
currentTenant = "yours";
|
currentTenant = "yours";
|
||||||
scope.inTransaction( session -> {
|
scope.inTransaction( session -> {
|
||||||
assertNotNull( session.find(Account.class, acc.id) );
|
//HHH-16830 Sessions applies tenantId filter on find()
|
||||||
|
assertNull( session.find(Account.class, acc.id) );
|
||||||
assertEquals( 0, session.createQuery("from Account", Account.class).getResultList().size() );
|
assertEquals( 0, session.createQuery("from Account", Account.class).getResultList().size() );
|
||||||
session.disableFilter(TenantIdBinder.FILTER_NAME);
|
session.disableFilter(TenantIdBinder.FILTER_NAME);
|
||||||
assertNotNull( session.find(Account.class, acc.id) );
|
assertNotNull( session.find(Account.class, acc.id) );
|
||||||
|
@ -247,9 +249,9 @@ public class TenantIdTest implements SessionFactoryProducer {
|
||||||
Record r = em.find( Record.class, record.id );
|
Record r = em.find( Record.class, record.id );
|
||||||
assertEquals( "mine", r.state.tenantId );
|
assertEquals( "mine", r.state.tenantId );
|
||||||
|
|
||||||
// Session seems to not apply tenant-id on #find
|
// HHH-16830 Session applies tenant-id on #find
|
||||||
Record yours = em.find( Record.class, record2.id );
|
Record yours = em.find( Record.class, record2.id );
|
||||||
assertEquals( "yours", yours.state.tenantId );
|
assertNull(yours);
|
||||||
|
|
||||||
|
|
||||||
em.createQuery( "from Record where id = :id", Record.class )
|
em.createQuery( "from Record where id = :id", Record.class )
|
||||||
|
|
|
@ -79,7 +79,8 @@ public class TenantLongIdTest implements SessionFactoryProducer {
|
||||||
|
|
||||||
currentTenant = yours;
|
currentTenant = yours;
|
||||||
scope.inTransaction( session -> {
|
scope.inTransaction( session -> {
|
||||||
assertNotNull( session.find(Account.class, acc.id) );
|
//HHH-16830 Sessions applies tenantId filter on find()
|
||||||
|
assertNull( session.find(Account.class, acc.id) );
|
||||||
assertEquals( 0, session.createQuery("from Account").getResultList().size() );
|
assertEquals( 0, session.createQuery("from Account").getResultList().size() );
|
||||||
session.disableFilter(TenantIdBinder.FILTER_NAME);
|
session.disableFilter(TenantIdBinder.FILTER_NAME);
|
||||||
assertNotNull( session.find(Account.class, acc.id) );
|
assertNotNull( session.find(Account.class, acc.id) );
|
||||||
|
|
|
@ -26,6 +26,7 @@ import org.junit.jupiter.api.Test;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
import static org.hibernate.cfg.AvailableSettings.JAKARTA_HBM2DDL_DATABASE_ACTION;
|
import static org.hibernate.cfg.AvailableSettings.JAKARTA_HBM2DDL_DATABASE_ACTION;
|
||||||
|
import static org.junit.Assert.assertNull;
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
@ -86,7 +87,8 @@ public class TenantUuidTest implements SessionFactoryProducer {
|
||||||
|
|
||||||
currentTenant = yours;
|
currentTenant = yours;
|
||||||
scope.inTransaction( session -> {
|
scope.inTransaction( session -> {
|
||||||
assertNotNull( session.find(Account.class, acc.id) );
|
//HHH-16830 Sessions applies tenantId filter on find()
|
||||||
|
assertNull( session.find(Account.class, acc.id) );
|
||||||
assertEquals( 0, session.createQuery("from Account").getResultList().size() );
|
assertEquals( 0, session.createQuery("from Account").getResultList().size() );
|
||||||
session.disableFilter(TenantIdBinder.FILTER_NAME);
|
session.disableFilter(TenantIdBinder.FILTER_NAME);
|
||||||
assertNotNull( session.find(Account.class, acc.id) );
|
assertNotNull( session.find(Account.class, acc.id) );
|
||||||
|
|
Loading…
Reference in New Issue