下面列出了怎么用org.hibernate.persister.collection.CollectionPropertyNames的API类实例代码及写法,或者点击链接到github查看源代码。
private void renderJoin(Join join, JoinFragment joinFragment) {
if ( CompositeQuerySpace.class.isInstance( join.getRightHandSide() ) ) {
handleCompositeJoin( join, joinFragment );
}
else if ( EntityQuerySpace.class.isInstance( join.getRightHandSide() ) ) {
// do not render the entity join for a one-to-many association, since the collection join
// already joins to the associated entity table (see doc in renderCollectionJoin()).
if ( join.getLeftHandSide().getDisposition() == QuerySpace.Disposition.COLLECTION ) {
if ( CollectionQuerySpace.class.cast( join.getLeftHandSide() ).getCollectionPersister().isManyToMany() ) {
renderManyToManyJoin( join, joinFragment );
}
else if ( JoinDefinedByMetadata.class.isInstance( join ) &&
CollectionPropertyNames.COLLECTION_INDICES.equals( JoinDefinedByMetadata.class.cast( join ).getJoinedPropertyName() ) ) {
renderManyToManyJoin( join, joinFragment );
}
}
else {
renderEntityJoin( join, joinFragment );
}
}
else if ( CollectionQuerySpace.class.isInstance( join.getRightHandSide() ) ) {
renderCollectionJoin( join, joinFragment );
}
}
public String[] toAliasedColumns(String alias, String propertyName) {
final QueryableCollection queryableCollection = (QueryableCollection) persister;
if ( propertyName.equals( CollectionPropertyNames.COLLECTION_ELEMENTS ) ) {
return queryableCollection.getElementColumnNames( alias );
}
else if ( propertyName.equals( CollectionPropertyNames.COLLECTION_INDICES ) ) {
return queryableCollection.getIndexColumnNames( alias );
}
else {
throw new IllegalArgumentException(
String.format(
"Collection propertyName must be either %s or %s; instead it was %s.",
CollectionPropertyNames.COLLECTION_ELEMENTS,
CollectionPropertyNames.COLLECTION_INDICES,
propertyName
)
);
}
}
@Override
public String[] toColumns(String alias, String propertyName) throws QueryException {
validate( propertyName );
final String joinTableAlias = joinSequence.getFirstJoin().getAlias();
if ( CollectionPropertyNames.COLLECTION_INDEX.equals( propertyName ) ) {
return queryableCollection.toColumns( joinTableAlias, propertyName );
}
final String[] cols = queryableCollection.getIndexColumnNames( joinTableAlias );
if ( CollectionPropertyNames.COLLECTION_MIN_INDEX.equals( propertyName ) ) {
if ( cols.length != 1 ) {
throw new QueryException( "composite collection index in minIndex()" );
}
return new String[] {"min(" + cols[0] + ')'};
}
else {
if ( cols.length != 1 ) {
throw new QueryException( "composite collection index in maxIndex()" );
}
return new String[] {"max(" + cols[0] + ')'};
}
}
private void preprocess(String token, QueryTranslatorImpl q) throws QueryException {
// ugly hack for cases like "elements(foo.bar.collection)"
// (multi-part path expression ending in elements or indices)
String[] tokens = StringHelper.split( ".", token, true );
if (
tokens.length > 5 &&
( CollectionPropertyNames.COLLECTION_ELEMENTS.equals( tokens[tokens.length - 1] )
|| CollectionPropertyNames.COLLECTION_INDICES.equals( tokens[tokens.length - 1] ) )
) {
pathExpressionParser.start( q );
for ( int i = 0; i < tokens.length - 3; i++ ) {
pathExpressionParser.token( tokens[i], q );
}
pathExpressionParser.token( null, q );
pathExpressionParser.end( q );
addJoin( pathExpressionParser.getWhereJoin(), q );
pathExpressionParser.ignoreInitialJoin();
}
}
public void end(QueryTranslatorImpl q) throws QueryException {
if ( !isCollectionValued() ) {
Type type = getPropertyType();
if ( type.isEntityType() ) {
// "finish off" the join
token( ".", q );
token( null, q );
}
else if ( type.isCollectionType() ) {
// default to element set if no elements() specified
token( ".", q );
token( CollectionPropertyNames.COLLECTION_ELEMENTS, q );
}
}
super.end( q );
}
private void preprocess(String token, QueryTranslatorImpl q) throws QueryException {
// ugly hack for cases like "elements(foo.bar.collection)"
// (multi-part path expression ending in elements or indices)
String[] tokens = StringHelper.split( ".", token, true );
if (
tokens.length > 5 &&
( CollectionPropertyNames.COLLECTION_ELEMENTS.equals( tokens[tokens.length - 1] )
|| CollectionPropertyNames.COLLECTION_INDICES.equals( tokens[tokens.length - 1] ) )
) {
pathExpressionParser.start( q );
for ( int i = 0; i < tokens.length - 3; i++ ) {
pathExpressionParser.token( tokens[i], q );
}
pathExpressionParser.token( null, q );
pathExpressionParser.end( q );
addJoin( pathExpressionParser.getWhereJoin(), q );
pathExpressionParser.ignoreInitialJoin();
}
}
public void end(QueryTranslatorImpl q) throws QueryException {
if ( !isCollectionValued() ) {
Type type = getPropertyType();
if ( type.isEntityType() ) {
// "finish off" the join
token( ".", q );
token( null, q );
}
else if ( type.isCollectionType() ) {
// default to element set if no elements() specified
token( ".", q );
token( CollectionPropertyNames.COLLECTION_ELEMENTS, q );
}
}
super.end( q );
}
@Override
public void addJoin(Join join) {
if ( JoinDefinedByMetadata.class.isInstance( join ) ) {
final JoinDefinedByMetadata joinDefinedByMetadata = (JoinDefinedByMetadata) join;
if ( joinDefinedByMetadata.getJoinedPropertyName().equals( CollectionPropertyNames.COLLECTION_ELEMENTS ) ) {
if ( elementJoin == null ) {
elementJoin = joinDefinedByMetadata;
}
else {
throw new IllegalStateException( "Attempt to add an element join, but an element join already exists." );
}
}
else if ( joinDefinedByMetadata.getJoinedPropertyName().equals( CollectionPropertyNames.COLLECTION_INDICES ) ) {
if ( indexJoin == null ) {
indexJoin = joinDefinedByMetadata;
}
else {
throw new IllegalStateException( "Attempt to add an index join, but an index join already exists." );
}
}
else {
throw new IllegalArgumentException(
String.format(
"Collection propertyName must be either %s or %s; instead the joined property name was %s.",
CollectionPropertyNames.COLLECTION_ELEMENTS,
CollectionPropertyNames.COLLECTION_INDICES,
joinDefinedByMetadata.getJoinedPropertyName()
)
);
}
}
internalGetJoins().add( join );
}
protected void resolveCollectionProperty(AST expr) throws SemanticException {
String propertyName = CollectionProperties.getNormalizedPropertyName( methodName );
if ( expr instanceof FromReferenceNode ) {
FromReferenceNode collectionNode = (FromReferenceNode) expr;
// If this is 'elements' then create a new FROM element.
if ( CollectionPropertyNames.COLLECTION_ELEMENTS.equals( propertyName ) ) {
handleElements( collectionNode, propertyName );
}
else {
// Not elements(x)
fromElement = collectionNode.getFromElement();
final CollectionPropertyReference cpr = fromElement.getCollectionPropertyReference( propertyName );
setDataType( cpr.getType() );
selectColumns = cpr.toColumns( fromElement.getTableAlias() );
// setDataType( fromElement.getPropertyType( propertyName, propertyName ) );
selectColumns = fromElement.toColumns( fromElement.getTableAlias(), propertyName, inSelect );
}
if ( collectionNode instanceof DotNode ) {
prepareAnyImplicitJoins( (DotNode) collectionNode );
}
if ( !inSelect ) {
fromElement.setText( "" );
fromElement.setUseWhereFragment( false );
}
prepareSelectColumns( selectColumns );
setText( selectColumns[0] );
setType( SqlTokenTypes.SQL_TOKEN );
}
else {
throw new SemanticException(
"Unexpected expression " + expr +
" found for collection function " + propertyName
);
}
}
private void validate(String propertyName) {
if ( !( CollectionPropertyNames.COLLECTION_INDEX.equals( propertyName )
|| CollectionPropertyNames.COLLECTION_MAX_INDEX.equals( propertyName )
|| CollectionPropertyNames.COLLECTION_MIN_INDEX.equals( propertyName ) ) ) {
throw new IllegalArgumentException( "Expecting index-related function call" );
}
}
public void resolveCollectionProperty(AST expr) throws SemanticException {
String propertyName = CollectionProperties.getNormalizedPropertyName( getMethodName() );
if ( expr instanceof FromReferenceNode ) {
FromReferenceNode collectionNode = ( FromReferenceNode ) expr;
// If this is 'elements' then create a new FROM element.
if ( CollectionPropertyNames.COLLECTION_ELEMENTS.equals( propertyName ) ) {
handleElements( collectionNode, propertyName );
}
else {
// Not elements(x)
fromElement = collectionNode.getFromElement();
setDataType( fromElement.getPropertyType( propertyName, propertyName ) );
selectColumns = fromElement.toColumns( fromElement.getTableAlias(), propertyName, inSelect );
}
if ( collectionNode instanceof DotNode ) {
prepareAnyImplicitJoins( ( DotNode ) collectionNode );
}
if ( !inSelect ) {
fromElement.setText( "" );
fromElement.setUseWhereFragment( false );
}
prepareSelectColumns( selectColumns );
setText( selectColumns[0] );
setType( SqlTokenTypes.SQL_TOKEN );
}
else {
throw new SemanticException(
"Unexpected expression " + expr +
" found for collection function " + propertyName
);
}
}
@Override
public String findAssignmentIdForGradebookLink(String context, String linkId) {
return String.valueOf(startCriteriaQuery()
.createAlias("properties", "p")
.add(Restrictions.eq("context", context))
.add(Restrictions.eq("p." + CollectionPropertyNames.COLLECTION_INDICES, AssignmentConstants.PROP_ASSIGNMENT_ASSOCIATE_GRADEBOOK_ASSIGNMENT))
.add(Restrictions.eq("p." + CollectionPropertyNames.COLLECTION_ELEMENTS, linkId))
.setProjection(Projections.property("id"))
.uniqueResult());
}
@Override
public String findAssignmentIdForGradebookLink(String context, String linkId) {
return String.valueOf(startCriteriaQuery()
.createAlias("properties", "p")
.add(Restrictions.eq("context", context))
.add(Restrictions.eq("p." + CollectionPropertyNames.COLLECTION_INDICES, AssignmentConstants.PROP_ASSIGNMENT_ASSOCIATE_GRADEBOOK_ASSIGNMENT))
.add(Restrictions.eq("p." + CollectionPropertyNames.COLLECTION_ELEMENTS, linkId))
.setProjection(Projections.property("id"))
.uniqueResult());
}
private void registerCollectionJoinAliases(AliasResolutionContextImpl mutableAliasResolutionContext,
CollectionQuerySpace rightHandSide) {
// The SQL join to the "collection table" needs to be rendered.
//
// In the case of a basic collection, that's the only join needed.
//
// For one-to-many/many-to-many, we need to render the "collection table join"
// here (as already stated). There will be a follow-on join (rhs will have a join) for the associated entity.
// For many-to-many, the follow-on join will join to the associated entity element table. For one-to-many,
// the collection table is the associated entity table, so the follow-on join will not be rendered..
// currently we do not explicitly track the joins under the CollectionQuerySpace to know which is
// the element join and which is the index join (maybe we should?).
JoinDefinedByMetadata collectionElementJoin = null;
JoinDefinedByMetadata collectionIndexJoin = null;
for ( Join collectionJoin : rightHandSide.getJoins() ) {
if ( JoinDefinedByMetadata.class.isInstance( collectionJoin ) ) {
final JoinDefinedByMetadata collectionJoinDefinedByMetadata = (JoinDefinedByMetadata) collectionJoin;
if ( CollectionPropertyNames.COLLECTION_ELEMENTS.equals( collectionJoinDefinedByMetadata.getJoinedPropertyName() ) ) {
if ( collectionElementJoin != null ) {
throw new AssertionFailure(
String.format(
"More than one element join defined for: %s",
rightHandSide.getCollectionPersister().getRole()
)
);
}
collectionElementJoin = collectionJoinDefinedByMetadata;
}
if ( CollectionPropertyNames.COLLECTION_INDICES.equals( collectionJoinDefinedByMetadata.getJoinedPropertyName() ) ) {
if ( collectionIndexJoin != null ) {
throw new AssertionFailure(
String.format(
"More than one index join defined for: %s",
rightHandSide.getCollectionPersister().getRole()
)
);
}
collectionIndexJoin = collectionJoinDefinedByMetadata;
}
}
}
if ( rightHandSide.getCollectionPersister().isOneToMany()
|| rightHandSide.getCollectionPersister().isManyToMany() ) {
// relatedly, for collections with entity elements (one-to-many, many-to-many) we need to register the
// sql aliases to use for the entity.
if ( collectionElementJoin == null ) {
throw new IllegalStateException(
String.format(
"Could not locate collection element join within collection join [%s : %s]",
rightHandSide.getUid(),
rightHandSide.getCollectionPersister()
)
);
}
mutableAliasResolutionContext.generateCollectionReferenceAliases(
rightHandSide.getUid(),
rightHandSide.getCollectionPersister(),
collectionElementJoin.getRightHandSide().getUid()
);
}
else {
mutableAliasResolutionContext.generateCollectionReferenceAliases(
rightHandSide.getUid(),
rightHandSide.getCollectionPersister(),
null
);
}
if ( rightHandSide.getCollectionPersister().hasIndex() &&
rightHandSide.getCollectionPersister().getIndexType().isEntityType() ) {
// for collections with entity index we need to register the
// sql aliases to use for the entity.
if ( collectionIndexJoin == null ) {
throw new IllegalStateException(
String.format(
"Could not locate collection index join within collection join [%s : %s]",
rightHandSide.getUid(),
rightHandSide.getCollectionPersister()
)
);
}
mutableAliasResolutionContext.generateEntityReferenceAliases(
collectionIndexJoin.getRightHandSide().getUid(),
rightHandSide.getCollectionPersister().getIndexDefinition().toEntityDefinition().getEntityPersister()
);
}
}
private void renderManyToManyJoin(
Join join,
JoinFragment joinFragment) {
// for many-to-many we have 3 table aliases. By way of example, consider a normal m-n: User<->Role
// where User is the FetchOwner and Role (User.roles) is the Fetch. We'd have:
// 1) the owner's table : user - in terms of rendering the joins (not the fetch select fragments), the
// lhs table alias is only needed to qualify the lhs join columns, but we already have the qualified
// columns here (aliasedLhsColumnNames)
//final String ownerTableAlias = ...;
// 2) the m-n table : user_role
// 3) the element table : role
final EntityPersister entityPersister = ( (EntityQuerySpace) join.getRightHandSide() ).getEntityPersister();
final String entityTableAlias = aliasResolutionContext.resolveSqlTableAliasFromQuerySpaceUid(
join.getRightHandSide().getUid()
);
if ( StringHelper.isEmpty( entityTableAlias ) ) {
throw new IllegalStateException( "Collection element (many-to-many) table alias cannot be empty" );
}
final String manyToManyFilter;
if ( JoinDefinedByMetadata.class.isInstance( join ) &&
CollectionPropertyNames.COLLECTION_ELEMENTS.equals( ( (JoinDefinedByMetadata) join ).getJoinedPropertyName() ) ) {
final CollectionQuerySpace leftHandSide = (CollectionQuerySpace) join.getLeftHandSide();
final CollectionPersister persister = leftHandSide.getCollectionPersister();
manyToManyFilter = persister.getManyToManyFilterFragment(
entityTableAlias,
queryInfluencers.getEnabledFilters()
);
}
else {
manyToManyFilter = null;
}
addJoins(
join,
joinFragment,
(Joinable) entityPersister,
manyToManyFilter
);
}
private CollectionFetchableIndex buildIndexGraph() {
final CollectionPersister persister = collectionQuerySpace.getCollectionPersister();
if ( persister.hasIndex() ) {
final Type type = persister.getIndexType();
if ( type.isAssociationType() ) {
if ( type.isEntityType() ) {
final EntityPersister indexPersister = persister.getFactory().getEntityPersister(
( (EntityType) type ).getAssociatedEntityName()
);
final ExpandingEntityQuerySpace entityQuerySpace = QuerySpaceHelper.INSTANCE.makeEntityQuerySpace(
collectionQuerySpace,
indexPersister,
CollectionPropertyNames.COLLECTION_INDICES,
(EntityType) persister.getIndexType(),
collectionQuerySpace.getExpandingQuerySpaces().generateImplicitUid(),
collectionQuerySpace.canJoinsBeRequired(),
allowIndexJoin
);
return new CollectionFetchableIndexEntityGraph( this, entityQuerySpace );
}
else if ( type.isAnyType() ) {
return new CollectionFetchableIndexAnyGraph( this );
}
}
else if ( type.isComponentType() ) {
final ExpandingCompositeQuerySpace compositeQuerySpace = QuerySpaceHelper.INSTANCE.makeCompositeQuerySpace(
collectionQuerySpace,
new CompositePropertyMapping(
(CompositeType) persister.getIndexType(),
(PropertyMapping) persister,
""
),
CollectionPropertyNames.COLLECTION_INDICES,
(CompositeType) persister.getIndexType(),
collectionQuerySpace.getExpandingQuerySpaces().generateImplicitUid(),
collectionQuerySpace.canJoinsBeRequired(),
allowIndexJoin
);
return new CollectionFetchableIndexCompositeGraph( this, compositeQuerySpace );
}
}
return null;
}
private CollectionFetchableElement buildElementGraph() {
final CollectionPersister persister = collectionQuerySpace.getCollectionPersister();
final Type type = persister.getElementType();
if ( type.isAssociationType() ) {
if ( type.isEntityType() ) {
final EntityPersister elementPersister = persister.getFactory().getEntityPersister(
( (EntityType) type ).getAssociatedEntityName()
);
final ExpandingEntityQuerySpace entityQuerySpace = QuerySpaceHelper.INSTANCE.makeEntityQuerySpace(
collectionQuerySpace,
elementPersister,
CollectionPropertyNames.COLLECTION_ELEMENTS,
(EntityType) persister.getElementType(),
collectionQuerySpace.getExpandingQuerySpaces().generateImplicitUid(),
collectionQuerySpace.canJoinsBeRequired(),
allowElementJoin
);
return new CollectionFetchableElementEntityGraph( this, entityQuerySpace );
}
else if ( type.isAnyType() ) {
return new CollectionFetchableElementAnyGraph( this );
}
}
else if ( type.isComponentType() ) {
final ExpandingCompositeQuerySpace compositeQuerySpace = QuerySpaceHelper.INSTANCE.makeCompositeQuerySpace(
collectionQuerySpace,
new CompositePropertyMapping(
(CompositeType) persister.getElementType(),
(PropertyMapping) persister,
""
),
CollectionPropertyNames.COLLECTION_ELEMENTS,
(CompositeType) persister.getElementType(),
collectionQuerySpace.getExpandingQuerySpaces().generateImplicitUid(),
collectionQuerySpace.canJoinsBeRequired(),
allowElementJoin
);
return new CollectionFetchableElementCompositeGraph( this, compositeQuerySpace );
}
return null;
}
@Override
protected AST lookupProperty(AST dot, boolean root, boolean inSelect) throws SemanticException {
DotNode dotNode = (DotNode) dot;
FromReferenceNode lhs = dotNode.getLhs();
AST rhs = lhs.getNextSibling();
// this used to be a switch statement based on the rhs's node type
// expecting it to be SqlTokenTypes.ELEMENTS or
// SqlTokenTypes.INDICES in the cases where the re-arranging is needed
//
// In such cases it additionally expects the RHS to be a CollectionFunction node.
//
// However, in my experience these assumptions sometimes did not works as sometimes the node
// types come in with the node type WEIRD_IDENT. What this does now is to:
// 1) see if the LHS is a collection
// 2) see if the RHS is a reference to one of the "collection properties".
// if both are true, we log a deprecation warning
if ( lhs.getDataType() != null
&& lhs.getDataType().isCollectionType() ) {
if ( CollectionProperties.isCollectionProperty( rhs.getText() ) ) {
DeprecationLogger.DEPRECATION_LOGGER.logDeprecationOfCollectionPropertiesInHql(
rhs.getText(),
lhs.getPath()
);
}
// perform the re-arrangement
if ( CollectionPropertyNames.COLLECTION_INDICES.equalsIgnoreCase( rhs.getText() )
|| CollectionPropertyNames.COLLECTION_ELEMENTS.equalsIgnoreCase( rhs.getText() ) ) {
if ( LOG.isDebugEnabled() ) {
LOG.debugf(
"lookupProperty() %s => %s(%s)",
dotNode.getPath(),
rhs.getText(),
lhs.getPath()
);
}
final CollectionFunction f;
if ( rhs instanceof CollectionFunction ) {
f = (CollectionFunction) rhs;
}
else {
f = new CollectionFunction();
f.initialize( SqlTokenTypes.METHOD_CALL, rhs.getText() );
f.initialize( this );
}
// Re-arrange the tree so that the collection function is the root and the lhs is the path.
f.setFirstChild( lhs );
lhs.setNextSibling( null );
dotNode.setFirstChild( f );
resolve( lhs ); // Don't forget to resolve the argument!
f.resolve( inSelect ); // Resolve the collection function now.
return f;
}
}
// otherwise, resolve the path and return it
dotNode.resolveFirstChild();
return dotNode;
}
/**
* Retrieves the column names corresponding to the collection elements for the given
* collection role.
*
* @param role The collection role
* @param roleAlias The sql column-qualification alias (i.e., the table alias)
*
* @return the collection element columns
*/
public String[] getCollectionElementColumns(String role, String roleAlias) {
return getCollectionPropertyMapping( role ).toColumns( roleAlias, CollectionPropertyNames.COLLECTION_ELEMENTS );
}
/**
* Retrieves the column names corresponding to the collection elements for the given
* collection role.
*
* @param role The collection role
* @param roleAlias The sql column-qualification alias (i.e., the table alias)
* @return the collection element columns
*/
public String[] getCollectionElementColumns(String role, String roleAlias) {
return getCollectionPropertyMapping( role ).toColumns( roleAlias, CollectionPropertyNames.COLLECTION_ELEMENTS );
}