📄 collectionbinder.java
字号:
} } else { if ( hasToBeSorted ) { throw new AnnotationException( "A sorted collection has to define @Sort: " + safeCollectionRole() ); } } //set cache if ( StringHelper.isNotEmpty( cacheConcurrencyStrategy ) ) { collection.setCacheConcurrencyStrategy( cacheConcurrencyStrategy ); collection.setCacheRegionName( cacheRegionName ); } //SQL overriding SQLInsert sqlInsert = property.getAnnotation( SQLInsert.class ); SQLUpdate sqlUpdate = property.getAnnotation( SQLUpdate.class ); SQLDelete sqlDelete = property.getAnnotation( SQLDelete.class ); SQLDeleteAll sqlDeleteAll = property.getAnnotation( SQLDeleteAll.class ); Loader loader = property.getAnnotation( Loader.class ); if ( sqlInsert != null ) { collection.setCustomSQLInsert( sqlInsert.sql().trim(), sqlInsert.callable(), ExecuteUpdateResultCheckStyle.parse( sqlInsert.check().toString().toLowerCase() ) ); } if ( sqlUpdate != null ) { collection.setCustomSQLUpdate( sqlUpdate.sql(), sqlUpdate.callable(), ExecuteUpdateResultCheckStyle.parse( sqlUpdate.check().toString().toLowerCase() ) ); } if ( sqlDelete != null ) { collection.setCustomSQLDelete( sqlDelete.sql(), sqlDelete.callable(), ExecuteUpdateResultCheckStyle.parse( sqlDelete.check().toString().toLowerCase() ) ); } if ( sqlDeleteAll != null ) { collection.setCustomSQLDeleteAll( sqlDeleteAll.sql(), sqlDeleteAll.callable(), ExecuteUpdateResultCheckStyle.parse( sqlDeleteAll.check().toString().toLowerCase() ) ); } if ( loader != null ) { collection.setLoaderName( loader.namedQuery() ); } //work on association boolean isMappedBy = !BinderHelper.isDefault( mappedBy ); collection.setInverse( isMappedBy ); //many to many may need some second pass informations if ( !oneToMany && isMappedBy ) { mappings.addMappedBy( getCollectionType().getName(), mappedBy, propertyName ); } //TODO reducce tableBinder != null and oneToMany XClass collectionType = getCollectionType(); SecondPass sp = getSecondPass( fkJoinColumns, joinColumns, inverseJoinColumns, elementColumns, mapKeyColumns, mapKeyManyToManyColumns, isEmbedded, property, collectionType, ignoreNotFound, oneToMany, tableBinder, mappings ); if ( collectionType.isAnnotationPresent( Embeddable.class ) || property.isAnnotationPresent( CollectionOfElements.class ) ) { // do it right away, otherwise @ManyToon on composite element call addSecondPass // and raise a ConcurrentModificationException //sp.doSecondPass( CollectionHelper.EMPTY_MAP ); mappings.addSecondPass( sp, !isMappedBy ); } else { mappings.addSecondPass( sp, !isMappedBy ); } mappings.addCollection( collection ); //property building PropertyBinder binder = new PropertyBinder(); binder.setName( propertyName ); binder.setValue( collection ); binder.setCascade( cascadeStrategy ); if ( cascadeStrategy != null && cascadeStrategy.indexOf( "delete-orphan" ) >= 0 ) { collection.setOrphanDelete( true ); } binder.setPropertyAccessorName( propertyAccessorName ); binder.setProperty( property ); binder.setInsertable( insertable ); binder.setUpdatable( updatable ); Property prop = binder.make(); //we don't care about the join stuffs because the column is on the association table. propertyHolder.addProperty( prop ); } private void defineFetchingStrategy() { LazyCollection lazy = property.getAnnotation( LazyCollection.class ); Fetch fetch = property.getAnnotation( Fetch.class ); OneToMany oneToMany = property.getAnnotation( OneToMany.class ); ManyToMany manyToMany = property.getAnnotation( ManyToMany.class ); CollectionOfElements elements = property.getAnnotation( CollectionOfElements.class ); ManyToAny manyToAny = property.getAnnotation( ManyToAny.class ); FetchType fetchType; if ( oneToMany != null ) { fetchType = oneToMany.fetch(); } else if ( manyToMany != null ) { fetchType = manyToMany.fetch(); } else if ( elements != null ) { fetchType = elements.fetch(); } else if ( manyToAny != null ) { fetchType = FetchType.LAZY; } else { throw new AssertionFailure( "Define fetch strategy on a property not annotated with @ManyToOne nor @OneToMany nor @CollectionOfElements" ); } if ( lazy != null ) { collection.setLazy( !( lazy.value() == LazyCollectionOption.FALSE ) ); collection.setExtraLazy( lazy.value() == LazyCollectionOption.EXTRA ); } else { collection.setLazy( fetchType == FetchType.LAZY ); collection.setExtraLazy( false ); } if ( fetch != null ) { if ( fetch.value() == org.hibernate.annotations.FetchMode.JOIN ) { collection.setFetchMode( FetchMode.JOIN ); collection.setLazy( false ); } else if ( fetch.value() == org.hibernate.annotations.FetchMode.SELECT ) { collection.setFetchMode( FetchMode.SELECT ); } else if ( fetch.value() == org.hibernate.annotations.FetchMode.SUBSELECT ) { collection.setFetchMode( FetchMode.SELECT ); collection.setSubselectLoadable( true ); collection.getOwner().setSubselectLoadableCollections( true ); } else { throw new AssertionFailure( "Unknown FetchMode: " + fetch.value() ); } } else { collection.setFetchMode( AnnotationBinder.getFetchMode( fetchType ) ); } } private XClass getCollectionType() { if ( AnnotationBinder.isDefault( targetEntity, mappings ) ) { if ( collectionType != null ) { return collectionType; } else { String errorMsg = "Collection has neither generic type or OneToMany.targetEntity() defined: " + safeCollectionRole(); throw new AnnotationException( errorMsg ); } } else { return targetEntity; } } public SecondPass getSecondPass( final Ejb3JoinColumn[] fkJoinColumns, final Ejb3JoinColumn[] keyColumns, final Ejb3JoinColumn[] inverseColumns, final Ejb3Column[] elementColumns, final Ejb3Column[] mapKeyColumns, final Ejb3JoinColumn[] mapKeyManyToManyColumns, final boolean isEmbedded, final XProperty property, final XClass collType, final boolean ignoreNotFound, final boolean unique, final TableBinder assocTableBinder, final ExtendedMappings mappings ) { return new CollectionSecondPass( mappings, collection ) { public void secondPass(java.util.Map persistentClasses, java.util.Map inheritedMetas) throws MappingException { bindStarToManySecondPass( persistentClasses, collType, fkJoinColumns, keyColumns, inverseColumns, elementColumns, isEmbedded, property, unique, assocTableBinder, ignoreNotFound, mappings ); } }; } /** * return true if it's a Fk, false if it's an association table */ protected boolean bindStarToManySecondPass( Map persistentClasses, XClass collType, Ejb3JoinColumn[] fkJoinColumns, Ejb3JoinColumn[] keyColumns, Ejb3JoinColumn[] inverseColumns, Ejb3Column[] elementColumns, boolean isEmbedded, XProperty property, boolean unique, TableBinder associationTableBinder, boolean ignoreNotFound, ExtendedMappings mappings ) { PersistentClass persistentClass = (PersistentClass) persistentClasses.get( collType.getName() ); boolean reversePropertyInJoin = false; if ( persistentClass != null && StringHelper.isNotEmpty( this.mappedBy ) ) { try { reversePropertyInJoin = 0 != persistentClass.getJoinNumber( persistentClass.getRecursiveProperty( this.mappedBy ) ); } catch (MappingException e) { StringBuilder error = new StringBuilder( 80 ); error.append( "mappedBy reference an unknown target entity property: " ) .append( collType ).append( "." ).append( this.mappedBy ) .append( " in " ) .append( collection.getOwnerEntityName() ) .append( "." ) .append( property.getName() ); throw new AnnotationException( error.toString() ); } } if ( persistentClass != null && !reversePropertyInJoin && oneToMany && !this.isExplicitAssociationTable && ( joinColumns[0].isImplicit() && !BinderHelper.isDefault( this.mappedBy ) //implicit @JoinColumn || !fkJoinColumns[0].isImplicit() ) //this is an explicit @JoinColumn ) { //this is a Foreign key bindOneToManySecondPass( getCollection(), persistentClasses, fkJoinColumns, collType, cascadeDeleteEnabled, ignoreNotFound, hqlOrderBy, mappings ); return true; } else { //this is an association table bindManyToManySecondPass( this.collection, persistentClasses, keyColumns, inverseColumns, elementColumns, isEmbedded, collType, ignoreNotFound, unique, cascadeDeleteEnabled, associationTableBinder, property, propertyHolder, hqlOrderBy, mappings ); return false; } } protected void bindOneToManySecondPass( Collection collection, Map persistentClasses, Ejb3JoinColumn[] fkJoinColumns, XClass collectionType, boolean cascadeDeleteEnabled, boolean ignoreNotFound, String hqlOrderBy, ExtendedMappings extendedMappings ) { if ( log.isDebugEnabled() ) { log.debug( "Binding a OneToMany: " + propertyHolder.getEntityName() + "." + propertyName + " through a foreign key" ); } org.hibernate.mapping.OneToMany oneToMany = new org.hibernate.mapping.OneToMany( collection.getOwner() ); collection.setElement( oneToMany ); oneToMany.setReferencedEntityName( collectionType.getName() ); oneToMany.setIgnoreNotFound( ignoreNotFound ); String assocClass = oneToMany.getReferencedEntityName(); PersistentClass associatedClass = (PersistentClass) persistentClasses.get( assocClass ); String orderBy = buildOrderByClauseFromHql( hqlOrderBy, associatedClass, collection.getRole() ); if ( orderBy != null ) collection.setOrderBy( orderBy ); if ( mappings == null ) { throw new AssertionFailure( "CollectionSecondPass for oneToMany should not be called with null mappings" ); } Map<String, Join> joins = mappings.getJoins( assocClass ); if ( associatedClass == null ) { throw new MappingException( "Association references unmapped class: " + assocClass ); } oneToMany.setAssociatedClass( associatedClass ); for (Ejb3JoinColumn column : fkJoinColumns) { column.setPersistentClass( associatedClass, joins ); column.setJoins( joins ); collection.setCollectionTable( column.getTable() ); } log.info( "Mapping collection: " + collection.getRole() + " -> " + collection.getCollectionTable().getName() ); bindFilters( false ); bindCollectionSecondPass( collection, null, fkJoinColumns, cascadeDeleteEnabled, property, mappings ); if ( !collection.isInverse() && !collection.getKey().isNullable() ) { // for non-inverse one-to-many, with a not-null fk, add a backref! String entityName = oneToMany.getReferencedEntityName(); PersistentClass referenced = mappings.getClass( entityName ); Backref prop = new Backref(); prop.setName( '_' + fkJoinColumns[0].getPropertyName() + "Backref" ); prop.setUpdateable( false ); prop.setSelectable( false ); prop.setCollectionRole( collection.getRole() ); prop.setEntityName( collection.getOwner().getEntityName() ); prop.setValue( collection.getKey() ); referenced.addProperty( prop ); } } private void bindFilters(boolean hasAssociationTable) { Filter simpleFilter = property.getAnnotation( Filter.class ); //set filtering //test incompatible choices //if ( StringHelper.isNotEmpty( where ) ) collection.setWhere( where ); if ( simpleFilter != null ) { if ( hasAssociationTable ) { collection.addManyToManyFilter( simpleFilter.name(), getCondition( simpleFilter ) ); } else { collection.addFilter( simpleFilter.name(), getCondition( simpleFilter ) ); } } Filters filters = property.getAnnotation( Filters.class ); if ( filters != null ) { for (Filter filter : filters.value()) { if ( hasAssociationTable ) { collection.addManyToManyFilter( filter.name(), getCondition( filter ) ); } else { collection.addFilter( filter.name(), getCondition( filter ) ); } } } FilterJoinTable simpleFilterJoinTable = property.getAnnotation( FilterJoinTable.class ); if ( simpleFilterJoinTable != null ) { if ( hasAssociationTable ) { collection.addFilter( simpleFilterJoinTable.name(), getCondition( simpleFilterJoinTable ) ); } else { throw new AnnotationException( "Illegal use of @FilterJoinTable on an association without join table:" + StringHelper.qualify( propertyHolder.getPath(), propertyName ) ); } } FilterJoinTables filterJoinTables = property.getAnnotation( FilterJoinTables.class ); if ( filterJoinTables != null ) { for (FilterJoinTable filter : filterJoinTables.value()) { if ( hasAssociationTable ) { collection.addFilter( filter.name(), getCondition( filter ) ); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -