Skip to content

Commit 37ee87a

Browse files
marko-bekhtabeikov
authored andcommitted
HHH-19036 Process all filters before going through classes
1 parent bb5c07e commit 37ee87a

File tree

3 files changed

+146
-4
lines changed

3 files changed

+146
-4
lines changed

hibernate-core/src/main/java/org/hibernate/boot/model/internal/AnnotationBinder.java

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@
4242
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
4343
import org.hibernate.boot.spi.MetadataBuildingContext;
4444
import org.hibernate.internal.CoreMessageLogger;
45-
import org.hibernate.internal.util.StringHelper;
4645
import org.hibernate.resource.beans.internal.FallbackBeanInstanceProducer;
4746
import org.hibernate.resource.beans.spi.ManagedBeanRegistry;
4847
import org.hibernate.type.descriptor.java.BasicJavaType;
@@ -69,7 +68,6 @@
6968

7069
import static org.hibernate.boot.model.internal.AnnotatedClassType.EMBEDDABLE;
7170
import static org.hibernate.boot.model.internal.AnnotatedClassType.ENTITY;
72-
import static org.hibernate.boot.model.internal.FilterDefBinder.bindFilterDefs;
7371
import static org.hibernate.boot.model.internal.GeneratorBinder.buildGenerators;
7472
import static org.hibernate.boot.model.internal.GeneratorBinder.buildIdGenerator;
7573
import static org.hibernate.boot.model.internal.InheritanceState.getInheritanceStateOfSuperEntity;
@@ -226,7 +224,7 @@ public static void bindPackage(ClassLoaderService cls, String packageName, Metad
226224

227225
bindGenericGenerators( annotatedPackage, context );
228226
bindQueries( annotatedPackage, context );
229-
bindFilterDefs( annotatedPackage, context );
227+
FilterDefBinder.bindFilterDefs( annotatedPackage, context );
230228
}
231229

232230
private static void handleIdGenerators(XPackage annotatedPackage, MetadataBuildingContext context) {
@@ -371,6 +369,12 @@ private static void bindNamedStoredProcedureQuery(
371369
}
372370
}
373371

372+
public static void bindFilterDefs(
373+
XClass annotatedClass,
374+
MetadataBuildingContext context) throws MappingException {
375+
FilterDefBinder.bindFilterDefs( annotatedClass, context );
376+
}
377+
374378
/**
375379
* Bind an annotated class. A subclass must be bound <em>after</em> its superclass.
376380
*
@@ -388,7 +392,6 @@ public static void bindClass(
388392

389393
bindQueries( annotatedClass, context );
390394
handleImport( annotatedClass, context );
391-
bindFilterDefs( annotatedClass, context );
392395
bindTypeDescriptorRegistrations( annotatedClass, context );
393396
bindEmbeddableInstantiatorRegistrations( annotatedClass, context );
394397
bindUserTypeRegistrations( annotatedClass, context );

hibernate-core/src/main/java/org/hibernate/boot/model/source/internal/annotations/AnnotationMetadataSourceProcessorImpl.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@
3737
import org.jboss.jandex.IndexView;
3838
import org.jboss.logging.Logger;
3939

40+
import static org.hibernate.boot.model.internal.AnnotationBinder.bindFilterDefs;
41+
4042
/**
4143
* @author Steve Ebersole
4244
*/
@@ -248,6 +250,13 @@ public void processEntityHierarchies(Set<String> processedEntityNames) {
248250
orderedClasses,
249251
rootMetadataBuildingContext
250252
);
253+
// we want to go through all classes and collect the filter definitions first,
254+
// so that when we bind the classes we have the complete list of filters to search from:
255+
for ( XClass clazz : orderedClasses ) {
256+
if ( !processedEntityNames.contains( clazz.getName() ) ) {
257+
bindFilterDefs( clazz, rootMetadataBuildingContext );
258+
}
259+
}
251260

252261
for ( XClass clazz : orderedClasses ) {
253262
if ( processedEntityNames.contains( clazz.getName() ) ) {
Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
/*
2+
* Hibernate, Relational Persistence for Idiomatic Java
3+
*
4+
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
5+
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
6+
*/
7+
package org.hibernate.orm.test.filter;
8+
9+
import jakarta.persistence.Column;
10+
import jakarta.persistence.Entity;
11+
import jakarta.persistence.GeneratedValue;
12+
import jakarta.persistence.GenerationType;
13+
import jakarta.persistence.Id;
14+
import org.hibernate.SharedSessionContract;
15+
import org.hibernate.annotations.Filter;
16+
import org.hibernate.annotations.FilterDef;
17+
import org.hibernate.testing.orm.junit.DomainModel;
18+
import org.hibernate.testing.orm.junit.JiraKey;
19+
import org.hibernate.testing.orm.junit.SessionFactoryScope;
20+
import org.junit.jupiter.api.AfterEach;
21+
import org.junit.jupiter.api.BeforeEach;
22+
import org.junit.jupiter.params.ParameterizedTest;
23+
import org.junit.jupiter.params.provider.MethodSource;
24+
25+
import java.util.List;
26+
import java.util.function.BiConsumer;
27+
import java.util.function.Consumer;
28+
29+
import static org.assertj.core.api.Assertions.assertThat;
30+
31+
@DomainModel(
32+
annotatedClasses = {
33+
FilterDefinitionOrderTest.AMyEntity.class,
34+
FilterDefinitionOrderTest.XEntity.class
35+
}
36+
)
37+
@JiraKey("HHH-19036")
38+
// Real test is if it actually starts, as that's where the filter binding happens,
39+
// but let's also check that it was actually processed as well:
40+
public class FilterDefinitionOrderTest extends AbstractStatefulStatelessFilterTest {
41+
42+
@BeforeEach
43+
void setUp() {
44+
scope.inTransaction(session -> {
45+
AMyEntity entity1 = new AMyEntity();
46+
entity1.setField("test");
47+
AMyEntity entity2 = new AMyEntity();
48+
entity2.setField("Hello");
49+
session.persist(entity1);
50+
session.persist(entity2);
51+
});
52+
}
53+
54+
@AfterEach
55+
void tearDown() {
56+
scope.inTransaction(session -> {
57+
session.createMutationQuery("delete from AMyEntity").executeUpdate();
58+
});
59+
}
60+
61+
@ParameterizedTest
62+
@MethodSource("transactionKind")
63+
void smokeTest(BiConsumer<SessionFactoryScope, Consumer<? extends SharedSessionContract>> inTransaction) {
64+
inTransaction.accept(scope, session -> {
65+
session.enableFilter("x_filter");
66+
List<AMyEntity> entities = session.createQuery("FROM AMyEntity", AMyEntity.class).getResultList();
67+
assertThat(entities).hasSize(1)
68+
.allSatisfy(entity -> assertThat(entity.getField()).isEqualTo("Hello"));
69+
70+
session.disableFilter("x_filter");
71+
entities = session.createQuery("FROM AMyEntity", AMyEntity.class).getResultList();
72+
assertThat(entities).hasSize(2);
73+
});
74+
}
75+
76+
@Entity(name = "AMyEntity")
77+
@Filter(name = "x_filter")
78+
public static class AMyEntity {
79+
@Id
80+
@GeneratedValue(strategy = GenerationType.SEQUENCE)
81+
@Column(nullable = false)
82+
private Long id;
83+
84+
public String field;
85+
86+
public Long getId() {
87+
return id;
88+
}
89+
90+
public void setId(Long id) {
91+
this.id = id;
92+
}
93+
94+
public String getField() {
95+
return field;
96+
}
97+
98+
public void setField(String field) {
99+
this.field = field;
100+
}
101+
}
102+
103+
@Entity(name = "XEntity")
104+
@FilterDef(name = "x_filter", defaultCondition = "field = 'Hello'")
105+
public static class XEntity {
106+
107+
@Id
108+
@GeneratedValue(strategy = GenerationType.SEQUENCE)
109+
@Column(nullable = false)
110+
private Long id;
111+
112+
public String field;
113+
114+
public Long getId() {
115+
return id;
116+
}
117+
118+
public void setId(Long id) {
119+
this.id = id;
120+
}
121+
122+
public String getField() {
123+
return field;
124+
}
125+
126+
public void setField(String field) {
127+
this.field = field;
128+
}
129+
}
130+
}

0 commit comments

Comments
 (0)