Skip to content

Commit 974e196

Browse files
authored
Merge pull request quarkusio#47792 from ayagmar/issues/46843_hibernate_orm_cdi
Add CDI support for additional JPA/Hibernate components
2 parents 59d33dc + 94de780 commit 974e196

15 files changed

+946
-58
lines changed

.gitignore

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,9 @@ lib
1414
bin
1515
!devtools/cli/distribution/java-binary/bin
1616
dependency-reduced-pom.xml
17-
derby.log
18-
hotspot.log
1917
.directory
2018
.java-version
2119
.graal-install
22-
hs_err_pid*.log
2320
dumps
2421
*.orig
2522
*.rej
@@ -31,9 +28,8 @@ ObjectStore
3128
.gradle
3229
docker/distroless/bazel-*
3330
/.apt_generated_tests/
34-
quarkus.log
35-
quarkus.log*
36-
replay_*.logß
31+
*.log
32+
*.log*
3733
nbactions.xml
3834
nb-configuration.xml
3935
.cache

docs/src/main/asciidoc/hibernate-orm.adoc

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -501,6 +501,47 @@ You can inject the `EntityManagerFactory` of a named persistence unit using the
501501
EntityManagerFactory entityManagerFactory;
502502
----
503503

504+
In addition to `EntityManager` and `EntityManagerFactory`, Quarkus also supports injecting the following JPA/Hibernate components:
505+
506+
[source,java]
507+
----
508+
@Inject
509+
CriteriaBuilder criteriaBuilder;
510+
511+
@Inject
512+
HibernateCriteriaBuilder hibernateCriteriaBuilder;
513+
514+
@Inject
515+
Metamodel metamodel;
516+
517+
@Inject
518+
org.hibernate.Metamodel metamodel;
519+
520+
@Inject
521+
JpaMetamodel jpaMetamodel;
522+
523+
@Inject
524+
Cache cache;
525+
526+
@Inject
527+
org.hibernate.Cache cache;
528+
529+
@Inject
530+
jakarta.persistence.PersistenceUnitUtil persistenceUnitUtil;
531+
532+
@Inject
533+
org.hibernate.relational.SchemaManager schemaManager;
534+
----
535+
536+
These components can also be injected with a specific persistence unit qualifier:
537+
538+
[source,java]
539+
----
540+
@Inject
541+
@PersistenceUnit("users")
542+
CriteriaBuilder criteriaBuilder;
543+
----
544+
504545
[[persistence-unit-active]]
505546
=== Activate/deactivate persistence units
506547

extensions/hibernate-orm/deployment/src/main/java/io/quarkus/hibernate/orm/deployment/ClassNames.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,16 @@ private static DotName createConstant(String fqcn) {
5353
public static final DotName ENTITY_MANAGER = createConstant("jakarta.persistence.EntityManager");
5454
public static final DotName SESSION = createConstant("org.hibernate.Session");
5555
public static final DotName STATELESS_SESSION = createConstant("org.hibernate.StatelessSession");
56+
public static final DotName CRITERIA_BUILDER = createConstant("jakarta.persistence.criteria.CriteriaBuilder");
57+
public static final DotName HIBERNATE_CRITERIA_BUILDER = createConstant(
58+
"org.hibernate.query.criteria.HibernateCriteriaBuilder");
59+
public static final DotName METAMODEL = createConstant("jakarta.persistence.metamodel.Metamodel");
60+
public static final DotName HIBERNATE_METAMODEL = createConstant("org.hibernate.Metamodel");
61+
public static final DotName JPA_METAMODEL = createConstant("org.hibernate.metamodel.model.domain.JpaMetamodel");
62+
public static final DotName SCHEMA_MANAGER = createConstant("org.hibernate.relational.SchemaManager");
63+
public static final DotName CACHE = createConstant("jakarta.persistence.Cache");
64+
public static final DotName HIBERNATE_CACHE = createConstant("org.hibernate.Cache");
65+
public static final DotName PERSISTENCE_UNIT_UTIL = createConstant("jakarta.persistence.PersistenceUnitUtil");
5666

5767
public static final DotName INTERCEPTOR = createConstant("org.hibernate.Interceptor");
5868
public static final DotName STATEMENT_INSPECTOR = createConstant("org.hibernate.resource.jdbc.spi.StatementInspector");

extensions/hibernate-orm/deployment/src/main/java/io/quarkus/hibernate/orm/deployment/HibernateOrmCdiProcessor.java

Lines changed: 135 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
package io.quarkus.hibernate.orm.deployment;
22

3+
import static org.apache.commons.lang3.BooleanUtils.isFalse;
4+
35
import java.util.ArrayList;
46
import java.util.Arrays;
57
import java.util.List;
68
import java.util.Locale;
79
import java.util.Set;
10+
import java.util.function.Function;
811
import java.util.stream.Collectors;
912

1013
import jakarta.enterprise.context.ApplicationScoped;
@@ -18,8 +21,11 @@
1821
import org.hibernate.Session;
1922
import org.hibernate.SessionFactory;
2023
import org.hibernate.StatelessSession;
24+
import org.hibernate.query.criteria.HibernateCriteriaBuilder;
25+
import org.hibernate.relational.SchemaManager;
2126
import org.jboss.jandex.AnnotationInstance;
2227
import org.jboss.jandex.AnnotationTarget.Kind;
28+
import org.jboss.jandex.AnnotationTransformation;
2329
import org.jboss.jandex.AnnotationValue;
2430
import org.jboss.jandex.ClassType;
2531
import org.jboss.jandex.DotName;
@@ -64,6 +70,13 @@ public class HibernateOrmCdiProcessor {
6470
ClassNames.SESSION_FACTORY);
6571
private static final List<DotName> SESSION_EXPOSED_TYPES = Arrays.asList(ClassNames.ENTITY_MANAGER, ClassNames.SESSION);
6672
private static final List<DotName> STATELESS_SESSION_EXPOSED_TYPES = List.of(ClassNames.STATELESS_SESSION);
73+
private static final List<DotName> CRITERIA_BUILDER_EXPOSED_TYPES = List.of(ClassNames.CRITERIA_BUILDER,
74+
ClassNames.HIBERNATE_CRITERIA_BUILDER);
75+
private static final List<DotName> METAMODEL_EXPOSED_TYPES = List.of(ClassNames.METAMODEL, ClassNames.JPA_METAMODEL,
76+
ClassNames.HIBERNATE_METAMODEL);
77+
private static final List<DotName> SCHEMA_MANAGER_EXPOSED_TYPES = List.of(ClassNames.SCHEMA_MANAGER);
78+
private static final List<DotName> CACHE_EXPOSED_TYPES = List.of(ClassNames.CACHE, ClassNames.HIBERNATE_CACHE);
79+
private static final List<DotName> PERSISTENCE_UNIT_UTIL_EXPOSED_TYPES = List.of(ClassNames.PERSISTENCE_UNIT_UTIL);
6780

6881
private static final Set<DotName> PERSISTENCE_UNIT_EXTENSION_VALID_TYPES = Set.of(
6982
ClassNames.TENANT_RESOLVER,
@@ -76,7 +89,7 @@ public class HibernateOrmCdiProcessor {
7689
AnnotationsTransformerBuildItem convertJpaResourceAnnotationsToQualifier(
7790
List<PersistenceUnitDescriptorBuildItem> persistenceUnitDescriptors,
7891
ImpliedBlockingPersistenceUnitTypeBuildItem impliedBlockingPersistenceUnitType) {
79-
AnnotationsTransformer transformer = new AnnotationsTransformer() {
92+
AnnotationTransformation transformer = new AnnotationsTransformer() {
8093

8194
@Override
8295
public boolean appliesTo(Kind kind) {
@@ -178,34 +191,22 @@ void generateDataSourceBeans(HibernateOrmRecorder recorder,
178191
return;
179192
}
180193

194+
Function<String, AnnotationInstance> createPersistenceUnitQualifier = (puName) -> AnnotationInstance
195+
.builder(PersistenceUnit.class).add("value", puName).build();
196+
AnnotationInstance defaultQualifierInstance = AnnotationInstance.builder(Default.class).build();
197+
181198
// we have only one persistence unit defined in a persistence.xml: we make it the default even if it has a name
182199
// NOTE: In this case we know we're not using Hibernate Reactive, because it doesn't support persistence.xml.
183200
if (persistenceUnitDescriptors.size() == 1 && persistenceUnitDescriptors.get(0).isFromPersistenceXml()) {
184201
String persistenceUnitName = persistenceUnitDescriptors.get(0).getPersistenceUnitName();
185202

186-
syntheticBeanBuildItemBuildProducer
187-
.produce(createSyntheticBean(persistenceUnitName,
188-
true, true,
189-
SessionFactory.class, SESSION_FACTORY_EXPOSED_TYPES, true)
190-
.createWith(recorder.sessionFactorySupplier(persistenceUnitName))
191-
.addInjectionPoint(ClassType.create(DotName.createSimple(JPAConfig.class)))
192-
.done());
193-
194-
syntheticBeanBuildItemBuildProducer
195-
.produce(createSyntheticBean(persistenceUnitName,
196-
true, true,
197-
Session.class, SESSION_EXPOSED_TYPES, false)
198-
.createWith(recorder.sessionSupplier(persistenceUnitName))
199-
.addInjectionPoint(ClassType.create(DotName.createSimple(TransactionSessions.class)))
200-
.done());
201-
202-
syntheticBeanBuildItemBuildProducer
203-
.produce(createSyntheticBean(persistenceUnitName,
204-
true, true,
205-
StatelessSession.class, STATELESS_SESSION_EXPOSED_TYPES, false)
206-
.createWith(recorder.statelessSessionSupplier(persistenceUnitName))
207-
.addInjectionPoint(ClassType.create(DotName.createSimple(TransactionSessions.class)))
208-
.done());
203+
produceSessionFactoryBean(syntheticBeanBuildItemBuildProducer, recorder, persistenceUnitName, true, true);
204+
205+
produceSessionBeans(syntheticBeanBuildItemBuildProducer, recorder, persistenceUnitName, true, true);
206+
207+
produceFactoryDependentBeans(syntheticBeanBuildItemBuildProducer, recorder, persistenceUnitName,
208+
true, true, defaultQualifierInstance);
209+
209210
return;
210211
}
211212

@@ -223,34 +224,22 @@ void generateDataSourceBeans(HibernateOrmRecorder recorder,
223224
// We will need to fix this at some point, see https://github.com/quarkusio/quarkus/issues/21110
224225
String persistenceUnitConfigName = persistenceUnitDescriptor.getConfigurationName();
225226
boolean isDefaultPU = PersistenceUnitUtil.isDefaultPersistenceUnit(persistenceUnitConfigName);
226-
boolean isNamedPU = !isDefaultPU;
227-
228-
syntheticBeanBuildItemBuildProducer
229-
.produce(createSyntheticBean(persistenceUnitName,
230-
isDefaultPU,
231-
isNamedPU,
232-
SessionFactory.class,
233-
SESSION_FACTORY_EXPOSED_TYPES,
234-
true)
235-
.createWith(recorder.sessionFactorySupplier(persistenceUnitName))
236-
.addInjectionPoint(ClassType.create(DotName.createSimple(JPAConfig.class)))
237-
.done());
238-
239-
syntheticBeanBuildItemBuildProducer
240-
.produce(createSyntheticBean(persistenceUnitName,
241-
isDefaultPU, isNamedPU,
242-
Session.class, SESSION_EXPOSED_TYPES, false)
243-
.createWith(recorder.sessionSupplier(persistenceUnitName))
244-
.addInjectionPoint(ClassType.create(DotName.createSimple(TransactionSessions.class)))
245-
.done());
246-
247-
syntheticBeanBuildItemBuildProducer
248-
.produce(createSyntheticBean(persistenceUnitName,
249-
isDefaultPU, isNamedPU,
250-
StatelessSession.class, STATELESS_SESSION_EXPOSED_TYPES, false)
251-
.createWith(recorder.statelessSessionSupplier(persistenceUnitName))
252-
.addInjectionPoint(ClassType.create(DotName.createSimple(TransactionSessions.class)))
253-
.done());
227+
boolean isNamedPU = isFalse(isDefaultPU);
228+
AnnotationInstance sessionFactoryQualifier;
229+
if (isDefaultPU) {
230+
sessionFactoryQualifier = defaultQualifierInstance;
231+
} else {
232+
sessionFactoryQualifier = createPersistenceUnitQualifier.apply(persistenceUnitName);
233+
}
234+
235+
produceSessionFactoryBean(syntheticBeanBuildItemBuildProducer, recorder, persistenceUnitName, isDefaultPU,
236+
isNamedPU);
237+
238+
produceSessionBeans(syntheticBeanBuildItemBuildProducer, recorder, persistenceUnitName, isDefaultPU, isNamedPU);
239+
240+
produceFactoryDependentBeans(syntheticBeanBuildItemBuildProducer, recorder, persistenceUnitName,
241+
isDefaultPU, isNamedPU, sessionFactoryQualifier);
242+
254243
}
255244
}
256245

@@ -352,4 +341,98 @@ private static <T> ExtendedBeanConfigurator createSyntheticBean(String persisten
352341

353342
return configurator;
354343
}
344+
345+
private void produceSessionBeans(
346+
BuildProducer<SyntheticBeanBuildItem> producer,
347+
HibernateOrmRecorder recorder,
348+
String persistenceUnitName,
349+
boolean isDefaultPU,
350+
boolean isNamedPU) {
351+
352+
// Create Session bean
353+
producer.produce(createSyntheticBean(persistenceUnitName,
354+
isDefaultPU, isNamedPU,
355+
Session.class, SESSION_EXPOSED_TYPES, false)
356+
.createWith(recorder.sessionSupplier(persistenceUnitName))
357+
.addInjectionPoint(ClassType.create(DotName.createSimple(TransactionSessions.class)))
358+
.done());
359+
360+
// Create StatelessSession bean
361+
producer.produce(createSyntheticBean(persistenceUnitName,
362+
isDefaultPU, isNamedPU,
363+
StatelessSession.class, STATELESS_SESSION_EXPOSED_TYPES, false)
364+
.createWith(recorder.statelessSessionSupplier(persistenceUnitName))
365+
.addInjectionPoint(ClassType.create(DotName.createSimple(TransactionSessions.class)))
366+
.done());
367+
}
368+
369+
private void produceSessionFactoryBean(
370+
BuildProducer<SyntheticBeanBuildItem> producer,
371+
HibernateOrmRecorder recorder,
372+
String persistenceUnitName,
373+
boolean isDefaultPU,
374+
boolean isNamedPU) {
375+
376+
producer.produce(createSyntheticBean(persistenceUnitName,
377+
isDefaultPU, isNamedPU,
378+
SessionFactory.class, SESSION_FACTORY_EXPOSED_TYPES, true)
379+
.createWith(recorder.sessionFactorySupplier(persistenceUnitName))
380+
.addInjectionPoint(ClassType.create(DotName.createSimple(JPAConfig.class)))
381+
.done());
382+
}
383+
384+
private void produceFactoryDependentBeans(
385+
BuildProducer<SyntheticBeanBuildItem> producer,
386+
HibernateOrmRecorder recorder,
387+
String persistenceUnitName,
388+
boolean isDefaultPU,
389+
boolean isNamedPU,
390+
AnnotationInstance sessionFactoryQualifier) {
391+
392+
// Create CriteriaBuilder bean
393+
producer.produce(createSyntheticBean(persistenceUnitName,
394+
isDefaultPU, isNamedPU,
395+
HibernateCriteriaBuilder.class, CRITERIA_BUILDER_EXPOSED_TYPES, false)
396+
.createWith(recorder.criteriaBuilderSupplier(persistenceUnitName))
397+
.addInjectionPoint(ClassType.create(DotName.createSimple(SessionFactory.class)),
398+
sessionFactoryQualifier)
399+
.done());
400+
401+
// Create Metamodel bean
402+
producer.produce(createSyntheticBean(persistenceUnitName,
403+
isDefaultPU, isNamedPU,
404+
org.hibernate.Metamodel.class, METAMODEL_EXPOSED_TYPES, false)
405+
.createWith(recorder.metamodelSupplier(persistenceUnitName))
406+
.addInjectionPoint(ClassType.create(DotName.createSimple(SessionFactory.class)),
407+
sessionFactoryQualifier)
408+
.done());
409+
410+
// Create SchemaManager bean
411+
producer.produce(createSyntheticBean(persistenceUnitName,
412+
isDefaultPU, isNamedPU,
413+
SchemaManager.class, SCHEMA_MANAGER_EXPOSED_TYPES, false)
414+
.createWith(recorder.schemaManagerSupplier(persistenceUnitName))
415+
.addInjectionPoint(ClassType.create(DotName.createSimple(SessionFactory.class)),
416+
sessionFactoryQualifier)
417+
.done());
418+
419+
// Create Cache bean
420+
producer.produce(createSyntheticBean(persistenceUnitName,
421+
isDefaultPU, isNamedPU,
422+
org.hibernate.Cache.class, CACHE_EXPOSED_TYPES, false)
423+
.createWith(recorder.cacheSupplier(persistenceUnitName))
424+
.addInjectionPoint(ClassType.create(DotName.createSimple(SessionFactory.class)),
425+
sessionFactoryQualifier)
426+
.done());
427+
428+
// Create PersistenceUnitUtil bean
429+
producer.produce(createSyntheticBean(persistenceUnitName,
430+
isDefaultPU, isNamedPU,
431+
jakarta.persistence.PersistenceUnitUtil.class, PERSISTENCE_UNIT_UTIL_EXPOSED_TYPES, false)
432+
.createWith(recorder.persistenceUnitUtilSupplier(persistenceUnitName))
433+
.addInjectionPoint(ClassType.create(DotName.createSimple(SessionFactory.class)),
434+
sessionFactoryQualifier)
435+
.done());
436+
}
437+
355438
}

0 commit comments

Comments
 (0)