HHH-6491 Binding @SqlResultSetMapping
This commit is contained in:
parent
1679b1d3fc
commit
c1e40df164
|
@ -107,12 +107,12 @@ public class ResultsetMappingSecondPass implements QuerySecondPass {
|
|||
int dotIndex = name.lastIndexOf( '.' );
|
||||
String reducedName = name.substring( 0, dotIndex );
|
||||
Iterator parentPropIter = getSubPropertyIterator( pc, reducedName );
|
||||
List followers = getFollowers( parentPropIter, reducedName, name );
|
||||
List<String> followers = getFollowers( parentPropIter, reducedName, name );
|
||||
|
||||
int index = propertyNames.size();
|
||||
int followersSize = followers.size();
|
||||
for (int loop = 0; loop < followersSize; loop++) {
|
||||
String follower = (String) followers.get( loop );
|
||||
String follower = followers.get( loop );
|
||||
int currentIndex = getIndexOfFirstMatchingProperty( propertyNames, follower );
|
||||
index = currentIndex != -1 && currentIndex < index ? currentIndex : index;
|
||||
}
|
||||
|
@ -123,8 +123,8 @@ public class ResultsetMappingSecondPass implements QuerySecondPass {
|
|||
|
||||
Set<String> uniqueReturnProperty = new HashSet<String>();
|
||||
Map<String, ArrayList<String>> propertyResultsTmp = new HashMap<String, ArrayList<String>>();
|
||||
for ( Object property : properties ) {
|
||||
final FieldResult propertyresult = ( FieldResult ) property;
|
||||
for ( FieldResult property : properties ) {
|
||||
final FieldResult propertyresult = property;
|
||||
final String name = propertyresult.name();
|
||||
if ( "class".equals( name ) ) {
|
||||
throw new MappingException(
|
||||
|
@ -132,13 +132,12 @@ public class ResultsetMappingSecondPass implements QuerySecondPass {
|
|||
);
|
||||
}
|
||||
|
||||
if ( uniqueReturnProperty.contains( name ) ) {
|
||||
if ( !uniqueReturnProperty.add( name ) ) {
|
||||
throw new MappingException(
|
||||
"duplicate @FieldResult for property " + name +
|
||||
" on @Entity " + entity.entityClass().getName() + " in " + ann.name()
|
||||
);
|
||||
}
|
||||
uniqueReturnProperty.add( name );
|
||||
|
||||
final String quotingNormalizedColumnName = mappings.getObjectNameNormalizer()
|
||||
.normalizeIdentifierQuoting( propertyresult.column() );
|
||||
|
@ -167,10 +166,6 @@ public class ResultsetMappingSecondPass implements QuerySecondPass {
|
|||
propertyResults.put( "class", new String[] { quotingNormalizedName } );
|
||||
}
|
||||
|
||||
if ( propertyResults.isEmpty() ) {
|
||||
propertyResults = java.util.Collections.emptyMap();
|
||||
}
|
||||
|
||||
NativeSQLQueryRootReturn result = new NativeSQLQueryRootReturn(
|
||||
"alias" + entityAliasIndex++,
|
||||
entity.entityClass().getName(),
|
||||
|
@ -202,7 +197,7 @@ public class ResultsetMappingSecondPass implements QuerySecondPass {
|
|||
@SuppressWarnings({ "unchecked" })
|
||||
private List getFollowers(Iterator parentPropIter, String reducedName, String name) {
|
||||
boolean hasFollowers = false;
|
||||
List followers = new ArrayList();
|
||||
List<String> followers = new ArrayList<String>();
|
||||
while ( parentPropIter.hasNext() ) {
|
||||
String currentPropertyName = ( (Property) parentPropIter.next() ).getName();
|
||||
String currentName = reducedName + '.' + currentPropertyName;
|
||||
|
|
|
@ -30,6 +30,7 @@ import java.util.Map;
|
|||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.LockMode;
|
||||
import org.hibernate.internal.util.collections.CollectionHelper;
|
||||
|
||||
/**
|
||||
* Represents the base information for a non-scalar return defined as part of
|
||||
|
@ -40,7 +41,7 @@ import org.hibernate.LockMode;
|
|||
public abstract class NativeSQLQueryNonScalarReturn implements NativeSQLQueryReturn, Serializable {
|
||||
private final String alias;
|
||||
private final LockMode lockMode;
|
||||
private final Map<String,String[]> propertyResults = new HashMap<String,String[]>();
|
||||
private final Map<String,String[]> propertyResults;
|
||||
private final int hashCode;
|
||||
|
||||
/**
|
||||
|
@ -50,15 +51,14 @@ public abstract class NativeSQLQueryNonScalarReturn implements NativeSQLQueryRet
|
|||
* @param propertyResults Any user-supplied column->property mappings
|
||||
* @param lockMode The lock mode to apply to the return.
|
||||
*/
|
||||
protected NativeSQLQueryNonScalarReturn(String alias, Map<String,String[]> propertyResults, LockMode lockMode) {
|
||||
protected NativeSQLQueryNonScalarReturn(String alias, Map<String, String[]> propertyResults, LockMode lockMode) {
|
||||
this.alias = alias;
|
||||
if ( alias == null ) {
|
||||
throw new HibernateException("alias must be specified");
|
||||
throw new HibernateException( "alias must be specified" );
|
||||
}
|
||||
this.lockMode = lockMode;
|
||||
if ( propertyResults != null ) {
|
||||
this.propertyResults.putAll( propertyResults );
|
||||
}
|
||||
this.propertyResults = CollectionHelper.isEmpty( propertyResults ) ? Collections.<String, String[]>emptyMap()
|
||||
: Collections.unmodifiableMap(new HashMap<String, String[]>( propertyResults ));
|
||||
this.hashCode = determineHashCode();
|
||||
}
|
||||
|
||||
|
@ -86,7 +86,7 @@ public abstract class NativeSQLQueryNonScalarReturn implements NativeSQLQueryRet
|
|||
* @return The property mappings.
|
||||
*/
|
||||
public Map<String,String[]> getPropertyResultsMap() {
|
||||
return Collections.unmodifiableMap( propertyResults );
|
||||
return propertyResults;
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
|
|
|
@ -52,6 +52,7 @@ import org.hibernate.engine.spi.NamedSQLQueryDefinition;
|
|||
import org.hibernate.engine.spi.QueryParameters;
|
||||
import org.hibernate.engine.spi.SessionImplementor;
|
||||
import org.hibernate.internal.util.StringHelper;
|
||||
import org.hibernate.internal.util.collections.CollectionHelper;
|
||||
import org.hibernate.type.Type;
|
||||
|
||||
/**
|
||||
|
@ -62,7 +63,7 @@ import org.hibernate.type.Type;
|
|||
*/
|
||||
public class SQLQueryImpl extends AbstractQueryImpl implements SQLQuery {
|
||||
|
||||
private List<NativeSQLQueryReturn> queryReturns;
|
||||
private NativeSQLQueryReturn[] queryReturns;
|
||||
private List<ReturnBuilder> queryReturnBuilders;
|
||||
private boolean autoDiscoverTypes;
|
||||
|
||||
|
@ -88,13 +89,13 @@ public class SQLQueryImpl extends AbstractQueryImpl implements SQLQuery {
|
|||
queryDef.getResultSetRef()
|
||||
);
|
||||
}
|
||||
this.queryReturns = Arrays.asList( definition.getQueryReturns() );
|
||||
this.queryReturns = definition.getQueryReturns();
|
||||
}
|
||||
else if ( queryDef.getQueryReturns() != null && queryDef.getQueryReturns().length > 0 ) {
|
||||
this.queryReturns = Arrays.asList( queryDef.getQueryReturns() );
|
||||
this.queryReturns = queryDef.getQueryReturns();
|
||||
}
|
||||
else {
|
||||
this.queryReturns = new ArrayList<NativeSQLQueryReturn>();
|
||||
this.queryReturns = new NativeSQLQueryReturn[]{};
|
||||
}
|
||||
|
||||
this.querySpaces = queryDef.getQuerySpaces();
|
||||
|
@ -112,14 +113,14 @@ public class SQLQueryImpl extends AbstractQueryImpl implements SQLQuery {
|
|||
ParameterMetadata parameterMetadata) {
|
||||
// TODO : this constructor form is *only* used from constructor directly below us; can it go away?
|
||||
super( sql, flushMode, session, parameterMetadata );
|
||||
queryReturns = new ArrayList<NativeSQLQueryReturn>( returnAliases.length );
|
||||
this.queryReturns = new NativeSQLQueryReturn[returnAliases.length];
|
||||
for ( int i=0; i<returnAliases.length; i++ ) {
|
||||
NativeSQLQueryRootReturn ret = new NativeSQLQueryRootReturn(
|
||||
returnAliases[i],
|
||||
returnClasses[i].getName(),
|
||||
lockModes==null ? LockMode.NONE : lockModes[i]
|
||||
);
|
||||
queryReturns.add(ret);
|
||||
queryReturns[i] = ret;
|
||||
}
|
||||
this.querySpaces = querySpaces;
|
||||
this.callable = false;
|
||||
|
@ -136,13 +137,13 @@ public class SQLQueryImpl extends AbstractQueryImpl implements SQLQuery {
|
|||
|
||||
SQLQueryImpl(String sql, SessionImplementor session, ParameterMetadata parameterMetadata) {
|
||||
super( sql, null, session, parameterMetadata );
|
||||
queryReturns = new ArrayList<NativeSQLQueryReturn>();
|
||||
queryReturns = new NativeSQLQueryReturn[0];
|
||||
querySpaces = null;
|
||||
callable = false;
|
||||
}
|
||||
|
||||
private NativeSQLQueryReturn[] getQueryReturns() {
|
||||
return queryReturns.toArray( new NativeSQLQueryReturn[queryReturns.size()] );
|
||||
return queryReturns;
|
||||
}
|
||||
|
||||
public List list() throws HibernateException {
|
||||
|
@ -208,13 +209,12 @@ public class SQLQueryImpl extends AbstractQueryImpl implements SQLQuery {
|
|||
// some preparation work.
|
||||
prepare();
|
||||
verifyParameters( callable );
|
||||
boolean noReturns = queryReturns==null || queryReturns.isEmpty();
|
||||
if ( noReturns ) {
|
||||
this.autoDiscoverTypes = noReturns;
|
||||
if ( CollectionHelper.isEmpty( queryReturns ) ) {
|
||||
this.autoDiscoverTypes = true;
|
||||
}
|
||||
else {
|
||||
for ( NativeSQLQueryReturn queryReturn : queryReturns ) {
|
||||
if ( queryReturn instanceof NativeSQLQueryScalarReturn ) {
|
||||
for ( final NativeSQLQueryReturn queryReturn : queryReturns ) {
|
||||
if ( NativeSQLQueryScalarReturn.class.isInstance( queryReturn ) ) {
|
||||
NativeSQLQueryScalarReturn scalar = (NativeSQLQueryScalarReturn) queryReturn;
|
||||
if ( scalar.getType() == null ) {
|
||||
autoDiscoverTypes = true;
|
||||
|
@ -229,12 +229,12 @@ public class SQLQueryImpl extends AbstractQueryImpl implements SQLQuery {
|
|||
if ( queryReturnBuilders != null ) {
|
||||
if ( ! queryReturnBuilders.isEmpty() ) {
|
||||
if ( queryReturns != null ) {
|
||||
queryReturns.clear();
|
||||
queryReturns = null;
|
||||
}
|
||||
queryReturns = new ArrayList<NativeSQLQueryReturn>();
|
||||
for ( ReturnBuilder builder : queryReturnBuilders ) {
|
||||
queryReturns.add( builder.buildReturn() );
|
||||
int size = queryReturnBuilders.size();
|
||||
queryReturns = new NativeSQLQueryReturn[size];
|
||||
for(int i=0;i<size;i++){
|
||||
queryReturns[i] = queryReturnBuilders.get( i ).buildReturn();
|
||||
}
|
||||
queryReturnBuilders.clear();
|
||||
}
|
||||
|
@ -251,11 +251,11 @@ public class SQLQueryImpl extends AbstractQueryImpl implements SQLQuery {
|
|||
public Type[] getReturnTypes() throws HibernateException {
|
||||
throw new UnsupportedOperationException("not yet implemented for SQL queries");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Query setLockMode(String alias, LockMode lockMode) {
|
||||
throw new UnsupportedOperationException("cannot set the lock mode for a native SQL query");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Query setLockOptions(LockOptions lockOptions) {
|
||||
throw new UnsupportedOperationException("cannot set lock options for a native SQL query");
|
||||
}
|
||||
|
@ -265,7 +265,7 @@ public class SQLQueryImpl extends AbstractQueryImpl implements SQLQuery {
|
|||
//we never need to apply locks to the SQL
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SQLQuery addScalar(final String columnAlias, final Type type) {
|
||||
if ( queryReturnBuilders == null ) {
|
||||
queryReturnBuilders = new ArrayList<ReturnBuilder>();
|
||||
|
@ -351,22 +351,22 @@ public class SQLQueryImpl extends AbstractQueryImpl implements SQLQuery {
|
|||
final String joinedPropertyName = path.substring( loc+1 );
|
||||
return addFetch( tableAlias, ownerTableAlias, joinedPropertyName );
|
||||
}
|
||||
|
||||
@Override
|
||||
public SQLQuery addJoin(String alias, String path, LockMode lockMode) {
|
||||
createFetchJoin( alias, path ).setLockMode( lockMode );
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SQLQuery setResultSetMapping(String name) {
|
||||
ResultSetMappingDefinition mapping = session.getFactory().getResultSetMapping( name );
|
||||
if ( mapping == null ) {
|
||||
throw new MappingException( "Unknown SqlResultSetMapping [" + name + "]" );
|
||||
}
|
||||
NativeSQLQueryReturn[] returns = mapping.getQueryReturns();
|
||||
queryReturns.addAll( Arrays.asList( returns ) );
|
||||
queryReturns = mapping.getQueryReturns();
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SQLQuery addSynchronizedQuerySpace(String querySpace) {
|
||||
if ( querySpaces == null ) {
|
||||
querySpaces = new ArrayList<String>();
|
||||
|
@ -374,11 +374,11 @@ public class SQLQueryImpl extends AbstractQueryImpl implements SQLQuery {
|
|||
querySpaces.add( querySpace );
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SQLQuery addSynchronizedEntityName(String entityName) {
|
||||
return addQuerySpaces( getSession().getFactory().getEntityPersister( entityName ).getQuerySpaces() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public SQLQuery addSynchronizedEntityClass(Class entityClass) {
|
||||
return addQuerySpaces( getSession().getFactory().getEntityPersister( entityClass.getName() ).getQuerySpaces() );
|
||||
}
|
||||
|
@ -392,7 +392,7 @@ public class SQLQueryImpl extends AbstractQueryImpl implements SQLQuery {
|
|||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int executeUpdate() throws HibernateException {
|
||||
Map namedParams = getNamedParams();
|
||||
before();
|
||||
|
|
|
@ -863,9 +863,7 @@ public final class SessionFactoryImpl
|
|||
namedSqlQueries.put( namedNativeQueryDefinition.getName(), namedNativeQueryDefinition );
|
||||
}
|
||||
sqlResultSetMappings = new HashMap<String, ResultSetMappingDefinition>();
|
||||
for( ResultSetMappingDefinition resultSetMappingDefinition : metadata.getResultSetMappingDefinitions() ) {
|
||||
sqlResultSetMappings.put( resultSetMappingDefinition.getName(), resultSetMappingDefinition );
|
||||
}
|
||||
sqlResultSetMappings.putAll( metadata.getResultSetMappingDefinitions() );
|
||||
imports = new HashMap<String,String>();
|
||||
for ( Map.Entry<String,String> importEntry : metadata.getImports() ) {
|
||||
imports.put( importEntry.getKey(), importEntry.getValue() );
|
||||
|
|
|
@ -146,4 +146,10 @@ public final class CollectionHelper {
|
|||
public static boolean isNotEmpty(Map map) {
|
||||
return !isEmpty( map );
|
||||
}
|
||||
public static boolean isEmpty(Object[] objs){
|
||||
return objs == null || objs.length ==0;
|
||||
}
|
||||
public static boolean isNotEmpty(Object[] objs){
|
||||
return !isEmpty( objs );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -107,7 +107,7 @@ public interface Metadata {
|
|||
|
||||
public Iterable<NamedSQLQueryDefinition> getNamedNativeQueryDefinitions();
|
||||
|
||||
public Iterable<ResultSetMappingDefinition> getResultSetMappingDefinitions();
|
||||
public Map<String, ResultSetMappingDefinition> getResultSetMappingDefinitions();
|
||||
|
||||
public Iterable<Map.Entry<String, String>> getImports();
|
||||
|
||||
|
|
|
@ -186,18 +186,7 @@ public class Binder {
|
|||
this.metadata = metadata;
|
||||
this.identifierGeneratorFactory = identifierGeneratorFactory;
|
||||
this.typeHelper = new HibernateTypeHelper( this, metadata );
|
||||
this.nameNormalizer = new ObjectNameNormalizer() {
|
||||
|
||||
@Override
|
||||
protected NamingStrategy getNamingStrategy() {
|
||||
return metadata.getNamingStrategy();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isUseQuotedIdentifiersGlobally() {
|
||||
return metadata.isGloballyQuotedIdentifiers();
|
||||
}
|
||||
};
|
||||
this.nameNormalizer = metadata.getObjectNameNormalizer();
|
||||
}
|
||||
|
||||
private AttributeBinding attributeBinding( final String entityName, final String attributeName ) {
|
||||
|
|
|
@ -36,6 +36,7 @@ import org.hibernate.SessionFactory;
|
|||
import org.hibernate.cache.spi.RegionFactory;
|
||||
import org.hibernate.cache.spi.access.AccessType;
|
||||
import org.hibernate.cfg.NamingStrategy;
|
||||
import org.hibernate.cfg.ObjectNameNormalizer;
|
||||
import org.hibernate.engine.ResultSetMappingDefinition;
|
||||
import org.hibernate.engine.spi.FilterDefinition;
|
||||
import org.hibernate.engine.spi.NamedQueryDefinition;
|
||||
|
@ -100,6 +101,7 @@ public class MetadataImpl implements MetadataImplementor, Serializable {
|
|||
private final Database database;
|
||||
|
||||
private final MappingDefaults mappingDefaults;
|
||||
private final ObjectNameNormalizer nameNormalizer;
|
||||
|
||||
private Map<String, TypeDefinition> typeDefinitionMap = new HashMap<String, TypeDefinition>();
|
||||
private Map<String, FilterDefinition> filterDefinitionMap = new HashMap<String, FilterDefinition>();
|
||||
|
@ -122,6 +124,18 @@ public class MetadataImpl implements MetadataImplementor, Serializable {
|
|||
this.database = new Database( options );
|
||||
|
||||
this.mappingDefaults = new MappingDefaultsImpl();
|
||||
this.nameNormalizer = new ObjectNameNormalizer() {
|
||||
|
||||
@Override
|
||||
protected NamingStrategy getNamingStrategy() {
|
||||
return MetadataImpl.this.getNamingStrategy();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isUseQuotedIdentifiersGlobally() {
|
||||
return MetadataImpl.this.isGloballyQuotedIdentifiers();
|
||||
}
|
||||
};
|
||||
|
||||
final MetadataSourceProcessor[] metadataSourceProcessors;
|
||||
if ( options.getMetadataSourceProcessingOrder() == MetadataSourceProcessingOrder.HBM_FIRST ) {
|
||||
|
@ -186,6 +200,11 @@ public class MetadataImpl implements MetadataImplementor, Serializable {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ObjectNameNormalizer getObjectNameNormalizer() {
|
||||
return nameNormalizer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addTypeDefinition(TypeDefinition typeDefinition) {
|
||||
if ( typeDefinition == null ) {
|
||||
|
@ -345,12 +364,19 @@ public class MetadataImpl implements MetadataImplementor, Serializable {
|
|||
if ( resultSetMappingDefinition == null || resultSetMappingDefinition.getName() == null ) {
|
||||
throw new IllegalArgumentException( "Result-set mapping object or name is null: " + resultSetMappingDefinition );
|
||||
}
|
||||
resultSetMappings.put( resultSetMappingDefinition.getName(), resultSetMappingDefinition );
|
||||
ResultSetMappingDefinition old = resultSetMappings.put(
|
||||
resultSetMappingDefinition.getName(),
|
||||
resultSetMappingDefinition
|
||||
);
|
||||
if ( old != null ) {
|
||||
LOG.warn( "Duplicated @SqlResultSetMappings with same name["+ resultSetMappingDefinition.getName() +"] found" );
|
||||
//todo mapping exception??
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<ResultSetMappingDefinition> getResultSetMappingDefinitions() {
|
||||
return resultSetMappings.values();
|
||||
public Map<String, ResultSetMappingDefinition> getResultSetMappingDefinitions() {
|
||||
return resultSetMappings;
|
||||
}
|
||||
|
||||
private ClassLoaderService classLoaderService() {
|
||||
|
@ -425,11 +451,11 @@ public class MetadataImpl implements MetadataImplementor, Serializable {
|
|||
|
||||
throw new AssertionFailure( "Entity binding has no root: " + entityName );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<EntityBinding> getEntityBindings() {
|
||||
return entityBindingMap.values();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addEntity(EntityBinding entityBinding) {
|
||||
final String entityName = entityBinding.getEntity().getName();
|
||||
if ( entityBindingMap.containsKey( entityName ) ) {
|
||||
|
|
|
@ -41,6 +41,7 @@ import org.hibernate.metamodel.MetadataSources;
|
|||
import org.hibernate.metamodel.internal.MetadataImpl;
|
||||
import org.hibernate.metamodel.internal.source.annotations.global.FetchProfileProcessor;
|
||||
import org.hibernate.metamodel.internal.source.annotations.global.QueryProcessor;
|
||||
import org.hibernate.metamodel.internal.source.annotations.global.SqlResultSetProcessor;
|
||||
import org.hibernate.metamodel.internal.source.annotations.global.TableProcessor;
|
||||
import org.hibernate.metamodel.internal.source.annotations.util.HibernateDotNames;
|
||||
import org.hibernate.metamodel.internal.source.annotations.util.JPADotNames;
|
||||
|
@ -178,6 +179,7 @@ public class AnnotationMetadataSourceProcessorImpl implements MetadataSourceProc
|
|||
TableProcessor.bind( bindingContext );
|
||||
FetchProfileProcessor.bind( bindingContext );
|
||||
QueryProcessor.bind( bindingContext );
|
||||
SqlResultSetProcessor.bind( bindingContext );
|
||||
}
|
||||
|
||||
private Index parseAndUpdateIndex(List<JaxbRoot<JaxbEntityMappings>> mappings, Index annotationIndex) {
|
||||
|
|
|
@ -279,22 +279,12 @@ public class QueryProcessor {
|
|||
if ( val == null ) {
|
||||
return null;
|
||||
}
|
||||
if ( val.equalsIgnoreCase( CacheMode.GET.toString() ) ) {
|
||||
return CacheMode.GET;
|
||||
try {
|
||||
return CacheMode.valueOf( val.toUpperCase() );
|
||||
}
|
||||
if ( val.equalsIgnoreCase( CacheMode.IGNORE.toString() ) ) {
|
||||
return CacheMode.IGNORE;
|
||||
catch ( IllegalArgumentException e ) {
|
||||
throw new AnnotationException( "Unknown CacheMode in hint: " + query + ":" + element );
|
||||
}
|
||||
if ( val.equalsIgnoreCase( CacheMode.NORMAL.toString() ) ) {
|
||||
return CacheMode.NORMAL;
|
||||
}
|
||||
if ( val.equalsIgnoreCase( CacheMode.PUT.toString() ) ) {
|
||||
return CacheMode.PUT;
|
||||
}
|
||||
if ( val.equalsIgnoreCase( CacheMode.REFRESH.toString() ) ) {
|
||||
return CacheMode.REFRESH;
|
||||
}
|
||||
throw new AnnotationException( "Unknown CacheMode in hint: " + query + ":" + element );
|
||||
}
|
||||
|
||||
private static FlushMode getFlushMode(AnnotationInstance[] hints, String element, String query) {
|
||||
|
@ -302,22 +292,10 @@ public class QueryProcessor {
|
|||
if ( val == null ) {
|
||||
return null;
|
||||
}
|
||||
if ( val.equalsIgnoreCase( FlushMode.ALWAYS.toString() ) ) {
|
||||
return FlushMode.ALWAYS;
|
||||
try {
|
||||
return FlushMode.valueOf( val.toUpperCase() );
|
||||
}
|
||||
else if ( val.equalsIgnoreCase( FlushMode.AUTO.toString() ) ) {
|
||||
return FlushMode.AUTO;
|
||||
}
|
||||
else if ( val.equalsIgnoreCase( FlushMode.COMMIT.toString() ) ) {
|
||||
return FlushMode.COMMIT;
|
||||
}
|
||||
else if ( val.equalsIgnoreCase( FlushMode.NEVER.toString() ) ) {
|
||||
return FlushMode.MANUAL;
|
||||
}
|
||||
else if ( val.equalsIgnoreCase( FlushMode.MANUAL.toString() ) ) {
|
||||
return FlushMode.MANUAL;
|
||||
}
|
||||
else {
|
||||
catch ( IllegalArgumentException e ) {
|
||||
throw new AnnotationException( "Unknown FlushMode in hint: " + query + ":" + element );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,218 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2011, 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.metamodel.internal.source.annotations.global;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
|
||||
import org.jboss.jandex.AnnotationInstance;
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import org.hibernate.LockMode;
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.engine.ResultSetMappingDefinition;
|
||||
import org.hibernate.engine.query.spi.sql.NativeSQLQueryRootReturn;
|
||||
import org.hibernate.engine.query.spi.sql.NativeSQLQueryScalarReturn;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
import org.hibernate.internal.util.StringHelper;
|
||||
import org.hibernate.metamodel.internal.source.annotations.AnnotationBindingContext;
|
||||
import org.hibernate.metamodel.internal.source.annotations.util.JPADotNames;
|
||||
import org.hibernate.metamodel.internal.source.annotations.util.JandexHelper;
|
||||
import org.hibernate.metamodel.spi.binding.AttributeBinding;
|
||||
import org.hibernate.metamodel.spi.binding.CompositeAttributeBinding;
|
||||
import org.hibernate.metamodel.spi.binding.EntityBinding;
|
||||
import org.hibernate.metamodel.spi.binding.ManyToOneAttributeBinding;
|
||||
import org.hibernate.metamodel.spi.binding.SingularAssociationAttributeBinding;
|
||||
|
||||
/**
|
||||
* Binds <ul>
|
||||
* <li>{@link javax.persistence.SqlResultSetMapping}</li>
|
||||
* <li>{@link javax.persistence.SqlResultSetMappings}</li>
|
||||
* <li>{@link javax.persistence.EntityResult}</li>
|
||||
* <li>{@link javax.persistence.FieldResult}</li>
|
||||
* <li>{@link javax.persistence.ColumnResult}</li>
|
||||
* </ul>
|
||||
*
|
||||
* @author Strong Liu <stliu@hibernate.org>
|
||||
*/
|
||||
public class SqlResultSetProcessor {
|
||||
private static final CoreMessageLogger LOG = Logger.getMessageLogger(
|
||||
CoreMessageLogger.class,
|
||||
QueryProcessor.class.getName()
|
||||
);
|
||||
|
||||
private SqlResultSetProcessor() {
|
||||
}
|
||||
|
||||
public static void bind(final AnnotationBindingContext bindingContext) {
|
||||
List<AnnotationInstance> annotations = bindingContext.getIndex()
|
||||
.getAnnotations( JPADotNames.SQL_RESULT_SET_MAPPING );
|
||||
for ( final AnnotationInstance sqlResultSetMappingAnnotationInstance : annotations ) {
|
||||
bindSqlResultSetMapping( bindingContext, sqlResultSetMappingAnnotationInstance );
|
||||
}
|
||||
|
||||
annotations = bindingContext.getIndex().getAnnotations( JPADotNames.SQL_RESULT_SET_MAPPINGS );
|
||||
for ( final AnnotationInstance sqlResultSetMappingsAnnotationInstance : annotations ) {
|
||||
for ( AnnotationInstance annotationInstance : JandexHelper.getValue(
|
||||
sqlResultSetMappingsAnnotationInstance,
|
||||
"value",
|
||||
AnnotationInstance[].class
|
||||
) ) {
|
||||
bindSqlResultSetMapping( bindingContext, annotationInstance );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static int entityAliasIndex = 0;
|
||||
|
||||
private static void bindSqlResultSetMapping(final AnnotationBindingContext bindingContext, final AnnotationInstance annotation) {
|
||||
entityAliasIndex = 0;
|
||||
final String name = JandexHelper.getValue( annotation, "name", String.class );
|
||||
final ResultSetMappingDefinition definition = new ResultSetMappingDefinition( name );
|
||||
for ( final AnnotationInstance entityResult : JandexHelper.getValue(
|
||||
annotation,
|
||||
"entities",
|
||||
AnnotationInstance[].class
|
||||
) ) {
|
||||
bindEntityResult( bindingContext, entityResult, definition );
|
||||
}
|
||||
for ( final AnnotationInstance columnResult : JandexHelper.getValue(
|
||||
annotation,
|
||||
"columns",
|
||||
AnnotationInstance[].class
|
||||
) ) {
|
||||
bindColumnResult( bindingContext, columnResult, definition );
|
||||
}
|
||||
|
||||
bindingContext.getMetadataImplementor().addResultSetMapping( definition );
|
||||
}
|
||||
|
||||
private static void bindEntityResult(final AnnotationBindingContext bindingContext,
|
||||
final AnnotationInstance entityResult,
|
||||
final ResultSetMappingDefinition definition) {
|
||||
final Class entityClass = JandexHelper.getValue( entityResult, "entityClass", Class.class );
|
||||
final String className = entityClass.getName();
|
||||
//todo look up the whole entitybindings to find the right one seems stupid, but there is no way to look entitybinding
|
||||
//by class name, since with hbm, hibernate actually supports map one class to multi entities.
|
||||
final Iterable<EntityBinding> entityBindings = bindingContext.getMetadataImplementor().getEntityBindings();
|
||||
EntityBinding targetEntityBinding = null;
|
||||
for ( final EntityBinding entityBinding : entityBindings ) {
|
||||
if ( className.equals( entityBinding.getEntity().getClass() ) ) {
|
||||
targetEntityBinding = entityBinding;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( targetEntityBinding == null ) {
|
||||
throw new MappingException(
|
||||
String.format(
|
||||
"Entity[%s] not found in SqlResultMapping[%s]",
|
||||
className,
|
||||
definition.getName()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
final String discriminatorColumn = JandexHelper.getValue( entityResult, "discriminatorColumn", String.class );
|
||||
|
||||
final Map<String, String[]> propertyResults = new HashMap<String, String[]>();
|
||||
|
||||
|
||||
if ( StringHelper.isNotEmpty( discriminatorColumn ) ) {
|
||||
final String quotingNormalizedName = bindingContext.getMetadataImplementor()
|
||||
.getObjectNameNormalizer()
|
||||
.normalizeIdentifierQuoting(
|
||||
discriminatorColumn
|
||||
);
|
||||
propertyResults.put( "class", new String[] { quotingNormalizedName } );
|
||||
}
|
||||
|
||||
|
||||
for ( final AnnotationInstance fieldResult : JandexHelper.getValue(
|
||||
entityResult,
|
||||
"fields",
|
||||
AnnotationInstance[].class
|
||||
) ) {
|
||||
bindFieldResult( bindingContext, targetEntityBinding, fieldResult, definition );
|
||||
}
|
||||
|
||||
final NativeSQLQueryRootReturn result = new NativeSQLQueryRootReturn(
|
||||
"alias" + entityAliasIndex++,
|
||||
targetEntityBinding.getEntity().getName(),
|
||||
propertyResults,
|
||||
LockMode.READ
|
||||
);
|
||||
definition.addQueryReturn( result );
|
||||
}
|
||||
|
||||
private static void bindFieldResult(final AnnotationBindingContext bindingContext,
|
||||
final EntityBinding entityBinding,
|
||||
final AnnotationInstance fieldResult,
|
||||
final ResultSetMappingDefinition definition) {
|
||||
final String name = JandexHelper.getValue( fieldResult, "name", String.class );
|
||||
final String column = JandexHelper.getValue( fieldResult, "column", String.class );
|
||||
final String quotingNormalizedColumnName = bindingContext.getMetadataImplementor().getObjectNameNormalizer()
|
||||
.normalizeIdentifierQuoting( column );
|
||||
if ( name.indexOf( '.' ) == -1 ) {
|
||||
|
||||
}
|
||||
else {
|
||||
int dotIndex = name.lastIndexOf( '.' );
|
||||
String reducedName = name.substring( 0, dotIndex );
|
||||
AttributeBinding attributeBinding = entityBinding.locateAttributeBinding( reducedName );
|
||||
if ( CompositeAttributeBinding.class.isInstance( attributeBinding ) ) {
|
||||
CompositeAttributeBinding compositeAttributeBinding = CompositeAttributeBinding.class.cast(
|
||||
attributeBinding
|
||||
);
|
||||
compositeAttributeBinding.attributeBindings();
|
||||
}
|
||||
else if ( ManyToOneAttributeBinding.class.isInstance( attributeBinding ) ) {
|
||||
ManyToOneAttributeBinding manyToOneAttributeBinding = ManyToOneAttributeBinding.class.cast(
|
||||
attributeBinding
|
||||
);
|
||||
EntityBinding referencedEntityBinding = manyToOneAttributeBinding.getReferencedEntityBinding();
|
||||
Set<SingularAssociationAttributeBinding> referencingAttributeBindings = manyToOneAttributeBinding.getEntityReferencingAttributeBindings();
|
||||
//todo see org.hibernate.cfg.annotations.ResultsetMappingSecondPass#getSubPropertyIterator
|
||||
|
||||
}
|
||||
else {
|
||||
throw new MappingException( "dotted notation reference neither a component nor a many/one to one" );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
private static void bindColumnResult(final AnnotationBindingContext bindingContext,
|
||||
final AnnotationInstance columnResult,
|
||||
final ResultSetMappingDefinition definition) {
|
||||
final String name = JandexHelper.getValue( columnResult, "name", String.class );
|
||||
final String normalizedName = bindingContext.getMetadataImplementor()
|
||||
.getObjectNameNormalizer()
|
||||
.normalizeIdentifierQuoting( name );
|
||||
definition.addQueryReturn( new NativeSQLQueryScalarReturn( normalizedName, null ) );
|
||||
}
|
||||
}
|
|
@ -121,7 +121,10 @@ public class TableProcessor {
|
|||
private static Column findColumn(Table table, String columnName) {
|
||||
Column column = null;
|
||||
for ( Value value : table.values() ) {
|
||||
if ( value instanceof Column && ( (Column) value ).getColumnName().getName().equals( columnName ) ) {
|
||||
if ( Column.class.isInstance( value ) && Column.class.cast( value )
|
||||
.getColumnName()
|
||||
.getName()
|
||||
.equals( columnName ) ) {
|
||||
column = (Column) value;
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@ import java.util.Collections;
|
|||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.hibernate.internal.util.Value;
|
||||
import org.hibernate.metamodel.spi.domain.Attribute;
|
||||
import org.hibernate.metamodel.spi.source.MetaAttributeContext;
|
||||
|
||||
|
@ -48,6 +49,7 @@ public abstract class AbstractAttributeBinding implements AttributeBinding {
|
|||
private boolean isAlternateUniqueKey;
|
||||
|
||||
private final MetaAttributeContext metaAttributeContext;
|
||||
private final Value<String> roleHolder;
|
||||
|
||||
protected AbstractAttributeBinding(
|
||||
AttributeBindingContainer container,
|
||||
|
@ -60,6 +62,14 @@ public abstract class AbstractAttributeBinding implements AttributeBinding {
|
|||
this.propertyAccessorName = propertyAccessorName;
|
||||
this.includedInOptimisticLocking = includedInOptimisticLocking;
|
||||
this.metaAttributeContext = metaAttributeContext;
|
||||
this.roleHolder = new Value<String>(
|
||||
new Value.DeferredInitializer<String>() {
|
||||
@Override
|
||||
public String initialize() {
|
||||
return getContainer().getPathBase() + '.' + getAttribute().getName();
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -73,7 +83,7 @@ public abstract class AbstractAttributeBinding implements AttributeBinding {
|
|||
}
|
||||
|
||||
protected String getRole() {
|
||||
return getContainer().getPathBase() + '.' + getAttribute().getName();
|
||||
return roleHolder.getValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -160,18 +160,17 @@ public class ManyToOneAttributeBinding
|
|||
|
||||
@Override
|
||||
public FetchMode getFetchMode() {
|
||||
if ( fetchStyle == FetchStyle.JOIN ) {
|
||||
return FetchMode.JOIN;
|
||||
switch ( fetchStyle ){
|
||||
case JOIN:
|
||||
return FetchMode.JOIN;
|
||||
case SELECT:
|
||||
return FetchMode.SELECT;
|
||||
case BATCH:
|
||||
// we need the subsequent select...
|
||||
return FetchMode.SELECT;
|
||||
default:
|
||||
throw new AssertionFailure( "Unexpected fetch style : " + fetchStyle.name() );
|
||||
}
|
||||
else if ( fetchStyle == FetchStyle.SELECT ) {
|
||||
return FetchMode.SELECT;
|
||||
}
|
||||
else if ( fetchStyle == FetchStyle.BATCH ) {
|
||||
// we need the subsequent select...
|
||||
return FetchMode.SELECT;
|
||||
}
|
||||
|
||||
throw new AssertionFailure( "Unexpected fetch style : " + fetchStyle.name() );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
*/
|
||||
package org.hibernate.metamodel.spi.source;
|
||||
|
||||
import org.hibernate.cfg.ObjectNameNormalizer;
|
||||
import org.hibernate.engine.ResultSetMappingDefinition;
|
||||
import org.hibernate.engine.spi.FilterDefinition;
|
||||
import org.hibernate.engine.spi.Mapping;
|
||||
|
@ -47,6 +48,8 @@ public interface MetadataImplementor extends Metadata, BindingContext, Mapping {
|
|||
|
||||
public TypeResolver getTypeResolver();
|
||||
|
||||
public ObjectNameNormalizer getObjectNameNormalizer();
|
||||
|
||||
public void addImport(String entityName, String entityName1);
|
||||
|
||||
public void addEntity(EntityBinding entityBinding);
|
||||
|
@ -69,7 +72,6 @@ public interface MetadataImplementor extends Metadata, BindingContext, Mapping {
|
|||
|
||||
public void addResultSetMapping(ResultSetMappingDefinition resultSetMappingDefinition);
|
||||
|
||||
// todo : this needs to move to AnnotationBindingContext
|
||||
public void setGloballyQuotedIdentifiers(boolean b);
|
||||
|
||||
public MetaAttributeContext getGlobalMetaAttributeContext();
|
||||
|
|
Loading…
Reference in New Issue