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

This commit is contained in:
Andrea Boriero 2019-10-03 16:01:31 +01:00
parent 52f9a36a6d
commit 841368175f
8 changed files with 294 additions and 155 deletions

View File

@ -368,18 +368,8 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil
ClassLoaderService providedClassLoaderService) { ClassLoaderService providedClassLoaderService) {
final BootstrapServiceRegistryBuilder bsrBuilder = new BootstrapServiceRegistryBuilder(); final BootstrapServiceRegistryBuilder bsrBuilder = new BootstrapServiceRegistryBuilder();
final IntegratorProvider integratorProvider = loadSettingInstance( applyIntegrationProvider( integrationSettings, bsrBuilder );
INTEGRATOR_PROVIDER,
integrationSettings.get( INTEGRATOR_PROVIDER ),
IntegratorProvider.class
);
if ( integratorProvider != null ) {
for ( Integrator integrator : integratorProvider.getIntegrators() ) {
bsrBuilder.applyIntegrator( integrator );
}
}
final StrategyRegistrationProviderList strategyRegistrationProviderList final StrategyRegistrationProviderList strategyRegistrationProviderList
= (StrategyRegistrationProviderList) integrationSettings.get( STRATEGY_REGISTRATION_PROVIDERS ); = (StrategyRegistrationProviderList) integrationSettings.get( STRATEGY_REGISTRATION_PROVIDERS );
if ( strategyRegistrationProviderList != null ) { if ( strategyRegistrationProviderList != null ) {
@ -443,6 +433,25 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil
return bsrBuilder.build(); return bsrBuilder.build();
} }
private void applyIntegrationProvider(Map integrationSettings, BootstrapServiceRegistryBuilder bsrBuilder) {
Object integrationSetting = integrationSettings.get( INTEGRATOR_PROVIDER );
if ( integrationSetting == null ) {
return;
}
final IntegratorProvider integratorProvider = loadSettingInstance(
INTEGRATOR_PROVIDER,
integrationSetting,
IntegratorProvider.class
);
if ( integratorProvider != null ) {
for ( Integrator integrator : integratorProvider.getIntegrators() ) {
bsrBuilder.applyIntegrator( integrator );
}
}
}
@SuppressWarnings("unchecked")
private MergedSettings mergeSettings( private MergedSettings mergeSettings(
PersistenceUnitDescriptor persistenceUnit, PersistenceUnitDescriptor persistenceUnit,
Map<?,?> integrationSettings, Map<?,?> integrationSettings,
@ -1375,10 +1384,6 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil
} }
private <T> T loadSettingInstance(String settingName, Object settingValue, Class<T> clazz) { private <T> T loadSettingInstance(String settingName, Object settingValue, Class<T> clazz) {
if ( settingValue == null ) {
return null;
}
T instance = null; T instance = null;
Class<? extends T> instanceClass = null; Class<? extends T> instanceClass = null;
@ -1416,7 +1421,7 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil
} }
catch (InstantiationException | IllegalAccessException e) { catch (InstantiationException | IllegalAccessException e) {
throw new IllegalArgumentException( throw new IllegalArgumentException(
"The MetadataBuilderContributor class [" + instanceClass + "] could not be instantiated!", "The " + clazz.getSimpleName() +" class [" + instanceClass + "] could not be instantiated!",
e e
); );
} }

View File

@ -0,0 +1,43 @@
/*
* 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.integrationprovider;
import java.util.Collections;
import java.util.List;
import org.hibernate.boot.Metadata;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.integrator.spi.Integrator;
import org.hibernate.jpa.boot.spi.IntegratorProvider;
import org.hibernate.service.spi.SessionFactoryServiceRegistry;
/**
* @author Andrea Boriero
*/
public 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) {
}
}
);
}
}

View File

@ -0,0 +1,48 @@
/*
* 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.integrationprovider;
import java.util.List;
import java.util.Map;
import org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl;
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
import org.hibernate.testing.TestForIssue;
import org.junit.Test;
import static org.hibernate.testing.transaction.TransactionUtil.doInJPA;
/**
* @author Vlad Mihalcea
*/
@TestForIssue(jiraKey = "HHH-13614")
public class IntegrationProviderSettingByClassTest 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 );
}
}

View File

@ -0,0 +1,48 @@
/*
* 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.integrationprovider;
import java.util.List;
import java.util.Map;
import org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl;
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
import org.hibernate.testing.TestForIssue;
import org.junit.Test;
import static org.hibernate.testing.transaction.TransactionUtil.doInJPA;
/**
* @author Vlad Mihalcea
*/
@TestForIssue(jiraKey = "HHH-13614")
public class IntegrationProviderSettingByObjectTest 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, new DtoIntegratorProvider() );
}
}

View File

@ -0,0 +1,48 @@
/*
* 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.integrationprovider;
import java.util.List;
import java.util.Map;
import org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl;
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
import org.hibernate.testing.TestForIssue;
import org.junit.Test;
import static org.hibernate.testing.transaction.TransactionUtil.doInJPA;
/**
* @author Vlad Mihalcea
*/
@TestForIssue(jiraKey = "HHH-13614")
public class IntegrationProviderSettingByStringTest 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() );
}
}

View File

@ -0,0 +1,49 @@
/*
* 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.integrationprovider;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
/**
* @author Andrea Boriero
*/
@Entity(name = "Person")
public 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;
}
}

View File

@ -0,0 +1,37 @@
/*
* 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.integrationprovider;
/**
* @author Andrea Boriero
*/
public 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;
}
}

View File

@ -1,139 +0,0 @@
/*
* 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;
}
}
}