merge master
This commit is contained in:
commit
a3184e16cb
|
@ -483,3 +483,5 @@ subprojects { subProject ->
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
task release(type: Task, dependsOn: 'release:release')
|
||||
|
|
|
@ -26,7 +26,6 @@ package org.hibernate;
|
|||
import java.io.Serializable;
|
||||
|
||||
import org.hibernate.procedure.ProcedureCall;
|
||||
import org.hibernate.procedure.ProcedureCallMemento;
|
||||
|
||||
/**
|
||||
* Contract methods shared between {@link Session} and {@link StatelessSession}.
|
||||
|
|
|
@ -61,14 +61,20 @@ public class RegionFactoryInitiator implements StandardServiceInitiator<RegionFa
|
|||
@Override
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
public RegionFactory initiateService(Map configurationValues, ServiceRegistryImplementor registry) {
|
||||
Properties p = new Properties();
|
||||
final Properties p = new Properties();
|
||||
if (configurationValues != null) {
|
||||
p.putAll( configurationValues );
|
||||
}
|
||||
|
||||
boolean useSecondLevelCache = ConfigurationHelper.getBoolean( AvailableSettings.USE_SECOND_LEVEL_CACHE,
|
||||
configurationValues, true );
|
||||
boolean useQueryCache = ConfigurationHelper.getBoolean( AvailableSettings.USE_QUERY_CACHE, configurationValues );
|
||||
final boolean useSecondLevelCache = ConfigurationHelper.getBoolean(
|
||||
AvailableSettings.USE_SECOND_LEVEL_CACHE,
|
||||
configurationValues,
|
||||
true
|
||||
);
|
||||
final boolean useQueryCache = ConfigurationHelper.getBoolean(
|
||||
AvailableSettings.USE_QUERY_CACHE,
|
||||
configurationValues
|
||||
);
|
||||
|
||||
RegionFactory regionFactory = NoCachingRegionFactory.INSTANCE;
|
||||
|
||||
|
@ -81,16 +87,6 @@ public class RegionFactoryInitiator implements StandardServiceInitiator<RegionFa
|
|||
try {
|
||||
regionFactory = registry.getService( StrategySelector.class )
|
||||
.resolveStrategy( RegionFactory.class, setting );
|
||||
// try {
|
||||
// regionFactory = regionFactoryClass.getConstructor( Properties.class ).newInstance( p );
|
||||
// }
|
||||
// catch ( NoSuchMethodException e ) {
|
||||
// // no constructor accepting Properties found, try no arg constructor
|
||||
// LOG.debugf(
|
||||
// "%s did not provide constructor accepting java.util.Properties; attempting no-arg constructor.",
|
||||
// regionFactoryClass.getSimpleName() );
|
||||
// regionFactory = regionFactoryClass.getConstructor().newInstance();
|
||||
// }
|
||||
}
|
||||
catch ( Exception e ) {
|
||||
throw new HibernateException( "could not instantiate RegionFactory [" + setting + "]", e );
|
||||
|
|
|
@ -209,6 +209,9 @@ public final class AnnotationBinder {
|
|||
|
||||
public static void bindDefaults(Mappings mappings) {
|
||||
Map defaults = mappings.getReflectionManager().getDefaults();
|
||||
|
||||
// id generators ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
{
|
||||
List<SequenceGenerator> anns = ( List<SequenceGenerator> ) defaults.get( SequenceGenerator.class );
|
||||
if ( anns != null ) {
|
||||
|
@ -231,6 +234,9 @@ public final class AnnotationBinder {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// queries ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
{
|
||||
List<NamedQuery> anns = ( List<NamedQuery> ) defaults.get( NamedQuery.class );
|
||||
if ( anns != null ) {
|
||||
|
@ -247,6 +253,9 @@ public final class AnnotationBinder {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// result-set-mappings ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
{
|
||||
List<SqlResultSetMapping> anns = ( List<SqlResultSetMapping> ) defaults.get( SqlResultSetMapping.class );
|
||||
if ( anns != null ) {
|
||||
|
@ -256,6 +265,8 @@ public final class AnnotationBinder {
|
|||
}
|
||||
}
|
||||
|
||||
// stored procs ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
{
|
||||
final List<NamedStoredProcedureQuery> annotations =
|
||||
(List<NamedStoredProcedureQuery>) defaults.get( NamedStoredProcedureQuery.class );
|
||||
|
@ -265,7 +276,6 @@ public final class AnnotationBinder {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
final List<NamedStoredProcedureQueries> annotations =
|
||||
(List<NamedStoredProcedureQueries>) defaults.get( NamedStoredProcedureQueries.class );
|
||||
|
|
|
@ -341,6 +341,7 @@ public class BinderHelper {
|
|||
*/
|
||||
if ( value instanceof ToOne ) {
|
||||
( (ToOne) value ).setReferencedPropertyName( syntheticPropertyName );
|
||||
( (ToOne) value ).setReferenceToPrimaryKey( syntheticPropertyName == null );
|
||||
mappings.addUniquePropertyReference( ownerEntity.getEntityName(), syntheticPropertyName );
|
||||
}
|
||||
else if ( value instanceof Collection ) {
|
||||
|
|
|
@ -84,6 +84,8 @@ import org.hibernate.annotations.common.reflection.java.JavaReflectionManager;
|
|||
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
|
||||
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
|
||||
import org.hibernate.boot.registry.internal.StandardServiceRegistryImpl;
|
||||
import org.hibernate.cache.spi.GeneralDataRegion;
|
||||
import org.hibernate.cfg.annotations.NamedEntityGraphDefinition;
|
||||
import org.hibernate.cfg.annotations.NamedProcedureCallDefinition;
|
||||
import org.hibernate.cfg.annotations.reflection.JPAMetadataProvider;
|
||||
import org.hibernate.context.spi.CurrentTenantIdentifierResolver;
|
||||
|
@ -217,6 +219,7 @@ public class Configuration implements Serializable {
|
|||
protected Map<String, NamedSQLQueryDefinition> namedSqlQueries;
|
||||
protected Map<String, NamedProcedureCallDefinition> namedProcedureCallMap;
|
||||
protected Map<String, ResultSetMappingDefinition> sqlResultSetMappings;
|
||||
protected Map<String, NamedEntityGraphDefinition> namedEntityGraphMap;
|
||||
|
||||
protected Map<String, TypeDef> typeDefs;
|
||||
protected Map<String, FilterDefinition> filterDefinitions;
|
||||
|
@ -299,6 +302,7 @@ public class Configuration implements Serializable {
|
|||
namedQueries = new HashMap<String,NamedQueryDefinition>();
|
||||
namedSqlQueries = new HashMap<String,NamedSQLQueryDefinition>();
|
||||
sqlResultSetMappings = new HashMap<String, ResultSetMappingDefinition>();
|
||||
namedEntityGraphMap = new HashMap<String, NamedEntityGraphDefinition>();
|
||||
|
||||
typeDefs = new HashMap<String,TypeDef>();
|
||||
filterDefinitions = new HashMap<String, FilterDefinition>();
|
||||
|
@ -2619,6 +2623,12 @@ public class Configuration implements Serializable {
|
|||
}
|
||||
}
|
||||
|
||||
public java.util.Collection<NamedEntityGraphDefinition> getNamedEntityGraphs() {
|
||||
return namedEntityGraphMap == null
|
||||
? Collections.<NamedEntityGraphDefinition>emptyList()
|
||||
: namedEntityGraphMap.values();
|
||||
}
|
||||
|
||||
|
||||
// Mappings impl ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
@ -2886,6 +2896,16 @@ public class Configuration implements Serializable {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addNamedEntityGraphDefintion(NamedEntityGraphDefinition definition)
|
||||
throws DuplicateMappingException {
|
||||
final String name = definition.getRegisteredName();
|
||||
final NamedEntityGraphDefinition previous = namedEntityGraphMap.put( name, definition );
|
||||
if ( previous != null ) {
|
||||
throw new DuplicateMappingException( "NamedEntityGraph", name );
|
||||
}
|
||||
}
|
||||
|
||||
public void addDefaultSQLQuery(String name, NamedSQLQueryDefinition query) {
|
||||
applySQLQuery( name, query );
|
||||
defaultNamedNativeQueryNames.add( name );
|
||||
|
|
|
@ -1620,6 +1620,7 @@ public final class HbmBinder {
|
|||
if ( ukName != null ) {
|
||||
manyToOne.setReferencedPropertyName( ukName.getValue() );
|
||||
}
|
||||
manyToOne.setReferenceToPrimaryKey( manyToOne.getReferencedPropertyName() == null );
|
||||
|
||||
manyToOne.setReferencedEntityName( getEntityName( node, mappings ) );
|
||||
|
||||
|
@ -1702,6 +1703,7 @@ public final class HbmBinder {
|
|||
|
||||
Attribute ukName = node.attribute( "property-ref" );
|
||||
if ( ukName != null ) oneToOne.setReferencedPropertyName( ukName.getValue() );
|
||||
oneToOne.setReferenceToPrimaryKey( oneToOne.getReferencedPropertyName() == null );
|
||||
|
||||
oneToOne.setPropertyName( node.attributeValue( "name" ) );
|
||||
|
||||
|
|
|
@ -36,6 +36,7 @@ import org.hibernate.MappingException;
|
|||
import org.hibernate.annotations.AnyMetaDef;
|
||||
import org.hibernate.annotations.common.reflection.ReflectionManager;
|
||||
import org.hibernate.annotations.common.reflection.XClass;
|
||||
import org.hibernate.cfg.annotations.NamedEntityGraphDefinition;
|
||||
import org.hibernate.cfg.annotations.NamedProcedureCallDefinition;
|
||||
import org.hibernate.engine.ResultSetMappingDefinition;
|
||||
import org.hibernate.engine.spi.FilterDefinition;
|
||||
|
@ -347,6 +348,15 @@ public interface Mappings {
|
|||
*/
|
||||
public void addNamedProcedureCallDefinition(NamedProcedureCallDefinition definition) throws DuplicateMappingException;
|
||||
|
||||
/**
|
||||
* Adds metadata for a named entity graph to this repository
|
||||
*
|
||||
* @param namedEntityGraphDefinition The procedure call information
|
||||
*
|
||||
* @throws DuplicateMappingException If an entity graph already exists with that name.
|
||||
*/
|
||||
public void addNamedEntityGraphDefintion(NamedEntityGraphDefinition namedEntityGraphDefinition);
|
||||
|
||||
/**
|
||||
* Get the metadata for a named SQL result set mapping.
|
||||
*
|
||||
|
|
|
@ -39,6 +39,7 @@ import org.hibernate.mapping.ManyToOne;
|
|||
import org.hibernate.mapping.OneToOne;
|
||||
import org.hibernate.mapping.PersistentClass;
|
||||
import org.hibernate.mapping.Property;
|
||||
import org.hibernate.mapping.Selectable;
|
||||
import org.hibernate.mapping.SimpleValue;
|
||||
import org.hibernate.type.ForeignKeyDirection;
|
||||
|
||||
|
@ -211,12 +212,10 @@ public class OneToOneSecondPass implements SecondPass {
|
|||
else {
|
||||
propertyHolder.addProperty( prop, inferredData.getDeclaringClass() );
|
||||
}
|
||||
|
||||
value.setReferencedPropertyName( mappedBy );
|
||||
|
||||
// HHH-6813
|
||||
// If otherSide's id is derived, do not set EntityType#uniqueKeyPropertyName.
|
||||
// EntityType#isReferenceToPrimaryKey() assumes that, if it's set,
|
||||
// a PK is not referenced. Example:
|
||||
//
|
||||
// Foo: @Id long id, @OneToOne(mappedBy="foo") Bar bar
|
||||
// Bar: @Id @OneToOne Foo foo
|
||||
boolean referencesDerivedId = false;
|
||||
|
@ -227,8 +226,14 @@ public class OneToOneSecondPass implements SecondPass {
|
|||
catch ( MappingException e ) {
|
||||
// ignore
|
||||
}
|
||||
String referencedPropertyName = referencesDerivedId ? null : mappedBy;
|
||||
value.setReferencedPropertyName( referencedPropertyName );
|
||||
boolean referenceToPrimaryKey = referencesDerivedId || mappedBy == null;
|
||||
value.setReferenceToPrimaryKey( referenceToPrimaryKey );
|
||||
|
||||
// If the other side is a derived ID, prevent an infinite
|
||||
// loop of attempts to resolve identifiers.
|
||||
if ( referencesDerivedId ) {
|
||||
( (ManyToOne) otherSideProperty.getValue() ).setReferenceToPrimaryKey( false );
|
||||
}
|
||||
|
||||
String propertyRef = value.getReferencedPropertyName();
|
||||
if ( propertyRef != null ) {
|
||||
|
|
|
@ -1511,6 +1511,7 @@ public abstract class CollectionBinder {
|
|||
( (ManyToOne) value ).setReferencedPropertyName( referencedPropertyName );
|
||||
mappings.addUniquePropertyReference( referencedEntity.getEntityName(), referencedPropertyName );
|
||||
}
|
||||
( (ManyToOne) value ).setReferenceToPrimaryKey( referencedPropertyName == null );
|
||||
value.createForeignKey();
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -31,6 +31,8 @@ import javax.persistence.Access;
|
|||
import javax.persistence.Entity;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.JoinTable;
|
||||
import javax.persistence.NamedEntityGraph;
|
||||
import javax.persistence.NamedEntityGraphs;
|
||||
import javax.persistence.PrimaryKeyJoinColumn;
|
||||
import javax.persistence.SecondaryTable;
|
||||
import javax.persistence.SecondaryTables;
|
||||
|
@ -83,7 +85,6 @@ import org.hibernate.cfg.ObjectNameSource;
|
|||
import org.hibernate.cfg.PropertyHolder;
|
||||
import org.hibernate.cfg.UniqueConstraintHolder;
|
||||
import org.hibernate.engine.OptimisticLockStyle;
|
||||
import org.hibernate.engine.internal.Versioning;
|
||||
import org.hibernate.engine.spi.ExecuteUpdateResultCheckStyle;
|
||||
import org.hibernate.engine.spi.FilterDefinition;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
|
@ -159,8 +160,27 @@ public class EntityBinder {
|
|||
this.annotatedClass = annotatedClass;
|
||||
bindEjb3Annotation( ejb3Ann );
|
||||
bindHibernateAnnotation();
|
||||
processNamedEntityGraphs();
|
||||
}
|
||||
|
||||
private void processNamedEntityGraphs() {
|
||||
processNamedEntityGraph( annotatedClass.getAnnotation( NamedEntityGraph.class ) );
|
||||
final NamedEntityGraphs graphs = annotatedClass.getAnnotation( NamedEntityGraphs.class );
|
||||
if ( graphs != null ) {
|
||||
for ( NamedEntityGraph graph : graphs.value() ) {
|
||||
processNamedEntityGraph( graph );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void processNamedEntityGraph(NamedEntityGraph annotation) {
|
||||
if ( annotation == null ) {
|
||||
return;
|
||||
}
|
||||
mappings.addNamedEntityGraphDefintion( new NamedEntityGraphDefinition( annotation, name, persistentClass.getEntityName() ) );
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("SimplifiableConditionalExpression")
|
||||
private void bindHibernateAnnotation() {
|
||||
{
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2013, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.cfg.annotations;
|
||||
|
||||
import javax.persistence.NamedEntityGraph;
|
||||
|
||||
/**
|
||||
* Models the definition of a {@link NamedEntityGraph} annotation
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class NamedEntityGraphDefinition {
|
||||
private final NamedEntityGraph annotation;
|
||||
private final String jpaEntityName;
|
||||
private final String entityName;
|
||||
|
||||
public NamedEntityGraphDefinition(NamedEntityGraph annotation, String jpaEntityName, String entityName) {
|
||||
this.annotation = annotation;
|
||||
this.jpaEntityName = jpaEntityName;
|
||||
this.entityName = entityName;
|
||||
}
|
||||
|
||||
public String getRegisteredName() {
|
||||
return jpaEntityName;
|
||||
}
|
||||
|
||||
public String getJpaEntityName() {
|
||||
return jpaEntityName;
|
||||
}
|
||||
|
||||
public String getEntityName() {
|
||||
return entityName;
|
||||
}
|
||||
|
||||
public NamedEntityGraph getAnnotation() {
|
||||
return annotation;
|
||||
}
|
||||
}
|
|
@ -299,6 +299,12 @@ public abstract class Dialect implements ConversionContext {
|
|||
|
||||
// database type mapping support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
/**
|
||||
* Allows the Dialect to contribute additional types
|
||||
*
|
||||
* @param typeContributions Callback to contribute the types
|
||||
* @param serviceRegistry The service registry
|
||||
*/
|
||||
public void contributeTypes(TypeContributions typeContributions, ServiceRegistry serviceRegistry) {
|
||||
// by default, nothing to do
|
||||
}
|
||||
|
@ -1362,7 +1368,7 @@ public abstract class Dialect implements ConversionContext {
|
|||
* @param lockOptions the lock options to apply
|
||||
* @return The appropriate <tt>FOR UPDATE OF column_list</tt> clause string.
|
||||
*/
|
||||
@SuppressWarnings( {"unchecked"})
|
||||
@SuppressWarnings({"unchecked", "UnusedParameters"})
|
||||
public String getForUpdateString(String aliases, LockOptions lockOptions) {
|
||||
LockMode lockMode = lockOptions.getLockMode();
|
||||
final Iterator<Map.Entry<String, LockMode>> itr = lockOptions.getAliasLockIterator();
|
||||
|
@ -1612,6 +1618,7 @@ public abstract class Dialect implements ConversionContext {
|
|||
*
|
||||
* @throws SQLException Indicates problems registering the param.
|
||||
*/
|
||||
@SuppressWarnings("UnusedParameters")
|
||||
public int registerResultSetOutParameter(CallableStatement statement, String name) throws SQLException {
|
||||
throw new UnsupportedOperationException(
|
||||
getClass().getName() +
|
||||
|
@ -1644,6 +1651,7 @@ public abstract class Dialect implements ConversionContext {
|
|||
*
|
||||
* @throws SQLException Indicates problems extracting the result set.
|
||||
*/
|
||||
@SuppressWarnings("UnusedParameters")
|
||||
public ResultSet getResultSet(CallableStatement statement, int position) throws SQLException {
|
||||
throw new UnsupportedOperationException(
|
||||
getClass().getName() + " does not support resultsets via stored procedures"
|
||||
|
@ -1661,6 +1669,7 @@ public abstract class Dialect implements ConversionContext {
|
|||
*
|
||||
* @throws SQLException Indicates problems extracting the result set.
|
||||
*/
|
||||
@SuppressWarnings("UnusedParameters")
|
||||
public ResultSet getResultSet(CallableStatement statement, String name) throws SQLException {
|
||||
throw new UnsupportedOperationException(
|
||||
getClass().getName() + " does not support resultsets via stored procedures"
|
||||
|
|
|
@ -40,7 +40,11 @@ import org.hibernate.service.spi.ServiceRegistryImplementor;
|
|||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
public class DialectResolverInitiator implements StandardServiceInitiator<DialectResolver> {
|
||||
/**
|
||||
* Singleton access
|
||||
*/
|
||||
public static final DialectResolverInitiator INSTANCE = new DialectResolverInitiator();
|
||||
|
||||
@Override
|
||||
|
|
|
@ -45,9 +45,9 @@ import org.hibernate.engine.jdbc.env.spi.QualifiedObjectNameSupport;
|
|||
import org.hibernate.engine.jdbc.env.spi.SQLStateType;
|
||||
import org.hibernate.engine.jdbc.env.spi.SchemaNameResolver;
|
||||
import org.hibernate.engine.jdbc.env.spi.StandardQualifiedObjectNameSupportImpl;
|
||||
import org.hibernate.engine.jdbc.internal.TypeInfo;
|
||||
import org.hibernate.engine.jdbc.internal.TypeInfoExtracter;
|
||||
import org.hibernate.engine.jdbc.spi.SqlExceptionHelper;
|
||||
import org.hibernate.engine.jdbc.spi.TypeInfo;
|
||||
import org.hibernate.exception.internal.SQLExceptionTypeDelegate;
|
||||
import org.hibernate.exception.internal.SQLStateConversionDelegate;
|
||||
import org.hibernate.exception.internal.StandardSQLExceptionConverter;
|
||||
|
|
|
@ -26,8 +26,8 @@ package org.hibernate.engine.jdbc.env.spi;
|
|||
import java.util.Set;
|
||||
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.engine.jdbc.internal.TypeInfo;
|
||||
import org.hibernate.engine.jdbc.spi.SqlExceptionHelper;
|
||||
import org.hibernate.engine.jdbc.spi.TypeInfo;
|
||||
import org.hibernate.metamodel.spi.relational.Identifier;
|
||||
import org.hibernate.service.Service;
|
||||
|
||||
|
|
|
@ -70,7 +70,6 @@ public class JdbcServicesImpl implements JdbcServices, ServiceRegistryAwareServi
|
|||
@Override
|
||||
public void configure(Map configValues) {
|
||||
this.jdbcEnvironment = serviceRegistry.getService( JdbcEnvironment.class );
|
||||
|
||||
this.connectionProvider = serviceRegistry.getService( ConnectionProvider.class );
|
||||
final boolean showSQL = ConfigurationHelper.getBoolean( Environment.SHOW_SQL, configValues, false );
|
||||
final boolean formatSQL = ConfigurationHelper.getBoolean( Environment.FORMAT_SQL, configValues, false );
|
||||
|
|
|
@ -30,6 +30,9 @@ import java.util.LinkedHashSet;
|
|||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import org.hibernate.engine.jdbc.spi.TypeInfo;
|
||||
import org.hibernate.engine.jdbc.spi.TypeNullability;
|
||||
import org.hibernate.engine.jdbc.spi.TypeSearchability;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
import org.hibernate.internal.util.collections.ArrayHelper;
|
||||
|
||||
|
|
|
@ -26,6 +26,8 @@ package org.hibernate.engine.jdbc.spi;
|
|||
import java.sql.Connection;
|
||||
|
||||
/**
|
||||
* A no-op adapter for ConnectionObserver.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class ConnectionObserverAdapter implements ConnectionObserver {
|
||||
|
|
|
@ -153,7 +153,8 @@ public interface JdbcCoordinator extends Serializable {
|
|||
*
|
||||
* @throws org.hibernate.TransactionException Indicates the time out period has already been exceeded.
|
||||
*/
|
||||
public int determineRemainingTransactionTimeOutPeriod();
|
||||
public int determineRemainingTransactionTimeOutPeriod();
|
||||
|
||||
/**
|
||||
* Register a JDBC statement.
|
||||
*
|
||||
|
@ -199,9 +200,15 @@ public interface JdbcCoordinator extends Serializable {
|
|||
* Release all registered resources.
|
||||
*/
|
||||
public void releaseResources();
|
||||
|
||||
|
||||
/**
|
||||
* Enable connection releases
|
||||
*/
|
||||
public void enableReleases();
|
||||
|
||||
|
||||
/**
|
||||
* Disable connection releases
|
||||
*/
|
||||
public void disableReleases();
|
||||
|
||||
/**
|
||||
|
@ -211,5 +218,10 @@ public interface JdbcCoordinator extends Serializable {
|
|||
*/
|
||||
public void registerLastQuery(Statement statement);
|
||||
|
||||
/**
|
||||
* Can this coordinator be serialized?
|
||||
*
|
||||
* @return {@code true} indicates the coordinator can be serialized.
|
||||
*/
|
||||
public boolean isReadyForSerialization();
|
||||
}
|
||||
|
|
|
@ -23,8 +23,6 @@
|
|||
*/
|
||||
package org.hibernate.engine.jdbc.spi;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.engine.jdbc.LobCreationContext;
|
||||
import org.hibernate.engine.jdbc.LobCreator;
|
||||
|
@ -90,7 +88,7 @@ public interface JdbcServices extends Service {
|
|||
public LobCreator getLobCreator(LobCreationContext lobCreationContext);
|
||||
|
||||
/**
|
||||
* Obtain service for wrapping a {@link ResultSet} in a "column name cache" wrapper.
|
||||
* Obtain service for wrapping a {@link java.sql.ResultSet} in a "column name cache" wrapper.
|
||||
* @return The ResultSet wrapper.
|
||||
*/
|
||||
public ResultSetWrapper getResultSetWrapper();
|
||||
|
|
|
@ -78,14 +78,35 @@ public interface LogicalConnectionImplementor extends LogicalConnection {
|
|||
* with which to reconnect. It is an error to pass a connection in the other strategies.
|
||||
*/
|
||||
public void manualReconnect(Connection suppliedConnection);
|
||||
|
||||
|
||||
/**
|
||||
* Perform an aggressive release
|
||||
*/
|
||||
public void aggressiveRelease();
|
||||
|
||||
|
||||
/**
|
||||
* Release any held connection.
|
||||
*
|
||||
* @throws JDBCException Indicates a problem releasing the connection
|
||||
*/
|
||||
public void releaseConnection() throws JDBCException;
|
||||
|
||||
/**
|
||||
* Is this logical connection in auto-commit mode?
|
||||
*
|
||||
* @return {@code true} if auto-commit
|
||||
*/
|
||||
public boolean isAutoCommit();
|
||||
|
||||
/**
|
||||
* Callback to notify all registered observers of a connection being prepared.
|
||||
*/
|
||||
public void notifyObserversStatementPrepared();
|
||||
|
||||
|
||||
/**
|
||||
* Does this logical connection wrap a user/application supplied connection?
|
||||
*
|
||||
* @return {@code true} if the underlying connection was user supplied.
|
||||
*/
|
||||
public boolean isUserSuppliedConnection();
|
||||
}
|
||||
|
|
|
@ -34,75 +34,84 @@ import java.sql.Statement;
|
|||
*
|
||||
* TODO: This could eventually utilize the new Return interface. It would be
|
||||
* great to have a common API shared.
|
||||
*
|
||||
* Generally the methods here dealing with CallableStatement are extremely limited, relying on the legacy
|
||||
*
|
||||
*
|
||||
* @author Brett Meyer
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface ResultSetReturn {
|
||||
|
||||
/**
|
||||
* Extract the ResultSet from the statement. If user passes {@link CallableStatement}
|
||||
* reference, method calls {@link #extract(CallableStatement)} internally.
|
||||
* Extract the ResultSet from the PreparedStatement.
|
||||
* <p/>
|
||||
* If user passes {@link CallableStatement} reference, this method calls {@link #extract(CallableStatement)}
|
||||
* internally. Otherwise, generally speaking, {@link java.sql.PreparedStatement#executeQuery()} is called
|
||||
*
|
||||
* @param statement
|
||||
* @param statement The PreparedStatement from which to extract the ResultSet
|
||||
*
|
||||
* @return the ResultSet
|
||||
* @return The extracted ResultSet
|
||||
*/
|
||||
public ResultSet extract( PreparedStatement statement );
|
||||
public ResultSet extract(PreparedStatement statement);
|
||||
|
||||
/**
|
||||
* Extract the ResultSet from the statement.
|
||||
* Extract the ResultSet from the CallableStatement. Note that this is the limited legacy form which delegates to
|
||||
* {@link org.hibernate.dialect.Dialect#getResultSet}. Better option is to integrate
|
||||
* {@link org.hibernate.procedure.ProcedureCall}-like hooks
|
||||
*
|
||||
* @param statement
|
||||
* @param callableStatement The CallableStatement from which to extract the ResultSet
|
||||
*
|
||||
* @return the ResultSet
|
||||
* @return The extracted ResultSet
|
||||
*/
|
||||
public ResultSet extract( CallableStatement statement );
|
||||
public ResultSet extract(CallableStatement callableStatement);
|
||||
|
||||
/**
|
||||
* Extract the ResultSet from the statement.
|
||||
* Performs the given SQL statement, expecting a ResultSet in return
|
||||
*
|
||||
* @param statement
|
||||
* @param sql
|
||||
* @param statement The JDBC Statement object to use
|
||||
* @param sql The SQL to execute
|
||||
*
|
||||
* @return the ResultSet
|
||||
* @return The resulting ResultSet
|
||||
*/
|
||||
public ResultSet extract( Statement statement, String sql );
|
||||
public ResultSet extract(Statement statement, String sql);
|
||||
|
||||
/**
|
||||
* Execute the Statement query and, if results in a ResultSet, extract it.
|
||||
* Execute the PreparedStatement return its first ResultSet, if any. If there is no ResultSet, returns {@code null}
|
||||
*
|
||||
* @param statement
|
||||
* @param statement The PreparedStatement to execute
|
||||
*
|
||||
* @return the ResultSet
|
||||
* @return The extracted ResultSet, or {@code null}
|
||||
*/
|
||||
public ResultSet execute( PreparedStatement statement );
|
||||
public ResultSet execute(PreparedStatement statement);
|
||||
|
||||
/**
|
||||
* Execute the Statement query and, if results in a ResultSet, extract it.
|
||||
* Performs the given SQL statement, returning its first ResultSet, if any. If there is no ResultSet,
|
||||
* returns {@code null}
|
||||
*
|
||||
* @param statement
|
||||
* @param sql
|
||||
* @param statement The JDBC Statement object to use
|
||||
* @param sql The SQL to execute
|
||||
*
|
||||
* @return the ResultSet
|
||||
* @return The extracted ResultSet, or {@code null}
|
||||
*/
|
||||
public ResultSet execute( Statement statement, String sql );
|
||||
public ResultSet execute(Statement statement, String sql);
|
||||
|
||||
/**
|
||||
* Execute the Statement queryUpdate.
|
||||
* Execute the PreparedStatement, returning its "affected row count".
|
||||
*
|
||||
* @param statement
|
||||
* @param statement The PreparedStatement to execute
|
||||
*
|
||||
* @return int
|
||||
* @return The {@link java.sql.PreparedStatement#executeUpdate()} result
|
||||
*/
|
||||
public int executeUpdate( PreparedStatement statement );
|
||||
public int executeUpdate(PreparedStatement statement);
|
||||
|
||||
/**
|
||||
* Execute the Statement query and, if results in a ResultSet, extract it.
|
||||
* Execute the given SQL statement returning its "affected row count".
|
||||
*
|
||||
* @param statement
|
||||
* @param sql
|
||||
* @param statement The JDBC Statement object to use
|
||||
* @param sql The SQL to execute
|
||||
*
|
||||
* @return the ResultSet
|
||||
* @return The {@link java.sql.PreparedStatement#executeUpdate(String)} result
|
||||
*/
|
||||
public int executeUpdate( Statement statement, String sql );
|
||||
public int executeUpdate(Statement statement, String sql);
|
||||
}
|
||||
|
|
|
@ -97,6 +97,12 @@ public class SqlStatementLogger {
|
|||
logStatement( statement, FormatStyle.BASIC.getFormatter() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Log a SQL statement string using the specified formatter
|
||||
*
|
||||
* @param statement The SQL statement.
|
||||
* @param formatter The formatter to use.
|
||||
*/
|
||||
public void logStatement(String statement, Formatter formatter) {
|
||||
if ( format ) {
|
||||
if ( logToStdout || LOG.isDebugEnabled() ) {
|
||||
|
|
|
@ -38,8 +38,6 @@ public interface StatementPreparer {
|
|||
/**
|
||||
* Create a statement.
|
||||
*
|
||||
* @param sql The SQL the statement to be created
|
||||
*
|
||||
* @return the statement
|
||||
*/
|
||||
public Statement createStatement();
|
||||
|
@ -64,14 +62,15 @@ public interface StatementPreparer {
|
|||
public PreparedStatement prepareStatement(String sql, boolean isCallable);
|
||||
|
||||
/**
|
||||
* Get a prepared statement to use for inserting using JDBC3
|
||||
* {@link java.sql.PreparedStatement#getGeneratedKeys getGeneratedKeys} processing.
|
||||
*
|
||||
* @param sql - the SQL for the statement to be prepared
|
||||
* @param autoGeneratedKeys - a flag indicating whether auto-generated keys should be returned; one of<ul>
|
||||
* Prepare an INSERT statement, specifying how auto-generated (by the database) keys should be handled. Really this
|
||||
* is a boolean, but JDBC opted to define it instead using 2 int constants:<ul>
|
||||
* <li>{@link PreparedStatement#RETURN_GENERATED_KEYS}</li>
|
||||
* <li>{@link PreparedStatement#NO_GENERATED_KEYS}</li>
|
||||
* </li>
|
||||
* </ul>
|
||||
* Generated keys are accessed afterwards via {@link java.sql.PreparedStatement#getGeneratedKeys}
|
||||
*
|
||||
* @param sql The INSERT SQL
|
||||
* @param autoGeneratedKeys The autoGeneratedKeys flag
|
||||
*
|
||||
* @return the prepared statement
|
||||
*
|
||||
|
@ -79,10 +78,9 @@ public interface StatementPreparer {
|
|||
*/
|
||||
public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys);
|
||||
|
||||
|
||||
/**
|
||||
* Get a prepared statement to use for inserting using JDBC3
|
||||
* {@link java.sql.PreparedStatement#getGeneratedKeys getGeneratedKeys} processing.
|
||||
* Prepare an INSERT statement, specifying columns which are auto-generated values to be returned.
|
||||
* Generated keys are accessed afterwards via {@link java.sql.PreparedStatement#getGeneratedKeys}
|
||||
*
|
||||
* @param sql - the SQL for the statement to be prepared
|
||||
* @param columnNames The name of the columns to be returned in the generated keys result set.
|
||||
|
|
|
@ -21,15 +21,30 @@
|
|||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.engine.jdbc.internal;
|
||||
package org.hibernate.engine.jdbc.spi;
|
||||
|
||||
import java.sql.DatabaseMetaData;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.LinkedHashSet;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
import org.hibernate.internal.util.collections.ArrayHelper;
|
||||
|
||||
/**
|
||||
* Models type info extracted from {@link java.sql.DatabaseMetaData#getTypeInfo()}
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
@SuppressWarnings("UnusedDeclaration")
|
||||
public class TypeInfo {
|
||||
private static final CoreMessageLogger LOG = Logger.getMessageLogger(
|
||||
CoreMessageLogger.class,
|
||||
TypeInfo.class.getName()
|
||||
);
|
||||
|
||||
private final String typeName;
|
||||
private final int jdbcTypeCode;
|
||||
private final String[] createParams;
|
||||
|
@ -73,6 +88,64 @@ public class TypeInfo {
|
|||
this.nullability = nullability;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract the type information from the JDBC driver's DatabaseMetaData
|
||||
*
|
||||
* @param metaData The JDBC metadata
|
||||
*
|
||||
* @return The extracted type info
|
||||
*/
|
||||
public static LinkedHashSet<TypeInfo> extractTypeInfo(DatabaseMetaData metaData) {
|
||||
final LinkedHashSet<TypeInfo> typeInfoSet = new LinkedHashSet<TypeInfo>();
|
||||
try {
|
||||
final ResultSet resultSet = metaData.getTypeInfo();
|
||||
try {
|
||||
while ( resultSet.next() ) {
|
||||
typeInfoSet.add(
|
||||
new TypeInfo(
|
||||
resultSet.getString( "TYPE_NAME" ),
|
||||
resultSet.getInt( "DATA_TYPE" ),
|
||||
interpretCreateParams( resultSet.getString( "CREATE_PARAMS" ) ),
|
||||
resultSet.getBoolean( "UNSIGNED_ATTRIBUTE" ),
|
||||
resultSet.getInt( "PRECISION" ),
|
||||
resultSet.getShort( "MINIMUM_SCALE" ),
|
||||
resultSet.getShort( "MAXIMUM_SCALE" ),
|
||||
resultSet.getBoolean( "FIXED_PREC_SCALE" ),
|
||||
resultSet.getString( "LITERAL_PREFIX" ),
|
||||
resultSet.getString( "LITERAL_SUFFIX" ),
|
||||
resultSet.getBoolean( "CASE_SENSITIVE" ),
|
||||
TypeSearchability.interpret( resultSet.getShort( "SEARCHABLE" ) ),
|
||||
TypeNullability.interpret( resultSet.getShort( "NULLABLE" ) )
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
catch ( SQLException e ) {
|
||||
LOG.unableToAccessTypeInfoResultSet( e.toString() );
|
||||
}
|
||||
finally {
|
||||
try {
|
||||
resultSet.close();
|
||||
}
|
||||
catch ( SQLException e ) {
|
||||
LOG.unableToReleaseTypeInfoResultSet();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch ( SQLException e ) {
|
||||
LOG.unableToRetrieveTypeInfoResultSet( e.toString() );
|
||||
}
|
||||
|
||||
return typeInfoSet;
|
||||
}
|
||||
|
||||
private static String[] interpretCreateParams(String value) {
|
||||
if ( value == null || value.length() == 0 ) {
|
||||
return ArrayHelper.EMPTY_STRING_ARRAY;
|
||||
}
|
||||
return value.split( "," );
|
||||
}
|
||||
|
||||
public String getTypeName() {
|
||||
return typeName;
|
||||
}
|
|
@ -21,7 +21,7 @@
|
|||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.engine.jdbc.internal;
|
||||
package org.hibernate.engine.jdbc.spi;
|
||||
|
||||
import java.sql.DatabaseMetaData;
|
||||
|
|
@ -21,7 +21,7 @@
|
|||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.engine.jdbc.internal;
|
||||
package org.hibernate.engine.jdbc.spi;
|
||||
|
||||
import java.sql.DatabaseMetaData;
|
||||
|
|
@ -30,7 +30,13 @@ import org.hibernate.HibernateException;
|
|||
* @author Steve Ebersole
|
||||
*/
|
||||
public class JndiException extends HibernateException {
|
||||
public JndiException(String string, Throwable root) {
|
||||
super( string, root );
|
||||
/**
|
||||
* Constructs a JndiException
|
||||
*
|
||||
* @param message Message explaining the exception condition
|
||||
* @param cause The underlying cause
|
||||
*/
|
||||
public JndiException(String message, Throwable cause) {
|
||||
super( message, cause );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,7 +31,13 @@ import org.hibernate.HibernateException;
|
|||
* @author Steve Ebersole
|
||||
*/
|
||||
public class JndiNameException extends HibernateException {
|
||||
public JndiNameException(String string, Throwable root) {
|
||||
super( string, root );
|
||||
/**
|
||||
* Constructs a JndiNameException
|
||||
*
|
||||
* @param message Message explaining the exception condition
|
||||
* @param cause The underlying cause.
|
||||
*/
|
||||
public JndiNameException(String message, Throwable cause) {
|
||||
super( message, cause );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,6 +25,8 @@ package org.hibernate.engine.jndi.internal;
|
|||
|
||||
import java.util.Hashtable;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
import javax.naming.Context;
|
||||
import javax.naming.InitialContext;
|
||||
import javax.naming.InvalidNameException;
|
||||
|
@ -36,11 +38,11 @@ import javax.naming.event.NamespaceChangeListener;
|
|||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import org.hibernate.cfg.Environment;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
import org.hibernate.engine.jndi.JndiException;
|
||||
import org.hibernate.engine.jndi.JndiNameException;
|
||||
import org.hibernate.engine.jndi.spi.JndiService;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
import org.hibernate.internal.util.jndi.JndiHelper;
|
||||
|
||||
/**
|
||||
* Standard implementation of JNDI services.
|
||||
|
@ -48,19 +50,66 @@ import org.hibernate.internal.util.jndi.JndiHelper;
|
|||
* @author Steve Ebersole
|
||||
*/
|
||||
public class JndiServiceImpl implements JndiService {
|
||||
|
||||
private static final CoreMessageLogger LOG = Logger.getMessageLogger(CoreMessageLogger.class, JndiServiceImpl.class.getName());
|
||||
private static final CoreMessageLogger LOG = Logger.getMessageLogger(
|
||||
CoreMessageLogger.class,
|
||||
JndiServiceImpl.class.getName()
|
||||
);
|
||||
|
||||
private final Hashtable initialContextSettings;
|
||||
|
||||
/**
|
||||
* Constructs a JndiServiceImpl
|
||||
*
|
||||
* @param configurationValues Map of configuration settings, some of which apply to JNDI support.
|
||||
*/
|
||||
public JndiServiceImpl(Map configurationValues) {
|
||||
this.initialContextSettings = JndiHelper.extractJndiProperties( configurationValues );
|
||||
this.initialContextSettings = extractJndiProperties( configurationValues );
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a hodgepodge of properties, extract out the ones relevant for JNDI interaction.
|
||||
*
|
||||
* @param configurationValues The map of config values
|
||||
*
|
||||
* @return The extracted JNDI specific properties.
|
||||
*/
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
public static Properties extractJndiProperties(Map configurationValues) {
|
||||
final Properties jndiProperties = new Properties();
|
||||
|
||||
for ( Map.Entry entry : (Set<Map.Entry>) configurationValues.entrySet() ) {
|
||||
if ( !String.class.isInstance( entry.getKey() ) ) {
|
||||
continue;
|
||||
}
|
||||
final String propertyName = (String) entry.getKey();
|
||||
final Object propertyValue = entry.getValue();
|
||||
if ( propertyName.startsWith( Environment.JNDI_PREFIX ) ) {
|
||||
// write the IntialContextFactory class and provider url to the result only if they are
|
||||
// non-null; this allows the environmental defaults (if any) to remain in effect
|
||||
if ( Environment.JNDI_CLASS.equals( propertyName ) ) {
|
||||
if ( propertyValue != null ) {
|
||||
jndiProperties.put( Context.INITIAL_CONTEXT_FACTORY, propertyValue );
|
||||
}
|
||||
}
|
||||
else if ( Environment.JNDI_URL.equals( propertyName ) ) {
|
||||
if ( propertyValue != null ) {
|
||||
jndiProperties.put( Context.PROVIDER_URL, propertyValue );
|
||||
}
|
||||
}
|
||||
else {
|
||||
final String passThruPropertyname = propertyName.substring( Environment.JNDI_PREFIX.length() + 1 );
|
||||
jndiProperties.put( passThruPropertyname, propertyValue );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return jndiProperties;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object locate(String jndiName) {
|
||||
InitialContext initialContext = buildInitialContext();
|
||||
Name name = parseName( jndiName, initialContext );
|
||||
final InitialContext initialContext = buildInitialContext();
|
||||
final Name name = parseName( jndiName, initialContext );
|
||||
try {
|
||||
return initialContext.lookup( name );
|
||||
}
|
||||
|
@ -104,8 +153,8 @@ public class JndiServiceImpl implements JndiService {
|
|||
|
||||
@Override
|
||||
public void bind(String jndiName, Object value) {
|
||||
InitialContext initialContext = buildInitialContext();
|
||||
Name name = parseName( jndiName, initialContext );
|
||||
final InitialContext initialContext = buildInitialContext();
|
||||
final Name name = parseName( jndiName, initialContext );
|
||||
try {
|
||||
bind( name, value, initialContext );
|
||||
}
|
||||
|
@ -172,8 +221,8 @@ public class JndiServiceImpl implements JndiService {
|
|||
|
||||
@Override
|
||||
public void unbind(String jndiName) {
|
||||
InitialContext initialContext = buildInitialContext();
|
||||
Name name = parseName( jndiName, initialContext );
|
||||
final InitialContext initialContext = buildInitialContext();
|
||||
final Name name = parseName( jndiName, initialContext );
|
||||
try {
|
||||
initialContext.unbind( name );
|
||||
}
|
||||
|
@ -187,8 +236,8 @@ public class JndiServiceImpl implements JndiService {
|
|||
|
||||
@Override
|
||||
public void addListener(String jndiName, NamespaceChangeListener listener) {
|
||||
InitialContext initialContext = buildInitialContext();
|
||||
Name name = parseName( jndiName, initialContext );
|
||||
final InitialContext initialContext = buildInitialContext();
|
||||
final Name name = parseName( jndiName, initialContext );
|
||||
try {
|
||||
( (EventContext) initialContext ).addNamingListener( name, EventContext.OBJECT_SCOPE, listener );
|
||||
}
|
||||
|
|
|
@ -35,6 +35,9 @@ import org.hibernate.service.spi.ServiceRegistryImplementor;
|
|||
* @author Steve Ebersole
|
||||
*/
|
||||
public class JndiServiceInitiator implements StandardServiceInitiator<JndiService> {
|
||||
/**
|
||||
* Singleton access
|
||||
*/
|
||||
public static final JndiServiceInitiator INSTANCE = new JndiServiceInitiator();
|
||||
|
||||
@Override
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
/**
|
||||
* Internal contracts defining the JNDI support within Hibernate
|
||||
*/
|
||||
package org.hibernate.engine.jndi.internal;
|
|
@ -0,0 +1,4 @@
|
|||
/**
|
||||
* Support for JNDI within Hibernate
|
||||
*/
|
||||
package org.hibernate.engine.jndi;
|
|
@ -0,0 +1,4 @@
|
|||
/**
|
||||
* The SPI contracts for Hibernate JNDI support
|
||||
*/
|
||||
package org.hibernate.engine.jndi.spi;
|
|
@ -27,6 +27,7 @@ import javax.transaction.SystemException;
|
|||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.TransactionException;
|
||||
import org.hibernate.cfg.Settings;
|
||||
import org.hibernate.engine.transaction.internal.jta.JtaStatusHelper;
|
||||
|
@ -56,9 +57,9 @@ public class SynchronizationCallbackCoordinatorImpl implements SynchronizationCa
|
|||
private AfterCompletionAction afterCompletionAction;
|
||||
private ExceptionMapper exceptionMapper;
|
||||
|
||||
private long registrationThreadId;
|
||||
private volatile long registrationThreadId;
|
||||
private final int NO_STATUS = -1;
|
||||
private int delayedCompletionHandlingStatus;
|
||||
private volatile int delayedCompletionHandlingStatus;
|
||||
|
||||
public SynchronizationCallbackCoordinatorImpl(TransactionCoordinator transactionCoordinator) {
|
||||
this.transactionCoordinator = transactionCoordinator;
|
||||
|
@ -154,11 +155,12 @@ public class SynchronizationCallbackCoordinatorImpl implements SynchronizationCa
|
|||
if ( delayedCompletionHandlingStatus != NO_STATUS ) {
|
||||
doAfterCompletion( delayedCompletionHandlingStatus );
|
||||
delayedCompletionHandlingStatus = NO_STATUS;
|
||||
throw new HibernateException("Transaction was rolled back in a different thread!");
|
||||
}
|
||||
}
|
||||
|
||||
private void doAfterCompletion(int status) {
|
||||
LOG.tracev( "Transaction after completion callback [status={0}]", status );
|
||||
LOG.tracev( "Transaction afterCompletion callback [status={0}]", status );
|
||||
|
||||
try {
|
||||
afterCompletionAction.doAction( transactionCoordinator, status );
|
||||
|
|
|
@ -74,8 +74,10 @@ public class DefaultInitializeCollectionEventListener implements InitializeColle
|
|||
source
|
||||
);
|
||||
|
||||
if ( foundInCache && traceEnabled ) {
|
||||
LOG.trace( "Collection initialized from cache" );
|
||||
if ( foundInCache ) {
|
||||
if ( traceEnabled ) {
|
||||
LOG.trace( "Collection initialized from cache" );
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ( traceEnabled ) {
|
||||
|
|
|
@ -94,6 +94,8 @@ public class JoinProcessor implements SqlTokenTypes {
|
|||
return JoinType.INNER_JOIN;
|
||||
case RIGHT_OUTER:
|
||||
return JoinType.RIGHT_OUTER_JOIN;
|
||||
case FULL:
|
||||
return JoinType.FULL_JOIN;
|
||||
default:
|
||||
throw new AssertionFailure( "undefined join type " + astJoinType );
|
||||
}
|
||||
|
|
|
@ -23,17 +23,16 @@
|
|||
*/
|
||||
package org.hibernate.internal.util.jndi;
|
||||
|
||||
import java.util.Hashtable;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
import javax.naming.Context;
|
||||
import javax.naming.InitialContext;
|
||||
import javax.naming.Name;
|
||||
import javax.naming.NameNotFoundException;
|
||||
import javax.naming.NamingException;
|
||||
import java.util.Hashtable;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.hibernate.cfg.Environment;
|
||||
import org.hibernate.engine.jndi.internal.JndiServiceImpl;
|
||||
|
||||
/**
|
||||
* Helper for dealing with JNDI.
|
||||
|
@ -54,42 +53,12 @@ public final class JndiHelper {
|
|||
*/
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
public static Properties extractJndiProperties(Map configurationValues) {
|
||||
final Properties jndiProperties = new Properties();
|
||||
|
||||
for ( Map.Entry entry : (Set<Map.Entry>) configurationValues.entrySet() ) {
|
||||
if ( !String.class.isInstance( entry.getKey() ) ) {
|
||||
continue;
|
||||
}
|
||||
final String propertyName = (String) entry.getKey();
|
||||
final Object propertyValue = entry.getValue();
|
||||
if ( propertyName.startsWith( Environment.JNDI_PREFIX ) ) {
|
||||
// write the IntialContextFactory class and provider url to the result only if they are
|
||||
// non-null; this allows the environmental defaults (if any) to remain in effect
|
||||
if ( Environment.JNDI_CLASS.equals( propertyName ) ) {
|
||||
if ( propertyValue != null ) {
|
||||
jndiProperties.put( Context.INITIAL_CONTEXT_FACTORY, propertyValue );
|
||||
}
|
||||
}
|
||||
else if ( Environment.JNDI_URL.equals( propertyName ) ) {
|
||||
if ( propertyValue != null ) {
|
||||
jndiProperties.put( Context.PROVIDER_URL, propertyValue );
|
||||
}
|
||||
}
|
||||
else {
|
||||
final String passThruPropertyname = propertyName.substring( Environment.JNDI_PREFIX.length() + 1 );
|
||||
jndiProperties.put( passThruPropertyname, propertyValue );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return jndiProperties;
|
||||
return JndiServiceImpl.extractJndiProperties( configurationValues );
|
||||
}
|
||||
|
||||
public static InitialContext getInitialContext(Properties props) throws NamingException {
|
||||
Hashtable hash = extractJndiProperties(props);
|
||||
return hash.size()==0 ?
|
||||
new InitialContext() :
|
||||
new InitialContext(hash);
|
||||
final Hashtable hash = extractJndiProperties( props );
|
||||
return hash.size() == 0 ? new InitialContext() : new InitialContext( hash );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -106,26 +75,26 @@ public final class JndiHelper {
|
|||
ctx.rebind(name, val);
|
||||
}
|
||||
catch (Exception e) {
|
||||
Name n = ctx.getNameParser("").parse(name);
|
||||
Name n = ctx.getNameParser( "" ).parse( name );
|
||||
while ( n.size() > 1 ) {
|
||||
String ctxName = n.get(0);
|
||||
final String ctxName = n.get( 0 );
|
||||
|
||||
Context subctx=null;
|
||||
Context subctx = null;
|
||||
try {
|
||||
subctx = (Context) ctx.lookup(ctxName);
|
||||
subctx = (Context) ctx.lookup( ctxName );
|
||||
}
|
||||
catch (NameNotFoundException ignore) {
|
||||
}
|
||||
|
||||
if (subctx!=null) {
|
||||
if ( subctx != null ) {
|
||||
ctx = subctx;
|
||||
}
|
||||
else {
|
||||
ctx = ctx.createSubcontext(ctxName);
|
||||
ctx = ctx.createSubcontext( ctxName );
|
||||
}
|
||||
n = n.getSuffix(1);
|
||||
n = n.getSuffix( 1 );
|
||||
}
|
||||
ctx.rebind(n, val);
|
||||
ctx.rebind( n, val );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -59,11 +59,8 @@ public abstract class AbstractJoinableAssociationImpl implements JoinableAssocia
|
|||
boolean hasRestriction,
|
||||
Map<String, Filter> enabledFilters) throws MappingException {
|
||||
this.propertyPath = currentFetch.getPropertyPath();
|
||||
final OuterJoinLoadable ownerPersister = (OuterJoinLoadable) currentFetch.getOwner().retrieveFetchSourcePersister();
|
||||
final int propertyNumber = ownerPersister.getEntityMetamodel().getPropertyIndex( currentFetch.getOwnerPropertyName() );
|
||||
final boolean isNullable = ownerPersister.isSubclassPropertyNullable( propertyNumber );
|
||||
if ( currentFetch.getFetchStrategy().getStyle() == FetchStyle.JOIN ) {
|
||||
joinType = isNullable ? JoinType.LEFT_OUTER_JOIN : JoinType.INNER_JOIN;
|
||||
joinType = currentFetch.isNullable() ? JoinType.LEFT_OUTER_JOIN : JoinType.INNER_JOIN;
|
||||
}
|
||||
else {
|
||||
joinType = JoinType.NONE;
|
||||
|
|
|
@ -27,7 +27,6 @@ import java.util.HashMap;
|
|||
import java.util.Map;
|
||||
|
||||
import org.hibernate.cfg.NotYetImplementedException;
|
||||
import org.hibernate.engine.internal.JoinHelper;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.internal.util.StringHelper;
|
||||
import org.hibernate.loader.CollectionAliases;
|
||||
|
@ -36,6 +35,8 @@ import org.hibernate.loader.EntityAliases;
|
|||
import org.hibernate.loader.GeneratedCollectionAliases;
|
||||
import org.hibernate.loader.plan.spi.CollectionReference;
|
||||
import org.hibernate.loader.plan.spi.CollectionReturn;
|
||||
import org.hibernate.loader.plan.spi.CompositeElementGraph;
|
||||
import org.hibernate.loader.plan.spi.CompositeIndexGraph;
|
||||
import org.hibernate.loader.plan.spi.EntityReference;
|
||||
import org.hibernate.loader.plan.spi.EntityReturn;
|
||||
import org.hibernate.loader.plan.spi.Fetch;
|
||||
|
@ -46,7 +47,6 @@ import org.hibernate.loader.spi.LoadQueryAliasResolutionContext;
|
|||
import org.hibernate.persister.collection.CollectionPersister;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.persister.entity.Loadable;
|
||||
import org.hibernate.persister.entity.OuterJoinLoadable;
|
||||
import org.hibernate.type.EntityType;
|
||||
|
||||
/**
|
||||
|
@ -214,9 +214,18 @@ public class LoadQueryAliasResolutionContextImpl implements LoadQueryAliasResolu
|
|||
if ( EntityReference.class.isInstance( currentFetch.getOwner() ) ) {
|
||||
lhsAlias = resolveEntityTableAlias( (EntityReference) currentFetch.getOwner() );
|
||||
}
|
||||
else {
|
||||
throw new NotYetImplementedException( "Cannot determine LHS alias for a FetchOwner that is not an EntityReference yet." );
|
||||
else if ( CompositeElementGraph.class.isInstance( currentFetch.getOwner() ) ) {
|
||||
CompositeElementGraph compositeElementGraph = (CompositeElementGraph) currentFetch.getOwner();
|
||||
lhsAlias = resolveCollectionTableAlias( compositeElementGraph.getCollectionReference() );
|
||||
}
|
||||
else if ( CompositeIndexGraph.class.isInstance( currentFetch.getOwner() ) ) {
|
||||
CompositeIndexGraph compositeIndexGraph = (CompositeIndexGraph) currentFetch.getOwner();
|
||||
lhsAlias = resolveCollectionTableAlias( compositeIndexGraph.getCollectionReference() );
|
||||
}
|
||||
else {
|
||||
throw new NotYetImplementedException( "Cannot determine LHS alias for FetchOwner." );
|
||||
}
|
||||
final String[] aliasedLhsColumnNames = StringHelper.qualify( lhsAlias, currentFetch.getColumnNames() );
|
||||
final String rhsAlias;
|
||||
if ( EntityReference.class.isInstance( currentFetch ) ) {
|
||||
rhsAlias = resolveEntityTableAlias( (EntityReference) currentFetch );
|
||||
|
@ -229,15 +238,6 @@ public class LoadQueryAliasResolutionContextImpl implements LoadQueryAliasResolu
|
|||
}
|
||||
|
||||
// TODO: can't this be found in CollectionAliases or EntityAliases? should be moved to LoadQueryAliasResolutionContextImpl
|
||||
final OuterJoinLoadable fetchSourcePersister = (OuterJoinLoadable) currentFetch.getOwner().retrieveFetchSourcePersister();
|
||||
final int propertyNumber = fetchSourcePersister.getEntityMetamodel().getPropertyIndex( currentFetch.getOwnerPropertyName() );
|
||||
final String[] aliasedLhsColumnNames = JoinHelper.getAliasedLHSColumnNames(
|
||||
joinableAssociation.getAssociationType(),
|
||||
lhsAlias,
|
||||
propertyNumber,
|
||||
fetchSourcePersister,
|
||||
sessionFactory
|
||||
);
|
||||
|
||||
aliases = new JoinableAssociationAliasesImpl( lhsAlias, aliasedLhsColumnNames, rhsAlias );
|
||||
aliasesByJoinableAssociation.put( joinableAssociation, aliases );
|
||||
|
|
|
@ -33,6 +33,7 @@ import org.hibernate.loader.plan.spi.FetchOwner;
|
|||
import org.hibernate.loader.plan.spi.build.LoadPlanBuildingContext;
|
||||
import org.hibernate.persister.walking.spi.AssociationAttributeDefinition;
|
||||
import org.hibernate.persister.walking.spi.CompositionDefinition;
|
||||
import org.hibernate.type.EntityType;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
|
@ -63,6 +64,7 @@ public class LoadPlanBuildingHelper {
|
|||
LockMode.NONE, // todo : for now
|
||||
fetchOwner,
|
||||
attributeDefinition.getName(),
|
||||
(EntityType) attributeDefinition.getType(),
|
||||
fetchStrategy
|
||||
);
|
||||
}
|
||||
|
@ -73,7 +75,7 @@ public class LoadPlanBuildingHelper {
|
|||
LoadPlanBuildingContext loadPlanBuildingContext) {
|
||||
return new CompositeFetch(
|
||||
loadPlanBuildingContext.getSessionFactory(),
|
||||
(AbstractFetchOwner) fetchOwner,
|
||||
fetchOwner,
|
||||
attributeDefinition.getName()
|
||||
);
|
||||
}
|
||||
|
|
|
@ -27,20 +27,24 @@ import java.util.ArrayList;
|
|||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.LockMode;
|
||||
import org.hibernate.engine.FetchStrategy;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.loader.plan.internal.LoadPlanBuildingHelper;
|
||||
import org.hibernate.loader.plan.spi.build.LoadPlanBuildingContext;
|
||||
import org.hibernate.persister.walking.spi.AssociationAttributeDefinition;
|
||||
import org.hibernate.persister.walking.spi.CompositionDefinition;
|
||||
import org.hibernate.type.Type;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
* @author Gail Badner
|
||||
*/
|
||||
public abstract class AbstractFetchOwner extends AbstractPlanNode implements FetchOwner {
|
||||
private final LockMode lockMode;
|
||||
|
||||
private List<Fetch> fetches;
|
||||
|
||||
public AbstractFetchOwner(SessionFactoryImplementor factory, LockMode lockMode) {
|
||||
public AbstractFetchOwner(SessionFactoryImplementor factory) {
|
||||
super( factory );
|
||||
this.lockMode = lockMode;
|
||||
validate();
|
||||
}
|
||||
|
||||
|
@ -50,11 +54,10 @@ public abstract class AbstractFetchOwner extends AbstractPlanNode implements Fet
|
|||
/**
|
||||
* A "copy" constructor. Used while making clones/copies of this.
|
||||
*
|
||||
* @param original
|
||||
* @param original - the original object to copy.
|
||||
*/
|
||||
protected AbstractFetchOwner(AbstractFetchOwner original, CopyContext copyContext) {
|
||||
super( original );
|
||||
this.lockMode = original.lockMode;
|
||||
validate();
|
||||
|
||||
copyContext.getReturnGraphVisitationStrategy().startingFetches( original );
|
||||
|
@ -62,6 +65,7 @@ public abstract class AbstractFetchOwner extends AbstractPlanNode implements Fet
|
|||
this.fetches = Collections.emptyList();
|
||||
}
|
||||
else {
|
||||
// TODO: don't think this is correct...
|
||||
List<Fetch> fetchesCopy = new ArrayList<Fetch>();
|
||||
for ( Fetch fetch : fetches ) {
|
||||
fetchesCopy.add( fetch.makeCopy( copyContext, this ) );
|
||||
|
@ -71,11 +75,6 @@ public abstract class AbstractFetchOwner extends AbstractPlanNode implements Fet
|
|||
copyContext.getReturnGraphVisitationStrategy().finishingFetches( original );
|
||||
}
|
||||
|
||||
public LockMode getLockMode() {
|
||||
return lockMode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addFetch(Fetch fetch) {
|
||||
if ( fetch.getOwner() != this ) {
|
||||
throw new IllegalArgumentException( "Fetch and owner did not match" );
|
||||
|
@ -92,4 +91,55 @@ public abstract class AbstractFetchOwner extends AbstractPlanNode implements Fet
|
|||
public Fetch[] getFetches() {
|
||||
return fetches == null ? NO_FETCHES : fetches.toArray( new Fetch[ fetches.size() ] );
|
||||
}
|
||||
|
||||
protected abstract FetchOwnerDelegate getFetchOwnerDelegate();
|
||||
|
||||
@Override
|
||||
public boolean isNullable(Fetch fetch) {
|
||||
return getFetchOwnerDelegate().isNullable( fetch );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getType(Fetch fetch) {
|
||||
return getFetchOwnerDelegate().getType( fetch );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getColumnNames(Fetch fetch) {
|
||||
return getFetchOwnerDelegate().getColumnNames( fetch );
|
||||
}
|
||||
|
||||
@Override
|
||||
public CollectionFetch buildCollectionFetch(
|
||||
AssociationAttributeDefinition attributeDefinition,
|
||||
FetchStrategy fetchStrategy,
|
||||
LoadPlanBuildingContext loadPlanBuildingContext) {
|
||||
return LoadPlanBuildingHelper.buildStandardCollectionFetch(
|
||||
this,
|
||||
attributeDefinition,
|
||||
fetchStrategy,
|
||||
loadPlanBuildingContext
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityFetch buildEntityFetch(
|
||||
AssociationAttributeDefinition attributeDefinition,
|
||||
FetchStrategy fetchStrategy,
|
||||
LoadPlanBuildingContext loadPlanBuildingContext) {
|
||||
return LoadPlanBuildingHelper.buildStandardEntityFetch(
|
||||
this,
|
||||
attributeDefinition,
|
||||
fetchStrategy,
|
||||
loadPlanBuildingContext
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompositeFetch buildCompositeFetch(
|
||||
CompositionDefinition attributeDefinition,
|
||||
LoadPlanBuildingContext loadPlanBuildingContext) {
|
||||
return LoadPlanBuildingHelper.buildStandardCompositeFetch( this, attributeDefinition, loadPlanBuildingContext );
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
package org.hibernate.loader.plan.spi;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.LockMode;
|
||||
import org.hibernate.engine.FetchStrategy;
|
||||
import org.hibernate.engine.FetchStyle;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
|
@ -42,11 +41,10 @@ public abstract class AbstractSingularAttributeFetch extends AbstractFetchOwner
|
|||
|
||||
public AbstractSingularAttributeFetch(
|
||||
SessionFactoryImplementor factory,
|
||||
LockMode lockMode,
|
||||
FetchOwner owner,
|
||||
String ownerProperty,
|
||||
FetchStrategy fetchStrategy) {
|
||||
super( factory, lockMode );
|
||||
super( factory );
|
||||
this.owner = owner;
|
||||
this.ownerProperty = ownerProperty;
|
||||
this.fetchStrategy = fetchStrategy;
|
||||
|
@ -77,6 +75,16 @@ public abstract class AbstractSingularAttributeFetch extends AbstractFetchOwner
|
|||
return ownerProperty;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNullable() {
|
||||
return owner.isNullable( this );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getColumnNames() {
|
||||
return owner.getColumnNames( this );
|
||||
}
|
||||
|
||||
@Override
|
||||
public FetchStrategy getFetchStrategy() {
|
||||
return fetchStrategy;
|
||||
|
|
|
@ -28,8 +28,10 @@ import java.sql.SQLException;
|
|||
|
||||
import org.hibernate.LockMode;
|
||||
import org.hibernate.engine.FetchStrategy;
|
||||
import org.hibernate.engine.internal.JoinHelper;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.loader.spi.ResultSetProcessingContext;
|
||||
import org.hibernate.persister.entity.Joinable;
|
||||
import org.hibernate.type.CollectionType;
|
||||
|
||||
/**
|
||||
|
@ -74,6 +76,16 @@ public class CollectionFetch extends AbstractCollectionReference implements Fetc
|
|||
return getPropertyPath().getProperty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNullable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getColumnNames() {
|
||||
return getOwner().getColumnNames( this );
|
||||
}
|
||||
|
||||
@Override
|
||||
public FetchStrategy getFetchStrategy() {
|
||||
return fetchStrategy;
|
||||
|
|
|
@ -1,29 +1,24 @@
|
|||
package org.hibernate.loader.plan.spi;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.engine.FetchStrategy;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.loader.PropertyPath;
|
||||
import org.hibernate.loader.plan.internal.LoadPlanBuildingHelper;
|
||||
import org.hibernate.loader.plan.spi.build.LoadPlanBuildingContext;
|
||||
import org.hibernate.persister.collection.CollectionPersister;
|
||||
import org.hibernate.persister.collection.QueryableCollection;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.persister.walking.spi.AssociationAttributeDefinition;
|
||||
import org.hibernate.persister.walking.spi.CompositionDefinition;
|
||||
import org.hibernate.type.CompositeType;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class CompositeElementGraph extends AbstractPlanNode implements FetchableCollectionElement {
|
||||
public class CompositeElementGraph extends AbstractFetchOwner implements FetchableCollectionElement {
|
||||
private final CollectionReference collectionReference;
|
||||
private final PropertyPath propertyPath;
|
||||
private final CollectionPersister collectionPersister;
|
||||
|
||||
private List<Fetch> fetches;
|
||||
private final FetchOwnerDelegate fetchOwnerDelegate;
|
||||
|
||||
public CompositeElementGraph(
|
||||
SessionFactoryImplementor sessionFactory,
|
||||
|
@ -34,39 +29,24 @@ public class CompositeElementGraph extends AbstractPlanNode implements Fetchable
|
|||
this.collectionReference = collectionReference;
|
||||
this.collectionPersister = collectionReference.getCollectionPersister();
|
||||
this.propertyPath = collectionPath.append( "<elements>" );
|
||||
this.fetchOwnerDelegate = new CompositeFetchOwnerDelegate(
|
||||
sessionFactory,
|
||||
(CompositeType) collectionPersister.getElementType(),
|
||||
( (QueryableCollection) collectionPersister ).getElementColumnNames()
|
||||
);
|
||||
}
|
||||
|
||||
public CompositeElementGraph(CompositeElementGraph original, CopyContext copyContext) {
|
||||
super( original );
|
||||
super( original, copyContext );
|
||||
this.collectionReference = original.collectionReference;
|
||||
this.collectionPersister = original.collectionPersister;
|
||||
this.propertyPath = original.propertyPath;
|
||||
|
||||
copyContext.getReturnGraphVisitationStrategy().startingFetches( original );
|
||||
if ( fetches == null || fetches.size() == 0 ) {
|
||||
this.fetches = Collections.emptyList();
|
||||
}
|
||||
else {
|
||||
List<Fetch> fetchesCopy = new ArrayList<Fetch>();
|
||||
for ( Fetch fetch : fetches ) {
|
||||
fetchesCopy.add( fetch.makeCopy( copyContext, this ) );
|
||||
}
|
||||
this.fetches = fetchesCopy;
|
||||
}
|
||||
copyContext.getReturnGraphVisitationStrategy().finishingFetches( original );
|
||||
this.fetchOwnerDelegate = original.fetchOwnerDelegate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addFetch(Fetch fetch) {
|
||||
if ( fetches == null ) {
|
||||
fetches = new ArrayList<Fetch>();
|
||||
}
|
||||
fetches.add( fetch );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Fetch[] getFetches() {
|
||||
return fetches == null ? NO_FETCHES : fetches.toArray( new Fetch[ fetches.size() ] );
|
||||
public CollectionReference getCollectionReference() {
|
||||
return collectionReference;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -83,6 +63,16 @@ public class CompositeElementGraph extends AbstractPlanNode implements Fetchable
|
|||
return propertyPath;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompositeElementGraph makeCopy(CopyContext copyContext) {
|
||||
return new CompositeElementGraph( this, copyContext );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected FetchOwnerDelegate getFetchOwnerDelegate() {
|
||||
return fetchOwnerDelegate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CollectionFetch buildCollectionFetch(
|
||||
AssociationAttributeDefinition attributeDefinition,
|
||||
|
@ -90,29 +80,4 @@ public class CompositeElementGraph extends AbstractPlanNode implements Fetchable
|
|||
LoadPlanBuildingContext loadPlanBuildingContext) {
|
||||
throw new HibernateException( "Collection composite element cannot define collections" );
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityFetch buildEntityFetch(
|
||||
AssociationAttributeDefinition attributeDefinition,
|
||||
FetchStrategy fetchStrategy,
|
||||
LoadPlanBuildingContext loadPlanBuildingContext) {
|
||||
return LoadPlanBuildingHelper.buildStandardEntityFetch(
|
||||
this,
|
||||
attributeDefinition,
|
||||
fetchStrategy,
|
||||
loadPlanBuildingContext
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompositeFetch buildCompositeFetch(
|
||||
CompositionDefinition attributeDefinition,
|
||||
LoadPlanBuildingContext loadPlanBuildingContext) {
|
||||
return LoadPlanBuildingHelper.buildStandardCompositeFetch( this, attributeDefinition, loadPlanBuildingContext );
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompositeElementGraph makeCopy(CopyContext copyContext) {
|
||||
return new CompositeElementGraph( this, copyContext );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,17 +25,17 @@ package org.hibernate.loader.plan.spi;
|
|||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
|
||||
import org.hibernate.LockMode;
|
||||
import org.hibernate.engine.FetchStrategy;
|
||||
import org.hibernate.engine.FetchStyle;
|
||||
import org.hibernate.engine.FetchTiming;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.loader.plan.internal.LoadPlanBuildingHelper;
|
||||
import org.hibernate.loader.plan.spi.build.LoadPlanBuildingContext;
|
||||
import org.hibernate.loader.spi.ResultSetProcessingContext;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.persister.walking.spi.AssociationAttributeDefinition;
|
||||
import org.hibernate.persister.walking.spi.CompositionDefinition;
|
||||
import org.hibernate.type.CompositeType;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
|
@ -43,15 +43,28 @@ import org.hibernate.persister.walking.spi.CompositionDefinition;
|
|||
public class CompositeFetch extends AbstractSingularAttributeFetch {
|
||||
public static final FetchStrategy FETCH_PLAN = new FetchStrategy( FetchTiming.IMMEDIATE, FetchStyle.JOIN );
|
||||
|
||||
private final FetchOwnerDelegate delegate;
|
||||
|
||||
public CompositeFetch(
|
||||
SessionFactoryImplementor sessionFactory,
|
||||
FetchOwner owner,
|
||||
String ownerProperty) {
|
||||
super( sessionFactory, LockMode.NONE, owner, ownerProperty, FETCH_PLAN );
|
||||
super( sessionFactory, owner, ownerProperty, FETCH_PLAN );
|
||||
this.delegate = new CompositeFetchOwnerDelegate(
|
||||
sessionFactory,
|
||||
(CompositeType) getOwner().getType( this ),
|
||||
getOwner().getColumnNames( this )
|
||||
);
|
||||
}
|
||||
|
||||
public CompositeFetch(CompositeFetch original, CopyContext copyContext, FetchOwner fetchOwnerCopy) {
|
||||
super( original, copyContext, fetchOwnerCopy );
|
||||
this.delegate = original.getFetchOwnerDelegate();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected FetchOwnerDelegate getFetchOwnerDelegate() {
|
||||
return delegate;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -72,13 +85,18 @@ public class CompositeFetch extends AbstractSingularAttributeFetch {
|
|||
AssociationAttributeDefinition attributeDefinition,
|
||||
FetchStrategy fetchStrategy,
|
||||
LoadPlanBuildingContext loadPlanBuildingContext) {
|
||||
return null; //To change body of implemented methods use File | Settings | File Templates.
|
||||
return LoadPlanBuildingHelper.buildStandardEntityFetch(
|
||||
this,
|
||||
attributeDefinition,
|
||||
fetchStrategy,
|
||||
loadPlanBuildingContext
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompositeFetch buildCompositeFetch(
|
||||
CompositionDefinition attributeDefinition, LoadPlanBuildingContext loadPlanBuildingContext) {
|
||||
return null; //To change body of implemented methods use File | Settings | File Templates.
|
||||
return LoadPlanBuildingHelper.buildStandardCompositeFetch( this, attributeDefinition, loadPlanBuildingContext );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -0,0 +1,98 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2013, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.loader.plan.spi;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.internal.util.collections.ArrayHelper;
|
||||
import org.hibernate.persister.walking.spi.WalkingException;
|
||||
import org.hibernate.type.CompositeType;
|
||||
import org.hibernate.type.Type;
|
||||
|
||||
/**
|
||||
* @author Gail Badner
|
||||
*/
|
||||
public class CompositeFetchOwnerDelegate implements FetchOwnerDelegate {
|
||||
private final SessionFactoryImplementor sessionFactory;
|
||||
private final CompositeType compositeType;
|
||||
private final String[] columnNames;
|
||||
|
||||
public CompositeFetchOwnerDelegate(
|
||||
SessionFactoryImplementor sessionFactory,
|
||||
CompositeType compositeType,
|
||||
String[] columnNames) {
|
||||
this.sessionFactory = sessionFactory;
|
||||
this.compositeType = compositeType;
|
||||
this.columnNames = columnNames;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNullable(Fetch fetch) {
|
||||
return compositeType.getPropertyNullability()[ determinePropertyIndex( fetch ) ];
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getType(Fetch fetch) {
|
||||
return compositeType.getSubtypes()[ determinePropertyIndex( fetch ) ];
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getColumnNames(Fetch fetch) {
|
||||
// TODO: probably want to cache this
|
||||
int begin = 0;
|
||||
String[] subColumnNames = null;
|
||||
for ( int i = 0; i < compositeType.getSubtypes().length; i++ ) {
|
||||
final int columnSpan = compositeType.getSubtypes()[i].getColumnSpan( sessionFactory );
|
||||
subColumnNames = ArrayHelper.slice( columnNames, begin, columnSpan );
|
||||
if ( compositeType.getPropertyNames()[ i ].equals( fetch.getOwnerPropertyName() ) ) {
|
||||
break;
|
||||
}
|
||||
begin += columnSpan;
|
||||
}
|
||||
return subColumnNames;
|
||||
}
|
||||
|
||||
private int determinePropertyIndex(Fetch fetch) {
|
||||
// TODO: probably want to cache this
|
||||
final String[] subAttributeNames = compositeType.getPropertyNames();
|
||||
int subAttributeIndex = -1;
|
||||
for ( int i = 0; i < subAttributeNames.length ; i++ ) {
|
||||
if ( subAttributeNames[ i ].equals( fetch.getOwnerPropertyName() ) ) {
|
||||
subAttributeIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( subAttributeIndex == -1 ) {
|
||||
throw new WalkingException(
|
||||
String.format(
|
||||
"Owner property [%s] not found in composite properties [%s]",
|
||||
fetch.getOwnerPropertyName(),
|
||||
Arrays.asList( subAttributeNames )
|
||||
)
|
||||
);
|
||||
}
|
||||
return subAttributeIndex;
|
||||
}
|
||||
}
|
|
@ -1,29 +1,24 @@
|
|||
package org.hibernate.loader.plan.spi;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.engine.FetchStrategy;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.loader.PropertyPath;
|
||||
import org.hibernate.loader.plan.internal.LoadPlanBuildingHelper;
|
||||
import org.hibernate.loader.plan.spi.build.LoadPlanBuildingContext;
|
||||
import org.hibernate.persister.collection.CollectionPersister;
|
||||
import org.hibernate.persister.collection.QueryableCollection;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.persister.walking.spi.AssociationAttributeDefinition;
|
||||
import org.hibernate.persister.walking.spi.CompositionDefinition;
|
||||
import org.hibernate.type.CompositeType;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class CompositeIndexGraph extends AbstractPlanNode implements FetchableCollectionIndex {
|
||||
public class CompositeIndexGraph extends AbstractFetchOwner implements FetchableCollectionIndex {
|
||||
private final CollectionReference collectionReference;
|
||||
private final PropertyPath propertyPath;
|
||||
private final CollectionPersister collectionPersister;
|
||||
|
||||
private List<Fetch> fetches;
|
||||
private final FetchOwnerDelegate fetchOwnerDelegate;
|
||||
|
||||
public CompositeIndexGraph(
|
||||
SessionFactoryImplementor sessionFactory,
|
||||
|
@ -33,39 +28,19 @@ public class CompositeIndexGraph extends AbstractPlanNode implements FetchableCo
|
|||
this.collectionReference = collectionReference;
|
||||
this.collectionPersister = collectionReference.getCollectionPersister();
|
||||
this.propertyPath = propertyPath.append( "<index>" );
|
||||
this.fetchOwnerDelegate = new CompositeFetchOwnerDelegate(
|
||||
sessionFactory,
|
||||
(CompositeType) collectionPersister.getIndexType(),
|
||||
( (QueryableCollection) collectionPersister ).getIndexColumnNames()
|
||||
);
|
||||
}
|
||||
|
||||
protected CompositeIndexGraph(CompositeIndexGraph original, CopyContext copyContext) {
|
||||
super( original );
|
||||
super( original, copyContext );
|
||||
this.collectionReference = original.collectionReference;
|
||||
this.collectionPersister = original.collectionPersister;
|
||||
this.propertyPath = original.propertyPath;
|
||||
|
||||
copyContext.getReturnGraphVisitationStrategy().startingFetches( original );
|
||||
if ( fetches == null || fetches.size() == 0 ) {
|
||||
this.fetches = Collections.emptyList();
|
||||
}
|
||||
else {
|
||||
List<Fetch> fetchesCopy = new ArrayList<Fetch>();
|
||||
for ( Fetch fetch : fetches ) {
|
||||
fetchesCopy.add( fetch.makeCopy( copyContext, this ) );
|
||||
}
|
||||
this.fetches = fetchesCopy;
|
||||
}
|
||||
copyContext.getReturnGraphVisitationStrategy().finishingFetches( original );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addFetch(Fetch fetch) {
|
||||
if ( fetches == null ) {
|
||||
fetches = new ArrayList<Fetch>();
|
||||
}
|
||||
fetches.add( fetch );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Fetch[] getFetches() {
|
||||
return fetches == null ? NO_FETCHES : fetches.toArray( new Fetch[ fetches.size() ] );
|
||||
this.fetchOwnerDelegate = original.fetchOwnerDelegate;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -77,12 +52,25 @@ public class CompositeIndexGraph extends AbstractPlanNode implements FetchableCo
|
|||
return collectionPersister.getOwnerEntityPersister();
|
||||
}
|
||||
|
||||
public CollectionReference getCollectionReference() {
|
||||
return collectionReference;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PropertyPath getPropertyPath() {
|
||||
return propertyPath;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompositeIndexGraph makeCopy(CopyContext copyContext) {
|
||||
return new CompositeIndexGraph( this, copyContext );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected FetchOwnerDelegate getFetchOwnerDelegate() {
|
||||
return fetchOwnerDelegate;
|
||||
}
|
||||
|
||||
public CollectionFetch buildCollectionFetch(
|
||||
AssociationAttributeDefinition attributeDefinition,
|
||||
FetchStrategy fetchStrategy,
|
||||
|
@ -90,28 +78,4 @@ public class CompositeIndexGraph extends AbstractPlanNode implements FetchableCo
|
|||
throw new HibernateException( "Composite index cannot define collections" );
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityFetch buildEntityFetch(
|
||||
AssociationAttributeDefinition attributeDefinition,
|
||||
FetchStrategy fetchStrategy,
|
||||
LoadPlanBuildingContext loadPlanBuildingContext) {
|
||||
return LoadPlanBuildingHelper.buildStandardEntityFetch(
|
||||
this,
|
||||
attributeDefinition,
|
||||
fetchStrategy,
|
||||
loadPlanBuildingContext
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompositeFetch buildCompositeFetch(
|
||||
CompositionDefinition attributeDefinition,
|
||||
LoadPlanBuildingContext loadPlanBuildingContext) {
|
||||
return LoadPlanBuildingHelper.buildStandardCompositeFetch( this, attributeDefinition, loadPlanBuildingContext );
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompositeIndexGraph makeCopy(CopyContext copyContext) {
|
||||
return new CompositeIndexGraph( this, copyContext );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,32 +1,23 @@
|
|||
package org.hibernate.loader.plan.spi;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.LockMode;
|
||||
import org.hibernate.engine.FetchStrategy;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.loader.PropertyPath;
|
||||
import org.hibernate.loader.plan.internal.LoadPlanBuildingHelper;
|
||||
import org.hibernate.loader.plan.spi.build.LoadPlanBuildingContext;
|
||||
import org.hibernate.persister.collection.CollectionPersister;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.persister.walking.spi.AssociationAttributeDefinition;
|
||||
import org.hibernate.persister.walking.spi.CompositionDefinition;
|
||||
import org.hibernate.type.AssociationType;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class EntityElementGraph extends AbstractPlanNode implements FetchableCollectionElement, EntityReference {
|
||||
public class EntityElementGraph extends AbstractFetchOwner implements FetchableCollectionElement, EntityReference {
|
||||
private final CollectionReference collectionReference;
|
||||
private final CollectionPersister collectionPersister;
|
||||
private final AssociationType elementType;
|
||||
private final EntityPersister elementPersister;
|
||||
private final PropertyPath propertyPath;
|
||||
|
||||
private List<Fetch> fetches;
|
||||
private final FetchOwnerDelegate fetchOwnerDelegate;
|
||||
|
||||
private IdentifierDescription identifierDescription;
|
||||
|
||||
|
@ -40,30 +31,19 @@ public class EntityElementGraph extends AbstractPlanNode implements FetchableCol
|
|||
this.collectionPersister = collectionReference.getCollectionPersister();
|
||||
this.elementType = (AssociationType) collectionPersister.getElementType();
|
||||
this.elementPersister = (EntityPersister) this.elementType.getAssociatedJoinable( sessionFactory() );
|
||||
this.propertyPath = collectionPath.append( "<elements>" );
|
||||
this.propertyPath = collectionPath;
|
||||
this.fetchOwnerDelegate = new EntityFetchOwnerDelegate( elementPersister );
|
||||
}
|
||||
|
||||
public EntityElementGraph(EntityElementGraph original, CopyContext copyContext) {
|
||||
super( original );
|
||||
super( original, copyContext );
|
||||
|
||||
this.collectionReference = original.collectionReference;
|
||||
this.collectionPersister = original.collectionReference.getCollectionPersister();
|
||||
this.elementType = original.elementType;
|
||||
this.elementPersister = original.elementPersister;
|
||||
this.propertyPath = original.propertyPath;
|
||||
|
||||
copyContext.getReturnGraphVisitationStrategy().startingFetches( original );
|
||||
if ( fetches == null || fetches.size() == 0 ) {
|
||||
this.fetches = Collections.emptyList();
|
||||
}
|
||||
else {
|
||||
List<Fetch> fetchesCopy = new ArrayList<Fetch>();
|
||||
for ( Fetch fetch : fetches ) {
|
||||
fetchesCopy.add( fetch.makeCopy( copyContext, this ) );
|
||||
}
|
||||
this.fetches = fetchesCopy;
|
||||
}
|
||||
copyContext.getReturnGraphVisitationStrategy().finishingFetches( original );
|
||||
this.fetchOwnerDelegate = original.fetchOwnerDelegate;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -86,19 +66,6 @@ public class EntityElementGraph extends AbstractPlanNode implements FetchableCol
|
|||
return identifierDescription;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addFetch(Fetch fetch) {
|
||||
if ( fetches == null ) {
|
||||
fetches = new ArrayList<Fetch>();
|
||||
}
|
||||
fetches.add( fetch );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Fetch[] getFetches() {
|
||||
return fetches == null ? NO_FETCHES : fetches.toArray( new Fetch[ fetches.size() ] );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void validateFetchPlan(FetchStrategy fetchStrategy) {
|
||||
}
|
||||
|
@ -113,39 +80,6 @@ public class EntityElementGraph extends AbstractPlanNode implements FetchableCol
|
|||
return propertyPath;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CollectionFetch buildCollectionFetch(
|
||||
AssociationAttributeDefinition attributeDefinition,
|
||||
FetchStrategy fetchStrategy,
|
||||
LoadPlanBuildingContext loadPlanBuildingContext) {
|
||||
return LoadPlanBuildingHelper.buildStandardCollectionFetch(
|
||||
this,
|
||||
attributeDefinition,
|
||||
fetchStrategy,
|
||||
loadPlanBuildingContext
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityFetch buildEntityFetch(
|
||||
AssociationAttributeDefinition attributeDefinition,
|
||||
FetchStrategy fetchStrategy,
|
||||
LoadPlanBuildingContext loadPlanBuildingContext) {
|
||||
return LoadPlanBuildingHelper.buildStandardEntityFetch(
|
||||
this,
|
||||
attributeDefinition,
|
||||
fetchStrategy,
|
||||
loadPlanBuildingContext
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompositeFetch buildCompositeFetch(
|
||||
CompositionDefinition attributeDefinition,
|
||||
LoadPlanBuildingContext loadPlanBuildingContext) {
|
||||
return LoadPlanBuildingHelper.buildStandardCompositeFetch( this, attributeDefinition, loadPlanBuildingContext );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void injectIdentifierDescription(IdentifierDescription identifierDescription) {
|
||||
this.identifierDescription = identifierDescription;
|
||||
|
@ -156,8 +90,18 @@ public class EntityElementGraph extends AbstractPlanNode implements FetchableCol
|
|||
return new EntityElementGraph( this, copyContext );
|
||||
}
|
||||
|
||||
@Override
|
||||
public CollectionReference getCollectionReference() {
|
||||
return collectionReference;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "EntityElementGraph(collection=" + collectionPersister.getRole() + ", type=" + elementPersister.getEntityName() + ")";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected FetchOwnerDelegate getFetchOwnerDelegate() {
|
||||
return fetchOwnerDelegate;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,21 +32,19 @@ import org.hibernate.engine.FetchStrategy;
|
|||
import org.hibernate.engine.FetchTiming;
|
||||
import org.hibernate.engine.spi.EntityKey;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.loader.plan.internal.LoadPlanBuildingHelper;
|
||||
import org.hibernate.loader.plan.spi.build.LoadPlanBuildingContext;
|
||||
import org.hibernate.loader.spi.ResultSetProcessingContext;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.persister.walking.spi.AssociationAttributeDefinition;
|
||||
import org.hibernate.persister.walking.spi.CompositionDefinition;
|
||||
import org.hibernate.type.EntityType;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class EntityFetch extends AbstractSingularAttributeFetch implements EntityReference {
|
||||
public class EntityFetch extends AbstractSingularAttributeFetch implements EntityReference, Fetch {
|
||||
|
||||
private final EntityType associationType;
|
||||
private final EntityPersister persister;
|
||||
private final LockMode lockMode;
|
||||
private final FetchOwnerDelegate fetchOwnerDelegate;
|
||||
|
||||
private IdentifierDescription identifierDescription;
|
||||
|
||||
|
@ -55,11 +53,14 @@ public class EntityFetch extends AbstractSingularAttributeFetch implements Entit
|
|||
LockMode lockMode,
|
||||
FetchOwner owner,
|
||||
String ownerProperty,
|
||||
EntityType entityType,
|
||||
FetchStrategy fetchStrategy) {
|
||||
super( sessionFactory, lockMode, owner, ownerProperty, fetchStrategy );
|
||||
super( sessionFactory, owner, ownerProperty, fetchStrategy );
|
||||
|
||||
this.associationType = (EntityType) owner.retrieveFetchSourcePersister().getPropertyType( ownerProperty );
|
||||
this.associationType = entityType;
|
||||
this.persister = sessionFactory.getEntityPersister( associationType.getAssociatedEntityName() );
|
||||
this.lockMode = lockMode;
|
||||
this.fetchOwnerDelegate = new EntityFetchOwnerDelegate( persister );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -72,6 +73,8 @@ public class EntityFetch extends AbstractSingularAttributeFetch implements Entit
|
|||
super( original, copyContext, fetchOwnerCopy );
|
||||
this.associationType = original.associationType;
|
||||
this.persister = original.persister;
|
||||
this.lockMode = original.lockMode;
|
||||
this.fetchOwnerDelegate = original.fetchOwnerDelegate;
|
||||
}
|
||||
|
||||
public EntityType getAssociationType() {
|
||||
|
@ -93,45 +96,16 @@ public class EntityFetch extends AbstractSingularAttributeFetch implements Entit
|
|||
return identifierDescription;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LockMode getLockMode() {
|
||||
return lockMode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityPersister retrieveFetchSourcePersister() {
|
||||
return persister;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public CollectionFetch buildCollectionFetch(
|
||||
AssociationAttributeDefinition attributeDefinition,
|
||||
FetchStrategy fetchStrategy,
|
||||
LoadPlanBuildingContext loadPlanBuildingContext) {
|
||||
return LoadPlanBuildingHelper.buildStandardCollectionFetch(
|
||||
this,
|
||||
attributeDefinition,
|
||||
fetchStrategy,
|
||||
loadPlanBuildingContext
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityFetch buildEntityFetch(
|
||||
AssociationAttributeDefinition attributeDefinition,
|
||||
FetchStrategy fetchStrategy,
|
||||
LoadPlanBuildingContext loadPlanBuildingContext) {
|
||||
return LoadPlanBuildingHelper.buildStandardEntityFetch(
|
||||
this,
|
||||
attributeDefinition,
|
||||
fetchStrategy,
|
||||
loadPlanBuildingContext
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompositeFetch buildCompositeFetch(
|
||||
CompositionDefinition attributeDefinition,
|
||||
LoadPlanBuildingContext loadPlanBuildingContext) {
|
||||
return LoadPlanBuildingHelper.buildStandardCompositeFetch( this, attributeDefinition, loadPlanBuildingContext );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void injectIdentifierDescription(IdentifierDescription identifierDescription) {
|
||||
this.identifierDescription = identifierDescription;
|
||||
|
@ -267,4 +241,9 @@ public class EntityFetch extends AbstractSingularAttributeFetch implements Entit
|
|||
copyContext.getReturnGraphVisitationStrategy().finishingEntityFetch( this );
|
||||
return copy;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected FetchOwnerDelegate getFetchOwnerDelegate() {
|
||||
return fetchOwnerDelegate;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2013, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.loader.plan.spi;
|
||||
|
||||
import org.hibernate.engine.internal.JoinHelper;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.persister.entity.OuterJoinLoadable;
|
||||
import org.hibernate.type.AssociationType;
|
||||
import org.hibernate.type.Type;
|
||||
|
||||
/**
|
||||
* @author Gail Badner
|
||||
*/
|
||||
public class EntityFetchOwnerDelegate implements FetchOwnerDelegate {
|
||||
private final EntityPersister entityPersister;
|
||||
|
||||
public EntityFetchOwnerDelegate(EntityPersister entityPersister) {
|
||||
this.entityPersister = entityPersister;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNullable(Fetch fetch) {
|
||||
return entityPersister.getPropertyNullability()[ determinePropertyIndex( fetch ) ];
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getType(Fetch fetch) {
|
||||
return entityPersister.getPropertyTypes()[ determinePropertyIndex( fetch ) ];
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getColumnNames(Fetch fetch) {
|
||||
final OuterJoinLoadable outerJoinLoadable = (OuterJoinLoadable) entityPersister;
|
||||
Type fetchType = getType( fetch );
|
||||
if ( fetchType.isAssociationType() ) {
|
||||
return JoinHelper.getLHSColumnNames(
|
||||
(AssociationType) fetchType,
|
||||
determinePropertyIndex( fetch ),
|
||||
outerJoinLoadable,
|
||||
outerJoinLoadable.getFactory()
|
||||
);
|
||||
}
|
||||
else {
|
||||
return outerJoinLoadable.getPropertyColumnNames( determinePropertyIndex( fetch ) );
|
||||
}
|
||||
}
|
||||
|
||||
private int determinePropertyIndex(Fetch fetch) {
|
||||
return entityPersister.getEntityMetamodel().getPropertyIndex( fetch.getOwnerPropertyName() );
|
||||
}
|
||||
}
|
|
@ -23,33 +23,24 @@
|
|||
*/
|
||||
package org.hibernate.loader.plan.spi;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.LockMode;
|
||||
import org.hibernate.engine.FetchStrategy;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.loader.PropertyPath;
|
||||
import org.hibernate.loader.plan.internal.LoadPlanBuildingHelper;
|
||||
import org.hibernate.loader.plan.spi.build.LoadPlanBuildingContext;
|
||||
import org.hibernate.persister.collection.CollectionPersister;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.persister.walking.spi.AssociationAttributeDefinition;
|
||||
import org.hibernate.persister.walking.spi.CompositionDefinition;
|
||||
import org.hibernate.type.AssociationType;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class EntityIndexGraph extends AbstractPlanNode implements FetchableCollectionIndex, EntityReference {
|
||||
public class EntityIndexGraph extends AbstractFetchOwner implements FetchableCollectionIndex, EntityReference {
|
||||
private final CollectionReference collectionReference;
|
||||
private final CollectionPersister collectionPersister;
|
||||
private final AssociationType indexType;
|
||||
private final EntityPersister indexPersister;
|
||||
private final PropertyPath propertyPath;
|
||||
|
||||
private List<Fetch> fetches;
|
||||
private final FetchOwnerDelegate fetchOwnerDelegate;
|
||||
|
||||
private IdentifierDescription identifierDescription;
|
||||
|
||||
|
@ -63,28 +54,17 @@ public class EntityIndexGraph extends AbstractPlanNode implements FetchableColle
|
|||
this.indexType = (AssociationType) collectionPersister.getIndexType();
|
||||
this.indexPersister = (EntityPersister) this.indexType.getAssociatedJoinable( sessionFactory() );
|
||||
this.propertyPath = collectionPath.append( "<index>" ); // todo : do we want the <index> part?
|
||||
this.fetchOwnerDelegate = new EntityFetchOwnerDelegate( indexPersister );
|
||||
}
|
||||
|
||||
public EntityIndexGraph(EntityIndexGraph original, CopyContext copyContext) {
|
||||
super( original );
|
||||
super( original, copyContext );
|
||||
this.collectionReference = original.collectionReference;
|
||||
this.collectionPersister = original.collectionReference.getCollectionPersister();
|
||||
this.indexType = original.indexType;
|
||||
this.indexPersister = original.indexPersister;
|
||||
this.propertyPath = original.propertyPath;
|
||||
|
||||
copyContext.getReturnGraphVisitationStrategy().startingFetches( original );
|
||||
if ( fetches == null || fetches.size() == 0 ) {
|
||||
this.fetches = Collections.emptyList();
|
||||
}
|
||||
else {
|
||||
List<Fetch> fetchesCopy = new ArrayList<Fetch>();
|
||||
for ( Fetch fetch : fetches ) {
|
||||
fetchesCopy.add( fetch.makeCopy( copyContext, this ) );
|
||||
}
|
||||
this.fetches = fetchesCopy;
|
||||
}
|
||||
copyContext.getReturnGraphVisitationStrategy().finishingFetches( original );
|
||||
this.fetchOwnerDelegate = original.fetchOwnerDelegate;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -107,19 +87,6 @@ public class EntityIndexGraph extends AbstractPlanNode implements FetchableColle
|
|||
return identifierDescription;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addFetch(Fetch fetch) {
|
||||
if ( fetches == null ) {
|
||||
fetches = new ArrayList<Fetch>();
|
||||
}
|
||||
fetches.add( fetch );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Fetch[] getFetches() {
|
||||
return fetches == null ? NO_FETCHES : fetches.toArray( new Fetch[ fetches.size() ] );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void validateFetchPlan(FetchStrategy fetchStrategy) {
|
||||
}
|
||||
|
@ -134,39 +101,6 @@ public class EntityIndexGraph extends AbstractPlanNode implements FetchableColle
|
|||
return propertyPath;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CollectionFetch buildCollectionFetch(
|
||||
AssociationAttributeDefinition attributeDefinition,
|
||||
FetchStrategy fetchStrategy,
|
||||
LoadPlanBuildingContext loadPlanBuildingContext) {
|
||||
return LoadPlanBuildingHelper.buildStandardCollectionFetch(
|
||||
this,
|
||||
attributeDefinition,
|
||||
fetchStrategy,
|
||||
loadPlanBuildingContext
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityFetch buildEntityFetch(
|
||||
AssociationAttributeDefinition attributeDefinition,
|
||||
FetchStrategy fetchStrategy,
|
||||
LoadPlanBuildingContext loadPlanBuildingContext) {
|
||||
return LoadPlanBuildingHelper.buildStandardEntityFetch(
|
||||
this,
|
||||
attributeDefinition,
|
||||
fetchStrategy,
|
||||
loadPlanBuildingContext
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompositeFetch buildCompositeFetch(
|
||||
CompositionDefinition attributeDefinition,
|
||||
LoadPlanBuildingContext loadPlanBuildingContext) {
|
||||
return LoadPlanBuildingHelper.buildStandardCompositeFetch( this, attributeDefinition, loadPlanBuildingContext );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void injectIdentifierDescription(IdentifierDescription identifierDescription) {
|
||||
this.identifierDescription = identifierDescription;
|
||||
|
@ -176,4 +110,9 @@ public class EntityIndexGraph extends AbstractPlanNode implements FetchableColle
|
|||
public EntityIndexGraph makeCopy(CopyContext copyContext) {
|
||||
return new EntityIndexGraph( this, copyContext );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected FetchOwnerDelegate getFetchOwnerDelegate() {
|
||||
return fetchOwnerDelegate;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,12 +32,8 @@ import org.hibernate.engine.FetchStrategy;
|
|||
import org.hibernate.engine.spi.EntityKey;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.loader.PropertyPath;
|
||||
import org.hibernate.loader.plan.internal.LoadPlanBuildingHelper;
|
||||
import org.hibernate.loader.plan.spi.build.LoadPlanBuildingContext;
|
||||
import org.hibernate.loader.spi.ResultSetProcessingContext;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.persister.walking.spi.AssociationAttributeDefinition;
|
||||
import org.hibernate.persister.walking.spi.CompositionDefinition;
|
||||
|
||||
import static org.hibernate.loader.spi.ResultSetProcessingContext.IdentifierResolutionContext;
|
||||
|
||||
|
@ -50,24 +46,32 @@ public class EntityReturn extends AbstractFetchOwner implements Return, EntityRe
|
|||
|
||||
private final PropertyPath propertyPath = new PropertyPath(); // its a root
|
||||
|
||||
private final LockMode lockMode;
|
||||
|
||||
private final FetchOwnerDelegate fetchOwnerDelegate;
|
||||
|
||||
private IdentifierDescription identifierDescription;
|
||||
|
||||
public EntityReturn(
|
||||
SessionFactoryImplementor sessionFactory,
|
||||
LockMode lockMode,
|
||||
String entityName) {
|
||||
super( sessionFactory, lockMode );
|
||||
|
||||
super( sessionFactory );
|
||||
this.persister = sessionFactory.getEntityPersister( entityName );
|
||||
this.lockMode = lockMode;
|
||||
this.fetchOwnerDelegate = new EntityFetchOwnerDelegate( persister );
|
||||
}
|
||||
|
||||
protected EntityReturn(EntityReturn original, CopyContext copyContext) {
|
||||
super( original, copyContext );
|
||||
this.persister = original.persister;
|
||||
this.lockMode = original.lockMode;
|
||||
this.fetchOwnerDelegate = original.fetchOwnerDelegate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LockMode getLockMode() {
|
||||
return super.getLockMode();
|
||||
return lockMode;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -99,42 +103,9 @@ public class EntityReturn extends AbstractFetchOwner implements Return, EntityRe
|
|||
return propertyPath;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CollectionFetch buildCollectionFetch(
|
||||
AssociationAttributeDefinition attributeDefinition,
|
||||
FetchStrategy fetchStrategy,
|
||||
LoadPlanBuildingContext loadPlanBuildingContext) {
|
||||
return LoadPlanBuildingHelper.buildStandardCollectionFetch(
|
||||
this,
|
||||
attributeDefinition,
|
||||
fetchStrategy,
|
||||
loadPlanBuildingContext
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityFetch buildEntityFetch(
|
||||
AssociationAttributeDefinition attributeDefinition,
|
||||
FetchStrategy fetchStrategy,
|
||||
LoadPlanBuildingContext loadPlanBuildingContext) {
|
||||
return LoadPlanBuildingHelper.buildStandardEntityFetch(
|
||||
this,
|
||||
attributeDefinition,
|
||||
fetchStrategy,
|
||||
loadPlanBuildingContext
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompositeFetch buildCompositeFetch(
|
||||
CompositionDefinition attributeDefinition,
|
||||
LoadPlanBuildingContext loadPlanBuildingContext) {
|
||||
return LoadPlanBuildingHelper.buildStandardCompositeFetch( this, attributeDefinition, loadPlanBuildingContext );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hydrate(ResultSet resultSet, ResultSetProcessingContext context) throws SQLException {
|
||||
EntityKey entityKey = context.getDictatedRootEntityKey();
|
||||
EntityKey entityKey = getEntityKeyFromContext( context );
|
||||
if ( entityKey != null ) {
|
||||
context.getIdentifierResolutionContext( this ).registerEntityKey( entityKey );
|
||||
return;
|
||||
|
@ -147,6 +118,19 @@ public class EntityReturn extends AbstractFetchOwner implements Return, EntityRe
|
|||
}
|
||||
}
|
||||
|
||||
private EntityKey getEntityKeyFromContext(ResultSetProcessingContext context) {
|
||||
if ( context.getDictatedRootEntityKey() != null ) {
|
||||
return context.getDictatedRootEntityKey();
|
||||
}
|
||||
else if ( context.getQueryParameters().getOptionalId() != null ) {
|
||||
return context.getSession().generateEntityKey(
|
||||
context.getQueryParameters().getOptionalId(),
|
||||
getEntityPersister()
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resolve(ResultSet resultSet, ResultSetProcessingContext context) throws SQLException {
|
||||
final IdentifierResolutionContext identifierResolutionContext = context.getIdentifierResolutionContext( this );
|
||||
|
@ -194,4 +178,9 @@ public class EntityReturn extends AbstractFetchOwner implements Return, EntityRe
|
|||
public EntityReturn makeCopy(CopyContext copyContext) {
|
||||
return new EntityReturn( this, copyContext );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected FetchOwnerDelegate getFetchOwnerDelegate() {
|
||||
return fetchOwnerDelegate;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -52,6 +52,10 @@ public interface Fetch extends CopyableFetch {
|
|||
*/
|
||||
public String getOwnerPropertyName();
|
||||
|
||||
public boolean isNullable();
|
||||
|
||||
public String[] getColumnNames();
|
||||
|
||||
public FetchStrategy getFetchStrategy();
|
||||
|
||||
/**
|
||||
|
|
|
@ -29,6 +29,7 @@ import org.hibernate.loader.plan.spi.build.LoadPlanBuildingContext;
|
|||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.persister.walking.spi.AssociationAttributeDefinition;
|
||||
import org.hibernate.persister.walking.spi.CompositionDefinition;
|
||||
import org.hibernate.type.Type;
|
||||
|
||||
/**
|
||||
* Contract for owners of fetches. Any non-scalar return could be a fetch owner.
|
||||
|
@ -56,6 +57,12 @@ public interface FetchOwner {
|
|||
*/
|
||||
public Fetch[] getFetches();
|
||||
|
||||
public Type getType(Fetch fetch);
|
||||
|
||||
public boolean isNullable(Fetch fetch);
|
||||
|
||||
public String[] getColumnNames(Fetch fetch);
|
||||
|
||||
/**
|
||||
* Is the asserted plan valid from this owner to a fetch?
|
||||
*
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2013, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.loader.plan.spi;
|
||||
|
||||
import org.hibernate.type.Type;
|
||||
|
||||
/**
|
||||
* @author Gail Badner
|
||||
*/
|
||||
public interface FetchOwnerDelegate {
|
||||
|
||||
public boolean isNullable(Fetch fetch);
|
||||
|
||||
public Type getType(Fetch fetch);
|
||||
|
||||
public String[] getColumnNames(Fetch fetch);
|
||||
}
|
|
@ -23,10 +23,14 @@
|
|||
*/
|
||||
package org.hibernate.loader.plan.spi;
|
||||
|
||||
import org.hibernate.persister.collection.CollectionPersister;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface FetchableCollectionElement extends FetchOwner, CopyableReturn {
|
||||
@Override
|
||||
public FetchableCollectionElement makeCopy(CopyContext copyContext);
|
||||
|
||||
public CollectionReference getCollectionReference();
|
||||
}
|
||||
|
|
|
@ -37,6 +37,7 @@ import org.jboss.logging.MDC;
|
|||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.LockMode;
|
||||
import org.hibernate.cfg.NotYetImplementedException;
|
||||
import org.hibernate.engine.FetchStrategy;
|
||||
import org.hibernate.engine.FetchTiming;
|
||||
import org.hibernate.engine.spi.EntityKey;
|
||||
|
@ -44,19 +45,24 @@ import org.hibernate.engine.spi.SessionFactoryImplementor;
|
|||
import org.hibernate.internal.util.StringHelper;
|
||||
import org.hibernate.loader.PropertyPath;
|
||||
import org.hibernate.loader.plan.internal.LoadPlanBuildingHelper;
|
||||
import org.hibernate.loader.plan.spi.AbstractSingularAttributeFetch;
|
||||
import org.hibernate.loader.plan.spi.CollectionFetch;
|
||||
import org.hibernate.loader.plan.spi.CollectionReference;
|
||||
import org.hibernate.loader.plan.spi.CollectionReturn;
|
||||
import org.hibernate.loader.plan.spi.CompositeElementGraph;
|
||||
import org.hibernate.loader.plan.spi.CompositeFetch;
|
||||
import org.hibernate.loader.plan.spi.CompositeFetchOwnerDelegate;
|
||||
import org.hibernate.loader.plan.spi.EntityFetch;
|
||||
import org.hibernate.loader.plan.spi.EntityReference;
|
||||
import org.hibernate.loader.plan.spi.EntityReturn;
|
||||
import org.hibernate.loader.plan.spi.Fetch;
|
||||
import org.hibernate.loader.plan.spi.FetchOwner;
|
||||
import org.hibernate.loader.plan.spi.FetchOwnerDelegate;
|
||||
import org.hibernate.loader.plan.spi.IdentifierDescription;
|
||||
import org.hibernate.loader.plan.spi.Return;
|
||||
import org.hibernate.loader.spi.ResultSetProcessingContext;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.persister.entity.Loadable;
|
||||
import org.hibernate.persister.spi.HydratedCompoundValueHandler;
|
||||
import org.hibernate.persister.walking.spi.AssociationAttributeDefinition;
|
||||
import org.hibernate.persister.walking.spi.AttributeDefinition;
|
||||
|
@ -64,9 +70,11 @@ import org.hibernate.persister.walking.spi.CollectionDefinition;
|
|||
import org.hibernate.persister.walking.spi.CollectionElementDefinition;
|
||||
import org.hibernate.persister.walking.spi.CollectionIndexDefinition;
|
||||
import org.hibernate.persister.walking.spi.CompositionDefinition;
|
||||
import org.hibernate.persister.walking.spi.CompositionElementDefinition;
|
||||
import org.hibernate.persister.walking.spi.EntityDefinition;
|
||||
import org.hibernate.persister.walking.spi.EntityIdentifierDefinition;
|
||||
import org.hibernate.persister.walking.spi.WalkingException;
|
||||
import org.hibernate.type.CompositeType;
|
||||
import org.hibernate.type.Type;
|
||||
|
||||
import static org.hibernate.loader.spi.ResultSetProcessingContext.IdentifierResolutionContext;
|
||||
|
@ -190,7 +198,12 @@ public abstract class AbstractLoadPlanBuilderStrategy implements LoadPlanBuilder
|
|||
|
||||
final FetchOwner identifierAttributeCollector;
|
||||
if ( entityIdentifierDefinition.isEncapsulated() ) {
|
||||
identifierAttributeCollector = new EncapsulatedIdentifierAttributeCollector( entityReference );
|
||||
if ( entityIdentifierDefinition.getEntityDefinition().getEntityPersister().getIdentifierType().isComponentType() ) {
|
||||
identifierAttributeCollector = new EncapsulatedCompositeIdentifierAttributeCollector( entityReference );
|
||||
}
|
||||
else {
|
||||
identifierAttributeCollector = new EncapsulatedIdentifierAttributeCollector( entityReference );
|
||||
}
|
||||
}
|
||||
else {
|
||||
identifierAttributeCollector = new NonEncapsulatedIdentifierAttributeCollector( entityReference );
|
||||
|
@ -305,6 +318,35 @@ public abstract class AbstractLoadPlanBuilderStrategy implements LoadPlanBuilder
|
|||
// - the element graph pushed while starting would be popped in finishing/Entity/finishingComposite
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startingCompositeElement(CompositionElementDefinition compositeElementDefinition) {
|
||||
System.out.println(
|
||||
String.format(
|
||||
"%s Starting composite collection element for (%s)",
|
||||
StringHelper.repeat( ">>", fetchOwnerStack.size() ),
|
||||
compositeElementDefinition.getCollectionDefinition().getCollectionPersister().getRole()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void finishingCompositeElement(CompositionElementDefinition compositeElementDefinition) {
|
||||
// pop the current fetch owner, and make sure what we just popped represents this composition
|
||||
final FetchOwner poppedFetchOwner = popFromStack();
|
||||
|
||||
if ( ! CompositeElementGraph.class.isInstance( poppedFetchOwner ) ) {
|
||||
throw new WalkingException( "Mismatched FetchOwner from stack on pop" );
|
||||
}
|
||||
|
||||
// NOTE : not much else we can really check here atm since on the walking spi side we do not have path
|
||||
|
||||
log.tracef(
|
||||
"%s Finished composite element for : %s",
|
||||
StringHelper.repeat( "<<", fetchOwnerStack.size() ),
|
||||
compositeElementDefinition.getCollectionDefinition().getCollectionPersister().getRole()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void finishingCollection(CollectionDefinition collectionDefinition) {
|
||||
// pop the current fetch owner, and make sure what we just popped represents this collection
|
||||
|
@ -413,7 +455,7 @@ public abstract class AbstractLoadPlanBuilderStrategy implements LoadPlanBuilder
|
|||
);
|
||||
}
|
||||
|
||||
if ( FetchOwner.class.isInstance( associationFetch ) ) {
|
||||
if ( FetchOwner.class.isInstance( associationFetch) ) {
|
||||
pushToStack( (FetchOwner) associationFetch );
|
||||
}
|
||||
|
||||
|
@ -487,15 +529,13 @@ public abstract class AbstractLoadPlanBuilderStrategy implements LoadPlanBuilder
|
|||
implements FetchOwner, EntityReference, FetchStackAware {
|
||||
|
||||
protected final EntityReference entityReference;
|
||||
private final PropertyPath propertyPath;
|
||||
|
||||
protected final List<EntityFetch> identifierFetches = new ArrayList<EntityFetch>();
|
||||
protected final Map<EntityFetch,HydratedCompoundValueHandler> fetchToHydratedStateExtractorMap
|
||||
= new HashMap<EntityFetch, HydratedCompoundValueHandler>();
|
||||
protected final List<AbstractSingularAttributeFetch> identifierFetches = new ArrayList<AbstractSingularAttributeFetch>();
|
||||
protected final Map<AbstractSingularAttributeFetch,HydratedCompoundValueHandler> fetchToHydratedStateExtractorMap
|
||||
= new HashMap<AbstractSingularAttributeFetch, HydratedCompoundValueHandler>();
|
||||
|
||||
public AbstractIdentifierAttributeCollector(EntityReference entityReference) {
|
||||
this.entityReference = entityReference;
|
||||
this.propertyPath = ( (FetchOwner) entityReference ).getPropertyPath().append( "<id>" );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -513,6 +553,11 @@ public abstract class AbstractLoadPlanBuilderStrategy implements LoadPlanBuilder
|
|||
return entityReference.getEntityPersister();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNullable(Fetch fetch) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IdentifierDescription getIdentifierDescription() {
|
||||
return entityReference.getIdentifierDescription();
|
||||
|
@ -533,7 +578,7 @@ public abstract class AbstractLoadPlanBuilderStrategy implements LoadPlanBuilder
|
|||
LoadPlanBuildingContext loadPlanBuildingContext) {
|
||||
// we have a key-many-to-one
|
||||
//
|
||||
// IMPL NOTE: we pass ourselves as the FetchOwner which will route the fetch back throw our #addFetch
|
||||
// IMPL NOTE: we pass ourselves as the FetchOwner which will route the fetch back through our #addFetch
|
||||
// impl. We collect them there and later build the IdentifierDescription
|
||||
final EntityFetch fetch = LoadPlanBuildingHelper.buildStandardEntityFetch(
|
||||
this,
|
||||
|
@ -551,7 +596,7 @@ public abstract class AbstractLoadPlanBuilderStrategy implements LoadPlanBuilder
|
|||
CompositionDefinition attributeDefinition, LoadPlanBuildingContext loadPlanBuildingContext) {
|
||||
// nested composition. Unusual, but not disallowed.
|
||||
//
|
||||
// IMPL NOTE: we pass ourselves as the FetchOwner which will route the fetch back throw our #addFetch
|
||||
// IMPL NOTE: we pass ourselves as the FetchOwner which will route the fetch back through our #addFetch
|
||||
// impl. We collect them there and later build the IdentifierDescription
|
||||
return LoadPlanBuildingHelper.buildStandardCompositeFetch(
|
||||
this,
|
||||
|
@ -570,7 +615,7 @@ public abstract class AbstractLoadPlanBuilderStrategy implements LoadPlanBuilder
|
|||
|
||||
@Override
|
||||
public void addFetch(Fetch fetch) {
|
||||
identifierFetches.add( (EntityFetch) fetch );
|
||||
identifierFetches.add( (AbstractSingularAttributeFetch) fetch );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -588,11 +633,6 @@ public abstract class AbstractLoadPlanBuilderStrategy implements LoadPlanBuilder
|
|||
return ( (FetchOwner) entityReference ).retrieveFetchSourcePersister();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PropertyPath getPropertyPath() {
|
||||
return propertyPath;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void injectIdentifierDescription(IdentifierDescription identifierDescription) {
|
||||
throw new WalkingException(
|
||||
|
@ -601,44 +641,144 @@ public abstract class AbstractLoadPlanBuilderStrategy implements LoadPlanBuilder
|
|||
}
|
||||
}
|
||||
|
||||
protected static class EncapsulatedIdentifierAttributeCollector extends AbstractIdentifierAttributeCollector {
|
||||
public EncapsulatedIdentifierAttributeCollector(EntityReference entityReference) {
|
||||
super( entityReference );
|
||||
}
|
||||
protected static abstract class AbstractCompositeIdentifierAttributeCollector extends AbstractIdentifierAttributeCollector {
|
||||
|
||||
@Override
|
||||
protected IdentifierDescription buildIdentifierDescription() {
|
||||
return new IdentifierDescriptionImpl(
|
||||
entityReference,
|
||||
identifierFetches.toArray( new EntityFetch[ identifierFetches.size() ] ),
|
||||
null
|
||||
);
|
||||
public AbstractCompositeIdentifierAttributeCollector(EntityReference entityReference) {
|
||||
super( entityReference );
|
||||
}
|
||||
}
|
||||
|
||||
protected static class NonEncapsulatedIdentifierAttributeCollector extends AbstractIdentifierAttributeCollector {
|
||||
public NonEncapsulatedIdentifierAttributeCollector(EntityReference entityReference) {
|
||||
protected static class EncapsulatedIdentifierAttributeCollector extends AbstractIdentifierAttributeCollector {
|
||||
private final PropertyPath propertyPath;
|
||||
|
||||
public EncapsulatedIdentifierAttributeCollector(EntityReference entityReference) {
|
||||
super( entityReference );
|
||||
this.propertyPath = ( (FetchOwner) entityReference ).getPropertyPath();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IdentifierDescription buildIdentifierDescription() {
|
||||
return new IdentifierDescriptionImpl(
|
||||
entityReference,
|
||||
identifierFetches.toArray( new EntityFetch[ identifierFetches.size() ] ),
|
||||
identifierFetches.toArray( new AbstractSingularAttributeFetch[ identifierFetches.size() ] ),
|
||||
null
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getType(Fetch fetch) {
|
||||
return null; //To change body of implemented methods use File | Settings | File Templates.
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getColumnNames(Fetch fetch) {
|
||||
return ( (Loadable) entityReference.getEntityPersister() ).getIdentifierColumnNames();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PropertyPath getPropertyPath() {
|
||||
return propertyPath;
|
||||
}
|
||||
}
|
||||
|
||||
protected static class EncapsulatedCompositeIdentifierAttributeCollector extends AbstractCompositeIdentifierAttributeCollector {
|
||||
private final PropertyPath propertyPath;
|
||||
|
||||
public EncapsulatedCompositeIdentifierAttributeCollector(EntityReference entityReference) {
|
||||
super( entityReference );
|
||||
this.propertyPath = ( (FetchOwner) entityReference ).getPropertyPath();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IdentifierDescription buildIdentifierDescription() {
|
||||
return new IdentifierDescriptionImpl(
|
||||
entityReference,
|
||||
identifierFetches.toArray( new AbstractSingularAttributeFetch[ identifierFetches.size() ] ),
|
||||
null
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PropertyPath getPropertyPath() {
|
||||
return propertyPath;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getType(Fetch fetch) {
|
||||
if ( !fetch.getOwnerPropertyName().equals( entityReference.getEntityPersister().getIdentifierPropertyName() ) ) {
|
||||
throw new IllegalArgumentException(
|
||||
String.format(
|
||||
"Fetch owner property name [%s] is not the same as the identifier property name [%s].",
|
||||
fetch.getOwnerPropertyName(),
|
||||
entityReference.getEntityPersister().getIdentifierPropertyName()
|
||||
)
|
||||
);
|
||||
}
|
||||
return entityReference.getEntityPersister().getIdentifierType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getColumnNames(Fetch fetch) {
|
||||
return ( (Loadable) entityReference.getEntityPersister() ).getIdentifierColumnNames();
|
||||
}
|
||||
}
|
||||
|
||||
protected static class NonEncapsulatedIdentifierAttributeCollector extends AbstractCompositeIdentifierAttributeCollector {
|
||||
private final PropertyPath propertyPath;
|
||||
private final FetchOwnerDelegate fetchOwnerDelegate;
|
||||
|
||||
public NonEncapsulatedIdentifierAttributeCollector(EntityReference entityReference) {
|
||||
super( entityReference );
|
||||
this.propertyPath = ( (FetchOwner) entityReference ).getPropertyPath().append( "<id>" );
|
||||
this.fetchOwnerDelegate = new CompositeFetchOwnerDelegate(
|
||||
entityReference.getEntityPersister().getFactory(),
|
||||
(CompositeType) entityReference.getEntityPersister().getIdentifierType(),
|
||||
( (Loadable) entityReference.getEntityPersister() ).getIdentifierColumnNames()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IdentifierDescription buildIdentifierDescription() {
|
||||
return new IdentifierDescriptionImpl(
|
||||
entityReference,
|
||||
identifierFetches.toArray( new AbstractSingularAttributeFetch[ identifierFetches.size() ] ),
|
||||
fetchToHydratedStateExtractorMap
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PropertyPath getPropertyPath() {
|
||||
return propertyPath;
|
||||
}
|
||||
|
||||
|
||||
public Type getType(Fetch fetch) {
|
||||
if ( !fetch.getOwnerPropertyName().equals( entityReference.getEntityPersister().getIdentifierPropertyName() ) ) {
|
||||
throw new IllegalArgumentException(
|
||||
String.format(
|
||||
"Fetch owner property name [%s] is not the same as the identifier property name [%s].",
|
||||
fetch.getOwnerPropertyName(),
|
||||
entityReference.getEntityPersister().getIdentifierPropertyName()
|
||||
)
|
||||
);
|
||||
}
|
||||
return fetchOwnerDelegate.getType( fetch );
|
||||
}
|
||||
|
||||
public String[] getColumnNames(Fetch fetch) {
|
||||
return fetchOwnerDelegate.getColumnNames( fetch );
|
||||
}
|
||||
}
|
||||
|
||||
private static class IdentifierDescriptionImpl implements IdentifierDescription {
|
||||
private final EntityReference entityReference;
|
||||
private final EntityFetch[] identifierFetches;
|
||||
private final Map<EntityFetch,HydratedCompoundValueHandler> fetchToHydratedStateExtractorMap;
|
||||
private final AbstractSingularAttributeFetch[] identifierFetches;
|
||||
private final Map<AbstractSingularAttributeFetch,HydratedCompoundValueHandler> fetchToHydratedStateExtractorMap;
|
||||
|
||||
private IdentifierDescriptionImpl(
|
||||
EntityReference entityReference, EntityFetch[] identifierFetches,
|
||||
Map<EntityFetch, HydratedCompoundValueHandler> fetchToHydratedStateExtractorMap) {
|
||||
EntityReference entityReference,
|
||||
AbstractSingularAttributeFetch[] identifierFetches,
|
||||
Map<AbstractSingularAttributeFetch, HydratedCompoundValueHandler> fetchToHydratedStateExtractorMap) {
|
||||
this.entityReference = entityReference;
|
||||
this.identifierFetches = identifierFetches;
|
||||
this.fetchToHydratedStateExtractorMap = fetchToHydratedStateExtractorMap;
|
||||
|
@ -656,24 +796,28 @@ public abstract class AbstractLoadPlanBuilderStrategy implements LoadPlanBuilder
|
|||
final Object ownerIdentifierHydratedState = ownerIdentifierResolutionContext.getHydratedForm();
|
||||
|
||||
if ( ownerIdentifierHydratedState != null ) {
|
||||
for ( EntityFetch fetch : identifierFetches ) {
|
||||
final IdentifierResolutionContext identifierResolutionContext =
|
||||
context.getIdentifierResolutionContext( fetch );
|
||||
// if the identifier was already hydrated, nothing to do
|
||||
if ( identifierResolutionContext.getHydratedForm() != null ) {
|
||||
continue;
|
||||
}
|
||||
for ( AbstractSingularAttributeFetch fetch : identifierFetches ) {
|
||||
if ( fetch instanceof EntityFetch ) {
|
||||
final IdentifierResolutionContext identifierResolutionContext =
|
||||
context.getIdentifierResolutionContext( (EntityFetch) fetch );
|
||||
// if the identifier was already hydrated, nothing to do
|
||||
if ( identifierResolutionContext.getHydratedForm() != null ) {
|
||||
continue;
|
||||
}
|
||||
// try to extract the sub-hydrated value from the owners tuple array
|
||||
if ( fetchToHydratedStateExtractorMap != null && ownerIdentifierHydratedState != null ) {
|
||||
Serializable extracted = (Serializable) fetchToHydratedStateExtractorMap.get( fetch )
|
||||
.extract( ownerIdentifierHydratedState );
|
||||
identifierResolutionContext.registerHydratedForm( extracted );
|
||||
continue;
|
||||
}
|
||||
|
||||
// try to extract the sub-hydrated value from the owners tuple array
|
||||
if ( fetchToHydratedStateExtractorMap != null && ownerIdentifierHydratedState != null ) {
|
||||
Serializable extracted = (Serializable) fetchToHydratedStateExtractorMap.get( fetch )
|
||||
.extract( ownerIdentifierHydratedState );
|
||||
identifierResolutionContext.registerHydratedForm( extracted );
|
||||
continue;
|
||||
// if we can't, then read from result set
|
||||
fetch.hydrate( resultSet, context );
|
||||
}
|
||||
else {
|
||||
throw new NotYetImplementedException( "Cannot hydrate identifier Fetch that is not an EntityFetch" );
|
||||
}
|
||||
|
||||
// if we can't, then read from result set
|
||||
fetch.hydrate( resultSet, context );
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -689,15 +833,8 @@ public abstract class AbstractLoadPlanBuilderStrategy implements LoadPlanBuilder
|
|||
|
||||
@Override
|
||||
public EntityKey resolve(ResultSet resultSet, ResultSetProcessingContext context) throws SQLException {
|
||||
for ( EntityFetch fetch : identifierFetches ) {
|
||||
final IdentifierResolutionContext identifierResolutionContext =
|
||||
context.getIdentifierResolutionContext( fetch );
|
||||
if ( identifierResolutionContext.getEntityKey() != null ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
EntityKey fetchKey = fetch.resolveInIdentifier( resultSet, context );
|
||||
identifierResolutionContext.registerEntityKey( fetchKey );
|
||||
for ( AbstractSingularAttributeFetch fetch : identifierFetches ) {
|
||||
resolveIdentifierFetch( resultSet, context, fetch );
|
||||
}
|
||||
|
||||
final IdentifierResolutionContext ownerIdentifierResolutionContext =
|
||||
|
@ -710,6 +847,28 @@ public abstract class AbstractLoadPlanBuilderStrategy implements LoadPlanBuilder
|
|||
}
|
||||
}
|
||||
|
||||
private static void resolveIdentifierFetch(
|
||||
ResultSet resultSet,
|
||||
ResultSetProcessingContext context,
|
||||
AbstractSingularAttributeFetch fetch) throws SQLException {
|
||||
if ( fetch instanceof EntityFetch ) {
|
||||
EntityFetch entityFetch = (EntityFetch) fetch;
|
||||
final IdentifierResolutionContext identifierResolutionContext =
|
||||
context.getIdentifierResolutionContext( entityFetch );
|
||||
if ( identifierResolutionContext.getEntityKey() != null ) {
|
||||
return;
|
||||
}
|
||||
|
||||
EntityKey fetchKey = entityFetch.resolveInIdentifier( resultSet, context );
|
||||
identifierResolutionContext.registerEntityKey( fetchKey );
|
||||
}
|
||||
else if ( fetch instanceof CompositeFetch ) {
|
||||
for ( Fetch subFetch : fetch.getFetches() ) {
|
||||
resolveIdentifierFetch( resultSet, context, (AbstractSingularAttributeFetch) subFetch );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class MDCStack {
|
||||
private ArrayDeque<PropertyPath> pathStack = new ArrayDeque<PropertyPath>();
|
||||
|
||||
|
|
|
@ -45,7 +45,8 @@ public class ManyToOne extends ToOne {
|
|||
|
||||
public Type getType() throws MappingException {
|
||||
return getMappings().getTypeResolver().getTypeFactory().manyToOne(
|
||||
getReferencedEntityName(),
|
||||
getReferencedEntityName(),
|
||||
referenceToPrimaryKey,
|
||||
getReferencedPropertyName(),
|
||||
isLazy(),
|
||||
isUnwrapProxy(),
|
||||
|
|
|
@ -46,7 +46,8 @@ public class OneToMany implements Value {
|
|||
|
||||
private EntityType getEntityType() {
|
||||
return mappings.getTypeResolver().getTypeFactory().manyToOne(
|
||||
getReferencedEntityName(),
|
||||
getReferencedEntityName(),
|
||||
true,
|
||||
null,
|
||||
false,
|
||||
false,
|
||||
|
|
|
@ -69,7 +69,8 @@ public class OneToOne extends ToOne {
|
|||
if ( getColumnIterator().hasNext() ) {
|
||||
return getMappings().getTypeResolver().getTypeFactory().specialOneToOne(
|
||||
getReferencedEntityName(),
|
||||
foreignKeyType,
|
||||
foreignKeyType,
|
||||
referenceToPrimaryKey,
|
||||
referencedPropertyName,
|
||||
isLazy(),
|
||||
isUnwrapProxy(),
|
||||
|
@ -80,7 +81,8 @@ public class OneToOne extends ToOne {
|
|||
else {
|
||||
return getMappings().getTypeResolver().getTypeFactory().oneToOne(
|
||||
getReferencedEntityName(),
|
||||
foreignKeyType,
|
||||
foreignKeyType,
|
||||
referenceToPrimaryKey,
|
||||
referencedPropertyName,
|
||||
isLazy(),
|
||||
isUnwrapProxy(),
|
||||
|
|
|
@ -40,6 +40,7 @@ public abstract class ToOne extends SimpleValue implements Fetchable {
|
|||
private String referencedEntityName;
|
||||
private boolean lazy = true;
|
||||
protected boolean unwrapProxy;
|
||||
protected boolean referenceToPrimaryKey = true;
|
||||
|
||||
protected ToOne(Mappings mappings, Table table) {
|
||||
super( mappings, table );
|
||||
|
@ -110,5 +111,13 @@ public abstract class ToOne extends SimpleValue implements Fetchable {
|
|||
public void setUnwrapProxy(boolean unwrapProxy) {
|
||||
this.unwrapProxy = unwrapProxy;
|
||||
}
|
||||
|
||||
public boolean isReferenceToPrimaryKey() {
|
||||
return referenceToPrimaryKey;
|
||||
}
|
||||
|
||||
public void setReferenceToPrimaryKey(boolean referenceToPrimaryKey) {
|
||||
this.referenceToPrimaryKey = referenceToPrimaryKey;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -35,6 +35,7 @@ import org.hibernate.SessionFactory;
|
|||
import org.hibernate.boot.registry.StandardServiceRegistry;
|
||||
import org.hibernate.cache.spi.access.AccessType;
|
||||
import org.hibernate.cfg.NamingStrategy;
|
||||
import org.hibernate.cfg.annotations.NamedEntityGraphDefinition;
|
||||
import org.hibernate.engine.ResultSetMappingDefinition;
|
||||
import org.hibernate.engine.spi.FilterDefinition;
|
||||
import org.hibernate.engine.spi.NamedQueryDefinition;
|
||||
|
@ -115,6 +116,8 @@ public interface Metadata {
|
|||
|
||||
public Iterable<NamedQueryDefinition> getNamedQueryDefinitions();
|
||||
|
||||
public Map<String, NamedEntityGraphDefinition> getNamedEntityGraphMap();
|
||||
|
||||
public Iterable<NamedSQLQueryDefinition> getNamedNativeQueryDefinitions();
|
||||
|
||||
public Map<String, ResultSetMappingDefinition> getResultSetMappingDefinitions();
|
||||
|
|
|
@ -47,6 +47,7 @@ import org.hibernate.boot.spi.CacheRegionDefinition;
|
|||
import org.hibernate.cache.spi.access.AccessType;
|
||||
import org.hibernate.cfg.NamingStrategy;
|
||||
import org.hibernate.cfg.ObjectNameNormalizer;
|
||||
import org.hibernate.cfg.annotations.NamedEntityGraphDefinition;
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.engine.ResultSetMappingDefinition;
|
||||
import org.hibernate.engine.jdbc.spi.JdbcServices;
|
||||
|
@ -134,7 +135,7 @@ public class MetadataImpl implements MetadataImplementor, Serializable {
|
|||
private final MappingDefaults mappingDefaults;
|
||||
private final ObjectNameNormalizer nameNormalizer;
|
||||
|
||||
private Map<String, TypeDefinition> typeDefinitionMap = new HashMap<String, TypeDefinition>();
|
||||
private final Map<String, TypeDefinition> typeDefinitionMap = new HashMap<String, TypeDefinition>();
|
||||
private Map<String, FilterDefinition> filterDefinitionMap = new HashMap<String, FilterDefinition>();
|
||||
|
||||
private Map<String, EntityBinding> entityBindingMap = new HashMap<String, EntityBinding>();
|
||||
|
@ -145,6 +146,7 @@ public class MetadataImpl implements MetadataImplementor, Serializable {
|
|||
private Map<String, NamedQueryDefinition> namedQueryDefs = new HashMap<String, NamedQueryDefinition>();
|
||||
private Map<String, NamedSQLQueryDefinition> namedNativeQueryDefs = new HashMap<String, NamedSQLQueryDefinition>();
|
||||
private Map<String, ResultSetMappingDefinition> resultSetMappings = new HashMap<String, ResultSetMappingDefinition>();
|
||||
private final Map<String, NamedEntityGraphDefinition> namedEntityGraphMap = new HashMap<String, NamedEntityGraphDefinition>( );
|
||||
|
||||
private boolean globallyQuotedIdentifiers = false;
|
||||
|
||||
|
@ -375,6 +377,19 @@ public class MetadataImpl implements MetadataImplementor, Serializable {
|
|||
return typeDefinitionMap.get( registrationKey );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addNamedEntityGraph(NamedEntityGraphDefinition definition) {
|
||||
final String name = definition.getRegisteredName();
|
||||
final NamedEntityGraphDefinition previous = namedEntityGraphMap.put( name, definition );
|
||||
if ( previous != null ) {
|
||||
throw new DuplicateMappingException( "NamedEntityGraph", name );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, NamedEntityGraphDefinition> getNamedEntityGraphMap() {
|
||||
return namedEntityGraphMap;
|
||||
}
|
||||
|
||||
// filter definitions ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
package org.hibernate.metamodel.spi;
|
||||
|
||||
import org.hibernate.cfg.ObjectNameNormalizer;
|
||||
import org.hibernate.cfg.annotations.NamedEntityGraphDefinition;
|
||||
import org.hibernate.engine.ResultSetMappingDefinition;
|
||||
import org.hibernate.engine.spi.FilterDefinition;
|
||||
import org.hibernate.engine.spi.Mapping;
|
||||
|
@ -69,6 +70,8 @@ public interface MetadataImplementor extends Metadata, BindingContext, Mapping {
|
|||
|
||||
public void addNamedNativeQuery(NamedSQLQueryDefinition def);
|
||||
|
||||
public void addNamedEntityGraph(NamedEntityGraphDefinition def);
|
||||
|
||||
public void addNamedQuery(NamedQueryDefinition def);
|
||||
|
||||
public void addResultSetMapping(ResultSetMappingDefinition resultSetMappingDefinition);
|
||||
|
|
|
@ -101,10 +101,14 @@ import org.hibernate.persister.entity.EntityPersister;
|
|||
import org.hibernate.persister.entity.Loadable;
|
||||
import org.hibernate.persister.entity.PropertyMapping;
|
||||
import org.hibernate.persister.entity.Queryable;
|
||||
import org.hibernate.persister.walking.internal.CompositionSingularSubAttributesHelper;
|
||||
import org.hibernate.persister.walking.spi.AttributeDefinition;
|
||||
import org.hibernate.persister.walking.spi.AttributeSource;
|
||||
import org.hibernate.persister.walking.spi.CollectionDefinition;
|
||||
import org.hibernate.persister.walking.spi.CollectionElementDefinition;
|
||||
import org.hibernate.persister.walking.spi.CollectionIndexDefinition;
|
||||
import org.hibernate.persister.walking.spi.CompositionDefinition;
|
||||
import org.hibernate.persister.walking.spi.CompositionElementDefinition;
|
||||
import org.hibernate.persister.walking.spi.EntityDefinition;
|
||||
import org.hibernate.pretty.MessageHelper;
|
||||
import org.hibernate.sql.Alias;
|
||||
|
@ -2342,7 +2346,6 @@ public abstract class AbstractCollectionPersister
|
|||
|
||||
public abstract FilterAliasGenerator getFilterAliasGenerator(final String rootAlias);
|
||||
|
||||
|
||||
// ColectionDefinition impl ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
@Override
|
||||
|
@ -2408,12 +2411,42 @@ public abstract class AbstractCollectionPersister
|
|||
}
|
||||
|
||||
@Override
|
||||
public CompositionDefinition toCompositeDefinition() {
|
||||
public CompositionElementDefinition toCompositeElementDefinition() {
|
||||
final String propertyName = role.substring( entityName.length() + 1 );
|
||||
final int propertyIndex = ownerPersister.getEntityMetamodel().getPropertyIndex( propertyName );
|
||||
|
||||
if ( ! getType().isComponentType() ) {
|
||||
throw new IllegalStateException( "Cannot treat entity collection element type as composite" );
|
||||
}
|
||||
// todo : implement
|
||||
throw new NotYetImplementedException();
|
||||
|
||||
return new CompositionElementDefinition() {
|
||||
@Override
|
||||
public String getName() {
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getType() {
|
||||
return getElementType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AttributeSource getSource() {
|
||||
// TODO: what if this is a collection w/in an encapsulated composition attribute?
|
||||
// should return the encapsulated composition attribute instead???
|
||||
return getOwnerEntityPersister();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<AttributeDefinition> getAttributes() {
|
||||
return CompositionSingularSubAttributesHelper.getCompositionElementSubAttributes( this );
|
||||
}
|
||||
|
||||
@Override
|
||||
public CollectionDefinition getCollectionDefinition() {
|
||||
return AbstractCollectionPersister.this;
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -62,7 +62,6 @@ import org.hibernate.cache.spi.entry.ReferenceCacheEntryImpl;
|
|||
import org.hibernate.cache.spi.entry.StandardCacheEntryImpl;
|
||||
import org.hibernate.cache.spi.entry.StructuredCacheEntry;
|
||||
import org.hibernate.cache.spi.entry.UnstructuredCacheEntry;
|
||||
import org.hibernate.cfg.NotYetImplementedException;
|
||||
import org.hibernate.dialect.lock.LockingStrategy;
|
||||
import org.hibernate.engine.OptimisticLockStyle;
|
||||
import org.hibernate.engine.internal.StatefulPersistenceContext;
|
||||
|
@ -120,12 +119,9 @@ import org.hibernate.metamodel.spi.relational.DerivedValue;
|
|||
import org.hibernate.metamodel.spi.relational.Table;
|
||||
import org.hibernate.metamodel.spi.relational.TableSpecification;
|
||||
import org.hibernate.metamodel.spi.relational.Value;
|
||||
import org.hibernate.persister.walking.internal.EntityIdentifierDefinitionHelper;
|
||||
import org.hibernate.persister.walking.spi.AttributeDefinition;
|
||||
import org.hibernate.persister.walking.spi.AttributeSource;
|
||||
import org.hibernate.persister.walking.spi.EncapsulatedEntityIdentifierDefinition;
|
||||
import org.hibernate.persister.walking.spi.EntityDefinition;
|
||||
import org.hibernate.persister.walking.spi.EntityIdentifierDefinition;
|
||||
import org.hibernate.persister.walking.spi.NonEncapsulatedEntityIdentifierDefinition;
|
||||
import org.hibernate.pretty.MessageHelper;
|
||||
import org.hibernate.property.BackrefPropertyAccessor;
|
||||
import org.hibernate.sql.Alias;
|
||||
|
@ -5290,80 +5286,20 @@ public abstract class AbstractEntityPersister
|
|||
final Type idType = getIdentifierType();
|
||||
|
||||
if ( !idType.isComponentType() ) {
|
||||
entityIdentifierDefinition = buildEncapsulatedIdentifierDefinition();
|
||||
entityIdentifierDefinition =
|
||||
EntityIdentifierDefinitionHelper.buildSimpleEncapsulatedIdentifierDefinition( this );
|
||||
return;
|
||||
}
|
||||
|
||||
final CompositeType cidType = (CompositeType) idType;
|
||||
if ( !cidType.isEmbedded() ) {
|
||||
entityIdentifierDefinition = buildEncapsulatedIdentifierDefinition();
|
||||
entityIdentifierDefinition =
|
||||
EntityIdentifierDefinitionHelper.buildEncapsulatedCompositeIdentifierDefinition( this );
|
||||
return;
|
||||
}
|
||||
|
||||
entityIdentifierDefinition = new NonEncapsulatedEntityIdentifierDefinition() {
|
||||
@Override
|
||||
public Iterable<AttributeDefinition> getAttributes() {
|
||||
// todo : implement
|
||||
throw new NotYetImplementedException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class getSeparateIdentifierMappingClass() {
|
||||
// todo : implement
|
||||
throw new NotYetImplementedException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEncapsulated() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityDefinition getEntityDefinition() {
|
||||
return AbstractEntityPersister.this;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private EntityIdentifierDefinition buildEncapsulatedIdentifierDefinition() {
|
||||
final AttributeDefinition simpleIdentifierAttributeAdapter = new AttributeDefinition() {
|
||||
@Override
|
||||
public String getName() {
|
||||
return entityMetamodel.getIdentifierProperty().getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getType() {
|
||||
return entityMetamodel.getIdentifierProperty().getType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AttributeSource getSource() {
|
||||
return AbstractEntityPersister.this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "<identifier-property:" + getName() + ">";
|
||||
}
|
||||
};
|
||||
|
||||
return new EncapsulatedEntityIdentifierDefinition() {
|
||||
@Override
|
||||
public AttributeDefinition getAttributeDefinition() {
|
||||
return simpleIdentifierAttributeAdapter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEncapsulated() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityDefinition getEntityDefinition() {
|
||||
return AbstractEntityPersister.this;
|
||||
}
|
||||
};
|
||||
entityIdentifierDefinition =
|
||||
EntityIdentifierDefinitionHelper.buildNonEncapsulatedCompositeIdentifierDefinition( this );
|
||||
}
|
||||
|
||||
private void collectAttributeDefinitions() {
|
||||
|
|
|
@ -0,0 +1,212 @@
|
|||
package org.hibernate.persister.walking.internal;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
import org.hibernate.engine.FetchStrategy;
|
||||
import org.hibernate.engine.FetchStyle;
|
||||
import org.hibernate.engine.FetchTiming;
|
||||
import org.hibernate.engine.spi.CascadeStyle;
|
||||
import org.hibernate.engine.spi.CascadeStyles;
|
||||
import org.hibernate.engine.spi.LoadQueryInfluencers;
|
||||
import org.hibernate.internal.util.collections.ArrayHelper;
|
||||
import org.hibernate.loader.PropertyPath;
|
||||
import org.hibernate.persister.collection.QueryableCollection;
|
||||
import org.hibernate.persister.entity.AbstractEntityPersister;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.persister.entity.OuterJoinLoadable;
|
||||
import org.hibernate.persister.spi.HydratedCompoundValueHandler;
|
||||
import org.hibernate.persister.walking.spi.AssociationAttributeDefinition;
|
||||
import org.hibernate.persister.walking.spi.AssociationKey;
|
||||
import org.hibernate.persister.walking.spi.AttributeDefinition;
|
||||
import org.hibernate.persister.walking.spi.AttributeSource;
|
||||
import org.hibernate.persister.walking.spi.CollectionDefinition;
|
||||
import org.hibernate.persister.walking.spi.CompositionDefinition;
|
||||
import org.hibernate.persister.walking.spi.CompositionElementDefinition;
|
||||
import org.hibernate.persister.walking.spi.EntityDefinition;
|
||||
import org.hibernate.persister.walking.spi.WalkingException;
|
||||
import org.hibernate.type.AssociationType;
|
||||
import org.hibernate.type.CompositeType;
|
||||
import org.hibernate.type.Type;
|
||||
|
||||
/**
|
||||
* @author Gail Badner
|
||||
*/
|
||||
public class CompositionSingularSubAttributesHelper {
|
||||
|
||||
public static Iterable<AttributeDefinition> getIdentifierSubAttributes(
|
||||
final AbstractEntityPersister entityPersister) {
|
||||
return getSingularSubAttributes(
|
||||
entityPersister,
|
||||
entityPersister,
|
||||
(CompositeType) entityPersister.getIdentifierType(),
|
||||
entityPersister.getTableName(),
|
||||
entityPersister.getRootTableIdentifierColumnNames()
|
||||
);
|
||||
}
|
||||
|
||||
public static Iterable<AttributeDefinition> getCompositionElementSubAttributes(
|
||||
CompositionElementDefinition compositionElementDefinition) {
|
||||
final QueryableCollection collectionPersister =
|
||||
(QueryableCollection) compositionElementDefinition.getCollectionDefinition().getCollectionPersister();
|
||||
return getSingularSubAttributes(
|
||||
compositionElementDefinition.getSource(),
|
||||
(OuterJoinLoadable) collectionPersister.getOwnerEntityPersister(),
|
||||
(CompositeType) collectionPersister.getElementType(),
|
||||
collectionPersister.getTableName(),
|
||||
collectionPersister.getElementColumnNames()
|
||||
);
|
||||
}
|
||||
|
||||
private static Iterable<AttributeDefinition> getSingularSubAttributes(
|
||||
final AttributeSource source,
|
||||
final OuterJoinLoadable ownerEntityPersister,
|
||||
final CompositeType compositeType,
|
||||
final String lhsTableName,
|
||||
final String[] lhsColumns) {
|
||||
return new Iterable<AttributeDefinition>() {
|
||||
@Override
|
||||
public Iterator<AttributeDefinition> iterator() {
|
||||
return new Iterator<AttributeDefinition>() {
|
||||
private final int numberOfAttributes = compositeType.getSubtypes().length;
|
||||
private int currentSubAttributeNumber = 0;
|
||||
private int currentColumnPosition = 0;
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return currentSubAttributeNumber < numberOfAttributes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AttributeDefinition next() {
|
||||
final int subAttributeNumber = currentSubAttributeNumber;
|
||||
currentSubAttributeNumber++;
|
||||
|
||||
final String name = compositeType.getPropertyNames()[subAttributeNumber];
|
||||
final Type type = compositeType.getSubtypes()[subAttributeNumber];
|
||||
|
||||
final int columnPosition = currentColumnPosition;
|
||||
final int columnSpan = type.getColumnSpan( ownerEntityPersister.getFactory() );
|
||||
final String[] subAttributeLhsColumns = ArrayHelper.slice( lhsColumns, columnPosition, columnSpan );
|
||||
|
||||
currentColumnPosition += columnSpan;
|
||||
|
||||
if ( type.isAssociationType() ) {
|
||||
final AssociationType aType = (AssociationType) type;
|
||||
return new AssociationAttributeDefinition() {
|
||||
@Override
|
||||
public AssociationKey getAssociationKey() {
|
||||
/* TODO: is this always correct? */
|
||||
//return new AssociationKey(
|
||||
// joinable.getTableName(),
|
||||
// JoinHelper.getRHSColumnNames( aType, getEntityPersister().getFactory() )
|
||||
//);
|
||||
return new AssociationKey(
|
||||
lhsTableName,
|
||||
subAttributeLhsColumns
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCollection() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityDefinition toEntityDefinition() {
|
||||
return (EntityPersister) aType.getAssociatedJoinable( ownerEntityPersister.getFactory() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public CollectionDefinition toCollectionDefinition() {
|
||||
throw new WalkingException( "A collection cannot be mapped to a composite ID sub-attribute." );
|
||||
}
|
||||
|
||||
@Override
|
||||
public FetchStrategy determineFetchPlan(LoadQueryInfluencers loadQueryInfluencers, PropertyPath propertyPath) {
|
||||
return new FetchStrategy( FetchTiming.IMMEDIATE, FetchStyle.JOIN );
|
||||
}
|
||||
|
||||
@Override
|
||||
public CascadeStyle determineCascadeStyle() {
|
||||
return CascadeStyles.NONE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HydratedCompoundValueHandler getHydratedCompoundValueExtractor() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AttributeSource getSource() {
|
||||
return source;
|
||||
}
|
||||
};
|
||||
}
|
||||
else if ( type.isComponentType() ) {
|
||||
return new CompositionDefinition() {
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AttributeSource getSource() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<AttributeDefinition> getAttributes() {
|
||||
return CompositionSingularSubAttributesHelper.getSingularSubAttributes(
|
||||
this,
|
||||
ownerEntityPersister,
|
||||
(CompositeType) type,
|
||||
lhsTableName,
|
||||
subAttributeLhsColumns
|
||||
);
|
||||
}
|
||||
};
|
||||
}
|
||||
else {
|
||||
return new AttributeDefinition() {
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AttributeSource getSource() {
|
||||
return source;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
throw new UnsupportedOperationException( "Remove operation not supported here" );
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
|
@ -0,0 +1,153 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2013, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.persister.walking.internal;
|
||||
|
||||
import org.hibernate.persister.entity.AbstractEntityPersister;
|
||||
import org.hibernate.persister.walking.spi.AttributeDefinition;
|
||||
import org.hibernate.persister.walking.spi.AttributeSource;
|
||||
import org.hibernate.persister.walking.spi.CompositionDefinition;
|
||||
import org.hibernate.persister.walking.spi.EncapsulatedEntityIdentifierDefinition;
|
||||
import org.hibernate.persister.walking.spi.EntityDefinition;
|
||||
import org.hibernate.persister.walking.spi.EntityIdentifierDefinition;
|
||||
import org.hibernate.persister.walking.spi.NonEncapsulatedEntityIdentifierDefinition;
|
||||
import org.hibernate.type.Type;
|
||||
|
||||
/**
|
||||
* @author Gail Badner
|
||||
*/
|
||||
public class EntityIdentifierDefinitionHelper {
|
||||
|
||||
public static EntityIdentifierDefinition buildSimpleEncapsulatedIdentifierDefinition(final AbstractEntityPersister entityPersister) {
|
||||
return new EncapsulatedEntityIdentifierDefinition() {
|
||||
@Override
|
||||
public AttributeDefinition getAttributeDefinition() {
|
||||
return new AttributeDefinitionAdapter( entityPersister);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEncapsulated() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityDefinition getEntityDefinition() {
|
||||
return entityPersister;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static EntityIdentifierDefinition buildEncapsulatedCompositeIdentifierDefinition(
|
||||
final AbstractEntityPersister entityPersister) {
|
||||
|
||||
return new EncapsulatedEntityIdentifierDefinition() {
|
||||
@Override
|
||||
public AttributeDefinition getAttributeDefinition() {
|
||||
return new CompositionDefinitionAdapter( entityPersister );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEncapsulated() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityDefinition getEntityDefinition() {
|
||||
return entityPersister;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static EntityIdentifierDefinition buildNonEncapsulatedCompositeIdentifierDefinition(final AbstractEntityPersister entityPersister) {
|
||||
return new NonEncapsulatedEntityIdentifierDefinition() {
|
||||
@Override
|
||||
public Iterable<AttributeDefinition> getAttributes() {
|
||||
return CompositionSingularSubAttributesHelper.getIdentifierSubAttributes( entityPersister );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class getSeparateIdentifierMappingClass() {
|
||||
return entityPersister.getEntityMetamodel().getIdentifierProperty().getType().getReturnedClass();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEncapsulated() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityDefinition getEntityDefinition() {
|
||||
return entityPersister;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static class AttributeDefinitionAdapter implements AttributeDefinition {
|
||||
private final AbstractEntityPersister entityPersister;
|
||||
|
||||
AttributeDefinitionAdapter(AbstractEntityPersister entityPersister) {
|
||||
this.entityPersister = entityPersister;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return entityPersister.getEntityMetamodel().getIdentifierProperty().getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getType() {
|
||||
return entityPersister.getEntityMetamodel().getIdentifierProperty().getType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AttributeSource getSource() {
|
||||
return entityPersister;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "<identifier-property:" + getName() + ">";
|
||||
}
|
||||
|
||||
protected AbstractEntityPersister getEntityPersister() {
|
||||
return entityPersister;
|
||||
}
|
||||
}
|
||||
|
||||
private static class CompositionDefinitionAdapter extends AttributeDefinitionAdapter implements CompositionDefinition {
|
||||
|
||||
CompositionDefinitionAdapter(AbstractEntityPersister entityPersister) {
|
||||
super( entityPersister );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "<identifier-property:" + getName() + ">";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<AttributeDefinition> getAttributes() {
|
||||
return CompositionSingularSubAttributesHelper.getIdentifierSubAttributes( getEntityPersister() );
|
||||
}
|
||||
}
|
||||
}
|
|
@ -42,7 +42,7 @@ import org.hibernate.type.AssociationType;
|
|||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class Helper {
|
||||
public class FetchStrategyHelper {
|
||||
/**
|
||||
* Determine the fetch-style (if one) explicitly set for this association via fetch profiles.
|
||||
* <p/>
|
|
@ -55,6 +55,9 @@ public interface AssociationVisitationStrategy {
|
|||
public void startingComposite(CompositionDefinition compositionDefinition);
|
||||
public void finishingComposite(CompositionDefinition compositionDefinition);
|
||||
|
||||
public void startingCompositeElement(CompositionElementDefinition compositionElementDefinition);
|
||||
public void finishingCompositeElement(CompositionElementDefinition compositionElementDefinition);
|
||||
|
||||
public boolean startingAttribute(AttributeDefinition attributeDefinition);
|
||||
public void finishingAttribute(AttributeDefinition attributeDefinition);
|
||||
}
|
||||
|
|
|
@ -35,5 +35,5 @@ public interface CollectionElementDefinition {
|
|||
|
||||
public EntityDefinition toEntityDefinition();
|
||||
|
||||
public CompositionDefinition toCompositeDefinition();
|
||||
public CompositionElementDefinition toCompositeElementDefinition();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2013, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.persister.walking.spi;
|
||||
|
||||
/**
|
||||
* @author Gail Badner
|
||||
*/
|
||||
public interface CompositionElementDefinition extends CompositionDefinition{
|
||||
public CollectionDefinition getCollectionDefinition();
|
||||
}
|
|
@ -114,10 +114,10 @@ public class MetadataDrivenModelGraphVisitor {
|
|||
log.debug( "Visiting attribute path : " + subPath.getFullPath() );
|
||||
|
||||
final boolean continueWalk;
|
||||
if ( attributeDefinition.getType().isAssociationType() ) {
|
||||
continueWalk =
|
||||
! isDuplicateAssociation( ( (AssociationAttributeDefinition) attributeDefinition ).getAssociationKey() ) &&
|
||||
strategy.startingAttribute( attributeDefinition );
|
||||
if ( attributeDefinition.getType().isAssociationType() &&
|
||||
isDuplicateAssociationKey( ( (AssociationAttributeDefinition) attributeDefinition ).getAssociationKey() ) ) {
|
||||
log.debug( "Property path deemed to be circular : " + subPath.getFullPath() );
|
||||
continueWalk = false;
|
||||
}
|
||||
else {
|
||||
continueWalk = strategy.startingAttribute( attributeDefinition );
|
||||
|
@ -143,6 +143,8 @@ public class MetadataDrivenModelGraphVisitor {
|
|||
private void visitAssociation(AssociationAttributeDefinition attribute) {
|
||||
// todo : do "too deep" checks; but see note about adding depth to PropertyPath
|
||||
|
||||
addAssociationKey( attribute.getAssociationKey() );
|
||||
|
||||
if ( attribute.isCollection() ) {
|
||||
visitCollectionDefinition( attribute.toCollectionDefinition() );
|
||||
}
|
||||
|
@ -200,7 +202,7 @@ public class MetadataDrivenModelGraphVisitor {
|
|||
strategy.startingCollectionElements( elementDefinition );
|
||||
|
||||
if ( elementDefinition.getType().isComponentType() ) {
|
||||
visitCompositeDefinition( elementDefinition.toCompositeDefinition() );
|
||||
visitCompositeElementDefinition( elementDefinition.toCompositeElementDefinition() );
|
||||
}
|
||||
else if ( elementDefinition.getType().isEntityType() ) {
|
||||
visitEntityDefinition( elementDefinition.toEntityDefinition() );
|
||||
|
@ -209,18 +211,37 @@ public class MetadataDrivenModelGraphVisitor {
|
|||
strategy.finishingCollectionElements( elementDefinition );
|
||||
}
|
||||
|
||||
private void visitCompositeElementDefinition(CompositionElementDefinition compositionElementDefinition) {
|
||||
strategy.startingCompositeElement( compositionElementDefinition );
|
||||
|
||||
visitAttributes( compositionElementDefinition );
|
||||
|
||||
strategy.finishingCompositeElement( compositionElementDefinition );
|
||||
}
|
||||
|
||||
private final Set<AssociationKey> visitedAssociationKeys = new HashSet<AssociationKey>();
|
||||
|
||||
protected boolean isDuplicateAssociation(AssociationKey associationKey) {
|
||||
boolean isDuplicate = !visitedAssociationKeys.add( associationKey );
|
||||
if ( isDuplicate ) {
|
||||
log.debug( "Property path deemed to be circular : " + currentPropertyPath.getFullPath() );
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
/**
|
||||
* Add association key to indicate the association is being visited.
|
||||
* @param associationKey - the association key.
|
||||
* @throws WalkingException if the association with the specified association key
|
||||
* has already been visited.
|
||||
*/
|
||||
protected void addAssociationKey(AssociationKey associationKey) {
|
||||
if ( ! visitedAssociationKeys.add( associationKey ) ) {
|
||||
throw new WalkingException(
|
||||
String.format( "Association has already been visited: %s", associationKey )
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Has an association with the specified key been visited already?
|
||||
* @param associationKey - the association key.
|
||||
* @return true, if the association with the specified association key has already been visited;
|
||||
* false, otherwise.
|
||||
*/
|
||||
protected boolean isDuplicateAssociationKey(AssociationKey associationKey) {
|
||||
return visitedAssociationKeys.contains( associationKey );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,7 +39,7 @@ public abstract class AbstractCompositeBasedAttribute
|
|||
private final int ownerAttributeNumber;
|
||||
|
||||
public AbstractCompositeBasedAttribute(
|
||||
AbstractCompositionDefinition source,
|
||||
AbstractCompositionAttribute source,
|
||||
SessionFactoryImplementor sessionFactory,
|
||||
int attributeNumber,
|
||||
String attributeName,
|
||||
|
@ -55,7 +55,7 @@ public abstract class AbstractCompositeBasedAttribute
|
|||
}
|
||||
|
||||
@Override
|
||||
public AbstractCompositionDefinition getSource() {
|
||||
return (AbstractCompositionDefinition) super.getSource();
|
||||
public AbstractCompositionAttribute getSource() {
|
||||
return (AbstractCompositionAttribute) super.getSource();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -48,9 +48,9 @@ import static org.hibernate.engine.internal.JoinHelper.getRHSColumnNames;
|
|||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public abstract class AbstractCompositionDefinition extends AbstractNonIdentifierAttribute implements
|
||||
public abstract class AbstractCompositionAttribute extends AbstractNonIdentifierAttribute implements
|
||||
CompositionDefinition {
|
||||
protected AbstractCompositionDefinition(
|
||||
protected AbstractCompositionAttribute(
|
||||
AttributeSource source,
|
||||
SessionFactoryImplementor sessionFactory,
|
||||
int attributeNumber,
|
||||
|
@ -72,21 +72,21 @@ public abstract class AbstractCompositionDefinition extends AbstractNonIdentifie
|
|||
public Iterator<AttributeDefinition> iterator() {
|
||||
return new Iterator<AttributeDefinition>() {
|
||||
private final int numberOfAttributes = getType().getSubtypes().length;
|
||||
private int currentAttributeNumber = 0;
|
||||
private int currentSubAttributeNumber = 0;
|
||||
private int currentColumnPosition = 0;
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return currentAttributeNumber < numberOfAttributes;
|
||||
return currentSubAttributeNumber < numberOfAttributes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AttributeDefinition next() {
|
||||
final int attributeNumber = currentAttributeNumber;
|
||||
currentAttributeNumber++;
|
||||
final int subAttributeNumber = currentSubAttributeNumber;
|
||||
currentSubAttributeNumber++;
|
||||
|
||||
final String name = getType().getPropertyNames()[attributeNumber];
|
||||
final Type type = getType().getSubtypes()[attributeNumber];
|
||||
final String name = getType().getPropertyNames()[subAttributeNumber];
|
||||
final Type type = getType().getSubtypes()[subAttributeNumber];
|
||||
|
||||
int columnPosition = currentColumnPosition;
|
||||
currentColumnPosition += type.getColumnSpan( sessionFactory() );
|
||||
|
@ -101,13 +101,13 @@ public abstract class AbstractCompositionDefinition extends AbstractNonIdentifie
|
|||
getLHSTableName(
|
||||
aType,
|
||||
attributeNumber(),
|
||||
(OuterJoinLoadable) joinable
|
||||
(OuterJoinLoadable) locateOwningPersister()
|
||||
),
|
||||
getLHSColumnNames(
|
||||
aType,
|
||||
attributeNumber(),
|
||||
columnPosition,
|
||||
(OuterJoinLoadable) joinable,
|
||||
(OuterJoinLoadable) locateOwningPersister(),
|
||||
sessionFactory()
|
||||
)
|
||||
);
|
||||
|
@ -120,63 +120,63 @@ public abstract class AbstractCompositionDefinition extends AbstractNonIdentifie
|
|||
}
|
||||
|
||||
return new CompositeBasedAssociationAttribute(
|
||||
AbstractCompositionDefinition.this,
|
||||
AbstractCompositionAttribute.this,
|
||||
sessionFactory(),
|
||||
currentAttributeNumber,
|
||||
subAttributeNumber,
|
||||
name,
|
||||
(AssociationType) type,
|
||||
new BaselineAttributeInformation.Builder()
|
||||
.setInsertable( AbstractCompositionDefinition.this.isInsertable() )
|
||||
.setUpdateable( AbstractCompositionDefinition.this.isUpdateable() )
|
||||
.setInsertGenerated( AbstractCompositionDefinition.this.isInsertGenerated() )
|
||||
.setUpdateGenerated( AbstractCompositionDefinition.this.isUpdateGenerated() )
|
||||
.setNullable( getType().getPropertyNullability()[currentAttributeNumber] )
|
||||
.setInsertable( AbstractCompositionAttribute.this.isInsertable() )
|
||||
.setUpdateable( AbstractCompositionAttribute.this.isUpdateable() )
|
||||
.setInsertGenerated( AbstractCompositionAttribute.this.isInsertGenerated() )
|
||||
.setUpdateGenerated( AbstractCompositionAttribute.this.isUpdateGenerated() )
|
||||
.setNullable( getType().getPropertyNullability()[subAttributeNumber] )
|
||||
.setDirtyCheckable( true )
|
||||
.setVersionable( AbstractCompositionDefinition.this.isVersionable() )
|
||||
.setCascadeStyle( getType().getCascadeStyle( currentAttributeNumber ) )
|
||||
.setFetchMode( getType().getFetchMode( currentAttributeNumber ) )
|
||||
.setVersionable( AbstractCompositionAttribute.this.isVersionable() )
|
||||
.setCascadeStyle( getType().getCascadeStyle( subAttributeNumber ) )
|
||||
.setFetchMode( getType().getFetchMode( subAttributeNumber ) )
|
||||
.createInformation(),
|
||||
AbstractCompositionDefinition.this.attributeNumber(),
|
||||
AbstractCompositionAttribute.this.attributeNumber(),
|
||||
associationKey
|
||||
);
|
||||
}
|
||||
else if ( type.isComponentType() ) {
|
||||
return new CompositionBasedCompositionAttribute(
|
||||
AbstractCompositionDefinition.this,
|
||||
AbstractCompositionAttribute.this,
|
||||
sessionFactory(),
|
||||
currentAttributeNumber,
|
||||
subAttributeNumber,
|
||||
name,
|
||||
(CompositeType) type,
|
||||
new BaselineAttributeInformation.Builder()
|
||||
.setInsertable( AbstractCompositionDefinition.this.isInsertable() )
|
||||
.setUpdateable( AbstractCompositionDefinition.this.isUpdateable() )
|
||||
.setInsertGenerated( AbstractCompositionDefinition.this.isInsertGenerated() )
|
||||
.setUpdateGenerated( AbstractCompositionDefinition.this.isUpdateGenerated() )
|
||||
.setNullable( getType().getPropertyNullability()[currentAttributeNumber] )
|
||||
.setInsertable( AbstractCompositionAttribute.this.isInsertable() )
|
||||
.setUpdateable( AbstractCompositionAttribute.this.isUpdateable() )
|
||||
.setInsertGenerated( AbstractCompositionAttribute.this.isInsertGenerated() )
|
||||
.setUpdateGenerated( AbstractCompositionAttribute.this.isUpdateGenerated() )
|
||||
.setNullable( getType().getPropertyNullability()[subAttributeNumber] )
|
||||
.setDirtyCheckable( true )
|
||||
.setVersionable( AbstractCompositionDefinition.this.isVersionable() )
|
||||
.setCascadeStyle( getType().getCascadeStyle( currentAttributeNumber ) )
|
||||
.setFetchMode( getType().getFetchMode( currentAttributeNumber ) )
|
||||
.setVersionable( AbstractCompositionAttribute.this.isVersionable() )
|
||||
.setCascadeStyle( getType().getCascadeStyle( subAttributeNumber ) )
|
||||
.setFetchMode( getType().getFetchMode( subAttributeNumber ) )
|
||||
.createInformation()
|
||||
);
|
||||
}
|
||||
else {
|
||||
return new CompositeBasedBasicAttribute(
|
||||
AbstractCompositionDefinition.this,
|
||||
AbstractCompositionAttribute.this,
|
||||
sessionFactory(),
|
||||
currentAttributeNumber,
|
||||
subAttributeNumber,
|
||||
name,
|
||||
type,
|
||||
new BaselineAttributeInformation.Builder()
|
||||
.setInsertable( AbstractCompositionDefinition.this.isInsertable() )
|
||||
.setUpdateable( AbstractCompositionDefinition.this.isUpdateable() )
|
||||
.setInsertGenerated( AbstractCompositionDefinition.this.isInsertGenerated() )
|
||||
.setUpdateGenerated( AbstractCompositionDefinition.this.isUpdateGenerated() )
|
||||
.setNullable( getType().getPropertyNullability()[currentAttributeNumber] )
|
||||
.setInsertable( AbstractCompositionAttribute.this.isInsertable() )
|
||||
.setUpdateable( AbstractCompositionAttribute.this.isUpdateable() )
|
||||
.setInsertGenerated( AbstractCompositionAttribute.this.isInsertGenerated() )
|
||||
.setUpdateGenerated( AbstractCompositionAttribute.this.isUpdateGenerated() )
|
||||
.setNullable( getType().getPropertyNullability()[subAttributeNumber] )
|
||||
.setDirtyCheckable( true )
|
||||
.setVersionable( AbstractCompositionDefinition.this.isVersionable() )
|
||||
.setCascadeStyle( getType().getCascadeStyle( currentAttributeNumber ) )
|
||||
.setFetchMode( getType().getFetchMode( currentAttributeNumber ) )
|
||||
.setVersionable( AbstractCompositionAttribute.this.isVersionable() )
|
||||
.setCascadeStyle( getType().getCascadeStyle( subAttributeNumber ) )
|
||||
.setFetchMode( getType().getFetchMode( subAttributeNumber ) )
|
||||
.createInformation()
|
||||
);
|
||||
}
|
||||
|
@ -196,7 +196,7 @@ public abstract class AbstractCompositionDefinition extends AbstractNonIdentifie
|
|||
return ( (EntityDefinition) getSource() ).getEntityPersister();
|
||||
}
|
||||
else {
|
||||
return ( (AbstractCompositionDefinition) getSource() ).locateOwningPersister();
|
||||
return ( (AbstractCompositionAttribute) getSource() ).locateOwningPersister();
|
||||
}
|
||||
}
|
||||
|
|
@ -35,7 +35,7 @@ import org.hibernate.persister.collection.CollectionPersister;
|
|||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.persister.entity.Joinable;
|
||||
import org.hibernate.persister.spi.HydratedCompoundValueHandler;
|
||||
import org.hibernate.persister.walking.internal.Helper;
|
||||
import org.hibernate.persister.walking.internal.FetchStrategyHelper;
|
||||
import org.hibernate.persister.walking.spi.AssociationAttributeDefinition;
|
||||
import org.hibernate.persister.walking.spi.AssociationKey;
|
||||
import org.hibernate.persister.walking.spi.CollectionDefinition;
|
||||
|
@ -55,7 +55,7 @@ public class CompositeBasedAssociationAttribute
|
|||
private Joinable joinable;
|
||||
|
||||
public CompositeBasedAssociationAttribute(
|
||||
AbstractCompositionDefinition source,
|
||||
AbstractCompositionAttribute source,
|
||||
SessionFactoryImplementor factory,
|
||||
int attributeNumber,
|
||||
String attributeName,
|
||||
|
@ -130,7 +130,7 @@ public class CompositeBasedAssociationAttribute
|
|||
EntityPersister owningPersister,
|
||||
PropertyPath propertyPath,
|
||||
int ownerAttributeNumber) {
|
||||
return Helper.determineFetchStyleByProfile(
|
||||
return FetchStrategyHelper.determineFetchStyleByProfile(
|
||||
loadQueryInfluencers,
|
||||
owningPersister,
|
||||
propertyPath,
|
||||
|
@ -139,11 +139,11 @@ public class CompositeBasedAssociationAttribute
|
|||
}
|
||||
|
||||
protected FetchStyle determineFetchStyleByMetadata(FetchMode fetchMode, AssociationType type) {
|
||||
return Helper.determineFetchStyleByMetadata( fetchMode, type, sessionFactory() );
|
||||
return FetchStrategyHelper.determineFetchStyleByMetadata( fetchMode, type, sessionFactory() );
|
||||
}
|
||||
|
||||
private FetchTiming determineFetchTiming(FetchStyle style) {
|
||||
return Helper.determineFetchTiming( style, getType(), sessionFactory() );
|
||||
return FetchStrategyHelper.determineFetchTiming( style, getType(), sessionFactory() );
|
||||
}
|
||||
|
||||
private EntityPersister locateOwningPersister() {
|
||||
|
|
|
@ -32,7 +32,7 @@ import org.hibernate.type.CompositeType;
|
|||
* @author Steve Ebersole
|
||||
*/
|
||||
public class CompositionBasedCompositionAttribute
|
||||
extends AbstractCompositionDefinition
|
||||
extends AbstractCompositionAttribute
|
||||
implements CompositionDefinition {
|
||||
public CompositionBasedCompositionAttribute(
|
||||
CompositionDefinition source,
|
||||
|
|
|
@ -34,7 +34,7 @@ import org.hibernate.persister.entity.EntityPersister;
|
|||
import org.hibernate.persister.entity.Joinable;
|
||||
import org.hibernate.persister.entity.OuterJoinLoadable;
|
||||
import org.hibernate.persister.spi.HydratedCompoundValueHandler;
|
||||
import org.hibernate.persister.walking.internal.Helper;
|
||||
import org.hibernate.persister.walking.internal.FetchStrategyHelper;
|
||||
import org.hibernate.persister.walking.spi.AssociationAttributeDefinition;
|
||||
import org.hibernate.persister.walking.spi.AssociationKey;
|
||||
import org.hibernate.persister.walking.spi.CollectionDefinition;
|
||||
|
@ -129,22 +129,22 @@ public class EntityBasedAssociationAttribute
|
|||
public FetchStrategy determineFetchPlan(LoadQueryInfluencers loadQueryInfluencers, PropertyPath propertyPath) {
|
||||
final EntityPersister owningPersister = getSource().getEntityPersister();
|
||||
|
||||
FetchStyle style = Helper.determineFetchStyleByProfile(
|
||||
FetchStyle style = FetchStrategyHelper.determineFetchStyleByProfile(
|
||||
loadQueryInfluencers,
|
||||
owningPersister,
|
||||
propertyPath,
|
||||
attributeNumber()
|
||||
);
|
||||
if ( style == null ) {
|
||||
style = Helper.determineFetchStyleByMetadata(
|
||||
((OuterJoinLoadable) getSource().getEntityPersister()).getFetchMode( attributeNumber() ),
|
||||
style = FetchStrategyHelper.determineFetchStyleByMetadata(
|
||||
( (OuterJoinLoadable) getSource().getEntityPersister() ).getFetchMode( attributeNumber() ),
|
||||
getType(),
|
||||
sessionFactory()
|
||||
);
|
||||
}
|
||||
|
||||
return new FetchStrategy(
|
||||
Helper.determineFetchTiming( style, getType(), sessionFactory() ),
|
||||
FetchStrategyHelper.determineFetchTiming( style, getType(), sessionFactory() ),
|
||||
style
|
||||
);
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ package org.hibernate.tuple.entity;
|
|||
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.tuple.component.AbstractCompositionDefinition;
|
||||
import org.hibernate.tuple.component.AbstractCompositionAttribute;
|
||||
import org.hibernate.persister.walking.spi.CompositionDefinition;
|
||||
import org.hibernate.tuple.BaselineAttributeInformation;
|
||||
import org.hibernate.type.CompositeType;
|
||||
|
@ -34,7 +34,7 @@ import org.hibernate.type.CompositeType;
|
|||
* @author Steve Ebersole
|
||||
*/
|
||||
public class EntityBasedCompositionAttribute
|
||||
extends AbstractCompositionDefinition
|
||||
extends AbstractCompositionAttribute
|
||||
implements CompositionDefinition {
|
||||
|
||||
public EntityBasedCompositionAttribute(
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
*/
|
||||
package org.hibernate.type;
|
||||
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
|
@ -34,7 +35,11 @@ import org.hibernate.Filter;
|
|||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.engine.internal.ForeignKeys;
|
||||
import org.hibernate.engine.spi.*;
|
||||
import org.hibernate.engine.spi.EntityUniqueKey;
|
||||
import org.hibernate.engine.spi.Mapping;
|
||||
import org.hibernate.engine.spi.PersistenceContext;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.engine.spi.SessionImplementor;
|
||||
import org.hibernate.internal.util.ReflectHelper;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.persister.entity.Joinable;
|
||||
|
@ -53,6 +58,7 @@ public abstract class EntityType extends AbstractType implements AssociationType
|
|||
protected final String uniqueKeyPropertyName;
|
||||
private final boolean eager;
|
||||
private final boolean unwrapProxy;
|
||||
private final boolean referenceToPrimaryKey;
|
||||
|
||||
private transient Class returnedClass;
|
||||
|
||||
|
@ -67,29 +73,46 @@ public abstract class EntityType extends AbstractType implements AssociationType
|
|||
* @param unwrapProxy Is unwrapping of proxies allowed for this association; unwrapping
|
||||
* says to return the "implementation target" of lazy prooxies; typically only possible
|
||||
* with lazy="no-proxy".
|
||||
*
|
||||
* @deprecated Use {@link #EntityType(org.hibernate.type.TypeFactory.TypeScope, String, boolean, String, boolean, boolean)} instead.
|
||||
* See Jira issue: <a href="https://hibernate.onjira.com/browse/HHH-7771">HHH-7771</a>
|
||||
*/
|
||||
@Deprecated
|
||||
protected EntityType(
|
||||
TypeFactory.TypeScope scope,
|
||||
String entityName,
|
||||
String uniqueKeyPropertyName,
|
||||
boolean eager,
|
||||
boolean unwrapProxy) {
|
||||
this(scope, entityName, uniqueKeyPropertyName, eager, unwrapProxy, null);
|
||||
this( scope, entityName, uniqueKeyPropertyName == null, uniqueKeyPropertyName, eager, unwrapProxy );
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs the requested entity type mapping.
|
||||
*
|
||||
* @param scope The type scope
|
||||
* @param entityName The name of the associated entity.
|
||||
* @param referenceToPrimaryKey True if association references a primary key.
|
||||
* @param uniqueKeyPropertyName The property-ref name, or null if we
|
||||
* reference the PK of the associated entity.
|
||||
* @param eager Is eager fetching enabled.
|
||||
* @param unwrapProxy Is unwrapping of proxies allowed for this association; unwrapping
|
||||
* says to return the "implementation target" of lazy prooxies; typically only possible
|
||||
* with lazy="no-proxy".
|
||||
*/
|
||||
protected EntityType(
|
||||
TypeFactory.TypeScope scope,
|
||||
String entityName,
|
||||
boolean referenceToPrimaryKey,
|
||||
String uniqueKeyPropertyName,
|
||||
boolean eager,
|
||||
boolean unwrapProxy,
|
||||
Class returnedClass) {
|
||||
boolean unwrapProxy) {
|
||||
this.scope = scope;
|
||||
this.associatedEntityName = entityName;
|
||||
this.uniqueKeyPropertyName = uniqueKeyPropertyName;
|
||||
this.eager = eager;
|
||||
this.unwrapProxy = unwrapProxy;
|
||||
this.returnedClass = returnedClass;
|
||||
this.referenceToPrimaryKey = referenceToPrimaryKey;
|
||||
}
|
||||
|
||||
|
||||
|
@ -146,11 +169,13 @@ public abstract class EntityType extends AbstractType implements AssociationType
|
|||
* @return True if this association reference the PK of the associated entity.
|
||||
*/
|
||||
public boolean isReferenceToPrimaryKey() {
|
||||
return uniqueKeyPropertyName==null;
|
||||
return referenceToPrimaryKey;
|
||||
}
|
||||
|
||||
public String getRHSUniqueKeyPropertyName() {
|
||||
return uniqueKeyPropertyName;
|
||||
// Return null if this type references a PK. This is important for
|
||||
// associations' use of mappedBy referring to a derived ID.
|
||||
return referenceToPrimaryKey ? null : uniqueKeyPropertyName;
|
||||
}
|
||||
|
||||
public String getLHSPropertyName() {
|
||||
|
@ -211,7 +236,7 @@ public abstract class EntityType extends AbstractType implements AssociationType
|
|||
private Class determineAssociatedEntityClass() {
|
||||
final String entityName = getAssociatedEntityName();
|
||||
try {
|
||||
return ReflectHelper.classForName(entityName);
|
||||
return ReflectHelper.classForName( entityName );
|
||||
}
|
||||
catch ( ClassNotFoundException cnfe ) {
|
||||
return this.scope.resolveFactory().getEntityPersister(entityName).
|
||||
|
@ -314,7 +339,7 @@ public abstract class EntityType extends AbstractType implements AssociationType
|
|||
}
|
||||
|
||||
final Serializable id;
|
||||
if (x instanceof HibernateProxy) {
|
||||
if (x instanceof HibernateProxy ) {
|
||||
id = ( (HibernateProxy) x ).getHibernateLazyInitializer().getIdentifier();
|
||||
}
|
||||
else {
|
||||
|
@ -397,14 +422,15 @@ public abstract class EntityType extends AbstractType implements AssociationType
|
|||
if ( isNull( owner, session ) ) {
|
||||
return null; //EARLY EXIT!
|
||||
}
|
||||
|
||||
if ( isReferenceToPrimaryKey() ) {
|
||||
return resolveIdentifier( (Serializable) value, session );
|
||||
}
|
||||
else {
|
||||
else if ( uniqueKeyPropertyName != null ) {
|
||||
return loadByUniqueKey( getAssociatedEntityName(), uniqueKeyPropertyName, value, session );
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public Type getSemiResolvedType(SessionFactoryImplementor factory) {
|
||||
|
@ -412,7 +438,7 @@ public abstract class EntityType extends AbstractType implements AssociationType
|
|||
}
|
||||
|
||||
protected final Object getIdentifier(Object value, SessionImplementor session) throws HibernateException {
|
||||
if ( isReferenceToPrimaryKey() ) {
|
||||
if ( isReferenceToPrimaryKey() || uniqueKeyPropertyName == null) {
|
||||
return ForeignKeys.getEntityIdentifierIfNotUnsaved( getAssociatedEntityName(), value, session ); //tolerates nulls
|
||||
}
|
||||
else if ( value == null ) {
|
||||
|
@ -516,7 +542,7 @@ public abstract class EntityType extends AbstractType implements AssociationType
|
|||
* or unique key property name.
|
||||
*/
|
||||
public final Type getIdentifierOrUniqueKeyType(Mapping factory) throws MappingException {
|
||||
if ( isReferenceToPrimaryKey() ) {
|
||||
if ( isReferenceToPrimaryKey() || uniqueKeyPropertyName == null ) {
|
||||
return getIdentifierType(factory);
|
||||
}
|
||||
else {
|
||||
|
@ -538,7 +564,7 @@ public abstract class EntityType extends AbstractType implements AssociationType
|
|||
*/
|
||||
public final String getIdentifierOrUniqueKeyPropertyName(Mapping factory)
|
||||
throws MappingException {
|
||||
if ( isReferenceToPrimaryKey() ) {
|
||||
if ( isReferenceToPrimaryKey() || uniqueKeyPropertyName == null ) {
|
||||
return factory.getIdentifierPropertyName( getAssociatedEntityName() );
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -67,9 +67,15 @@ public class ManyToOneType extends EntityType {
|
|||
* @param lazy Should the association be handled lazily
|
||||
*/
|
||||
public ManyToOneType(TypeFactory.TypeScope scope, String referencedEntityName, boolean lazy) {
|
||||
this( scope, referencedEntityName, null, lazy, true, false, false );
|
||||
this( scope, referencedEntityName, true, null, lazy, true, false, false );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link #ManyToOneType(TypeFactory.TypeScope, String, boolean, String, boolean, boolean, boolean, boolean ) } instead.
|
||||
* See Jira issue: <a href="https://hibernate.onjira.com/browse/HHH-7771">HHH-7771</a>
|
||||
*/
|
||||
@Deprecated
|
||||
public ManyToOneType(
|
||||
TypeFactory.TypeScope scope,
|
||||
String referencedEntityName,
|
||||
|
@ -78,20 +84,18 @@ public class ManyToOneType extends EntityType {
|
|||
boolean unwrapProxy,
|
||||
boolean ignoreNotFound,
|
||||
boolean isLogicalOneToOne) {
|
||||
super( scope, referencedEntityName, uniqueKeyPropertyName, !lazy, unwrapProxy );
|
||||
this.ignoreNotFound = ignoreNotFound;
|
||||
this.isLogicalOneToOne = isLogicalOneToOne;
|
||||
this( scope, referencedEntityName, uniqueKeyPropertyName == null, uniqueKeyPropertyName, lazy, unwrapProxy, ignoreNotFound, isLogicalOneToOne );
|
||||
}
|
||||
public ManyToOneType(
|
||||
TypeFactory.TypeScope scope,
|
||||
String referencedEntityName,
|
||||
boolean referenceToPrimaryKey,
|
||||
String uniqueKeyPropertyName,
|
||||
boolean lazy,
|
||||
boolean unwrapProxy,
|
||||
boolean ignoreNotFound,
|
||||
boolean isLogicalOneToOne,
|
||||
Class returnedClass) {
|
||||
super( scope, referencedEntityName, uniqueKeyPropertyName, !lazy, unwrapProxy, returnedClass );
|
||||
boolean isLogicalOneToOne) {
|
||||
super( scope, referencedEntityName, referenceToPrimaryKey, uniqueKeyPropertyName, !lazy, unwrapProxy );
|
||||
this.ignoreNotFound = ignoreNotFound;
|
||||
this.isLogicalOneToOne = isLogicalOneToOne;
|
||||
}
|
||||
|
|
|
@ -47,6 +47,12 @@ public class OneToOneType extends EntityType {
|
|||
private final String propertyName;
|
||||
private final String entityName;
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link #OneToOneType(TypeFactory.TypeScope, String, ForeignKeyDirection, boolean, String, boolean, boolean, String, String)}
|
||||
* instead.
|
||||
* See Jira issue: <a href="https://hibernate.onjira.com/browse/HHH-7771">HHH-7771</a>
|
||||
*/
|
||||
@Deprecated
|
||||
public OneToOneType(
|
||||
TypeFactory.TypeScope scope,
|
||||
String referencedEntityName,
|
||||
|
@ -56,23 +62,20 @@ public class OneToOneType extends EntityType {
|
|||
boolean unwrapProxy,
|
||||
String entityName,
|
||||
String propertyName) {
|
||||
super( scope, referencedEntityName, uniqueKeyPropertyName, !lazy, unwrapProxy );
|
||||
this.foreignKeyType = foreignKeyType;
|
||||
this.propertyName = propertyName;
|
||||
this.entityName = entityName;
|
||||
this( scope, referencedEntityName, foreignKeyType, uniqueKeyPropertyName == null, uniqueKeyPropertyName, lazy, unwrapProxy, entityName, propertyName );
|
||||
}
|
||||
|
||||
public OneToOneType(
|
||||
TypeFactory.TypeScope scope,
|
||||
String referencedEntityName,
|
||||
ForeignKeyDirection foreignKeyType,
|
||||
boolean referenceToPrimaryKey,
|
||||
String uniqueKeyPropertyName,
|
||||
boolean lazy,
|
||||
boolean unwrapProxy,
|
||||
String entityName,
|
||||
String propertyName,
|
||||
Class returnedClass) {
|
||||
super( scope, referencedEntityName, uniqueKeyPropertyName, !lazy, unwrapProxy, returnedClass );
|
||||
String propertyName) {
|
||||
super( scope, referencedEntityName, referenceToPrimaryKey, uniqueKeyPropertyName, !lazy, unwrapProxy );
|
||||
this.foreignKeyType = foreignKeyType;
|
||||
this.propertyName = propertyName;
|
||||
this.entityName = entityName;
|
||||
|
|
20
hibernate-core/src/main/java/org/hibernate/type/SpecialOneToOneType.java
Executable file → Normal file
20
hibernate-core/src/main/java/org/hibernate/type/SpecialOneToOneType.java
Executable file → Normal file
|
@ -43,6 +43,10 @@ import org.hibernate.metamodel.spi.relational.Size;
|
|||
*/
|
||||
public class SpecialOneToOneType extends OneToOneType {
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link #SpecialOneToOneType(org.hibernate.type.TypeFactory.TypeScope, String, ForeignKeyDirection, boolean, String, boolean, boolean, String, String)} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public SpecialOneToOneType(
|
||||
TypeFactory.TypeScope scope,
|
||||
String referencedEntityName,
|
||||
|
@ -52,10 +56,24 @@ public class SpecialOneToOneType extends OneToOneType {
|
|||
boolean unwrapProxy,
|
||||
String entityName,
|
||||
String propertyName) {
|
||||
this( scope, referencedEntityName, foreignKeyType, uniqueKeyPropertyName == null, uniqueKeyPropertyName, lazy, unwrapProxy, entityName, propertyName );
|
||||
}
|
||||
|
||||
public SpecialOneToOneType(
|
||||
TypeFactory.TypeScope scope,
|
||||
String referencedEntityName,
|
||||
ForeignKeyDirection foreignKeyType,
|
||||
boolean referenceToPrimaryKey,
|
||||
String uniqueKeyPropertyName,
|
||||
boolean lazy,
|
||||
boolean unwrapProxy,
|
||||
String entityName,
|
||||
String propertyName) {
|
||||
super(
|
||||
scope,
|
||||
referencedEntityName,
|
||||
foreignKeyType,
|
||||
foreignKeyType,
|
||||
referenceToPrimaryKey,
|
||||
uniqueKeyPropertyName,
|
||||
lazy,
|
||||
unwrapProxy,
|
||||
|
|
|
@ -27,8 +27,6 @@ import java.io.Serializable;
|
|||
import java.util.Comparator;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.classic.Lifecycle;
|
||||
|
@ -39,6 +37,7 @@ import org.hibernate.tuple.component.ComponentMetamodel;
|
|||
import org.hibernate.usertype.CompositeUserType;
|
||||
import org.hibernate.usertype.ParameterizedType;
|
||||
import org.hibernate.usertype.UserType;
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
/**
|
||||
* Used internally to build instances of {@link Type}, specifically it builds instances of
|
||||
|
@ -208,6 +207,11 @@ public final class TypeFactory implements Serializable {
|
|||
|
||||
// one-to-one type builders ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link #oneToOne(String, ForeignKeyDirection, String, boolean, boolean, String, String, boolean)} instead.
|
||||
* See Jira issue: <a href="https://hibernate.onjira.com/browse/HHH-7771">HHH-7771</a>
|
||||
*/
|
||||
@Deprecated
|
||||
public EntityType oneToOne(
|
||||
String persistentClass,
|
||||
ForeignKeyDirection foreignKeyType,
|
||||
|
@ -216,10 +220,28 @@ public final class TypeFactory implements Serializable {
|
|||
boolean unwrapProxy,
|
||||
String entityName,
|
||||
String propertyName) {
|
||||
return new OneToOneType( typeScope, persistentClass, foreignKeyType, uniqueKeyPropertyName,
|
||||
lazy, unwrapProxy, entityName, propertyName );
|
||||
return oneToOne( persistentClass, foreignKeyType, uniqueKeyPropertyName == null, uniqueKeyPropertyName, lazy, unwrapProxy, entityName,
|
||||
propertyName );
|
||||
}
|
||||
|
||||
|
||||
public EntityType oneToOne(
|
||||
String persistentClass,
|
||||
ForeignKeyDirection foreignKeyType,
|
||||
boolean referenceToPrimaryKey,
|
||||
String uniqueKeyPropertyName,
|
||||
boolean lazy,
|
||||
boolean unwrapProxy,
|
||||
String entityName,
|
||||
String propertyName) {
|
||||
return new OneToOneType( typeScope, persistentClass, foreignKeyType, referenceToPrimaryKey,
|
||||
uniqueKeyPropertyName, lazy, unwrapProxy, entityName, propertyName );
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link #specialOneToOne(String, ForeignKeyDirection, String, boolean, boolean, String, String, boolean)} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public EntityType specialOneToOne(
|
||||
String persistentClass,
|
||||
ForeignKeyDirection foreignKeyType,
|
||||
|
@ -228,34 +250,21 @@ public final class TypeFactory implements Serializable {
|
|||
boolean unwrapProxy,
|
||||
String entityName,
|
||||
String propertyName) {
|
||||
return new SpecialOneToOneType( typeScope, persistentClass, foreignKeyType, uniqueKeyPropertyName,
|
||||
lazy, unwrapProxy, entityName, propertyName );
|
||||
}
|
||||
|
||||
public EntityType oneToOne(
|
||||
String persistentClass,
|
||||
ForeignKeyDirection foreignKeyType,
|
||||
String uniqueKeyPropertyName,
|
||||
boolean lazy,
|
||||
boolean unwrapProxy,
|
||||
String entityName,
|
||||
String propertyName,
|
||||
Class returnedClass) {
|
||||
return new OneToOneType( typeScope, persistentClass, foreignKeyType, uniqueKeyPropertyName,
|
||||
lazy, unwrapProxy, entityName, propertyName, returnedClass );
|
||||
return specialOneToOne( persistentClass, foreignKeyType, uniqueKeyPropertyName == null, uniqueKeyPropertyName, lazy, unwrapProxy,
|
||||
entityName, propertyName );
|
||||
}
|
||||
|
||||
public EntityType specialOneToOne(
|
||||
String persistentClass,
|
||||
ForeignKeyDirection foreignKeyType,
|
||||
boolean referenceToPrimaryKey,
|
||||
String uniqueKeyPropertyName,
|
||||
boolean lazy,
|
||||
boolean unwrapProxy,
|
||||
String entityName,
|
||||
String propertyName,
|
||||
Class returnedClass) {
|
||||
return new SpecialOneToOneType( typeScope, persistentClass, foreignKeyType, uniqueKeyPropertyName,
|
||||
lazy, unwrapProxy, entityName, propertyName, returnedClass );
|
||||
String propertyName) {
|
||||
return new SpecialOneToOneType( typeScope, persistentClass, foreignKeyType, referenceToPrimaryKey,
|
||||
uniqueKeyPropertyName, lazy, unwrapProxy, entityName, propertyName );
|
||||
}
|
||||
|
||||
|
||||
|
@ -269,6 +278,11 @@ public final class TypeFactory implements Serializable {
|
|||
return new ManyToOneType( typeScope, persistentClass, lazy );
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link #manyToOne(String, boolean, String, boolean, boolean, boolean, boolean)} instead.
|
||||
* See Jira issue: <a href="https://hibernate.onjira.com/browse/HHH-7771">HHH-7771</a>
|
||||
*/
|
||||
@Deprecated
|
||||
public EntityType manyToOne(
|
||||
String persistentClass,
|
||||
String uniqueKeyPropertyName,
|
||||
|
@ -276,9 +290,23 @@ public final class TypeFactory implements Serializable {
|
|||
boolean unwrapProxy,
|
||||
boolean ignoreNotFound,
|
||||
boolean isLogicalOneToOne) {
|
||||
return manyToOne( persistentClass, uniqueKeyPropertyName == null, uniqueKeyPropertyName, lazy, unwrapProxy, ignoreNotFound,
|
||||
isLogicalOneToOne );
|
||||
}
|
||||
|
||||
|
||||
public EntityType manyToOne(
|
||||
String persistentClass,
|
||||
boolean referenceToPrimaryKey,
|
||||
String uniqueKeyPropertyName,
|
||||
boolean lazy,
|
||||
boolean unwrapProxy,
|
||||
boolean ignoreNotFound,
|
||||
boolean isLogicalOneToOne) {
|
||||
return new ManyToOneType(
|
||||
typeScope,
|
||||
persistentClass,
|
||||
referenceToPrimaryKey,
|
||||
uniqueKeyPropertyName,
|
||||
lazy,
|
||||
unwrapProxy,
|
||||
|
@ -287,26 +315,6 @@ public final class TypeFactory implements Serializable {
|
|||
);
|
||||
}
|
||||
|
||||
public EntityType manyToOne(
|
||||
String persistentClass,
|
||||
String uniqueKeyPropertyName,
|
||||
boolean lazy,
|
||||
boolean unwrapProxy,
|
||||
boolean ignoreNotFound,
|
||||
boolean isLogicalOneToOne,
|
||||
Class returnedClass) {
|
||||
return new ManyToOneType(
|
||||
typeScope,
|
||||
persistentClass,
|
||||
uniqueKeyPropertyName,
|
||||
lazy,
|
||||
unwrapProxy,
|
||||
ignoreNotFound,
|
||||
isLogicalOneToOne ,
|
||||
returnedClass
|
||||
);
|
||||
}
|
||||
|
||||
// collection type builders ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
public CollectionType array(String role, String propertyRef, Class elementClass) {
|
||||
|
|
|
@ -0,0 +1,352 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2013, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.loader;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.ElementCollection;
|
||||
import javax.persistence.Embeddable;
|
||||
import javax.persistence.Embedded;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.EnumType;
|
||||
import javax.persistence.Enumerated;
|
||||
import javax.persistence.FetchType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.ManyToOne;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.engine.spi.LoadQueryInfluencers;
|
||||
import org.hibernate.engine.spi.QueryParameters;
|
||||
import org.hibernate.engine.spi.SessionImplementor;
|
||||
import org.hibernate.jdbc.Work;
|
||||
import org.hibernate.loader.internal.EntityLoadQueryBuilderImpl;
|
||||
import org.hibernate.loader.internal.LoadQueryAliasResolutionContextImpl;
|
||||
import org.hibernate.loader.internal.ResultSetProcessorImpl;
|
||||
import org.hibernate.loader.plan.internal.SingleRootReturnLoadPlanBuilderStrategy;
|
||||
import org.hibernate.loader.plan.spi.LoadPlan;
|
||||
import org.hibernate.loader.plan.spi.build.LoadPlanBuilder;
|
||||
import org.hibernate.loader.spi.LoadQueryAliasResolutionContext;
|
||||
import org.hibernate.loader.spi.NamedParameterContext;
|
||||
import org.hibernate.loader.spi.NoOpLoadPlanAdvisor;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.test.component.cascading.toone.PersonalInfo;
|
||||
import org.hibernate.testing.FailureExpected;
|
||||
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
||||
import org.hibernate.testing.junit4.ExtraAssertions;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertSame;
|
||||
|
||||
/**
|
||||
* @author Gail Badner
|
||||
*/
|
||||
public class EncapsulatedCompositeAttributeResultSetProcessorTest extends BaseCoreFunctionalTestCase {
|
||||
|
||||
@Override
|
||||
protected Class<?>[] getAnnotatedClasses() {
|
||||
return new Class[] { Person.class, Customer.class };
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSimpleNestedCompositeAttributeProcessing() throws Exception {
|
||||
// create some test data
|
||||
Session session = openSession();
|
||||
session.beginTransaction();
|
||||
Person person = new Person();
|
||||
person.id = 1;
|
||||
person.name = "Joe Blow";
|
||||
person.address = new Address();
|
||||
person.address.address1 = "1313 Mockingbird Lane";
|
||||
person.address.city = "Pleasantville";
|
||||
person.address.country = "USA";
|
||||
AddressType addressType = new AddressType();
|
||||
addressType.typeName = "snail mail";
|
||||
person.address.type = addressType;
|
||||
session.save( person );
|
||||
session.getTransaction().commit();
|
||||
session.close();
|
||||
|
||||
session = openSession();
|
||||
session.beginTransaction();
|
||||
Person personGotten = (Person) session.get( Person.class, person.id );
|
||||
assertEquals( person.id, personGotten.id );
|
||||
assertEquals( person.address.address1, personGotten.address.address1 );
|
||||
assertEquals( person.address.city, personGotten.address.city );
|
||||
assertEquals( person.address.country, personGotten.address.country );
|
||||
assertEquals( person.address.type.typeName, personGotten.address.type.typeName );
|
||||
session.getTransaction().commit();
|
||||
session.close();
|
||||
|
||||
List results = getResults( sessionFactory().getEntityPersister( Person.class.getName() ) );
|
||||
assertEquals( 1, results.size() );
|
||||
Object result = results.get( 0 );
|
||||
assertNotNull( result );
|
||||
|
||||
Person personWork = ExtraAssertions.assertTyping( Person.class, result );
|
||||
assertEquals( person.id, personWork.id );
|
||||
assertEquals( person.address.address1, personWork.address.address1 );
|
||||
assertEquals( person.address.city, personWork.address.city );
|
||||
assertEquals( person.address.country, personWork.address.country );
|
||||
assertEquals( person.address.type.typeName, personGotten.address.type.typeName );
|
||||
|
||||
// clean up test data
|
||||
session = openSession();
|
||||
session.beginTransaction();
|
||||
session.createQuery( "delete Person" ).executeUpdate();
|
||||
session.getTransaction().commit();
|
||||
session.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNestedCompositeElementCollectionProcessing() throws Exception {
|
||||
// create some test data
|
||||
Session session = openSession();
|
||||
session.beginTransaction();
|
||||
Person person = new Person();
|
||||
person.id = 1;
|
||||
person.name = "Joe Blow";
|
||||
session.save( person );
|
||||
Customer customer = new Customer();
|
||||
customer.id = 1L;
|
||||
Investment investment1 = new Investment();
|
||||
investment1.description = "stock";
|
||||
investment1.date = new Date();
|
||||
investment1.monetaryAmount = new MonetaryAmount();
|
||||
investment1.monetaryAmount.currency = MonetaryAmount.CurrencyCode.USD;
|
||||
investment1.monetaryAmount.amount = BigDecimal.valueOf( 1234, 2 );
|
||||
investment1.performedBy = person;
|
||||
Investment investment2 = new Investment();
|
||||
investment2.description = "bond";
|
||||
investment2.date = new Date();
|
||||
investment2.monetaryAmount = new MonetaryAmount();
|
||||
investment2.monetaryAmount.currency = MonetaryAmount.CurrencyCode.EUR;
|
||||
investment2.monetaryAmount.amount = BigDecimal.valueOf( 98176, 1 );
|
||||
customer.investments.add( investment1 );
|
||||
customer.investments.add( investment2 );
|
||||
session.save( customer );
|
||||
session.getTransaction().commit();
|
||||
session.close();
|
||||
|
||||
session = openSession();
|
||||
session.beginTransaction();
|
||||
Customer customerGotten = (Customer) session.get( Customer.class, customer.id );
|
||||
assertEquals( customer.id, customerGotten.id );
|
||||
session.getTransaction().commit();
|
||||
session.close();
|
||||
|
||||
List results = getResults( sessionFactory().getEntityPersister( Customer.class.getName() ) );
|
||||
|
||||
assertEquals( 2, results.size() );
|
||||
assertSame( results.get( 0 ), results.get( 1 ) );
|
||||
Object result = results.get( 0 );
|
||||
assertNotNull( result );
|
||||
|
||||
Customer customerWork = ExtraAssertions.assertTyping( Customer.class, result );
|
||||
|
||||
// clean up test data
|
||||
session = openSession();
|
||||
session.beginTransaction();
|
||||
session.delete( customerWork.investments.get( 0 ).performedBy );
|
||||
session.delete( customerWork );
|
||||
session.getTransaction().commit();
|
||||
session.close();
|
||||
}
|
||||
|
||||
private List<?> getResults(EntityPersister entityPersister ) {
|
||||
final SingleRootReturnLoadPlanBuilderStrategy strategy = new SingleRootReturnLoadPlanBuilderStrategy(
|
||||
sessionFactory(),
|
||||
LoadQueryInfluencers.NONE
|
||||
);
|
||||
final LoadPlan plan = LoadPlanBuilder.buildRootEntityLoadPlan( strategy, entityPersister );
|
||||
final LoadQueryAliasResolutionContext aliasResolutionContext =
|
||||
new LoadQueryAliasResolutionContextImpl(
|
||||
sessionFactory(),
|
||||
0,
|
||||
Collections.singletonMap( plan.getReturns().get( 0 ), new String[] { "abc" } )
|
||||
);
|
||||
final EntityLoadQueryBuilderImpl queryBuilder = new EntityLoadQueryBuilderImpl(
|
||||
LoadQueryInfluencers.NONE,
|
||||
plan
|
||||
);
|
||||
final String sql = queryBuilder.generateSql( 1, sessionFactory(), aliasResolutionContext );
|
||||
|
||||
final ResultSetProcessorImpl resultSetProcessor = new ResultSetProcessorImpl( plan );
|
||||
final List results = new ArrayList();
|
||||
|
||||
final Session workSession = openSession();
|
||||
workSession.beginTransaction();
|
||||
workSession.doWork(
|
||||
new Work() {
|
||||
@Override
|
||||
public void execute(Connection connection) throws SQLException {
|
||||
PreparedStatement ps = connection.prepareStatement( sql );
|
||||
ps.setInt( 1, 1 );
|
||||
ResultSet resultSet = ps.executeQuery();
|
||||
results.addAll(
|
||||
resultSetProcessor.extractResults(
|
||||
NoOpLoadPlanAdvisor.INSTANCE,
|
||||
resultSet,
|
||||
(SessionImplementor) workSession,
|
||||
new QueryParameters(),
|
||||
new NamedParameterContext() {
|
||||
@Override
|
||||
public int[] getNamedParameterLocations(String name) {
|
||||
return new int[0];
|
||||
}
|
||||
},
|
||||
aliasResolutionContext,
|
||||
true,
|
||||
false,
|
||||
null,
|
||||
null
|
||||
)
|
||||
);
|
||||
resultSet.close();
|
||||
ps.close();
|
||||
}
|
||||
}
|
||||
);
|
||||
workSession.getTransaction().commit();
|
||||
workSession.close();
|
||||
return results;
|
||||
}
|
||||
|
||||
@Entity( name = "Person" )
|
||||
public static class Person implements Serializable {
|
||||
@Id
|
||||
Integer id;
|
||||
String name;
|
||||
|
||||
@Embedded
|
||||
Address address;
|
||||
}
|
||||
|
||||
@Embeddable
|
||||
public static class Address implements Serializable {
|
||||
String address1;
|
||||
String city;
|
||||
String country;
|
||||
AddressType type;
|
||||
}
|
||||
|
||||
@Embeddable
|
||||
public static class AddressType {
|
||||
String typeName;
|
||||
}
|
||||
|
||||
@Entity( name = "Customer" )
|
||||
public static class Customer {
|
||||
private Long id;
|
||||
private List<Investment> investments = new ArrayList<Investment>();
|
||||
|
||||
@Id
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
@ElementCollection(fetch = FetchType.EAGER)
|
||||
public List<Investment> getInvestments() {
|
||||
return investments;
|
||||
}
|
||||
public void setInvestments(List<Investment> investments) {
|
||||
this.investments = investments;
|
||||
}
|
||||
}
|
||||
|
||||
@Embeddable
|
||||
public static class Investment {
|
||||
private MonetaryAmount monetaryAmount;
|
||||
private String description;
|
||||
private Date date;
|
||||
private Person performedBy;
|
||||
|
||||
@Embedded
|
||||
public MonetaryAmount getMonetaryAmount() {
|
||||
return monetaryAmount;
|
||||
}
|
||||
public void setMonetaryAmount(MonetaryAmount monetaryAmount) {
|
||||
this.monetaryAmount = monetaryAmount;
|
||||
}
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
public Date getDate() {
|
||||
return date;
|
||||
}
|
||||
public void setDate(Date date) {
|
||||
this.date = date;
|
||||
}
|
||||
@ManyToOne
|
||||
public Person getPerformedBy() {
|
||||
return performedBy;
|
||||
}
|
||||
public void setPerformedBy(Person performedBy) {
|
||||
this.performedBy = performedBy;
|
||||
}
|
||||
}
|
||||
|
||||
@Embeddable
|
||||
public static class MonetaryAmount {
|
||||
public static enum CurrencyCode {
|
||||
USD,
|
||||
EUR
|
||||
}
|
||||
private BigDecimal amount;
|
||||
@Column(length = 3)
|
||||
@Enumerated(EnumType.STRING)
|
||||
private CurrencyCode currency;
|
||||
|
||||
public BigDecimal getAmount() {
|
||||
return amount;
|
||||
}
|
||||
public void setAmount(BigDecimal amount) {
|
||||
this.amount = amount;
|
||||
}
|
||||
|
||||
public CurrencyCode getCurrency() {
|
||||
return currency;
|
||||
}
|
||||
public void setCurrency(CurrencyCode currency) {
|
||||
this.currency = currency;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,434 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2013, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.loader;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import javax.persistence.Embeddable;
|
||||
import javax.persistence.EmbeddedId;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.ManyToOne;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.hibernate.LockOptions;
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.engine.spi.LoadQueryInfluencers;
|
||||
import org.hibernate.engine.spi.QueryParameters;
|
||||
import org.hibernate.engine.spi.SessionImplementor;
|
||||
import org.hibernate.jdbc.Work;
|
||||
import org.hibernate.loader.internal.EntityLoadQueryBuilderImpl;
|
||||
import org.hibernate.loader.internal.LoadQueryAliasResolutionContextImpl;
|
||||
import org.hibernate.loader.internal.ResultSetProcessorImpl;
|
||||
import org.hibernate.loader.plan.internal.SingleRootReturnLoadPlanBuilderStrategy;
|
||||
import org.hibernate.loader.plan.spi.LoadPlan;
|
||||
import org.hibernate.loader.plan.spi.build.LoadPlanBuilder;
|
||||
import org.hibernate.loader.spi.LoadQueryAliasResolutionContext;
|
||||
import org.hibernate.loader.spi.NamedParameterContext;
|
||||
import org.hibernate.loader.spi.NoOpLoadPlanAdvisor;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
||||
import org.hibernate.testing.junit4.ExtraAssertions;
|
||||
import org.hibernate.type.Type;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* @author Gail Badner
|
||||
*/
|
||||
public class EncapsulatedCompositeIdResultSetProcessorTest extends BaseCoreFunctionalTestCase {
|
||||
|
||||
@Override
|
||||
protected Class<?>[] getAnnotatedClasses() {
|
||||
return new Class[] { Parent.class, CardField.class, Card.class };
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSimpleCompositeId() throws Exception {
|
||||
|
||||
// create some test data
|
||||
Session session = openSession();
|
||||
session.beginTransaction();
|
||||
Parent parent = new Parent();
|
||||
parent.id = new ParentPK();
|
||||
parent.id.firstName = "Joe";
|
||||
parent.id.lastName = "Blow";
|
||||
session.save( parent );
|
||||
session.getTransaction().commit();
|
||||
session.close();
|
||||
|
||||
session = openSession();
|
||||
session.beginTransaction();
|
||||
Parent parentGotten = (Parent) session.get( Parent.class, parent.id );
|
||||
assertEquals( parent, parentGotten );
|
||||
session.getTransaction().commit();
|
||||
session.close();
|
||||
|
||||
final List results = getResults(
|
||||
sessionFactory().getEntityPersister( Parent.class.getName() ),
|
||||
new Callback() {
|
||||
@Override
|
||||
public void bind(PreparedStatement ps) throws SQLException {
|
||||
ps.setString( 1, "Joe" );
|
||||
ps.setString( 2, "Blow" );
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryParameters getQueryParameters() {
|
||||
return new QueryParameters();
|
||||
}
|
||||
|
||||
}
|
||||
);
|
||||
assertEquals( 1, results.size() );
|
||||
Object result = results.get( 0 );
|
||||
assertNotNull( result );
|
||||
|
||||
Parent parentWork = ExtraAssertions.assertTyping( Parent.class, result );
|
||||
assertEquals( parent, parentWork );
|
||||
|
||||
// clean up test data
|
||||
session = openSession();
|
||||
session.beginTransaction();
|
||||
session.createQuery( "delete Parent" ).executeUpdate();
|
||||
session.getTransaction().commit();
|
||||
session.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCompositeIdWithKeyManyToOne() throws Exception {
|
||||
final String cardId = "ace-of-spades";
|
||||
|
||||
// create some test data
|
||||
Session session = openSession();
|
||||
session.beginTransaction();
|
||||
Card card = new Card( cardId );
|
||||
final CardField cardField = new CardField( card, 1 );
|
||||
session.persist( card );
|
||||
session.persist( cardField );
|
||||
session.getTransaction().commit();
|
||||
session.close();
|
||||
|
||||
session = openSession();
|
||||
session.beginTransaction();
|
||||
Card cardProxy = (Card) session.load( Card.class, cardId );
|
||||
final CardFieldPK cardFieldPK = new CardFieldPK( cardProxy, 1 );
|
||||
CardField cardFieldGotten = (CardField) session.get( CardField.class, cardFieldPK );
|
||||
|
||||
//assertEquals( card, cardGotten );
|
||||
session.getTransaction().commit();
|
||||
session.close();
|
||||
|
||||
final EntityPersister entityPersister = sessionFactory().getEntityPersister( CardField.class.getName() );
|
||||
|
||||
final List results = getResults(
|
||||
entityPersister,
|
||||
new Callback() {
|
||||
@Override
|
||||
public void bind(PreparedStatement ps) throws SQLException {
|
||||
ps.setString( 1, cardField.primaryKey.card.id );
|
||||
ps.setInt( 2, cardField.primaryKey.fieldNumber );
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryParameters getQueryParameters() {
|
||||
QueryParameters qp = new QueryParameters();
|
||||
qp.setPositionalParameterTypes( new Type[] { entityPersister.getIdentifierType() } );
|
||||
qp.setPositionalParameterValues( new Object[] { cardFieldPK } );
|
||||
qp.setOptionalObject( null );
|
||||
qp.setOptionalEntityName( entityPersister.getEntityName() );
|
||||
qp.setOptionalId( cardFieldPK );
|
||||
qp.setLockOptions( LockOptions.NONE );
|
||||
return qp;
|
||||
}
|
||||
|
||||
}
|
||||
);
|
||||
assertEquals( 1, results.size() );
|
||||
Object result = results.get( 0 );
|
||||
assertNotNull( result );
|
||||
|
||||
CardField cardFieldWork = ExtraAssertions.assertTyping( CardField.class, result );
|
||||
assertEquals( cardFieldGotten, cardFieldWork );
|
||||
|
||||
// clean up test data
|
||||
session = openSession();
|
||||
session.beginTransaction();
|
||||
session.createQuery( "delete CardField" ).executeUpdate();
|
||||
session.createQuery( "delete Card" ).executeUpdate();
|
||||
session.getTransaction().commit();
|
||||
session.close();
|
||||
}
|
||||
|
||||
private List getResults(final EntityPersister entityPersister, final Callback callback) {
|
||||
final SingleRootReturnLoadPlanBuilderStrategy strategy = new SingleRootReturnLoadPlanBuilderStrategy(
|
||||
sessionFactory(),
|
||||
LoadQueryInfluencers.NONE
|
||||
);
|
||||
final LoadPlan plan = LoadPlanBuilder.buildRootEntityLoadPlan( strategy, entityPersister );
|
||||
final LoadQueryAliasResolutionContext aliasResolutionContext =
|
||||
new LoadQueryAliasResolutionContextImpl(
|
||||
sessionFactory(),
|
||||
0,
|
||||
Collections.singletonMap( plan.getReturns().get( 0 ), new String[] { "abc" } )
|
||||
);
|
||||
final EntityLoadQueryBuilderImpl queryBuilder = new EntityLoadQueryBuilderImpl(
|
||||
LoadQueryInfluencers.NONE,
|
||||
plan
|
||||
);
|
||||
final String sql = queryBuilder.generateSql( 1, sessionFactory(), aliasResolutionContext );
|
||||
|
||||
final ResultSetProcessorImpl resultSetProcessor = new ResultSetProcessorImpl( plan );
|
||||
final List results = new ArrayList();
|
||||
|
||||
final Session workSession = openSession();
|
||||
workSession.beginTransaction();
|
||||
workSession.doWork(
|
||||
new Work() {
|
||||
@Override
|
||||
public void execute(Connection connection) throws SQLException {
|
||||
PreparedStatement ps = connection.prepareStatement( sql );
|
||||
callback.bind( ps );
|
||||
ResultSet resultSet = ps.executeQuery();
|
||||
//callback.beforeExtractResults( workSession );
|
||||
results.addAll(
|
||||
resultSetProcessor.extractResults(
|
||||
NoOpLoadPlanAdvisor.INSTANCE,
|
||||
resultSet,
|
||||
(SessionImplementor) workSession,
|
||||
callback.getQueryParameters(),
|
||||
new NamedParameterContext() {
|
||||
@Override
|
||||
public int[] getNamedParameterLocations(String name) {
|
||||
return new int[0];
|
||||
}
|
||||
},
|
||||
aliasResolutionContext,
|
||||
true,
|
||||
false,
|
||||
null,
|
||||
null
|
||||
)
|
||||
);
|
||||
resultSet.close();
|
||||
ps.close();
|
||||
}
|
||||
}
|
||||
);
|
||||
workSession.getTransaction().commit();
|
||||
workSession.close();
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
|
||||
private interface Callback {
|
||||
void bind(PreparedStatement ps) throws SQLException;
|
||||
QueryParameters getQueryParameters ();
|
||||
}
|
||||
|
||||
@Entity ( name = "Parent" )
|
||||
public static class Parent {
|
||||
@EmbeddedId
|
||||
public ParentPK id;
|
||||
|
||||
public boolean equals(Object o) {
|
||||
if ( this == o ) return true;
|
||||
if ( !( o instanceof Parent ) ) return false;
|
||||
|
||||
final Parent parent = (Parent) o;
|
||||
|
||||
if ( !id.equals( parent.id ) ) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return id.hashCode();
|
||||
}
|
||||
}
|
||||
|
||||
@Embeddable
|
||||
public static class ParentPK implements Serializable {
|
||||
private String firstName;
|
||||
private String lastName;
|
||||
|
||||
public boolean equals(Object o) {
|
||||
if ( this == o ) return true;
|
||||
if ( !( o instanceof ParentPK ) ) return false;
|
||||
|
||||
final ParentPK parentPk = (ParentPK) o;
|
||||
|
||||
if ( !firstName.equals( parentPk.firstName ) ) return false;
|
||||
if ( !lastName.equals( parentPk.lastName ) ) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
int result;
|
||||
result = firstName.hashCode();
|
||||
result = 29 * result + lastName.hashCode();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@Entity ( name = "CardField" )
|
||||
public static class CardField implements Serializable {
|
||||
|
||||
@EmbeddedId
|
||||
private CardFieldPK primaryKey;
|
||||
|
||||
CardField(Card card, int fieldNumber) {
|
||||
this.primaryKey = new CardFieldPK(card, fieldNumber);
|
||||
}
|
||||
|
||||
CardField() {
|
||||
}
|
||||
|
||||
public CardFieldPK getPrimaryKey() {
|
||||
return primaryKey;
|
||||
}
|
||||
|
||||
public void setPrimaryKey(CardFieldPK primaryKey) {
|
||||
this.primaryKey = primaryKey;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if ( this == o ) {
|
||||
return true;
|
||||
}
|
||||
if ( o == null || getClass() != o.getClass() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
CardField cardField = (CardField) o;
|
||||
|
||||
if ( primaryKey != null ? !primaryKey.equals( cardField.primaryKey ) : cardField.primaryKey != null ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return primaryKey != null ? primaryKey.hashCode() : 0;
|
||||
}
|
||||
}
|
||||
|
||||
@Embeddable
|
||||
public static class CardFieldPK implements Serializable {
|
||||
@ManyToOne(optional = false)
|
||||
private Card card;
|
||||
|
||||
private int fieldNumber;
|
||||
|
||||
public CardFieldPK(Card card, int fieldNumber) {
|
||||
this.card = card;
|
||||
this.fieldNumber = fieldNumber;
|
||||
}
|
||||
|
||||
CardFieldPK() {
|
||||
}
|
||||
|
||||
public Card getCard() {
|
||||
return card;
|
||||
}
|
||||
|
||||
public void setCard(Card card) {
|
||||
this.card = card;
|
||||
}
|
||||
|
||||
public int getFieldNumber() {
|
||||
return fieldNumber;
|
||||
}
|
||||
|
||||
public void setFieldNumber(int fieldNumber) {
|
||||
this.fieldNumber = fieldNumber;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if ( this == o ) {
|
||||
return true;
|
||||
}
|
||||
if ( o == null || getClass() != o.getClass() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
CardFieldPK that = (CardFieldPK) o;
|
||||
|
||||
if ( fieldNumber != that.fieldNumber ) {
|
||||
return false;
|
||||
}
|
||||
if ( card != null ? !card.equals( that.card ) : that.card != null ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = card != null ? card.hashCode() : 0;
|
||||
result = 31 * result + fieldNumber;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@Entity ( name = "Card" )
|
||||
public static class Card implements Serializable {
|
||||
@Id
|
||||
private String id;
|
||||
|
||||
public Card(String id) {
|
||||
this();
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
Card() {
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -69,7 +69,7 @@ import static org.junit.Assert.assertTrue;
|
|||
* @author Gail Badner
|
||||
*/
|
||||
@FailureExpectedWithNewMetamodel
|
||||
public class EntityWithCollectionResultSetProcessorTest extends BaseCoreFunctionalTestCase {
|
||||
public class EntityWithNonLazyCollectionResultSetProcessorTest extends BaseCoreFunctionalTestCase {
|
||||
|
||||
@Override
|
||||
protected Class<?>[] getAnnotatedClasses() {
|
|
@ -0,0 +1,215 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2013, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.loader;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
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.junit.Test;
|
||||
|
||||
import org.hibernate.Hibernate;
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.engine.spi.LoadQueryInfluencers;
|
||||
import org.hibernate.engine.spi.QueryParameters;
|
||||
import org.hibernate.engine.spi.SessionImplementor;
|
||||
import org.hibernate.jdbc.Work;
|
||||
import org.hibernate.loader.internal.EntityLoadQueryBuilderImpl;
|
||||
import org.hibernate.loader.internal.LoadQueryAliasResolutionContextImpl;
|
||||
import org.hibernate.loader.internal.ResultSetProcessorImpl;
|
||||
import org.hibernate.loader.plan.internal.SingleRootReturnLoadPlanBuilderStrategy;
|
||||
import org.hibernate.loader.plan.spi.LoadPlan;
|
||||
import org.hibernate.loader.plan.spi.build.LoadPlanBuilder;
|
||||
import org.hibernate.loader.spi.LoadQueryAliasResolutionContext;
|
||||
import org.hibernate.loader.spi.NamedParameterContext;
|
||||
import org.hibernate.loader.spi.NoOpLoadPlanAdvisor;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
||||
import org.hibernate.testing.junit4.ExtraAssertions;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* @author Gail Badner
|
||||
*/
|
||||
public class EntityWithNonLazyOneToManyListResultSetProcessorTest extends BaseCoreFunctionalTestCase {
|
||||
|
||||
@Override
|
||||
protected Class<?>[] getAnnotatedClasses() {
|
||||
return new Class[] { Poster.class, Message.class };
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEntityWithList() throws Exception {
|
||||
final EntityPersister entityPersister = sessionFactory().getEntityPersister( Poster.class.getName() );
|
||||
|
||||
// create some test data
|
||||
Session session = openSession();
|
||||
session.beginTransaction();
|
||||
Poster poster = new Poster();
|
||||
poster.pid = 0;
|
||||
poster.name = "John Doe";
|
||||
Message message1 = new Message();
|
||||
message1.mid = 1;
|
||||
message1.msgTxt = "Howdy!";
|
||||
message1.poster = poster;
|
||||
poster.messages.add( message1 );
|
||||
Message message2 = new Message();
|
||||
message2.mid = 2;
|
||||
message2.msgTxt = "Bye!";
|
||||
message2.poster = poster;
|
||||
poster.messages.add( message2 );
|
||||
session.save( poster );
|
||||
session.getTransaction().commit();
|
||||
session.close();
|
||||
|
||||
session = openSession();
|
||||
session.beginTransaction();
|
||||
Poster posterGotten = (Poster) session.get( Poster.class, poster.pid );
|
||||
assertEquals( 0, posterGotten.pid.intValue() );
|
||||
assertEquals( poster.name, posterGotten.name );
|
||||
assertTrue( Hibernate.isInitialized( posterGotten.messages ) );
|
||||
assertEquals( 2, posterGotten.messages.size() );
|
||||
assertEquals( message1.msgTxt, posterGotten.messages.get( 0 ).msgTxt );
|
||||
assertEquals( message2.msgTxt, posterGotten.messages.get( 1 ).msgTxt );
|
||||
assertSame( posterGotten, posterGotten.messages.get( 0 ).poster );
|
||||
assertSame( posterGotten, posterGotten.messages.get( 1 ).poster );
|
||||
session.getTransaction().commit();
|
||||
session.close();
|
||||
|
||||
{
|
||||
final SingleRootReturnLoadPlanBuilderStrategy strategy = new SingleRootReturnLoadPlanBuilderStrategy(
|
||||
sessionFactory(),
|
||||
LoadQueryInfluencers.NONE
|
||||
);
|
||||
final LoadPlan plan = LoadPlanBuilder.buildRootEntityLoadPlan( strategy, entityPersister );
|
||||
final LoadQueryAliasResolutionContext aliasResolutionContext =
|
||||
new LoadQueryAliasResolutionContextImpl(
|
||||
sessionFactory(),
|
||||
0,
|
||||
Collections.singletonMap( plan.getReturns().get( 0 ), new String[] { "abc" } )
|
||||
);
|
||||
final EntityLoadQueryBuilderImpl queryBuilder = new EntityLoadQueryBuilderImpl(
|
||||
LoadQueryInfluencers.NONE,
|
||||
plan
|
||||
);
|
||||
final String sql = queryBuilder.generateSql( 1, sessionFactory(), aliasResolutionContext );
|
||||
|
||||
final ResultSetProcessorImpl resultSetProcessor = new ResultSetProcessorImpl( plan );
|
||||
final List results = new ArrayList();
|
||||
|
||||
final Session workSession = openSession();
|
||||
workSession.beginTransaction();
|
||||
workSession.doWork(
|
||||
new Work() {
|
||||
@Override
|
||||
public void execute(Connection connection) throws SQLException {
|
||||
PreparedStatement ps = connection.prepareStatement( sql );
|
||||
ps.setInt( 1, 0 );
|
||||
ResultSet resultSet = ps.executeQuery();
|
||||
results.addAll(
|
||||
resultSetProcessor.extractResults(
|
||||
NoOpLoadPlanAdvisor.INSTANCE,
|
||||
resultSet,
|
||||
(SessionImplementor) workSession,
|
||||
new QueryParameters(),
|
||||
new NamedParameterContext() {
|
||||
@Override
|
||||
public int[] getNamedParameterLocations(String name) {
|
||||
return new int[0];
|
||||
}
|
||||
},
|
||||
aliasResolutionContext,
|
||||
true,
|
||||
false,
|
||||
null,
|
||||
null
|
||||
)
|
||||
);
|
||||
resultSet.close();
|
||||
ps.close();
|
||||
}
|
||||
}
|
||||
);
|
||||
assertEquals( 2, results.size() );
|
||||
Object result1 = results.get( 0 );
|
||||
assertNotNull( result1 );
|
||||
assertSame( result1, results.get( 1 ) );
|
||||
|
||||
Poster workPoster = ExtraAssertions.assertTyping( Poster.class, result1 );
|
||||
assertEquals( 0, workPoster.pid.intValue() );
|
||||
assertEquals( poster.name, workPoster.name );
|
||||
assertTrue( Hibernate.isInitialized( workPoster.messages ) );
|
||||
assertEquals( 2, workPoster.messages.size() );
|
||||
assertTrue( Hibernate.isInitialized( posterGotten.messages ) );
|
||||
assertEquals( 2, workPoster.messages.size() );
|
||||
assertEquals( message1.msgTxt, workPoster.messages.get( 0 ).msgTxt );
|
||||
assertEquals( message2.msgTxt, workPoster.messages.get( 1 ).msgTxt );
|
||||
assertSame( workPoster, workPoster.messages.get( 0 ).poster );
|
||||
assertSame( workPoster, workPoster.messages.get( 1 ).poster );
|
||||
workSession.getTransaction().commit();
|
||||
workSession.close();
|
||||
}
|
||||
|
||||
// clean up test data
|
||||
session = openSession();
|
||||
session.beginTransaction();
|
||||
session.delete( poster );
|
||||
session.getTransaction().commit();
|
||||
session.close();
|
||||
}
|
||||
|
||||
@Entity( name = "Message" )
|
||||
public static class Message {
|
||||
@Id
|
||||
private Integer mid;
|
||||
private String msgTxt;
|
||||
@ManyToOne
|
||||
@JoinColumn
|
||||
private Poster poster;
|
||||
}
|
||||
|
||||
@Entity( name = "Poster" )
|
||||
public static class Poster {
|
||||
@Id
|
||||
private Integer pid;
|
||||
private String name;
|
||||
@OneToMany(mappedBy = "poster", fetch = FetchType.EAGER, cascade = CascadeType.ALL )
|
||||
private List<Message> messages = new ArrayList<Message>();
|
||||
}
|
||||
}
|
|
@ -72,7 +72,7 @@ import static org.junit.Assert.fail;
|
|||
* @author Gail Badner
|
||||
*/
|
||||
@FailureExpectedWithNewMetamodel
|
||||
public class EntityWithOneToManyResultSetProcessorTest extends BaseCoreFunctionalTestCase {
|
||||
public class EntityWithNonLazyOneToManySetResultSetProcessorTest extends BaseCoreFunctionalTestCase {
|
||||
|
||||
@Override
|
||||
protected Class<?>[] getAnnotatedClasses() {
|
|
@ -38,6 +38,7 @@ import org.hibernate.persister.walking.spi.CollectionDefinition;
|
|||
import org.hibernate.persister.walking.spi.CollectionElementDefinition;
|
||||
import org.hibernate.persister.walking.spi.CollectionIndexDefinition;
|
||||
import org.hibernate.persister.walking.spi.CompositionDefinition;
|
||||
import org.hibernate.persister.walking.spi.CompositionElementDefinition;
|
||||
import org.hibernate.persister.walking.spi.EntityDefinition;
|
||||
import org.hibernate.persister.walking.spi.EntityIdentifierDefinition;
|
||||
import org.hibernate.persister.walking.spi.MetadataDrivenModelGraphVisitor;
|
||||
|
@ -168,6 +169,28 @@ public class BasicWalkingTest extends BaseCoreFunctionalTestCase {
|
|||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startingCompositeElement(CompositionElementDefinition compositionElementDefinition) {
|
||||
System.out.println(
|
||||
String.format(
|
||||
"%s Starting composite (%s)",
|
||||
StringHelper.repeat( ">>", ++depth ),
|
||||
compositionElementDefinition.toString()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void finishingCompositeElement(CompositionElementDefinition compositionElementDefinition) {
|
||||
System.out.println(
|
||||
String.format(
|
||||
"%s Finishing composite (%s)",
|
||||
StringHelper.repeat( ">>", depth-- ),
|
||||
compositionElementDefinition.toString()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean startingAttribute(AttributeDefinition attributeDefinition) {
|
||||
System.out.println(
|
||||
|
|
|
@ -26,6 +26,9 @@ package org.hibernate.test.annotations.derivedidentities.bidirectional;
|
|||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.Query;
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.testing.FailureExpected;
|
||||
import org.hibernate.testing.TestForIssue;
|
||||
|
@ -35,6 +38,7 @@ import org.junit.Test;
|
|||
@FailureExpected(jiraKey = "HHH-5695")
|
||||
public class OneToOneWithDerivedIdentityTest extends BaseCoreFunctionalTestCase {
|
||||
@Test
|
||||
@TestForIssue(jiraKey = "HHH-5695")
|
||||
public void testInsertFooAndBarWithDerivedId() {
|
||||
Session s = openSession();
|
||||
s.beginTransaction();
|
||||
|
@ -81,11 +85,50 @@ public class OneToOneWithDerivedIdentityTest extends BaseCoreFunctionalTestCase
|
|||
s.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestForIssue(jiraKey = "HHH-6813")
|
||||
// Regression test utilizing multiple types of queries.
|
||||
public void testCase() {
|
||||
Session s = openSession();
|
||||
s.getTransaction().begin();
|
||||
|
||||
Person p = new Person();
|
||||
p.setName( "Alfio" );
|
||||
PersonInfo pi = new PersonInfo();
|
||||
pi.setId( p );
|
||||
pi.setInfo( "Some information" );
|
||||
s.persist( p );
|
||||
s.persist( pi );
|
||||
|
||||
s.getTransaction().commit();
|
||||
s.clear();
|
||||
|
||||
s.getTransaction().begin();
|
||||
|
||||
Query q = s.getNamedQuery( "PersonQuery" );
|
||||
List<Person> persons = q.list();
|
||||
assertEquals( persons.size(), 1 );
|
||||
assertEquals( persons.get( 0 ).getName(), "Alfio" );
|
||||
|
||||
s.getTransaction().commit();
|
||||
s.clear();
|
||||
|
||||
s.getTransaction().begin();
|
||||
|
||||
p = (Person) s.get( Person.class, persons.get( 0 ).getId() );
|
||||
assertEquals( p.getName(), "Alfio" );
|
||||
|
||||
s.getTransaction().commit();
|
||||
s.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<?>[] getAnnotatedClasses() {
|
||||
return new Class<?>[] {
|
||||
Foo.class,
|
||||
Bar.class
|
||||
Bar.class,
|
||||
Person.class,
|
||||
PersonInfo.class
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,77 @@
|
|||
package org.hibernate.test.annotations.derivedidentities.bidirectional;
|
||||
|
||||
import java.io.Serializable;
|
||||
import javax.persistence.Basic;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.NamedQuery;
|
||||
import javax.persistence.OneToOne;
|
||||
|
||||
@Entity
|
||||
@NamedQuery(name="PersonQuery", query="SELECT p FROM Person p")
|
||||
public class Person
|
||||
implements Serializable
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy=GenerationType.AUTO)
|
||||
private Integer id;
|
||||
|
||||
@Basic
|
||||
private String name;
|
||||
|
||||
@OneToOne(mappedBy="id")
|
||||
private PersonInfo personInfo;
|
||||
|
||||
public Integer getId()
|
||||
{
|
||||
return this.id;
|
||||
}
|
||||
|
||||
public void setId(Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public int hashCode()
|
||||
{
|
||||
int hash = 0;
|
||||
hash += (this.id != null ? this.id.hashCode() : 0);
|
||||
return hash;
|
||||
}
|
||||
|
||||
public boolean equals(Object object)
|
||||
{
|
||||
if (!(object instanceof Person)) {
|
||||
return false;
|
||||
}
|
||||
Person other = (Person)object;
|
||||
|
||||
return ((this.id != null) || (other.id == null)) && ((this.id == null) || (this.id.equals(other.id)));
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
return "nogroup.hibertest.Person[ id=" + this.id + " ]";
|
||||
}
|
||||
|
||||
public PersonInfo getPersonInfo()
|
||||
{
|
||||
return this.personInfo;
|
||||
}
|
||||
|
||||
public void setPersonInfo(PersonInfo personInfo)
|
||||
{
|
||||
this.personInfo = personInfo;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
package org.hibernate.test.annotations.derivedidentities.bidirectional;
|
||||
|
||||
import java.io.Serializable;
|
||||
import javax.persistence.Basic;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.OneToOne;
|
||||
|
||||
@Entity
|
||||
public class PersonInfo
|
||||
implements Serializable
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Id
|
||||
@OneToOne
|
||||
private Person id;
|
||||
|
||||
@Basic
|
||||
private String info;
|
||||
|
||||
public Person getId()
|
||||
{
|
||||
return this.id;
|
||||
}
|
||||
|
||||
public void setId(Person id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getInfo() {
|
||||
return this.info;
|
||||
}
|
||||
|
||||
public void setInfo(String info) {
|
||||
this.info = info;
|
||||
}
|
||||
|
||||
public int hashCode()
|
||||
{
|
||||
int hash = 0;
|
||||
hash += (this.id != null ? this.id.hashCode() : 0);
|
||||
return hash;
|
||||
}
|
||||
|
||||
public boolean equals(Object object)
|
||||
{
|
||||
if (!(object instanceof PersonInfo)) {
|
||||
return false;
|
||||
}
|
||||
PersonInfo other = (PersonInfo)object;
|
||||
|
||||
return ((this.id != null) || (other.id == null)) && ((this.id == null) || (this.id.equals(other.id)));
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
return "nogroup.hibertest.PersonInfo[ id=" + this.id + " ]";
|
||||
}
|
||||
}
|
|
@ -38,7 +38,7 @@ import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
|
|||
import org.hibernate.engine.jdbc.env.spi.LobCreatorBuilder;
|
||||
import org.hibernate.engine.jdbc.env.spi.QualifiedObjectNameSupport;
|
||||
import org.hibernate.engine.jdbc.internal.ResultSetWrapperImpl;
|
||||
import org.hibernate.engine.jdbc.internal.TypeInfo;
|
||||
import org.hibernate.engine.jdbc.spi.TypeInfo;
|
||||
import org.hibernate.engine.jdbc.spi.JdbcServices;
|
||||
import org.hibernate.engine.jdbc.spi.ResultSetWrapper;
|
||||
import org.hibernate.engine.jdbc.spi.SqlExceptionHelper;
|
||||
|
|
|
@ -1007,7 +1007,8 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil
|
|||
sessionFactory,
|
||||
settings,
|
||||
configurationValues,
|
||||
serviceRegistry.getService( ConfigurationService.class ).getSettings()
|
||||
serviceRegistry.getService( ConfigurationService.class ).getSettings(),
|
||||
metadata
|
||||
);
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -68,7 +68,7 @@ public abstract class AbstractScannerImpl implements Scanner {
|
|||
|
||||
if ( persistenceUnit.getPersistenceUnitRootUrl() != null ) {
|
||||
final ArchiveDescriptor descriptor = buildArchiveDescriptor( persistenceUnit.getPersistenceUnitRootUrl(), true, scanOptions );
|
||||
final ArchiveContext context = buildArchiveContext( persistenceUnit, false, resultCollector );
|
||||
final ArchiveContext context = buildArchiveContext( persistenceUnit, true, resultCollector );
|
||||
descriptor.visitArchive( context );
|
||||
}
|
||||
|
||||
|
|
|
@ -162,42 +162,42 @@ public abstract class AbstractGraphNode<T> implements GraphNodeImplementor {
|
|||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <X> Subgraph<X> addSubgraph(Attribute<T, X> attribute) {
|
||||
public <X> SubgraphImpl<X> addSubgraph(Attribute<T, X> attribute) {
|
||||
return addAttribute( attribute ).makeSubgraph();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <X> Subgraph<? extends X> addSubgraph(Attribute<T, X> attribute, Class<? extends X> type) {
|
||||
public <X> SubgraphImpl<? extends X> addSubgraph(Attribute<T, X> attribute, Class<? extends X> type) {
|
||||
return addAttribute( attribute ).makeSubgraph( type );
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <X> Subgraph<X> addSubgraph(String attributeName) {
|
||||
public <X> SubgraphImpl<X> addSubgraph(String attributeName) {
|
||||
return addAttribute( attributeName ).makeSubgraph();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <X> Subgraph<X> addSubgraph(String attributeName, Class<X> type) {
|
||||
public <X> SubgraphImpl<X> addSubgraph(String attributeName, Class<X> type) {
|
||||
return addAttribute( attributeName ).makeSubgraph( type );
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <X> Subgraph<X> addKeySubgraph(Attribute<T, X> attribute) {
|
||||
public <X> SubgraphImpl<X> addKeySubgraph(Attribute<T, X> attribute) {
|
||||
return addAttribute( attribute ).makeKeySubgraph();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <X> Subgraph<? extends X> addKeySubgraph(Attribute<T, X> attribute, Class<? extends X> type) {
|
||||
public <X> SubgraphImpl<? extends X> addKeySubgraph(Attribute<T, X> attribute, Class<? extends X> type) {
|
||||
return addAttribute( attribute ).makeKeySubgraph( type );
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <X> Subgraph<X> addKeySubgraph(String attributeName) {
|
||||
public <X> SubgraphImpl<X> addKeySubgraph(String attributeName) {
|
||||
return addAttribute( attributeName ).makeKeySubgraph();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <X> Subgraph<X> addKeySubgraph(String attributeName, Class<X> type) {
|
||||
public <X> SubgraphImpl<X> addKeySubgraph(String attributeName, Class<X> type) {
|
||||
return addAttribute( attributeName ).makeKeySubgraph( type );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -108,16 +108,16 @@ public class AttributeNodeImpl<T> implements AttributeNode<T>, AttributeNodeImpl
|
|||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> Subgraph<T> makeSubgraph() {
|
||||
return (Subgraph<T>) internalMakeSubgraph( null );
|
||||
public <T> SubgraphImpl<T> makeSubgraph() {
|
||||
return (SubgraphImpl<T>) internalMakeSubgraph( null );
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <X extends T> Subgraph<X> makeSubgraph(Class<X> type) {
|
||||
return (Subgraph<X>) internalMakeSubgraph( type );
|
||||
public <X extends T> SubgraphImpl<X> makeSubgraph(Class<X> type) {
|
||||
return (SubgraphImpl<X>) internalMakeSubgraph( type );
|
||||
}
|
||||
|
||||
private Subgraph internalMakeSubgraph(Class type) {
|
||||
private SubgraphImpl internalMakeSubgraph(Class type) {
|
||||
if ( attribute.getPersistentAttributeType() == Attribute.PersistentAttributeType.BASIC
|
||||
|| attribute.getPersistentAttributeType() == Attribute.PersistentAttributeType.EMBEDDED ) {
|
||||
throw new IllegalArgumentException(
|
||||
|
@ -193,12 +193,17 @@ public class AttributeNodeImpl<T> implements AttributeNode<T>, AttributeNodeImpl
|
|||
return type.isAssignableFrom( entityPersister.getMappedClass() );
|
||||
}
|
||||
|
||||
public <T> Subgraph<T> makeKeySubgraph() {
|
||||
return (SubgraphImpl<T>) makeKeySubgraph( null );
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> SubgraphImpl<T> makeKeySubgraph() {
|
||||
return (SubgraphImpl<T>) internalMakeKeySubgraph( null );
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <X extends T> Subgraph<X> makeKeySubgraph(Class<X> type) {
|
||||
public <X extends T> SubgraphImpl<X> makeKeySubgraph(Class<X> type) {
|
||||
return (SubgraphImpl<X>) internalMakeKeySubgraph( type );
|
||||
}
|
||||
|
||||
public SubgraphImpl internalMakeKeySubgraph(Class type) {
|
||||
if ( ! attribute.isCollection() ) {
|
||||
throw new IllegalArgumentException(
|
||||
String.format( "Non-collection attribute [%s] cannot be target of key subgraph", getAttributeName() )
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue