HHH-13614 Allow the IntegratorProvider to be supplied via its FQN in the JPA persistence.xml

This commit is contained in:
Vlad Mihalcea 2019-09-07 04:03:59 +03:00 committed by Andrea Boriero
parent f5fb84cfe2
commit 52f9a36a6d
2 changed files with 201 additions and 32 deletions

View File

@ -276,37 +276,11 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil
return;
}
MetadataBuilderContributor metadataBuilderContributor = null;
Class<? extends MetadataBuilderContributor> metadataBuilderContributorImplClass = null;
if ( metadataBuilderContributorSetting instanceof MetadataBuilderContributor ) {
metadataBuilderContributor = (MetadataBuilderContributor) metadataBuilderContributorSetting;
}
else if ( metadataBuilderContributorSetting instanceof Class ) {
metadataBuilderContributorImplClass = (Class<? extends MetadataBuilderContributor>) metadataBuilderContributorSetting;
}
else if ( metadataBuilderContributorSetting instanceof String ) {
final ClassLoaderService classLoaderService = standardServiceRegistry.getService( ClassLoaderService.class );
metadataBuilderContributorImplClass = classLoaderService.classForName( (String) metadataBuilderContributorSetting );
}
else {
throw new IllegalArgumentException(
"The provided " + METADATA_BUILDER_CONTRIBUTOR + " setting value [" + metadataBuilderContributorSetting + "] is not supported!"
);
}
if ( metadataBuilderContributorImplClass != null ) {
try {
metadataBuilderContributor = metadataBuilderContributorImplClass.newInstance();
}
catch (InstantiationException | IllegalAccessException e) {
throw new IllegalArgumentException(
"The MetadataBuilderContributor class [" + metadataBuilderContributorImplClass + "] could not be instantiated!",
e
);
}
}
MetadataBuilderContributor metadataBuilderContributor = loadSettingInstance(
METADATA_BUILDER_CONTRIBUTOR,
metadataBuilderContributorSetting,
MetadataBuilderContributor.class
);
if ( metadataBuilderContributor != null ) {
metadataBuilderContributor.contribute( metamodelBuilder );
@ -394,7 +368,12 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil
ClassLoaderService providedClassLoaderService) {
final BootstrapServiceRegistryBuilder bsrBuilder = new BootstrapServiceRegistryBuilder();
final IntegratorProvider integratorProvider = (IntegratorProvider) integrationSettings.get( INTEGRATOR_PROVIDER );
final IntegratorProvider integratorProvider = loadSettingInstance(
INTEGRATOR_PROVIDER,
integrationSettings.get( INTEGRATOR_PROVIDER ),
IntegratorProvider.class
);
if ( integratorProvider != null ) {
for ( Integrator integrator : integratorProvider.getIntegrators() ) {
bsrBuilder.applyIntegrator( integrator );
@ -1394,4 +1373,55 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil
this.cacheRegionDefinitions.add( cacheRegionDefinition );
}
}
private <T> T loadSettingInstance(String settingName, Object settingValue, Class<T> clazz) {
if ( settingValue == null ) {
return null;
}
T instance = null;
Class<? extends T> instanceClass = null;
if ( clazz.isAssignableFrom( settingValue.getClass() ) ) {
instance = (T) settingValue;
}
else if ( settingValue instanceof Class ) {
instanceClass = (Class<? extends T>) settingValue;
}
else if ( settingValue instanceof String ) {
String settingStringValue = (String) settingValue;
if ( standardServiceRegistry != null ) {
final ClassLoaderService classLoaderService = standardServiceRegistry.getService( ClassLoaderService.class );
instanceClass = classLoaderService.classForName( settingStringValue );
}
else {
try {
instanceClass = (Class<? extends T>) Class.forName( settingStringValue );
}
catch (ClassNotFoundException e) {
throw new IllegalArgumentException( "Can't load class: " + settingStringValue, e );
}
}
}
else {
throw new IllegalArgumentException(
"The provided " + settingName + " setting value [" + settingValue + "] is not supported!"
);
}
if ( instanceClass != null ) {
try {
instance = instanceClass.newInstance();
}
catch (InstantiationException | IllegalAccessException e) {
throw new IllegalArgumentException(
"The MetadataBuilderContributor class [" + instanceClass + "] could not be instantiated!",
e
);
}
}
return instance;
}
}

View File

@ -0,0 +1,139 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.jpa.test.query;
import java.util.*;
import javax.persistence.*;
import org.hibernate.FlushMode;
import org.hibernate.Session;
import org.hibernate.boot.Metadata;
import org.hibernate.dialect.Oracle8iDialect;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.integrator.spi.Integrator;
import org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl;
import org.hibernate.jpa.boot.spi.IntegratorProvider;
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
import org.hibernate.service.spi.SessionFactoryServiceRegistry;
import org.hibernate.testing.SkipForDialect;
import org.junit.Test;
import static org.hibernate.testing.junit4.ExtraAssertions.assertTyping;
import static org.hibernate.testing.transaction.TransactionUtil.doInJPA;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
/**
* @author Vlad Mihalcea
*/
public class ConstructorResultDtoTest extends BaseEntityManagerFunctionalTestCase {
@Override
protected Class<?>[] getAnnotatedClasses() {
return new Class<?>[]{
Person.class
};
}
@Test
public void test() {
doInJPA(this::entityManagerFactory, entityManager -> {
List<PersonDto> dtos = entityManager.createQuery(
"select new PersonDto(id, name) " +
"from Person", PersonDto.class)
.getResultList();
});
}
@Override
protected void addMappings(Map settings) {
settings.put(EntityManagerFactoryBuilderImpl.INTEGRATOR_PROVIDER, DtoIntegratorProvider.class.getName());
}
public static class DtoIntegratorProvider implements IntegratorProvider {
@Override
public List<Integrator> getIntegrators() {
return Collections.singletonList(
new Integrator() {
@Override
public void integrate(Metadata metadata, SessionFactoryImplementor sessionFactory, SessionFactoryServiceRegistry serviceRegistry) {
metadata.getImports().put("PersonDto", PersonDto.class.getName());
}
@Override
public void disintegrate(SessionFactoryImplementor sessionFactory, SessionFactoryServiceRegistry serviceRegistry) {
}
}
);
}
}
@Entity(name = "Person")
public static class Person {
@Id
@GeneratedValue
private Long id;
private String name;
private int age;
public Person() {
}
public Person(String name) {
this.name = name;
}
public Long getId() {
return id;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
public static class PersonDto {
private Long id;
private String name;
public PersonDto(Long id, String name) {
this.id = id;
this.name = name;
}
public void setId(Long id) {
this.id = id;
}
public void setName(String name) {
this.name = name;
}
public Long getId() {
return id;
}
public String getName() {
return name;
}
}
}