|
41 | 41 | import org.hibernate.graph.RootGraph;
|
42 | 42 | import org.hibernate.graph.spi.AppliedGraph;
|
43 | 43 | import org.hibernate.graph.spi.RootGraphImplementor;
|
| 44 | +import org.hibernate.id.BulkInsertionCapableIdentifierGenerator; |
| 45 | +import org.hibernate.id.IdentifierGenerator; |
| 46 | +import org.hibernate.id.OptimizableGenerator; |
| 47 | +import org.hibernate.id.enhanced.Optimizer; |
44 | 48 | import org.hibernate.internal.CoreLogging;
|
45 | 49 | import org.hibernate.internal.CoreMessageLogger;
|
46 | 50 | import org.hibernate.internal.util.collections.IdentitySet;
|
| 51 | +import org.hibernate.metamodel.mapping.EntityIdentifierMapping; |
| 52 | +import org.hibernate.metamodel.mapping.internal.SingleAttributeIdentifierMapping; |
47 | 53 | import org.hibernate.metamodel.model.domain.EntityDomainType;
|
| 54 | +import org.hibernate.persister.entity.AbstractEntityPersister; |
48 | 55 | import org.hibernate.persister.entity.EntityPersister;
|
49 | 56 | import org.hibernate.query.BindableType;
|
50 | 57 | import org.hibernate.query.IllegalQueryOperationException;
|
|
76 | 83 | import org.hibernate.query.spi.QueryParameterBindings;
|
77 | 84 | import org.hibernate.query.spi.ScrollableResultsImplementor;
|
78 | 85 | import org.hibernate.query.spi.SelectQueryPlan;
|
| 86 | +import org.hibernate.query.sqm.SqmPathSource; |
79 | 87 | import org.hibernate.query.sqm.internal.SqmInterpretationsKey.InterpretationsKeySource;
|
80 | 88 | import org.hibernate.query.sqm.mutation.spi.SqmMultiTableInsertStrategy;
|
81 | 89 | import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
|
|
88 | 96 | import org.hibernate.query.sqm.tree.expression.SqmExpression;
|
89 | 97 | import org.hibernate.query.sqm.tree.expression.SqmJpaCriteriaParameterWrapper;
|
90 | 98 | import org.hibernate.query.sqm.tree.expression.SqmParameter;
|
| 99 | +import org.hibernate.query.sqm.tree.from.SqmRoot; |
91 | 100 | import org.hibernate.query.sqm.tree.insert.SqmInsertSelectStatement;
|
92 | 101 | import org.hibernate.query.sqm.tree.insert.SqmInsertStatement;
|
93 | 102 | import org.hibernate.query.sqm.tree.insert.SqmInsertValuesStatement;
|
@@ -820,20 +829,56 @@ private NonSelectQueryPlan buildInsertQueryPlan() {
|
820 | 829 | final SqmInsertStatement sqmInsert = (SqmInsertStatement) getSqmStatement();
|
821 | 830 |
|
822 | 831 | final String entityNameToInsert = sqmInsert.getTarget().getModel().getHibernateEntityName();
|
823 |
| - final EntityPersister entityDescriptor = getSessionFactory().getRuntimeMetamodels() |
| 832 | + final AbstractEntityPersister entityDescriptor = (AbstractEntityPersister) getSessionFactory().getRuntimeMetamodels() |
824 | 833 | .getMappingMetamodel()
|
825 | 834 | .getEntityDescriptor( entityNameToInsert );
|
826 | 835 |
|
827 |
| - final SqmMultiTableInsertStrategy multiTableStrategy = entityDescriptor.getSqmMultiTableInsertStrategy(); |
828 |
| - if ( multiTableStrategy == null || isSimpleValuesInsert( sqmInsert, entityDescriptor ) ) { |
| 836 | + boolean useMultiTableInsert = entityDescriptor.isMultiTable(); |
| 837 | + if ( !useMultiTableInsert && !isSimpleValuesInsert( sqmInsert, entityDescriptor ) ) { |
| 838 | + final IdentifierGenerator identifierGenerator = entityDescriptor.getIdentifierGenerator(); |
| 839 | + if ( identifierGenerator instanceof BulkInsertionCapableIdentifierGenerator && identifierGenerator instanceof OptimizableGenerator ) { |
| 840 | + final Optimizer optimizer = ( (OptimizableGenerator) identifierGenerator ).getOptimizer(); |
| 841 | + if ( optimizer != null && optimizer.getIncrementSize() > 1 ) { |
| 842 | + useMultiTableInsert = !hasIdentifierAssigned( sqmInsert, entityDescriptor ); |
| 843 | + } |
| 844 | + } |
| 845 | + } |
| 846 | + if ( !useMultiTableInsert ) { |
829 | 847 | return new SimpleInsertQueryPlan( sqmInsert, domainParameterXref );
|
830 | 848 | }
|
831 | 849 | else {
|
832 |
| - return new MultiTableInsertQueryPlan( sqmInsert, domainParameterXref, multiTableStrategy ); |
| 850 | + return new MultiTableInsertQueryPlan( |
| 851 | + sqmInsert, |
| 852 | + domainParameterXref, |
| 853 | + entityDescriptor.getSqmMultiTableInsertStrategy() |
| 854 | + ); |
| 855 | + } |
| 856 | + } |
| 857 | + |
| 858 | + private boolean hasIdentifierAssigned(SqmInsertStatement<?> sqmInsert, EntityPersister entityDescriptor) { |
| 859 | + final EntityIdentifierMapping identifierMapping = entityDescriptor.getIdentifierMapping(); |
| 860 | + final String partName; |
| 861 | + if ( identifierMapping instanceof SingleAttributeIdentifierMapping ) { |
| 862 | + partName = ( (SingleAttributeIdentifierMapping) identifierMapping ).getAttributeName(); |
| 863 | + } |
| 864 | + else { |
| 865 | + partName = EntityIdentifierMapping.ROLE_LOCAL_NAME; |
| 866 | + } |
| 867 | + for ( SqmPath<?> insertionTargetPath : sqmInsert.getInsertionTargetPaths() ) { |
| 868 | + final SqmPath<?> lhs = insertionTargetPath.getLhs(); |
| 869 | + if ( !( lhs instanceof SqmRoot<?> ) ) { |
| 870 | + continue; |
| 871 | + } |
| 872 | + final SqmPathSource<?> referencedPathSource = insertionTargetPath.getReferencedPathSource(); |
| 873 | + if ( referencedPathSource.getPathName().equals( partName ) ) { |
| 874 | + return true; |
| 875 | + } |
833 | 876 | }
|
| 877 | + |
| 878 | + return false; |
834 | 879 | }
|
835 | 880 |
|
836 |
| - private boolean isSimpleValuesInsert(@SuppressWarnings("rawtypes") SqmInsertStatement sqmInsert, EntityPersister entityDescriptor) { |
| 881 | + private boolean isSimpleValuesInsert(SqmInsertStatement<?> sqmInsert, EntityPersister entityDescriptor) { |
837 | 882 | // Simple means that we can translate the statement to a single plain insert
|
838 | 883 | return sqmInsert instanceof SqmInsertValuesStatement
|
839 | 884 | // An insert is only simple if no SqmMultiTableMutation strategy is available,
|
|
0 commit comments