Merge remote-tracking branch 'upstream/master' into wip/6.0
This commit is contained in:
commit
6250942e7f
|
@ -434,7 +434,7 @@ Enable lazy loading feature in runtime bytecode enhancement. This way, even basi
|
|||
Enable association management feature in runtime bytecode enhancement which automatically synchronizes a bidirectional association when only one side is changed.
|
||||
|
||||
`*hibernate.bytecode.provider*` (e.g. `bytebuddy` (default value))::
|
||||
The https://docs.jboss.org/hibernate/orm/{majorMinorVersion}/javadocs/org/hibernate/bytecode/spi/BytecodeProvider.html[`BytecodeProvider`] built-in implementation flavor. Currently, only `bytebuddy` and `javassist` are valid values.
|
||||
The https://docs.jboss.org/hibernate/orm/{majorMinorVersion}/javadocs/org/hibernate/bytecode/spi/BytecodeProvider.html[`BytecodeProvider`] built-in implementation flavor. Currently, only `bytebuddy` and `javassist` are valid values; `bytebuddy` is the default and recommended choice; `javassist` will be removed soon.
|
||||
|
||||
`*hibernate.bytecode.use_reflection_optimizer*` (e.g. `true` or `false` (default value))::
|
||||
Should we use reflection optimization? The reflection optimizer implements the https://docs.jboss.org/hibernate/orm/{majorMinorVersion}/javadocs/org/hibernate/bytecode/spi/ReflectionOptimizer.html[`ReflectionOptimizer`] interface and improves entity instantiation and property getter/setter calls.
|
||||
|
|
|
@ -30,6 +30,7 @@ import org.hibernate.boot.jaxb.Origin;
|
|||
import org.hibernate.boot.jaxb.SourceType;
|
||||
import org.hibernate.boot.model.convert.internal.ClassBasedConverterDescriptor;
|
||||
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
|
||||
import org.hibernate.boot.registry.classloading.spi.ClassLoadingException;
|
||||
import org.hibernate.boot.spi.BootstrapContext;
|
||||
import org.hibernate.boot.spi.ClassLoaderAccess;
|
||||
import org.hibernate.boot.spi.XmlMappingBinderAccess;
|
||||
|
@ -269,6 +270,16 @@ public class ScanningCoordinator {
|
|||
continue;
|
||||
}
|
||||
|
||||
// Last, try it by loading the class
|
||||
try {
|
||||
Class<?> clazz = classLoaderService.classForName( unresolvedListedClassName );
|
||||
managedResources.addAnnotatedClassReference( clazz );
|
||||
continue;
|
||||
}
|
||||
catch (ClassLoadingException ignore) {
|
||||
// ignore this error
|
||||
}
|
||||
|
||||
if ( log.isDebugEnabled() ) {
|
||||
log.debugf(
|
||||
"Unable to resolve class [%s] named in persistence unit [%s]",
|
||||
|
|
|
@ -238,18 +238,6 @@ public class OneToOneSecondPass implements SecondPass {
|
|||
boolean referenceToPrimaryKey = referencesDerivedId || mappedBy == null;
|
||||
value.setReferenceToPrimaryKey( referenceToPrimaryKey );
|
||||
|
||||
// If the other side is an entity with an ID that is derived from
|
||||
// this side's owner entity, and both sides of the association are eager,
|
||||
// then this side must be set to FetchMode.SELECT; otherwise,
|
||||
// there will be an infinite loop attempting to load the derived ID on
|
||||
// the opposite side.
|
||||
if ( referencesDerivedId &&
|
||||
!value.isLazy() &&
|
||||
value.getFetchMode() == FetchMode.JOIN &&
|
||||
!otherSideProperty.isLazy() ) {
|
||||
value.setFetchMode( FetchMode.SELECT );
|
||||
}
|
||||
|
||||
String propertyRef = value.getReferencedPropertyName();
|
||||
if ( propertyRef != null ) {
|
||||
buildingContext.getMetadataCollector().addUniquePropertyReference(
|
||||
|
|
|
@ -642,6 +642,10 @@ public abstract class AbstractPersistentCollection<E> implements Serializable, P
|
|||
LOG.queuedOperationWhenDetachFromSession( collectionInfoString );
|
||||
}
|
||||
}
|
||||
if ( allowLoadOutsideTransaction && !initialized && session.getLoadQueryInfluencers().hasEnabledFilters() ) {
|
||||
final String collectionInfoString = MessageHelper.collectionInfoString( getRole(), getKey() );
|
||||
LOG.enabledFiltersWhenDetachFromSession( collectionInfoString );
|
||||
}
|
||||
this.session = null;
|
||||
}
|
||||
return true;
|
||||
|
|
|
@ -185,7 +185,7 @@ public abstract class AbstractSharedSessionContract implements SharedSessionCont
|
|||
this.transactionCoordinator = sharedOptions.getTransactionCoordinator();
|
||||
this.jdbcCoordinator = sharedOptions.getJdbcCoordinator();
|
||||
|
||||
// todo : "wrap" the transaction to no-op comit/rollback attempts?
|
||||
// todo : "wrap" the transaction to no-op commit/rollback attempts?
|
||||
this.currentHibernateTransaction = sharedOptions.getTransaction();
|
||||
|
||||
if ( sharedOptions.shouldAutoJoinTransactions() ) {
|
||||
|
@ -292,7 +292,7 @@ public abstract class AbstractSharedSessionContract implements SharedSessionCont
|
|||
@Override
|
||||
public UUID getSessionIdentifier() {
|
||||
if ( this.sessionIdentifier == null ) {
|
||||
//Lazily initialized: otherwise all the UUID generations will cause of significant amount of contention.
|
||||
//Lazily initialized: otherwise all the UUID generations will cause significant amount of contention.
|
||||
this.sessionIdentifier = StandardRandomStrategy.INSTANCE.generateUUID( null );
|
||||
}
|
||||
return sessionIdentifier;
|
||||
|
|
|
@ -1828,4 +1828,13 @@ public interface CoreMessageLogger extends BasicLogger {
|
|||
@Message(value = "Ignoring ServiceConfigurationError caught while trying to instantiate service '%s'.", id = 505)
|
||||
void ignoringServiceConfigurationError(Class<?> serviceContract, @Cause ServiceConfigurationError error);
|
||||
|
||||
@LogMessage(level = WARN)
|
||||
@Message(value = "Detaching an uninitialized collection with enabled filters from a session: %s", id = 506)
|
||||
void enabledFiltersWhenDetachFromSession(String collectionInfoString);
|
||||
|
||||
@LogMessage(level = WARN)
|
||||
@Message(value = "The Javassist based BytecodeProvider is deprecated. Please switch to using the ByteBuddy based BytecodeProvider, " +
|
||||
"which is the default since Hibernate ORM 5.3. The Javassist one will be removed soon.", id = 507)
|
||||
void warnUsingJavassistBytecodeProviderIsDeprecated();
|
||||
|
||||
}
|
||||
|
|
|
@ -1332,30 +1332,48 @@ public abstract class AbstractProducedQuery<R> implements QueryImplementor<R> {
|
|||
// entityGraphHintedQueryPlan = null;
|
||||
// }
|
||||
// else {
|
||||
// final SharedSessionContractImplementor producer = getProducer();
|
||||
// entityGraphHintedQueryPlan = new HQLQueryPlan(
|
||||
// hql,
|
||||
// false,
|
||||
// getSession().getLoadQueryInfluencers().getEnabledFilters(),
|
||||
// getSession().getFactory(),
|
||||
// producer.getLoadQueryInfluencers().getEnabledFilters(),
|
||||
// producer.getFactory(),
|
||||
// entityGraphQueryHint
|
||||
// );
|
||||
// }
|
||||
//
|
||||
// final QueryParameters queryParameters = new QueryParameters(
|
||||
// QueryParameters queryParameters = new QueryParameters(
|
||||
// getQueryParameterBindings(),
|
||||
// getLockOptions(),
|
||||
// queryOptions,
|
||||
// true,
|
||||
// isReadOnly(),
|
||||
// cacheable,
|
||||
// cacheRegion,
|
||||
// comment,
|
||||
// dbHints,
|
||||
// null,
|
||||
// optionalObject,
|
||||
// optionalEntityName,
|
||||
// optionalId,
|
||||
// resultTransformer
|
||||
// );
|
||||
// queryParameters.setQueryPlan( entityGraphHintedQueryPlan );
|
||||
//
|
||||
// appendQueryPlanToQueryParameters( hql, queryParameters, entityGraphHintedQueryPlan );
|
||||
//
|
||||
// if ( passDistinctThrough != null ) {
|
||||
// queryParameters.setPassDistinctThrough( passDistinctThrough );
|
||||
// }
|
||||
// return queryParameters;
|
||||
// }
|
||||
|
||||
// protected void appendQueryPlanToQueryParameters(
|
||||
// String hql,
|
||||
// QueryParameters queryParameters,
|
||||
// HQLQueryPlan queryPlan) {
|
||||
// if ( queryPlan != null ) {
|
||||
// queryParameters.setQueryPlan( queryPlan );
|
||||
// }
|
||||
// }
|
||||
|
||||
private FlushMode sessionFlushMode;
|
||||
|
@ -1551,7 +1569,7 @@ public abstract class AbstractProducedQuery<R> implements QueryImplementor<R> {
|
|||
this.optionalObject = optionalObject;
|
||||
}
|
||||
|
||||
private boolean isSelect() {
|
||||
protected boolean isSelect() {
|
||||
throw new NotYetImplementedFor6Exception( getClass() );
|
||||
|
||||
// return getSession().getFactory().getQueryInterpretationCache()
|
||||
|
|
|
@ -13,6 +13,7 @@ import java.sql.ResultSet;
|
|||
import java.sql.SQLException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
import org.hibernate.EntityMode;
|
||||
|
@ -517,5 +518,18 @@ public class AnyType extends AbstractType implements CompositeType, AssociationT
|
|||
this.entityName = entityName;
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return Objects.hash( entityName, id );
|
||||
}
|
||||
|
||||
public boolean equals(Object object) {
|
||||
if (object instanceof ObjectTypeCacheEntry) {
|
||||
ObjectTypeCacheEntry objectTypeCacheEntry = (ObjectTypeCacheEntry)object;
|
||||
return Objects.equals( objectTypeCacheEntry.entityName, entityName ) && Objects.equals( objectTypeCacheEntry.id, id );
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,10 +24,10 @@ import org.hibernate.boot.archive.spi.InputStreamAccess;
|
|||
import org.hibernate.boot.model.convert.spi.ConverterDescriptor;
|
||||
import org.hibernate.boot.registry.StandardServiceRegistry;
|
||||
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
|
||||
import org.hibernate.boot.registry.classloading.spi.ClassLoadingException;
|
||||
import org.hibernate.boot.spi.BootstrapContext;
|
||||
import org.hibernate.boot.spi.XmlMappingBinderAccess;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
|
||||
import org.hibernate.testing.TestForIssue;
|
||||
import org.hibernate.testing.junit4.BaseUnitTestCase;
|
||||
import org.hibernate.testing.logger.LoggerInspectionRule;
|
||||
|
@ -41,6 +41,11 @@ import org.jboss.logging.Logger;
|
|||
import org.mockito.Mockito;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.ArgumentMatchers.same;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
/**
|
||||
|
@ -67,9 +72,11 @@ public class ScanningCoordinatorTest extends BaseUnitTestCase {
|
|||
|
||||
@Before
|
||||
public void init() {
|
||||
Mockito.reset( managedResources );
|
||||
Mockito.reset( scanResult );
|
||||
Mockito.reset( bootstrapContext );
|
||||
Mockito.reset( scanEnvironment );
|
||||
Mockito.reset( classLoaderService );
|
||||
|
||||
when( bootstrapContext.getScanEnvironment() ).thenReturn( scanEnvironment );
|
||||
when( bootstrapContext.getServiceRegistry() ).thenReturn( serviceRegistry );
|
||||
|
@ -78,7 +85,9 @@ public class ScanningCoordinatorTest extends BaseUnitTestCase {
|
|||
when( scanEnvironment.getExplicitlyListedClassNames() ).thenReturn(
|
||||
Arrays.asList( "a.b.C" ) );
|
||||
|
||||
when( classLoaderService.classForName( "a.b.C" ) ).thenReturn( Object.class );
|
||||
when( classLoaderService.classForName( eq( "a.b.C" ) ) ).thenThrow( ClassLoadingException.class );
|
||||
when( classLoaderService.locateResource( eq( "a/b/c.class" ) ) ).thenReturn( null );
|
||||
when( classLoaderService.locateResource( eq( "a/b/c/package-info.class" ) ) ).thenReturn( null );
|
||||
|
||||
triggerable = logInspection.watchForLogMessages( "Unable" );
|
||||
triggerable.reset();
|
||||
|
@ -110,6 +119,24 @@ public class ScanningCoordinatorTest extends BaseUnitTestCase {
|
|||
assertEquals( "Unable to resolve class [a.b.C] named in persistence unit [http://http://hibernate.org/]", triggerable.triggerMessage() );
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestForIssue(jiraKey = "HHH-14473")
|
||||
public void testApplyScanResultsToManagedResultsWhileExplicitClassNameLoadable() {
|
||||
Class<Object> expectedClass = Object.class;
|
||||
when( classLoaderService.classForName( eq( "a.b.C" ) ) ).thenReturn( expectedClass );
|
||||
|
||||
ScanningCoordinator.INSTANCE.applyScanResultsToManagedResources(
|
||||
managedResources,
|
||||
scanResult,
|
||||
bootstrapContext,
|
||||
xmlMappingBinderAccess
|
||||
);
|
||||
|
||||
verify( managedResources, times( 0 ) ).addAnnotatedClassName( any() );
|
||||
verify( managedResources, times( 1 ) ).addAnnotatedClassReference( same( expectedClass ) );
|
||||
verify( classLoaderService, times( 1 ) ).classForName( eq( "a.b.C" ) );
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestForIssue(jiraKey = "HHH-12505")
|
||||
public void testManagedResourcesAfterCoordinateScanWithDisabledScanner() {
|
||||
|
|
|
@ -6,22 +6,28 @@
|
|||
*/
|
||||
package org.hibernate.stat.internal;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.LockModeType;
|
||||
import javax.persistence.NamedQuery;
|
||||
import javax.persistence.Tuple;
|
||||
import javax.persistence.TypedQuery;
|
||||
|
||||
import org.hibernate.SessionFactory;
|
||||
import org.hibernate.cfg.Environment;
|
||||
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
|
||||
import org.hibernate.stat.QueryStatistics;
|
||||
import org.hibernate.stat.Statistics;
|
||||
|
||||
import org.hibernate.testing.TestForIssue;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.hibernate.testing.transaction.TransactionUtil.doInJPA;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
|
@ -39,6 +45,7 @@ public class QueryPlanCacheStatisticsTest extends BaseEntityManagerFunctionalTes
|
|||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addConfigOptions(Map options) {
|
||||
options.put( Environment.GENERATE_STATISTICS, "true" );
|
||||
}
|
||||
|
@ -63,6 +70,7 @@ public class QueryPlanCacheStatisticsTest extends BaseEntityManagerFunctionalTes
|
|||
@Test
|
||||
public void test() {
|
||||
|
||||
statistics.clear();
|
||||
assertEquals( 0, statistics.getQueryPlanCacheHitCount() );
|
||||
assertEquals( 0, statistics.getQueryPlanCacheMissCount() );
|
||||
|
||||
|
@ -115,6 +123,165 @@ public class QueryPlanCacheStatisticsTest extends BaseEntityManagerFunctionalTes
|
|||
} );
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestForIssue( jiraKey = "HHH-13077" )
|
||||
public void testCreateQueryHitCount() {
|
||||
statistics.clear();
|
||||
|
||||
doInJPA( this::entityManagerFactory, entityManager -> {
|
||||
|
||||
List<Employee> employees = entityManager.createQuery(
|
||||
"select e from Employee e", Employee.class )
|
||||
.getResultList();
|
||||
|
||||
assertEquals( 5, employees.size() );
|
||||
|
||||
//First time, we get a cache miss, so the query is compiled
|
||||
assertEquals( 1, statistics.getQueryPlanCacheMissCount() );
|
||||
//The hit count should be 0 as we don't need to go to the cache after we already compiled the query
|
||||
assertEquals( 0, statistics.getQueryPlanCacheHitCount() );
|
||||
} );
|
||||
|
||||
doInJPA( this::entityManagerFactory, entityManager -> {
|
||||
|
||||
List<Employee> employees = entityManager.createQuery(
|
||||
"select e from Employee e", Employee.class )
|
||||
.getResultList();
|
||||
|
||||
assertEquals( 5, employees.size() );
|
||||
|
||||
//The miss count is still 1, as no we got the query plan from the cache
|
||||
assertEquals( 1, statistics.getQueryPlanCacheMissCount() );
|
||||
//And the cache hit count increases.
|
||||
assertEquals( 1, statistics.getQueryPlanCacheHitCount() );
|
||||
} );
|
||||
|
||||
doInJPA( this::entityManagerFactory, entityManager -> {
|
||||
|
||||
List<Employee> employees = entityManager.createQuery(
|
||||
"select e from Employee e", Employee.class )
|
||||
.getResultList();
|
||||
|
||||
assertEquals( 5, employees.size() );
|
||||
|
||||
//The miss count is still 1, as no we got the query plan from the cache
|
||||
assertEquals( 1, statistics.getQueryPlanCacheMissCount() );
|
||||
//And the cache hit count increases.
|
||||
assertEquals( 2, statistics.getQueryPlanCacheHitCount() );
|
||||
} );
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestForIssue( jiraKey = "HHH-13077" )
|
||||
public void testCreateNamedQueryHitCount() {
|
||||
//This is for the NamedQuery that gets compiled
|
||||
assertEquals( 1, statistics.getQueryPlanCacheMissCount() );
|
||||
statistics.clear();
|
||||
|
||||
doInJPA( this::entityManagerFactory, entityManager -> {
|
||||
|
||||
Employee employees = entityManager.createNamedQuery(
|
||||
"find_employee_by_name", Employee.class )
|
||||
.setParameter( "name", "Employee: 1" )
|
||||
.getSingleResult();
|
||||
|
||||
//The miss count is 0 because the plan was compiled when the EMF was built, and we cleared the Statistics
|
||||
assertEquals( 0, statistics.getQueryPlanCacheMissCount() );
|
||||
//The hit count is 1 since we got the plan from the cache
|
||||
assertEquals( 1, statistics.getQueryPlanCacheHitCount() );
|
||||
} );
|
||||
|
||||
doInJPA( this::entityManagerFactory, entityManager -> {
|
||||
|
||||
Employee employees = entityManager.createNamedQuery(
|
||||
"find_employee_by_name", Employee.class )
|
||||
.setParameter( "name", "Employee: 1" )
|
||||
.getSingleResult();
|
||||
|
||||
//The miss count is still 0 because the plan was compiled when the EMF was built, and we cleared the Statistics
|
||||
assertEquals( 0, statistics.getQueryPlanCacheMissCount() );
|
||||
//The hit count is 2 since we got the plan from the cache twice
|
||||
assertEquals( 2, statistics.getQueryPlanCacheHitCount() );
|
||||
} );
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestForIssue( jiraKey = "HHH-13077" )
|
||||
public void testCreateQueryTupleHitCount() {
|
||||
statistics.clear();
|
||||
|
||||
doInJPA( this::entityManagerFactory, entityManager -> {
|
||||
|
||||
List<Tuple> employees = entityManager.createQuery(
|
||||
"select e.id, e.name from Employee e", Tuple.class )
|
||||
.getResultList();
|
||||
|
||||
assertEquals( 5, employees.size() );
|
||||
|
||||
//First time, we get a cache miss, so the query is compiled
|
||||
assertEquals( 1, statistics.getQueryPlanCacheMissCount() );
|
||||
//The hit count should be 0 as we don't need to go to the cache after we already compiled the query
|
||||
assertEquals( 0, statistics.getQueryPlanCacheHitCount() );
|
||||
} );
|
||||
|
||||
doInJPA( this::entityManagerFactory, entityManager -> {
|
||||
|
||||
List<Tuple> employees = entityManager.createQuery(
|
||||
"select e.id, e.name from Employee e", Tuple.class )
|
||||
.getResultList();
|
||||
|
||||
assertEquals( 5, employees.size() );
|
||||
|
||||
//The miss count is still 1, as no we got the query plan from the cache
|
||||
assertEquals( 1, statistics.getQueryPlanCacheMissCount() );
|
||||
//And the cache hit count increases.
|
||||
assertEquals( 1, statistics.getQueryPlanCacheHitCount() );
|
||||
} );
|
||||
|
||||
doInJPA( this::entityManagerFactory, entityManager -> {
|
||||
|
||||
List<Tuple> employees = entityManager.createQuery(
|
||||
"select e.id, e.name from Employee e", Tuple.class )
|
||||
.getResultList();
|
||||
|
||||
assertEquals( 5, employees.size() );
|
||||
|
||||
//The miss count is still 1, as no we got the query plan from the cache
|
||||
assertEquals( 1, statistics.getQueryPlanCacheMissCount() );
|
||||
//And the cache hit count increases.
|
||||
assertEquals( 2, statistics.getQueryPlanCacheHitCount() );
|
||||
} );
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestForIssue(jiraKey = "HHH-13077")
|
||||
public void testLockModeHitCount() {
|
||||
statistics.clear();
|
||||
|
||||
doInJPA( this::entityManagerFactory, entityManager -> {
|
||||
TypedQuery<Employee> typedQuery = entityManager.createQuery( "select e from Employee e", Employee.class );
|
||||
|
||||
List<Employee> employees = typedQuery.getResultList();
|
||||
|
||||
assertEquals( 5, employees.size() );
|
||||
|
||||
//First time, we get a cache miss, so the query is compiled
|
||||
assertEquals( 1, statistics.getQueryPlanCacheMissCount() );
|
||||
//The hit count should be 0 as we don't need to go to the cache after we already compiled the query
|
||||
assertEquals( 0, statistics.getQueryPlanCacheHitCount() );
|
||||
|
||||
typedQuery.setLockMode( LockModeType.READ );
|
||||
|
||||
//The hit count should still be 0 as setLockMode() shouldn't trigger a cache hit
|
||||
assertEquals( 0, statistics.getQueryPlanCacheHitCount() );
|
||||
|
||||
assertNotNull( typedQuery.getLockMode() );
|
||||
|
||||
//The hit count should still be 0 as getLockMode() shouldn't trigger a cache hit
|
||||
assertEquals( 0, statistics.getQueryPlanCacheHitCount() );
|
||||
} );
|
||||
}
|
||||
|
||||
private void assertQueryStatistics(String hql, int hitCount) {
|
||||
QueryStatistics queryStatistics = statistics.getQueryStatistics( hql );
|
||||
|
||||
|
@ -125,6 +292,10 @@ public class QueryPlanCacheStatisticsTest extends BaseEntityManagerFunctionalTes
|
|||
}
|
||||
|
||||
@Entity(name = "Employee")
|
||||
@NamedQuery(
|
||||
name = "find_employee_by_name",
|
||||
query = "select e from Employee e where e.name = :name"
|
||||
)
|
||||
public static class Employee {
|
||||
|
||||
@Id
|
||||
|
|
|
@ -0,0 +1,236 @@
|
|||
/*
|
||||
* 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.test.annotations.derivedidentities.bidirectional;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.HashSet;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import javax.persistence.CascadeType;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.FetchType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.OneToMany;
|
||||
|
||||
import org.hibernate.Hibernate;
|
||||
|
||||
import org.hibernate.testing.TestForIssue;
|
||||
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class ManyToOneEagerDerivedIdFetchModeJoinTest extends BaseCoreFunctionalTestCase {
|
||||
private Foo foo;
|
||||
|
||||
@Test
|
||||
@TestForIssue(jiraKey = "HHH-14466")
|
||||
public void testQuery() {
|
||||
doInHibernate( this::sessionFactory, session -> {
|
||||
Bar newBar = (Bar) session.createQuery( "SELECT b FROM Bar b WHERE b.foo.id = :id" )
|
||||
.setParameter( "id", foo.getId() )
|
||||
.uniqueResult();
|
||||
assertNotNull( newBar );
|
||||
assertNotNull( newBar.getFoo() );
|
||||
assertTrue( Hibernate.isInitialized( newBar.getFoo() ) );
|
||||
assertEquals( foo.getId(), newBar.getFoo().getId() );
|
||||
assertTrue( Hibernate.isInitialized( newBar.getFoo().getBars() ) );
|
||||
assertEquals( 1, newBar.getFoo().getBars().size() );
|
||||
assertSame( newBar, newBar.getFoo().getBars().iterator().next() );
|
||||
assertEquals( "Some details", newBar.getDetails() );
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestForIssue(jiraKey = "HHH-14466")
|
||||
public void testQueryById() {
|
||||
|
||||
doInHibernate( this::sessionFactory, session -> {
|
||||
Bar newBar = (Bar) session.createQuery( "SELECT b FROM Bar b WHERE b.foo = :foo" )
|
||||
.setParameter( "foo", foo )
|
||||
.uniqueResult();
|
||||
assertNotNull( newBar );
|
||||
assertNotNull( newBar.getFoo() );
|
||||
assertTrue( Hibernate.isInitialized( newBar.getFoo() ) );
|
||||
assertEquals( foo.getId(), newBar.getFoo().getId() );
|
||||
assertTrue( Hibernate.isInitialized( newBar.getFoo().getBars() ) );
|
||||
assertEquals( 1, newBar.getFoo().getBars().size() );
|
||||
assertSame( newBar, newBar.getFoo().getBars().iterator().next() );
|
||||
assertEquals( "Some details", newBar.getDetails() );
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestForIssue(jiraKey = "HHH-14466")
|
||||
public void testFindByPrimaryKey() {
|
||||
|
||||
doInHibernate( this::sessionFactory, session -> {
|
||||
Bar newBar = session.find( Bar.class, foo.getId() );
|
||||
assertNotNull( newBar );
|
||||
assertNotNull( newBar.getFoo() );
|
||||
assertTrue( Hibernate.isInitialized( newBar.getFoo() ) );
|
||||
assertEquals( foo.getId(), newBar.getFoo().getId() );
|
||||
assertTrue( Hibernate.isInitialized( newBar.getFoo().getBars() ) );
|
||||
assertEquals( 1, newBar.getFoo().getBars().size() );
|
||||
assertSame( newBar, newBar.getFoo().getBars().iterator().next() );
|
||||
assertEquals( "Some details", newBar.getDetails() );
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestForIssue(jiraKey = "HHH-14466")
|
||||
public void testFindByInversePrimaryKey() {
|
||||
|
||||
doInHibernate( this::sessionFactory, session -> {
|
||||
Foo newFoo = session.find( Foo.class, foo.getId() );
|
||||
assertNotNull( newFoo );
|
||||
assertNotNull( newFoo.getBars() );
|
||||
assertTrue( Hibernate.isInitialized( newFoo.getBars() ) );
|
||||
assertEquals( 1, newFoo.getBars().size() );
|
||||
assertSame( newFoo, newFoo.getBars().iterator().next().getFoo() );
|
||||
assertEquals( "Some details", newFoo.getBars().iterator().next().getDetails() );
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setupData() {
|
||||
this.foo = doInHibernate( this::sessionFactory, session -> {
|
||||
Foo foo = new Foo();
|
||||
foo.id = 1L;
|
||||
session.persist( foo );
|
||||
|
||||
Bar bar = new Bar();
|
||||
bar.setFoo( foo );
|
||||
bar.setDetails( "Some details" );
|
||||
|
||||
foo.getBars().add( bar );
|
||||
|
||||
session.persist( bar );
|
||||
|
||||
session.flush();
|
||||
|
||||
assertNotNull( foo.getId() );
|
||||
assertEquals( foo.getId(), bar.getFoo().getId() );
|
||||
|
||||
return foo;
|
||||
});
|
||||
}
|
||||
|
||||
@After
|
||||
public void cleanupData() {
|
||||
doInHibernate( this::sessionFactory, session -> {
|
||||
session.delete( session.find( Foo.class, foo.id ) );
|
||||
});
|
||||
this.foo = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<?>[] getAnnotatedClasses() {
|
||||
return new Class<?>[] {
|
||||
Foo.class,
|
||||
Bar.class,
|
||||
};
|
||||
}
|
||||
|
||||
@Entity(name = "Foo")
|
||||
public static class Foo {
|
||||
|
||||
@Id
|
||||
private Long id;
|
||||
|
||||
private String name;
|
||||
|
||||
@OneToMany(mappedBy = "foo", cascade = CascadeType.ALL, fetch = FetchType.EAGER, orphanRemoval = true)
|
||||
private Set<Bar> bars = new HashSet<>();
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public Set<Bar> getBars() {
|
||||
return bars;
|
||||
}
|
||||
|
||||
public void setBars(Set<Bar> bars) {
|
||||
this.bars = bars;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if ( this == o ) {
|
||||
return true;
|
||||
}
|
||||
if ( o == null || getClass() != o.getClass() ) {
|
||||
return false;
|
||||
}
|
||||
Foo foo = (Foo) o;
|
||||
return id.equals( foo.id );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash( id );
|
||||
}
|
||||
}
|
||||
|
||||
@Entity(name = "Bar")
|
||||
public static class Bar implements Serializable {
|
||||
|
||||
@Id
|
||||
@ManyToOne(fetch = FetchType.EAGER)
|
||||
@JoinColumn(name = "BAR_ID")
|
||||
private Foo foo;
|
||||
|
||||
private String details;
|
||||
|
||||
public Foo getFoo() {
|
||||
return foo;
|
||||
}
|
||||
|
||||
public void setFoo(Foo foo) {
|
||||
this.foo = foo;
|
||||
}
|
||||
|
||||
public String getDetails() {
|
||||
return details;
|
||||
}
|
||||
|
||||
public void setDetails(String details) {
|
||||
this.details = details;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if ( this == o ) {
|
||||
return true;
|
||||
}
|
||||
if ( o == null || getClass() != o.getClass() ) {
|
||||
return false;
|
||||
}
|
||||
Bar bar = (Bar) o;
|
||||
return foo.equals( bar.foo );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash( foo );
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,215 @@
|
|||
/*
|
||||
* 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.test.annotations.query;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.FetchType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.OneToMany;
|
||||
import javax.persistence.TypedQuery;
|
||||
|
||||
import org.hibernate.Hibernate;
|
||||
import org.hibernate.annotations.Fetch;
|
||||
import org.hibernate.annotations.FetchMode;
|
||||
import org.hibernate.cfg.Configuration;
|
||||
|
||||
import org.hibernate.testing.TestForIssue;
|
||||
import org.hibernate.testing.jdbc.SQLStatementInterceptor;
|
||||
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests the handling and expansion of list parameters,
|
||||
* particularly when using {@code @Fetch(FetchMode.SUBSELECT)}
|
||||
* (because this fetch mode involves building a map of parameters).
|
||||
*/
|
||||
public class QueryListParametersWithFetchSubSelectTest extends BaseCoreFunctionalTestCase {
|
||||
|
||||
private SQLStatementInterceptor sqlStatementInterceptor;
|
||||
|
||||
@Override
|
||||
protected void configure(Configuration configuration) {
|
||||
sqlStatementInterceptor = new SQLStatementInterceptor( configuration );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<?>[] getAnnotatedClasses() {
|
||||
return new Class<?>[] { Parent.class, Child.class };
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void afterSessionFactoryBuilt() {
|
||||
inTransaction( s -> {
|
||||
for ( int i = 0; i < 10; i++ ) {
|
||||
Parent parent = new Parent( i );
|
||||
s.persist( parent );
|
||||
for ( int j = 0; j < 10; j++ ) {
|
||||
Child child = new Child( i * 100 + j, parent );
|
||||
parent.children.add( child );
|
||||
s.persist( child );
|
||||
}
|
||||
}
|
||||
} );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void simple() {
|
||||
sqlStatementInterceptor.clear();
|
||||
|
||||
inTransaction( s -> {
|
||||
TypedQuery<Parent> query = s.createQuery( "select p from Parent p where id in :ids", Parent.class );
|
||||
query.setParameter( "ids", Arrays.asList( 0, 1, 2 ) );
|
||||
List<Parent> results = query.getResultList();
|
||||
assertThat( results )
|
||||
.allSatisfy( parent -> assertThat( Hibernate.isInitialized( parent.getChildren() ) ).isTrue() )
|
||||
.extracting( Parent::getId ).containsExactly( 0, 1, 2 );
|
||||
} );
|
||||
|
||||
// If we get here, children were initialized eagerly.
|
||||
// Did ORM actually use subselects?
|
||||
assertThat( sqlStatementInterceptor.getSqlQueries() ).hasSize( 2 );
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestForIssue(jiraKey = "HHH-14439")
|
||||
public void reusingQueryWithFewerNamedParameters() {
|
||||
sqlStatementInterceptor.clear();
|
||||
|
||||
inTransaction( s -> {
|
||||
TypedQuery<Parent> query = s.createQuery( "select p from Parent p where id in :ids", Parent.class );
|
||||
|
||||
query.setParameter( "ids", Arrays.asList( 0, 1, 2, 3 ) );
|
||||
List<Parent> results = query.getResultList();
|
||||
assertThat( results )
|
||||
.allSatisfy( parent -> assertThat( Hibernate.isInitialized( parent.getChildren() ) ).isTrue() )
|
||||
.extracting( Parent::getId ).containsExactly( 0, 1, 2, 3 );
|
||||
|
||||
query.setParameter( "ids", Arrays.asList( 4, 5, 6 ) );
|
||||
results = query.getResultList();
|
||||
assertThat( results )
|
||||
.allSatisfy( parent -> assertThat( Hibernate.isInitialized( parent.getChildren() ) ).isTrue() )
|
||||
.extracting( Parent::getId ).containsExactly( 4, 5, 6 );
|
||||
|
||||
query.setParameter( "ids", Arrays.asList( 7, 8 ) );
|
||||
results = query.getResultList();
|
||||
assertThat( results )
|
||||
.allSatisfy( parent -> assertThat( Hibernate.isInitialized( parent.getChildren() ) ).isTrue() )
|
||||
.extracting( Parent::getId ).containsExactly( 7, 8 );
|
||||
} );
|
||||
|
||||
// If we get here, children were initialized eagerly.
|
||||
// Did ORM actually use subselects?
|
||||
assertThat( sqlStatementInterceptor.getSqlQueries() ).hasSize( 3 * 2 );
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
@TestForIssue(jiraKey = "HHH-14439")
|
||||
public void reusingQueryWithFewerOrdinalParameters() {
|
||||
sqlStatementInterceptor.clear();
|
||||
|
||||
inTransaction( s -> {
|
||||
TypedQuery<Parent> query = s.createQuery( "select p from Parent p where id in ?0", Parent.class );
|
||||
|
||||
query.setParameter( 0, Arrays.asList( 0, 1, 2, 3 ) );
|
||||
List<Parent> results = query.getResultList();
|
||||
assertThat( results )
|
||||
.allSatisfy( parent -> assertThat( Hibernate.isInitialized( parent.getChildren() ) ).isTrue() )
|
||||
.extracting( Parent::getId ).containsExactly( 0, 1, 2, 3 );
|
||||
|
||||
query.setParameter( 0, Arrays.asList( 4, 5, 6 ) );
|
||||
results = query.getResultList();
|
||||
assertThat( results )
|
||||
.allSatisfy( parent -> assertThat( Hibernate.isInitialized( parent.getChildren() ) ).isTrue() )
|
||||
.extracting( Parent::getId ).containsExactly( 4, 5, 6 );
|
||||
|
||||
query.setParameter( 0, Arrays.asList( 7, 8 ) );
|
||||
results = query.getResultList();
|
||||
assertThat( results )
|
||||
.allSatisfy( parent -> assertThat( Hibernate.isInitialized( parent.getChildren() ) ).isTrue() )
|
||||
.extracting( Parent::getId ).containsExactly( 7, 8 );
|
||||
} );
|
||||
|
||||
// If we get here, children were initialized eagerly.
|
||||
// Did ORM actually use subselects?
|
||||
assertThat( sqlStatementInterceptor.getSqlQueries() ).hasSize( 3 * 2 );
|
||||
}
|
||||
|
||||
@Entity(name = "Parent")
|
||||
public static class Parent {
|
||||
@Id
|
||||
private Integer id;
|
||||
|
||||
@OneToMany(mappedBy = "parent", fetch = FetchType.EAGER)
|
||||
@Fetch(FetchMode.SUBSELECT)
|
||||
private List<Child> children = new ArrayList<>();
|
||||
|
||||
public Parent() {
|
||||
}
|
||||
|
||||
public Parent(Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public List<Child> getChildren() {
|
||||
return children;
|
||||
}
|
||||
|
||||
public void setChildren(List<Child> children) {
|
||||
this.children = children;
|
||||
}
|
||||
}
|
||||
|
||||
@Entity(name = "Child")
|
||||
public static class Child {
|
||||
|
||||
@Id
|
||||
private Integer id;
|
||||
|
||||
@ManyToOne
|
||||
private Parent parent;
|
||||
|
||||
public Child() {
|
||||
}
|
||||
|
||||
public Child(Integer id, Parent parent) {
|
||||
this.id = id;
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public Parent getParent() {
|
||||
return parent;
|
||||
}
|
||||
|
||||
public void setParent(Parent parent) {
|
||||
this.parent = parent;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,149 @@
|
|||
/*
|
||||
* 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.test.hql;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import javax.persistence.CollectionTable;
|
||||
import javax.persistence.ElementCollection;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.MapKeyColumn;
|
||||
import javax.persistence.OneToMany;
|
||||
|
||||
import org.hibernate.dialect.DerbyDialect;
|
||||
import org.hibernate.dialect.H2Dialect;
|
||||
|
||||
import org.hibernate.testing.RequiresDialect;
|
||||
import org.hibernate.testing.SkipForDialect;
|
||||
import org.hibernate.testing.TestForIssue;
|
||||
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
/**
|
||||
* @author Christian Beikov
|
||||
*/
|
||||
public class CountExpressionTest extends BaseCoreFunctionalTestCase {
|
||||
|
||||
@Override
|
||||
protected Class<?>[] getAnnotatedClasses() {
|
||||
return new Class[] {
|
||||
Document.class,
|
||||
Person.class
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void prepareTest() throws Exception {
|
||||
doInHibernate( this::sessionFactory, session -> {
|
||||
Document document = new Document();
|
||||
document.setId( 1 );
|
||||
|
||||
Person p1 = new Person();
|
||||
Person p2 = new Person();
|
||||
|
||||
p1.getLocalized().put(1, "p1.1");
|
||||
p1.getLocalized().put(2, "p1.2");
|
||||
p2.getLocalized().put(1, "p2.1");
|
||||
p2.getLocalized().put(2, "p2.2");
|
||||
|
||||
document.getContacts().put(1, p1);
|
||||
document.getContacts().put(2, p2);
|
||||
|
||||
session.persist(p1);
|
||||
session.persist(p2);
|
||||
session.persist(document);
|
||||
} );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isCleanupTestDataRequired() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestForIssue(jiraKey = "HHH-9182")
|
||||
@SkipForDialect(value = DerbyDialect.class, comment = "Derby can't cast from integer to varchar i.e. it requires an intermediary step")
|
||||
public void testCountDistinctExpression() {
|
||||
doInHibernate( this::sessionFactory, session -> {
|
||||
List results = session.createQuery(
|
||||
"SELECT " +
|
||||
" d.id, " +
|
||||
" COUNT(DISTINCT CONCAT(CAST(KEY(l) AS java.lang.String), 'test')) " +
|
||||
"FROM Document d " +
|
||||
"LEFT JOIN d.contacts c " +
|
||||
"LEFT JOIN c.localized l " +
|
||||
"GROUP BY d.id")
|
||||
.getResultList();
|
||||
|
||||
assertEquals(1, results.size());
|
||||
Object[] tuple = (Object[]) results.get( 0 );
|
||||
assertEquals(1, tuple[0]);
|
||||
} );
|
||||
}
|
||||
|
||||
@Entity(name = "Document")
|
||||
public static class Document {
|
||||
|
||||
private Integer id;
|
||||
private Map<Integer, Person> contacts = new HashMap<>();
|
||||
|
||||
@Id
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
@OneToMany
|
||||
@CollectionTable
|
||||
@MapKeyColumn(name = "position")
|
||||
public Map<Integer, Person> getContacts() {
|
||||
return contacts;
|
||||
}
|
||||
|
||||
public void setContacts(Map<Integer, Person> contacts) {
|
||||
this.contacts = contacts;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Entity(name = "Person")
|
||||
public static class Person {
|
||||
|
||||
private Integer id;
|
||||
|
||||
private Map<Integer, String> localized = new HashMap<>();
|
||||
|
||||
@Id
|
||||
@GeneratedValue
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
@ElementCollection
|
||||
public Map<Integer, String> getLocalized() {
|
||||
return localized;
|
||||
}
|
||||
|
||||
public void setLocalized(Map<Integer, String> localized) {
|
||||
this.localized = localized;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -138,6 +138,23 @@ public class MetaAttributeGenerationVisitor extends SimpleTypeVisitor6<Annotatio
|
|||
accessTypeInfo.setDefaultAccessType( entity.getEntityAccessTypeInfo().getAccessType() );
|
||||
}
|
||||
}
|
||||
if ( TypeUtils.containsAnnotation(
|
||||
element,
|
||||
Constants.BASIC,
|
||||
Constants.CONVERT,
|
||||
Constants.HIBERNATE_TYPE
|
||||
) && !TypeUtils.containsAnnotation(
|
||||
element,
|
||||
Constants.ONE_TO_MANY,
|
||||
Constants.MANY_TO_MANY,
|
||||
Constants.ELEMENT_COLLECTION
|
||||
) ) {
|
||||
return new AnnotationMetaSingleAttribute(
|
||||
entity,
|
||||
element,
|
||||
TypeUtils.toTypeString( declaredType )
|
||||
);
|
||||
}
|
||||
if ( collection.equals( Constants.MAP_ATTRIBUTE ) ) {
|
||||
return createAnnotationMetaAttributeForMap( declaredType, element, collection, targetEntity );
|
||||
}
|
||||
|
|
|
@ -0,0 +1,89 @@
|
|||
/*
|
||||
* 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.jpamodelgen.test.collectionbasictype;
|
||||
|
||||
import org.hibernate.jpamodelgen.test.util.CompilationTest;
|
||||
import org.hibernate.jpamodelgen.test.util.TestForIssue;
|
||||
import org.hibernate.jpamodelgen.test.util.WithClasses;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.hibernate.jpamodelgen.test.util.TestUtil.assertAttributeTypeInMetaModelFor;
|
||||
import static org.hibernate.jpamodelgen.test.util.TestUtil.assertListAttributeTypeInMetaModelFor;
|
||||
import static org.hibernate.jpamodelgen.test.util.TestUtil.assertMetamodelClassGeneratedFor;
|
||||
|
||||
/**
|
||||
* @author helloztt
|
||||
*/
|
||||
public class CollectionAsBasicTypeTest extends CompilationTest {
|
||||
|
||||
@Test
|
||||
@TestForIssue(jiraKey = "HHH-12338")
|
||||
@WithClasses({Goods.class, Product.class})
|
||||
public void testConvert() throws ClassNotFoundException, NoSuchFieldException {
|
||||
assertMetamodelClassGeneratedFor(Product.class);
|
||||
assertMetamodelClassGeneratedFor(Goods.class);
|
||||
assertListAttributeTypeInMetaModelFor(
|
||||
Goods.class,
|
||||
"productList",
|
||||
Product.class,
|
||||
"ListAttribute generic type should be Product"
|
||||
);
|
||||
assertAttributeTypeInMetaModelFor(
|
||||
Goods.class,
|
||||
"tags",
|
||||
Goods.class.getDeclaredField("tags").getGenericType(),
|
||||
"Wrong meta model type"
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestForIssue(jiraKey = "HHH-12338")
|
||||
@WithClasses({Person.class})
|
||||
public void testListType() throws ClassNotFoundException, NoSuchFieldException {
|
||||
assertMetamodelClassGeneratedFor(Person.class);
|
||||
|
||||
assertAttributeTypeInMetaModelFor(
|
||||
Person.class,
|
||||
"phones",
|
||||
Person.class.getDeclaredField("phones").getGenericType(),
|
||||
"Wrong meta model type"
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestForIssue(jiraKey = "HHH-12338")
|
||||
@WithClasses({PersonPhone.class})
|
||||
public void testListTypeWithImport() throws ClassNotFoundException, NoSuchFieldException {
|
||||
assertMetamodelClassGeneratedFor(PersonPhone.class);
|
||||
|
||||
assertAttributeTypeInMetaModelFor(
|
||||
PersonPhone.class,
|
||||
"phones",
|
||||
PersonPhone.class.getDeclaredField("phones").getGenericType(),
|
||||
"Wrong meta model type"
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestForIssue(jiraKey = "HHH-12338")
|
||||
@WithClasses({PhoneBook.class})
|
||||
public void testMapType() throws ClassNotFoundException, NoSuchFieldException {
|
||||
assertMetamodelClassGeneratedFor(PhoneBook.class);
|
||||
|
||||
assertAttributeTypeInMetaModelFor(
|
||||
PhoneBook.class,
|
||||
"phones",
|
||||
PhoneBook.class.getDeclaredField("phones").getGenericType(),
|
||||
"Wrong meta model type"
|
||||
);
|
||||
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue