下面列出了怎么用org.hibernate.mapping.OneToMany的API类实例代码及写法,或者点击链接到github查看源代码。
public void doSecondPass(java.util.Map persistentClasses)
throws MappingException {
final boolean debugEnabled = LOG.isDebugEnabled();
if ( debugEnabled ) {
LOG.debugf( "Second pass for collection: %s", collection.getRole() );
}
secondPass( persistentClasses, localInheritedMetas ); // using local since the inheritedMetas at this point is not the correct map since it is always the empty map
collection.createAllKeys();
if ( debugEnabled ) {
String msg = "Mapped collection key: " + columns( collection.getKey() );
if ( collection.isIndexed() )
msg += ", index: " + columns( ( (IndexedCollection) collection ).getIndex() );
if ( collection.isOneToMany() ) {
msg += ", one-to-many: "
+ ( (OneToMany) collection.getElement() ).getReferencedEntityName();
}
else {
msg += ", element: " + columns( collection.getElement() );
}
LOG.debug( msg );
}
}
protected void createBackReferences() {
if ( collectionBinding.isOneToMany()
&& !collectionBinding.isInverse()
&& !collectionBinding.getKey().isNullable() ) {
// for non-inverse one-to-many, with a not-null fk, add a backref!
String entityName = ( (OneToMany) collectionBinding.getElement() ).getReferencedEntityName();
PersistentClass referenced = mappingDocument.getMetadataCollector().getEntityBinding( entityName );
Backref prop = new Backref();
prop.setName( '_' + collectionBinding.getOwnerEntityName() + "." + pluralAttributeSource.getName() + "Backref" );
prop.setUpdateable( false );
prop.setSelectable( false );
prop.setCollectionRole( collectionBinding.getRole() );
prop.setEntityName( collectionBinding.getOwner().getEntityName() );
prop.setValue( collectionBinding.getKey() );
referenced.addProperty( prop );
log.debugf(
"Added virtual backref property [%s] : %s",
prop.getName(),
pluralAttributeSource.getAttributeRole().getFullPath()
);
}
}
private void createIndexBackRef(
MappingDocument mappingDocument,
IndexedPluralAttributeSource pluralAttributeSource,
IndexedCollection collectionBinding) {
if ( collectionBinding.isOneToMany()
&& !collectionBinding.getKey().isNullable()
&& !collectionBinding.isInverse() ) {
final String entityName = ( (OneToMany) collectionBinding.getElement() ).getReferencedEntityName();
final PersistentClass referenced = mappingDocument.getMetadataCollector().getEntityBinding( entityName );
final IndexBackref ib = new IndexBackref();
ib.setName( '_' + collectionBinding.getOwnerEntityName() + "." + pluralAttributeSource.getName() + "IndexBackref" );
ib.setUpdateable( false );
ib.setSelectable( false );
ib.setCollectionRole( collectionBinding.getRole() );
ib.setEntityName( collectionBinding.getOwner().getEntityName() );
ib.setValue( collectionBinding.getIndex() );
referenced.addProperty( ib );
}
}
/**
* Binds a unidirectional one-to-many creating a psuedo back reference property in the process.
*
* @param property
* @param mappings
* @param collection
*/
protected void bindUnidirectionalOneToMany(org.grails.datastore.mapping.model.types.OneToMany property, InFlightMetadataCollector mappings, Collection collection) {
Value v = collection.getElement();
v.createForeignKey();
String entityName;
if (v instanceof ManyToOne) {
ManyToOne manyToOne = (ManyToOne) v;
entityName = manyToOne.getReferencedEntityName();
} else {
entityName = ((OneToMany) v).getReferencedEntityName();
}
collection.setInverse(false);
PersistentClass referenced = mappings.getEntityBinding(entityName);
Backref prop = new Backref();
PersistentEntity owner = property.getOwner();
prop.setEntityName(owner.getName());
prop.setName(UNDERSCORE + addUnderscore(owner.getJavaClass().getSimpleName(), property.getName()) + "Backref");
prop.setUpdateable(false);
prop.setInsertable(true);
prop.setCollectionRole(collection.getRole());
prop.setValue(collection.getKey());
prop.setOptional(true);
referenced.addProperty(prop);
}
protected void createCollectionKeys() {
collection.createAllKeys();
if (LOG.isDebugEnabled()) {
String msg = "Mapped collection key: " + columns(collection.getKey());
if (collection.isIndexed())
msg += ", index: " + columns(((IndexedCollection) collection).getIndex());
if (collection.isOneToMany()) {
msg += ", one-to-many: "
+ ((OneToMany) collection.getElement()).getReferencedEntityName();
} else {
msg += ", element: " + columns(collection.getElement());
}
LOG.debug(msg);
}
}
public void doSecondPass(java.util.Map persistentClasses)
throws MappingException {
if ( log.isDebugEnabled() )
log.debug( "Second pass for collection: " + collection.getRole() );
secondPass( persistentClasses, localInheritedMetas ); // using local since the inheritedMetas at this point is not the correct map since it is always the empty map
collection.createAllKeys();
if ( log.isDebugEnabled() ) {
String msg = "Mapped collection key: " + columns( collection.getKey() );
if ( collection.isIndexed() )
msg += ", index: " + columns( ( (IndexedCollection) collection ).getIndex() );
if ( collection.isOneToMany() ) {
msg += ", one-to-many: "
+ ( (OneToMany) collection.getElement() ).getReferencedEntityName();
}
else {
msg += ", element: " + columns( collection.getElement() );
}
log.debug( msg );
}
}
public void testProperCallbacks() {
ValueVisitor vv = new ValueVisitorValidator();
new Any(new Table()).accept(vv);
new Array(new RootClass()).accept(vv);
new Bag(new RootClass()).accept(vv);
new Component(new RootClass()).accept(vv);
new DependantValue(null,null).accept(vv);
new IdentifierBag(null).accept(vv);
new List(null).accept(vv);
new ManyToOne(null).accept(vv);
new Map(null).accept(vv);
new OneToMany(null).accept(vv);
new OneToOne(null, new RootClass() ).accept(vv);
new PrimitiveArray(null).accept(vv);
new Set(null).accept(vv);
new SimpleValue().accept(vv);
}
private void makeOneToManyMapKeyColumnNullableIfNotInProperty(
final XProperty property) {
final org.hibernate.mapping.Map map = (org.hibernate.mapping.Map) this.collection;
if ( map.isOneToMany() &&
property.isAnnotationPresent( MapKeyColumn.class ) ) {
final Value indexValue = map.getIndex();
if ( indexValue.getColumnSpan() != 1 ) {
throw new AssertionFailure( "Map key mapped by @MapKeyColumn does not have 1 column" );
}
final Selectable selectable = indexValue.getColumnIterator().next();
if ( selectable.isFormula() ) {
throw new AssertionFailure( "Map key mapped by @MapKeyColumn is a Formula" );
}
Column column = (Column) map.getIndex().getColumnIterator().next();
if ( !column.isNullable() ) {
final PersistentClass persistentClass = ( ( OneToMany ) map.getElement() ).getAssociatedClass();
// check if the index column has been mapped by the associated entity to a property;
// @MapKeyColumn only maps a column to the primary table for the one-to-many, so we only
// need to check "un-joined" properties.
if ( !propertyIteratorContainsColumn( persistentClass.getUnjoinedPropertyIterator(), column ) ) {
// The index column is not mapped to an associated entity property so we can
// safely make the index column nullable.
column.setNullable( true );
}
}
}
}
@Override
public void doSecondPass(Map persistentClasses) throws org.hibernate.MappingException {
bindCollectionTable();
bindCollectionKey();
bindCollectionIdentifier();
bindCollectionIndex();
bindCollectionElement();
createBackReferences();
collectionBinding.createAllKeys();
if ( debugEnabled ) {
log.debugf( "Mapped collection : " + getPluralAttributeSource().getAttributeRole().getFullPath() );
log.debugf( " + table -> " + getCollectionBinding().getTable().getName() );
log.debugf( " + key -> " + columns( getCollectionBinding().getKey() ) );
if ( getCollectionBinding().isIndexed() ) {
log.debugf( " + index -> " + columns( ( (IndexedCollection) getCollectionBinding() ).getIndex() ) );
}
if ( getCollectionBinding().isOneToMany() ) {
log.debugf( " + one-to-many -> " + ( (OneToMany) getCollectionBinding().getElement() ).getReferencedEntityName() );
}
else {
log.debugf( " + element -> " + columns( getCollectionBinding().getElement() ) );
}
}
}
@Override
protected void createBackReferences() {
super.createBackReferences();
boolean indexIsFormula = false;
Iterator itr = getCollectionBinding().getIndex().getColumnIterator();
while ( itr.hasNext() ) {
if ( ( (Selectable) itr.next() ).isFormula() ) {
indexIsFormula = true;
}
}
if ( getCollectionBinding().isOneToMany()
&& !getCollectionBinding().getKey().isNullable()
&& !getCollectionBinding().isInverse()
&& !indexIsFormula ) {
final String entityName = ( (OneToMany) getCollectionBinding().getElement() ).getReferencedEntityName();
final PersistentClass referenced = getMappingDocument().getMetadataCollector().getEntityBinding( entityName );
final IndexBackref ib = new IndexBackref();
ib.setName( '_' + getCollectionBinding().getOwnerEntityName() + "." + getPluralAttributeSource().getName() + "IndexBackref" );
ib.setUpdateable( false );
ib.setSelectable( false );
ib.setCollectionRole( getCollectionBinding().getRole() );
ib.setEntityName( getCollectionBinding().getOwner().getEntityName() );
ib.setValue( getCollectionBinding().getIndex() );
referenced.addProperty( ib );
}
}
protected boolean shouldBindCollectionWithForeignKey(ToMany property) {
return ((property instanceof org.grails.datastore.mapping.model.types.OneToMany) && property.isBidirectional() ||
!shouldCollectionBindWithJoinColumn(property)) &&
!Map.class.isAssignableFrom(property.getType()) &&
!(property instanceof ManyToMany) &&
!(property instanceof Basic);
}
protected String getAssociationDescription(Association grailsProperty) {
String assType = "unknown";
if (grailsProperty instanceof ManyToMany) {
assType = "many-to-many";
} else if (grailsProperty instanceof org.grails.datastore.mapping.model.types.OneToMany) {
assType = "one-to-many";
} else if (grailsProperty instanceof org.grails.datastore.mapping.model.types.OneToOne) {
assType = "one-to-one";
} else if (grailsProperty instanceof org.grails.datastore.mapping.model.types.ManyToOne) {
assType = "many-to-one";
} else if (grailsProperty.isEmbedded()) {
assType = "embedded";
}
return assType;
}
protected String getDefaultColumnName(PersistentProperty property, String sessionFactoryBeanName) {
NamingStrategy namingStrategy = getNamingStrategy(sessionFactoryBeanName);
String columnName = namingStrategy.propertyToColumnName(property.getName());
if (property instanceof Association) {
Association association = (Association) property;
boolean isBasic = property instanceof Basic;
if(isBasic && ((PropertyConfig)property.getMapping().getMappedForm()).getType() != null ) {
return columnName;
}
if (isBasic) {
return getForeignKeyForPropertyDomainClass(property, sessionFactoryBeanName);
}
if (property instanceof ManyToMany) {
return getForeignKeyForPropertyDomainClass(property, sessionFactoryBeanName);
}
if (!association.isBidirectional() && association instanceof org.grails.datastore.mapping.model.types.OneToMany) {
String prefix = namingStrategy.classToTableName(property.getOwner().getName());
return addUnderscore(prefix, columnName) + FOREIGN_KEY_SUFFIX;
}
if (property.isInherited() && isBidirectionalManyToOne(property)) {
return namingStrategy.propertyToColumnName(property.getOwner().getName()) + '_'+ columnName + FOREIGN_KEY_SUFFIX;
}
return columnName + FOREIGN_KEY_SUFFIX;
}
return columnName;
}
/**
* Called for Lists, arrays, primitive arrays
*/
public static void bindListSecondPass(Element node, List list, java.util.Map classes,
Mappings mappings, java.util.Map inheritedMetas) throws MappingException {
bindCollectionSecondPass( node, list, classes, mappings, inheritedMetas );
Element subnode = node.element( "list-index" );
if ( subnode == null ) subnode = node.element( "index" );
SimpleValue iv = new SimpleValue( list.getCollectionTable() );
bindSimpleValue(
subnode,
iv,
list.isOneToMany(),
IndexedCollection.DEFAULT_INDEX_COLUMN_NAME,
mappings
);
iv.setTypeName( "integer" );
list.setIndex( iv );
String baseIndex = subnode.attributeValue( "base" );
if ( baseIndex != null ) list.setBaseIndex( Integer.parseInt( baseIndex ) );
list.setIndexNodeName( subnode.attributeValue("node") );
if ( list.isOneToMany() && !list.getKey().isNullable() && !list.isInverse() ) {
String entityName = ( (OneToMany) list.getElement() ).getReferencedEntityName();
PersistentClass referenced = mappings.getClass( entityName );
IndexBackref ib = new IndexBackref();
ib.setName( '_' + node.attributeValue( "name" ) + "IndexBackref" );
ib.setUpdateable( false );
ib.setSelectable( false );
ib.setCollectionRole( list.getRole() );
ib.setEntityName( list.getOwner().getEntityName() );
ib.setValue( list.getIndex() );
// ( (Column) ( (SimpleValue) ic.getIndex() ).getColumnIterator().next()
// ).setNullable(false);
referenced.addProperty( ib );
}
}
private void bindIndex(final MetadataBuildingContext buildingContext) {
if ( !indexColumn.isImplicit() ) {
PropertyHolder valueHolder = PropertyHolderBuilder.buildPropertyHolder(
this.collection,
StringHelper.qualify( this.collection.getRole(), "key" ),
null,
null,
propertyHolder,
getBuildingContext()
);
List list = (List) this.collection;
if ( !list.isOneToMany() ) indexColumn.forceNotNull();
indexColumn.setPropertyHolder( valueHolder );
SimpleValueBinder value = new SimpleValueBinder();
value.setColumns( new Ejb3Column[] { indexColumn } );
value.setExplicitType( "integer" );
value.setBuildingContext( getBuildingContext() );
SimpleValue indexValue = value.make();
indexColumn.linkWithValue( indexValue );
list.setIndex( indexValue );
list.setBaseIndex( indexColumn.getBase() );
if ( list.isOneToMany() && !list.getKey().isNullable() && !list.isInverse() ) {
String entityName = ( (OneToMany) list.getElement() ).getReferencedEntityName();
PersistentClass referenced = buildingContext.getMetadataCollector().getEntityBinding( entityName );
IndexBackref ib = new IndexBackref();
ib.setName( '_' + propertyName + "IndexBackref" );
ib.setUpdateable( false );
ib.setSelectable( false );
ib.setCollectionRole( list.getRole() );
ib.setEntityName( list.getOwner().getEntityName() );
ib.setValue( list.getIndex() );
referenced.addProperty( ib );
}
}
else {
Collection coll = this.collection;
throw new AnnotationException(
"List/array has to be annotated with an @OrderColumn (or @IndexColumn): "
+ coll.getRole()
);
}
}
protected void bindMapSecondPass(ToMany property, InFlightMetadataCollector mappings,
Map<?, ?> persistentClasses, org.hibernate.mapping.Map map, String sessionFactoryBeanName) {
bindCollectionSecondPass(property, mappings, persistentClasses, map, sessionFactoryBeanName);
SimpleValue value = new SimpleValue(metadataBuildingContext, map.getCollectionTable());
bindSimpleValue(getIndexColumnType(property, STRING_TYPE), value, true,
getIndexColumnName(property, sessionFactoryBeanName), mappings);
PropertyConfig pc = getPropertyConfig(property);
if (pc != null && pc.getIndexColumn() != null) {
bindColumnConfigToColumn(property, getColumnForSimpleValue(value), getSingleColumnConfig(pc.getIndexColumn()));
}
if (!value.isTypeSpecified()) {
throw new MappingException("map index element must specify a type: " + map.getRole());
}
map.setIndex(value);
if(!(property instanceof org.grails.datastore.mapping.model.types.OneToMany) && !(property instanceof ManyToMany)) {
SimpleValue elt = new SimpleValue(metadataBuildingContext, map.getCollectionTable());
map.setElement(elt);
String typeName = getTypeName(property,getPropertyConfig(property), getMapping(property.getOwner()));
if (typeName == null ) {
if(property instanceof Basic) {
Basic basic = (Basic) property;
typeName = basic.getComponentType().getName();
}
}
if(typeName == null || typeName.equals(Object.class.getName())) {
typeName = StandardBasicTypes.STRING.getName();
}
bindSimpleValue(typeName, elt, false, getMapElementName(property, sessionFactoryBeanName), mappings);
elt.setTypeName(typeName);
}
map.setInverse(false);
}
protected void bindListSecondPass(ToMany property, InFlightMetadataCollector mappings,
Map<?, ?> persistentClasses, org.hibernate.mapping.List list, String sessionFactoryBeanName) {
bindCollectionSecondPass(property, mappings, persistentClasses, list, sessionFactoryBeanName);
String columnName = getIndexColumnName(property, sessionFactoryBeanName);
final boolean isManyToMany = property instanceof ManyToMany;
if (isManyToMany && !property.isOwningSide()) {
throw new MappingException("Invalid association [" + property +
"]. List collection types only supported on the owning side of a many-to-many relationship.");
}
Table collectionTable = list.getCollectionTable();
SimpleValue iv = new SimpleValue(metadataBuildingContext, collectionTable);
bindSimpleValue("integer", iv, true, columnName, mappings);
iv.setTypeName("integer");
list.setIndex(iv);
list.setBaseIndex(0);
list.setInverse(false);
Value v = list.getElement();
v.createForeignKey();
if (property.isBidirectional()) {
String entityName;
Value element = list.getElement();
if (element instanceof ManyToOne) {
ManyToOne manyToOne = (ManyToOne) element;
entityName = manyToOne.getReferencedEntityName();
} else {
entityName = ((OneToMany) element).getReferencedEntityName();
}
PersistentClass referenced = mappings.getEntityBinding(entityName);
Class<?> mappedClass = referenced.getMappedClass();
Mapping m = getMapping(mappedClass);
boolean compositeIdProperty = isCompositeIdProperty(m, property.getInverseSide());
if (!compositeIdProperty) {
Backref prop = new Backref();
final PersistentEntity owner = property.getOwner();
prop.setEntityName(owner.getName());
prop.setName(UNDERSCORE + addUnderscore(owner.getJavaClass().getSimpleName(), property.getName()) + "Backref");
prop.setSelectable(false);
prop.setUpdateable(false);
if (isManyToMany) {
prop.setInsertable(false);
}
prop.setCollectionRole(list.getRole());
prop.setValue(list.getKey());
DependantValue value = (DependantValue) prop.getValue();
if (!property.isCircular()) {
value.setNullable(false);
}
value.setUpdateable(true);
prop.setOptional(false);
referenced.addProperty(prop);
}
if ((!list.getKey().isNullable() && !list.isInverse()) || compositeIdProperty) {
IndexBackref ib = new IndexBackref();
ib.setName(UNDERSCORE + property.getName() + "IndexBackref");
ib.setUpdateable(false);
ib.setSelectable(false);
if (isManyToMany) {
ib.setInsertable(false);
}
ib.setCollectionRole(list.getRole());
ib.setEntityName(list.getOwner().getEntityName());
ib.setValue(list.getIndex());
referenced.addProperty(ib);
}
}
}
/**
* First pass to bind collection to Hibernate metamodel, sets up second pass
*
* @param property The GrailsDomainClassProperty instance
* @param collection The collection
* @param owner The owning persistent class
* @param mappings The Hibernate mappings instance
* @param path
*/
protected void bindCollection(ToMany property, Collection collection,
PersistentClass owner, InFlightMetadataCollector mappings, String path, String sessionFactoryBeanName) {
// set role
String propertyName = getNameForPropertyAndPath(property, path);
collection.setRole(qualify(property.getOwner().getName(), propertyName));
PropertyConfig pc = getPropertyConfig(property);
// configure eager fetching
final FetchMode fetchMode = pc.getFetchMode();
if (fetchMode == FetchMode.JOIN) {
collection.setFetchMode(FetchMode.JOIN);
}
else if (pc.getFetchMode() != null) {
collection.setFetchMode(pc.getFetchMode());
}
else {
collection.setFetchMode(FetchMode.DEFAULT);
}
if (pc.getCascade() != null) {
collection.setOrphanDelete(pc.getCascade().equals(CASCADE_ALL_DELETE_ORPHAN));
}
// if it's a one-to-many mapping
if (shouldBindCollectionWithForeignKey(property)) {
OneToMany oneToMany = new OneToMany(metadataBuildingContext, collection.getOwner());
collection.setElement(oneToMany);
bindOneToMany((org.grails.datastore.mapping.model.types.OneToMany) property, oneToMany, mappings);
} else {
bindCollectionTable(property, mappings, collection, owner.getTable(), sessionFactoryBeanName);
if (!property.isOwningSide()) {
collection.setInverse(true);
}
}
if (pc.getBatchSize() != null) {
collection.setBatchSize(pc.getBatchSize());
}
// set up second pass
if (collection instanceof org.hibernate.mapping.Set) {
mappings.addSecondPass(new GrailsCollectionSecondPass(property, mappings, collection, sessionFactoryBeanName));
}
else if (collection instanceof org.hibernate.mapping.List) {
mappings.addSecondPass(new ListSecondPass(property, mappings, collection, sessionFactoryBeanName));
}
else if (collection instanceof org.hibernate.mapping.Map) {
mappings.addSecondPass(new MapSecondPass(property, mappings, collection, sessionFactoryBeanName));
}
else { // Collection -> Bag
mappings.addSecondPass(new GrailsCollectionSecondPass(property, mappings, collection, sessionFactoryBeanName));
}
}
protected void bindOneToMany(org.grails.datastore.mapping.model.types.OneToMany currentGrailsProp, OneToMany one, InFlightMetadataCollector mappings) {
one.setReferencedEntityName(currentGrailsProp.getAssociatedEntity().getName());
one.setIgnoreNotFound(true);
}
protected void setCascadeBehaviour(PersistentProperty grailsProperty, Property prop) {
String cascadeStrategy = "none";
// set to cascade all for the moment
PersistentEntity domainClass = grailsProperty.getOwner();
PropertyConfig config = getPropertyConfig(grailsProperty);
if (config != null && config.getCascade() != null) {
cascadeStrategy = config.getCascade();
} else if (grailsProperty instanceof Association) {
Association association = (Association) grailsProperty;
PersistentEntity referenced = association.getAssociatedEntity();
if (isHasOne(association)) {
cascadeStrategy = CASCADE_ALL;
}
else if (association instanceof org.grails.datastore.mapping.model.types.OneToOne) {
if (referenced != null && association.isOwningSide()) {
cascadeStrategy = CASCADE_ALL;
}
else {
cascadeStrategy = CASCADE_SAVE_UPDATE;
}
} else if (association instanceof org.grails.datastore.mapping.model.types.OneToMany) {
if (referenced != null && association.isOwningSide()) {
cascadeStrategy = CASCADE_ALL;
}
else {
cascadeStrategy = CASCADE_SAVE_UPDATE;
}
} else if (grailsProperty instanceof ManyToMany) {
if ((referenced != null && referenced.isOwningEntity(domainClass)) || association.isCircular()) {
cascadeStrategy = CASCADE_SAVE_UPDATE;
}
} else if (grailsProperty instanceof org.grails.datastore.mapping.model.types.ManyToOne) {
if (referenced != null && referenced.isOwningEntity(domainClass) && !isCircularAssociation(grailsProperty)) {
cascadeStrategy = CASCADE_ALL;
}
else if(isCompositeIdProperty((Mapping) domainClass.getMapping().getMappedForm(), grailsProperty)) {
cascadeStrategy = CASCADE_ALL;
}
else {
cascadeStrategy = CASCADE_NONE;
}
}
else if (grailsProperty instanceof Basic) {
cascadeStrategy = CASCADE_ALL;
}
else if (Map.class.isAssignableFrom(grailsProperty.getType())) {
referenced = association.getAssociatedEntity();
if (referenced != null && referenced.isOwningEntity(domainClass)) {
cascadeStrategy = CASCADE_ALL;
} else {
cascadeStrategy = CASCADE_SAVE_UPDATE;
}
}
logCascadeMapping(association, cascadeStrategy, referenced);
}
prop.setCascade(cascadeStrategy);
}
/**
* Called for Maps
*/
public static void bindMapSecondPass(Element node, Map map, java.util.Map classes,
Mappings mappings, java.util.Map inheritedMetas) throws MappingException {
bindCollectionSecondPass( node, map, classes, mappings, inheritedMetas );
Iterator iter = node.elementIterator();
while ( iter.hasNext() ) {
Element subnode = (Element) iter.next();
String name = subnode.getName();
if ( "index".equals( name ) || "map-key".equals( name ) ) {
SimpleValue value = new SimpleValue( map.getCollectionTable() );
bindSimpleValue(
subnode,
value,
map.isOneToMany(),
IndexedCollection.DEFAULT_INDEX_COLUMN_NAME,
mappings
);
if ( !value.isTypeSpecified() ) {
throw new MappingException( "map index element must specify a type: "
+ map.getRole() );
}
map.setIndex( value );
map.setIndexNodeName( subnode.attributeValue("node") );
}
else if ( "index-many-to-many".equals( name ) || "map-key-many-to-many".equals( name ) ) {
ManyToOne mto = new ManyToOne( map.getCollectionTable() );
bindManyToOne(
subnode,
mto,
IndexedCollection.DEFAULT_INDEX_COLUMN_NAME,
map.isOneToMany(),
mappings
);
map.setIndex( mto );
}
else if ( "composite-index".equals( name ) || "composite-map-key".equals( name ) ) {
Component component = new Component( map );
bindComposite(
subnode,
component,
map.getRole() + ".index",
map.isOneToMany(),
mappings,
inheritedMetas
);
map.setIndex( component );
}
else if ( "index-many-to-any".equals( name ) ) {
Any any = new Any( map.getCollectionTable() );
bindAny( subnode, any, map.isOneToMany(), mappings );
map.setIndex( any );
}
}
// TODO: this is a bit of copy/paste from IndexedCollection.createPrimaryKey()
boolean indexIsFormula = false;
Iterator colIter = map.getIndex().getColumnIterator();
while ( colIter.hasNext() ) {
if ( ( (Selectable) colIter.next() ).isFormula() ) indexIsFormula = true;
}
if ( map.isOneToMany() && !map.getKey().isNullable() && !map.isInverse() && !indexIsFormula ) {
String entityName = ( (OneToMany) map.getElement() ).getReferencedEntityName();
PersistentClass referenced = mappings.getClass( entityName );
IndexBackref ib = new IndexBackref();
ib.setName( '_' + node.attributeValue( "name" ) + "IndexBackref" );
ib.setUpdateable( false );
ib.setSelectable( false );
ib.setCollectionRole( map.getRole() );
ib.setEntityName( map.getOwner().getEntityName() );
ib.setValue( map.getIndex() );
// ( (Column) ( (SimpleValue) ic.getIndex() ).getColumnIterator().next()
// ).setNullable(false);
referenced.addProperty( ib );
}
}
public Object accept(OneToMany many) {
return validate(OneToMany.class, many);
}
public static void bindOneToMany(Element node, OneToMany oneToMany, Mappings mappings)
throws MappingException {
oneToMany.setReferencedEntityName( getEntityName( node, mappings ) );
String embed = node.attributeValue( "embed-xml" );
oneToMany.setEmbedded( embed == null || "true".equals( embed ) );
String notFound = node.attributeValue( "not-found" );
oneToMany.setIgnoreNotFound( "ignore".equals( notFound ) );
}
/**
* Checks whether a property is a unidirectional non-circular one-to-many
*
* @param property The property to check
* @return true if it is unidirectional and a one-to-many
*/
protected boolean isUnidirectionalOneToMany(PersistentProperty property) {
return ((property instanceof org.grails.datastore.mapping.model.types.OneToMany) && !((Association)property).isBidirectional());
}