use of org.hibernate.id.enhanced.Optimizer in project uPortal by Jasig.
the class HibernateStyleCounterStore method getNextId.
@Override
public int getNextId(String counterName) {
final int id;
final Optimizer counterOptimizer = this.getCounterOptimizer(counterName);
synchronized (counterOptimizer) {
id = getNextIdInternal(counterOptimizer, counterName);
}
return id;
}
use of org.hibernate.id.enhanced.Optimizer in project hibernate-orm by hibernate.
the class HiLoSequenceMismatchStrategyTest method testSequenceMismatchStrategyNotApplied.
@Test
public void testSequenceMismatchStrategyNotApplied(SessionFactoryScope scope) {
final EntityPersister persister = scope.getSessionFactory().getMappingMetamodel().getEntityDescriptor(TestEntity.class.getName());
assertThat(persister.getIdentifierGenerator(), instanceOf(SequenceStyleGenerator.class));
final SequenceStyleGenerator generator = (SequenceStyleGenerator) persister.getIdentifierGenerator();
final Optimizer optimizer = generator.getOptimizer();
assertThat(optimizer, instanceOf(HiLoOptimizer.class));
assertThat(optimizer.getIncrementSize(), not(is(1)));
assertThat(generator.getDatabaseStructure().getPhysicalName().render(), is(sequenceName));
}
use of org.hibernate.id.enhanced.Optimizer in project hibernate-orm by hibernate.
the class CteInsertHandler method execute.
@Override
public int execute(DomainQueryExecutionContext executionContext) {
final SqmInsertStatement<?> sqmInsertStatement = getSqmStatement();
final SessionFactoryImplementor factory = executionContext.getSession().getFactory();
final EntityPersister entityDescriptor = getEntityDescriptor().getEntityPersister();
final String explicitDmlTargetAlias;
if (sqmInsertStatement.getTarget().getExplicitAlias() == null) {
explicitDmlTargetAlias = "dml_target";
} else {
explicitDmlTargetAlias = sqmInsertStatement.getTarget().getExplicitAlias();
}
final MultiTableSqmMutationConverter sqmConverter = new MultiTableSqmMutationConverter(entityDescriptor, sqmInsertStatement, sqmInsertStatement.getTarget(), explicitDmlTargetAlias, domainParameterXref, executionContext.getQueryOptions(), executionContext.getSession().getLoadQueryInfluencers(), executionContext.getQueryParameterBindings(), factory);
final TableGroup insertingTableGroup = sqmConverter.getMutatingTableGroup();
final Map<SqmParameter<?>, List<List<JdbcParameter>>> parameterResolutions;
if (domainParameterXref.getSqmParameterCount() == 0) {
parameterResolutions = Collections.emptyMap();
} else {
parameterResolutions = new IdentityHashMap<>();
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// visit the insertion target using our special converter, collecting
// information about the target paths
final int size = sqmStatement.getInsertionTargetPaths().size();
final List<Map.Entry<SqmCteTableColumn, Assignment>> targetPathColumns = new ArrayList<>(size);
final List<SqmCteTableColumn> targetPathSqmCteColumns = new ArrayList<>(size);
final Map<SqmParameter<?>, MappingModelExpressible<?>> paramTypeResolutions = new LinkedHashMap<>();
final NamedTableReference entityTableReference = new NamedTableReference(cteTable.getCteName(), TemporaryTable.DEFAULT_ALIAS, true, sessionFactory);
final InsertStatement insertStatement = new InsertStatement(entityTableReference);
final BaseSqmToSqlAstConverter.AdditionalInsertValues additionalInsertValues = sqmConverter.visitInsertionTargetPaths((assignable, columnReferences) -> {
// Find a matching cte table column and set that at the current index
for (SqmCteTableColumn column : cteTable.getColumns()) {
if (column.getType() == ((Expression) assignable).getExpressionType()) {
insertStatement.addTargetColumnReferences(columnReferences);
targetPathSqmCteColumns.add(column);
targetPathColumns.add(new AbstractMap.SimpleEntry<>(column, new Assignment(assignable, (Expression) assignable)));
return;
}
}
throw new IllegalStateException("Couldn't find matching cte column for: " + ((Expression) assignable).getExpressionType());
}, sqmInsertStatement, entityDescriptor, insertingTableGroup, (sqmParameter, mappingType, jdbcParameters) -> {
parameterResolutions.computeIfAbsent(sqmParameter, k -> new ArrayList<>(1)).add(jdbcParameters);
paramTypeResolutions.put(sqmParameter, mappingType);
});
final boolean assignsId = targetPathSqmCteColumns.contains(cteTable.getColumns().get(0));
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Create the statement that represent the source for the entity cte
final Stack<SqlAstProcessingState> processingStateStack = sqmConverter.getProcessingStateStack();
final SqlAstProcessingState oldState = processingStateStack.pop();
final Statement queryStatement;
if (sqmInsertStatement instanceof SqmInsertSelectStatement) {
final QueryPart queryPart = sqmConverter.visitQueryPart(((SqmInsertSelectStatement<?>) sqmInsertStatement).getSelectQueryPart());
queryPart.visitQuerySpecs(querySpec -> {
// in which case we will fill the row_number column instead of the id column
if (additionalInsertValues.applySelections(querySpec, sessionFactory)) {
final SqmCteTableColumn rowNumberColumn = cteTable.getColumns().get(cteTable.getColumns().size() - 1);
final ColumnReference columnReference = new ColumnReference((String) null, rowNumberColumn.getColumnName(), false, null, null, (JdbcMapping) rowNumberColumn.getType(), sessionFactory);
insertStatement.getTargetColumnReferences().set(insertStatement.getTargetColumnReferences().size() - 1, columnReference);
targetPathSqmCteColumns.set(targetPathSqmCteColumns.size() - 1, rowNumberColumn);
}
if (!assignsId && entityDescriptor.getIdentifierGenerator() instanceof PostInsertIdentifierGenerator) {
final BasicType<Integer> rowNumberType = sessionFactory.getTypeConfiguration().getBasicTypeForJavaType(Integer.class);
querySpec.getSelectClause().addSqlSelection(new SqlSelectionImpl(1, 0, new Over<>(new SelfRenderingFunctionSqlAstExpression("row_number", (appender, args, walker) -> appender.appendSql("row_number()"), Collections.emptyList(), rowNumberType, rowNumberType), Collections.emptyList(), Collections.emptyList())));
}
});
queryStatement = new SelectStatement(queryPart);
} else {
final List<SqmValues> sqmValuesList = ((SqmInsertValuesStatement<?>) sqmInsertStatement).getValuesList();
final List<Values> valuesList = new ArrayList<>(sqmValuesList.size());
for (SqmValues sqmValues : sqmValuesList) {
final Values values = sqmConverter.visitValues(sqmValues);
additionalInsertValues.applyValues(values);
valuesList.add(values);
}
final QuerySpec querySpec = new QuerySpec(true);
final NavigablePath navigablePath = new NavigablePath(entityDescriptor.getRootPathName());
final List<String> columnNames = new ArrayList<>(targetPathColumns.size());
for (Map.Entry<SqmCteTableColumn, Assignment> entry : targetPathColumns) {
for (ColumnReference columnReference : entry.getValue().getAssignable().getColumnReferences()) {
columnNames.add(columnReference.getColumnExpression());
querySpec.getSelectClause().addSqlSelection(new SqlSelectionImpl(1, 0, columnReference));
}
}
final ValuesTableGroup valuesTableGroup = new ValuesTableGroup(navigablePath, entityDescriptor.getEntityPersister(), valuesList, insertingTableGroup.getPrimaryTableReference().getIdentificationVariable(), columnNames, true, factory);
querySpec.getFromClause().addRoot(valuesTableGroup);
queryStatement = new SelectStatement(querySpec);
}
processingStateStack.push(oldState);
sqmConverter.pruneTableGroupJoins();
if (!assignsId && entityDescriptor.getIdentifierGenerator() instanceof PostInsertIdentifierGenerator) {
// Add the row number to the assignments
final SqmCteTableColumn rowNumberColumn = cteTable.getColumns().get(cteTable.getColumns().size() - 1);
final ColumnReference columnReference = new ColumnReference((String) null, rowNumberColumn.getColumnName(), false, null, null, (JdbcMapping) rowNumberColumn.getType(), sessionFactory);
insertStatement.getTargetColumnReferences().add(columnReference);
targetPathSqmCteColumns.add(rowNumberColumn);
}
final CteTable entityCteTable = BaseSqmToSqlAstConverter.createCteTable(getCteTable(), targetPathSqmCteColumns, factory);
// Create the main query spec that will return the count of rows
final QuerySpec querySpec = new QuerySpec(true, 1);
final List<DomainResult<?>> domainResults = new ArrayList<>(1);
final SelectStatement statement = new SelectStatement(querySpec, domainResults);
final CteStatement entityCte;
if (additionalInsertValues.requiresRowNumberIntermediate()) {
final CteTable fullEntityCteTable = BaseSqmToSqlAstConverter.createCteTable(getCteTable(), factory);
final String baseTableName = "base_" + entityCteTable.getTableExpression();
final CteStatement baseEntityCte = new CteStatement(entityCteTable.withName(baseTableName), queryStatement, // The query cte will be reused multiple times
CteMaterialization.MATERIALIZED);
statement.addCteStatement(baseEntityCte);
final CteColumn rowNumberColumn = fullEntityCteTable.getCteColumns().get(fullEntityCteTable.getCteColumns().size() - 1);
final ColumnReference rowNumberColumnReference = new ColumnReference("e", rowNumberColumn.getColumnExpression(), false, null, null, rowNumberColumn.getJdbcMapping(), factory);
final CteColumn idColumn = fullEntityCteTable.getCteColumns().get(0);
final BasicValuedMapping idType = (BasicValuedMapping) idColumn.getJdbcMapping();
final Optimizer optimizer = ((OptimizableGenerator) entityDescriptor.getIdentifierGenerator()).getOptimizer();
final BasicValuedMapping integerType = (BasicValuedMapping) rowNumberColumn.getJdbcMapping();
final Expression rowNumberMinusOneModuloIncrement = new BinaryArithmeticExpression(new BinaryArithmeticExpression(rowNumberColumnReference, BinaryArithmeticOperator.SUBTRACT, new QueryLiteral<>(1, (BasicValuedMapping) rowNumberColumn.getJdbcMapping()), integerType), BinaryArithmeticOperator.MODULO, new QueryLiteral<>(optimizer.getIncrementSize(), integerType), integerType);
// Create the CTE that fetches a new sequence value for the row numbers that need it
{
final QuerySpec rowsWithSequenceQuery = new QuerySpec(true);
rowsWithSequenceQuery.getFromClause().addRoot(new CteTableGroup(new NamedTableReference(baseTableName, "e", false, factory)));
rowsWithSequenceQuery.getSelectClause().addSqlSelection(new SqlSelectionImpl(1, 0, rowNumberColumnReference));
final String fragment = ((BulkInsertionCapableIdentifierGenerator) entityDescriptor.getIdentifierGenerator()).determineBulkInsertionIdentifierGenerationSelectFragment(sessionFactory.getSqlStringGenerationContext());
rowsWithSequenceQuery.getSelectClause().addSqlSelection(new SqlSelectionImpl(2, 1, new SelfRenderingSqlFragmentExpression(fragment)));
rowsWithSequenceQuery.applyPredicate(new ComparisonPredicate(rowNumberMinusOneModuloIncrement, ComparisonOperator.EQUAL, new QueryLiteral<>(0, integerType)));
final CteTable rowsWithSequenceCteTable = new CteTable(ROW_NUMBERS_WITH_SEQUENCE_VALUE, Arrays.asList(rowNumberColumn, idColumn), sessionFactory);
final SelectStatement rowsWithSequenceStatement = new SelectStatement(rowsWithSequenceQuery);
final CteStatement rowsWithSequenceCte = new CteStatement(rowsWithSequenceCteTable, rowsWithSequenceStatement, // The query cte will be reused multiple times
CteMaterialization.MATERIALIZED);
statement.addCteStatement(rowsWithSequenceCte);
}
// Create the CTE that represents the entity cte
{
final QuerySpec entityQuery = new QuerySpec(true);
final NavigablePath navigablePath = new NavigablePath(baseTableName);
final TableGroup baseTableGroup = new TableGroupImpl(navigablePath, null, new NamedTableReference(baseTableName, "e", false, factory), null);
final TableGroup rowsWithSequenceTableGroup = new CteTableGroup(new NamedTableReference(ROW_NUMBERS_WITH_SEQUENCE_VALUE, "t", false, factory));
baseTableGroup.addTableGroupJoin(new TableGroupJoin(rowsWithSequenceTableGroup.getNavigablePath(), SqlAstJoinType.LEFT, rowsWithSequenceTableGroup, new ComparisonPredicate(new BinaryArithmeticExpression(rowNumberColumnReference, BinaryArithmeticOperator.SUBTRACT, rowNumberMinusOneModuloIncrement, integerType), ComparisonOperator.EQUAL, new ColumnReference("t", rowNumberColumn.getColumnExpression(), false, null, null, rowNumberColumn.getJdbcMapping(), factory))));
entityQuery.getFromClause().addRoot(baseTableGroup);
entityQuery.getSelectClause().addSqlSelection(new SqlSelectionImpl(1, 0, new BinaryArithmeticExpression(new ColumnReference("t", idColumn.getColumnExpression(), false, null, null, idColumn.getJdbcMapping(), factory), BinaryArithmeticOperator.ADD, new BinaryArithmeticExpression(rowNumberColumnReference, BinaryArithmeticOperator.SUBTRACT, new ColumnReference("t", rowNumberColumn.getColumnExpression(), false, null, null, rowNumberColumn.getJdbcMapping(), factory), integerType), idType)));
final CteTable finalEntityCteTable;
if (targetPathSqmCteColumns.contains(getCteTable().getColumns().get(0))) {
finalEntityCteTable = entityCteTable;
} else {
targetPathSqmCteColumns.add(0, getCteTable().getColumns().get(0));
finalEntityCteTable = BaseSqmToSqlAstConverter.createCteTable(getCteTable(), targetPathSqmCteColumns, factory);
}
final List<CteColumn> cteColumns = finalEntityCteTable.getCteColumns();
for (int i = 1; i < cteColumns.size(); i++) {
final CteColumn cteColumn = cteColumns.get(i);
entityQuery.getSelectClause().addSqlSelection(new SqlSelectionImpl(i + 1, i, new ColumnReference("e", cteColumn.getColumnExpression(), false, null, null, cteColumn.getJdbcMapping(), factory)));
}
final SelectStatement entityStatement = new SelectStatement(entityQuery);
entityCte = new CteStatement(finalEntityCteTable, entityStatement, // The query cte will be reused multiple times
CteMaterialization.MATERIALIZED);
statement.addCteStatement(entityCte);
}
} else if (!assignsId && entityDescriptor.getIdentifierGenerator() instanceof PostInsertIdentifierGenerator) {
final String baseTableName = "base_" + entityCteTable.getTableExpression();
final CteStatement baseEntityCte = new CteStatement(entityCteTable.withName(baseTableName), queryStatement, // The query cte will be reused multiple times
CteMaterialization.MATERIALIZED);
statement.addCteStatement(baseEntityCte);
targetPathSqmCteColumns.add(0, cteTable.getColumns().get(0));
final CteTable finalEntityCteTable = BaseSqmToSqlAstConverter.createCteTable(getCteTable(), targetPathSqmCteColumns, factory);
final QuerySpec finalQuerySpec = new QuerySpec(true);
final SelectStatement finalQueryStatement = new SelectStatement(finalQuerySpec);
entityCte = new CteStatement(finalEntityCteTable, finalQueryStatement, // The query cte will be reused multiple times
CteMaterialization.MATERIALIZED);
} else {
entityCte = new CteStatement(entityCteTable, queryStatement, // The query cte will be reused multiple times
CteMaterialization.MATERIALIZED);
statement.addCteStatement(entityCte);
}
// Add all CTEs
final String baseInsertCte = addDmlCtes(statement, entityCte, targetPathColumns, assignsId, sqmConverter, parameterResolutions, factory);
final Expression count = createCountStar(factory, sqmConverter);
domainResults.add(new BasicResult(0, null, ((SqlExpressible) count).getJdbcMapping().getJavaTypeDescriptor()));
querySpec.getSelectClause().addSqlSelection(new SqlSelectionImpl(1, 0, count));
querySpec.getFromClause().addRoot(new CteTableGroup(new NamedTableReference(// We want to return the insertion count of the base table
baseInsertCte, CTE_TABLE_IDENTIFIER, false, factory)));
// Execute the statement
final JdbcServices jdbcServices = factory.getJdbcServices();
final SqlAstTranslator<JdbcSelect> translator = jdbcServices.getJdbcEnvironment().getSqlAstTranslatorFactory().buildSelectTranslator(factory, statement);
final JdbcParameterBindings jdbcParameterBindings = SqmUtil.createJdbcParameterBindings(executionContext.getQueryParameterBindings(), domainParameterXref, SqmUtil.generateJdbcParamsXref(domainParameterXref, sqmConverter), factory.getRuntimeMetamodels().getMappingMetamodel(), navigablePath -> sqmConverter.getMutatingTableGroup(), new SqmParameterMappingModelResolutionAccess() {
@Override
@SuppressWarnings("unchecked")
public <T> MappingModelExpressible<T> getResolvedMappingModelType(SqmParameter<T> parameter) {
return (MappingModelExpressible<T>) paramTypeResolutions.get(parameter);
}
}, executionContext.getSession());
final JdbcSelect select = translator.translate(jdbcParameterBindings, executionContext.getQueryOptions());
executionContext.getSession().autoFlushIfRequired(select.getAffectedTableNames());
List<Object> list = jdbcServices.getJdbcSelectExecutor().list(select, jdbcParameterBindings, SqmJdbcExecutionContextAdapter.omittingLockingAndPaging(executionContext), row -> row[0], ListResultsConsumer.UniqueSemantic.NONE);
return ((Number) list.get(0)).intValue();
}
use of org.hibernate.id.enhanced.Optimizer in project hibernate-orm by hibernate.
the class InsertExecutionDelegate method insertRootTable.
private void insertRootTable(String tableExpression, int rows, String[] keyColumns, ExecutionContext executionContext) {
final TableReference updatingTableReference = updatingTableGroup.getTableReference(updatingTableGroup.getNavigablePath(), tableExpression, true, true);
final IdentifierGenerator identifierGenerator = entityDescriptor.getEntityPersister().getIdentifierGenerator();
final List<Assignment> assignments = assignmentsByTable.get(updatingTableReference);
if ((assignments == null || assignments.isEmpty()) && !(identifierGenerator instanceof PostInsertIdentifierGenerator)) {
throw new IllegalStateException("There must be at least a single root table assignment");
}
final NamedTableReference dmlTableReference = resolveUnionTableReference(updatingTableReference, tableExpression);
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Create the SQL AST and convert it into a JdbcOperation
final QuerySpec querySpec = new QuerySpec(true);
final NamedTableReference temporaryTableReference = new NamedTableReference(insertStatement.getTargetTable().getTableExpression(), updatingTableReference.getIdentificationVariable(), false, sessionFactory);
final TableGroupImpl temporaryTableGroup = new TableGroupImpl(updatingTableGroup.getNavigablePath(), null, temporaryTableReference, entityDescriptor);
querySpec.getFromClause().addRoot(temporaryTableGroup);
final InsertStatement insertStatement = new InsertStatement(dmlTableReference);
insertStatement.setSourceSelectStatement(querySpec);
for (Assignment assignment : assignments) {
insertStatement.addTargetColumnReferences(assignment.getAssignable().getColumnReferences());
for (ColumnReference columnReference : assignment.getAssignable().getColumnReferences()) {
querySpec.getSelectClause().addSqlSelection(new SqlSelectionImpl(1, 0, new ColumnReference(updatingTableReference.getIdentificationVariable(), columnReference.getColumnExpression(), false, null, null, columnReference.getJdbcMapping(), sessionFactory)));
}
}
final JdbcServices jdbcServices = sessionFactory.getJdbcServices();
final Map<Object, Object> entityTableToRootIdentity;
if (identifierGenerator instanceof PostInsertIdentifierGenerator) {
final BasicEntityIdentifierMapping identifierMapping = (BasicEntityIdentifierMapping) entityDescriptor.getIdentifierMapping();
final QuerySpec idSelectQuerySpec = new QuerySpec(true);
idSelectQuerySpec.getFromClause().addRoot(temporaryTableGroup);
final ColumnReference columnReference = new ColumnReference((String) null, TemporaryTable.ENTITY_TABLE_IDENTITY_COLUMN, false, null, null, identifierMapping.getJdbcMapping(), sessionFactory);
idSelectQuerySpec.getSelectClause().addSqlSelection(new SqlSelectionImpl(1, 0, columnReference));
idSelectQuerySpec.addSortSpecification(new SortSpecification(columnReference, SortOrder.ASCENDING));
final SelectStatement selectStatement = new SelectStatement(idSelectQuerySpec, Collections.singletonList(new BasicFetch<>(0, null, null, identifierMapping, null, FetchTiming.IMMEDIATE, null)));
final JdbcSelect jdbcSelect = jdbcServices.getJdbcEnvironment().getSqlAstTranslatorFactory().buildSelectTranslator(sessionFactory, selectStatement).translate(null, executionContext.getQueryOptions());
final List<Object> list = jdbcServices.getJdbcSelectExecutor().list(jdbcSelect, JdbcParameterBindings.NO_BINDINGS, executionContext, null, ListResultsConsumer.UniqueSemantic.NONE);
entityTableToRootIdentity = new LinkedHashMap<>(list.size());
for (Object o : list) {
entityTableToRootIdentity.put(o, null);
}
querySpec.applyPredicate(new ComparisonPredicate(columnReference, ComparisonOperator.EQUAL, new JdbcParameterImpl(identifierMapping.getJdbcMapping())));
} else {
entityTableToRootIdentity = null;
if (identifierGenerator instanceof OptimizableGenerator) {
final Optimizer optimizer = ((OptimizableGenerator) identifierGenerator).getOptimizer();
// but only if the target paths don't already contain the id
if (optimizer != null && optimizer.getIncrementSize() > 1 && insertStatement.getTargetColumnReferences().stream().noneMatch(c -> keyColumns[0].equals(c.getColumnExpression()))) {
final BasicEntityIdentifierMapping identifierMapping = (BasicEntityIdentifierMapping) entityDescriptor.getIdentifierMapping();
final JdbcParameter rowNumber = new JdbcParameterImpl(identifierMapping.getJdbcMapping());
final JdbcParameter rootIdentity = new JdbcParameterImpl(identifierMapping.getJdbcMapping());
final List<Assignment> temporaryTableAssignments = new ArrayList<>(1);
final ColumnReference idColumnReference = new ColumnReference((String) null, identifierMapping, sessionFactory);
temporaryTableAssignments.add(new Assignment(idColumnReference, rootIdentity));
final TemporaryTableColumn rowNumberColumn = entityTable.getColumns().get(entityTable.getColumns().size() - 1);
final UpdateStatement updateStatement = new UpdateStatement(temporaryTableReference, temporaryTableAssignments, new ComparisonPredicate(new ColumnReference((String) null, rowNumberColumn.getColumnName(), false, null, null, rowNumberColumn.getJdbcMapping(), sessionFactory), ComparisonOperator.EQUAL, rowNumber));
final JdbcUpdate jdbcUpdate = jdbcServices.getJdbcEnvironment().getSqlAstTranslatorFactory().buildUpdateTranslator(sessionFactory, updateStatement).translate(null, executionContext.getQueryOptions());
final JdbcParameterBindings updateBindings = new JdbcParameterBindingsImpl(2);
for (int i = 0; i < rows; i++) {
updateBindings.addBinding(rowNumber, new JdbcParameterBindingImpl(rowNumberColumn.getJdbcMapping(), i + 1));
updateBindings.addBinding(rootIdentity, new JdbcParameterBindingImpl(identifierMapping.getJdbcMapping(), identifierGenerator.generate(executionContext.getSession(), null)));
jdbcServices.getJdbcMutationExecutor().execute(jdbcUpdate, updateBindings, sql -> executionContext.getSession().getJdbcCoordinator().getStatementPreparer().prepareStatement(sql), (integer, preparedStatement) -> {
}, executionContext);
}
insertStatement.addTargetColumnReferences(new ColumnReference((String) null, keyColumns[0], false, null, null, identifierMapping.getJdbcMapping(), sessionFactory));
querySpec.getSelectClause().addSqlSelection(new SqlSelectionImpl(1, 0, new ColumnReference(updatingTableReference.getIdentificationVariable(), idColumnReference.getColumnExpression(), false, null, null, idColumnReference.getJdbcMapping(), sessionFactory)));
}
}
}
final JdbcInsert jdbcInsert = jdbcServices.getJdbcEnvironment().getSqlAstTranslatorFactory().buildInsertTranslator(sessionFactory, insertStatement).translate(null, executionContext.getQueryOptions());
if (identifierGenerator instanceof PostInsertIdentifierGenerator) {
final PostInsertIdentifierGenerator generator = (PostInsertIdentifierGenerator) identifierGenerator;
final boolean generatedKeysEnabled = sessionFactory.getSessionFactoryOptions().isGetGeneratedKeysEnabled();
final InsertGeneratedIdentifierDelegate identifierDelegate = generator.getInsertGeneratedIdentifierDelegate((PostInsertIdentityPersister) entityDescriptor.getEntityPersister(), jdbcServices.getDialect(), generatedKeysEnabled);
final String finalSql = identifierDelegate.prepareIdentifierGeneratingInsert(jdbcInsert.getSql());
final BasicEntityIdentifierMapping identifierMapping = (BasicEntityIdentifierMapping) entityDescriptor.getIdentifierMapping();
final ValueBinder jdbcValueBinder = identifierMapping.getJdbcMapping().getJdbcValueBinder();
for (Map.Entry<Object, Object> entry : entityTableToRootIdentity.entrySet()) {
final Object rootIdentity = identifierDelegate.performInsert(finalSql, executionContext.getSession(), new Binder() {
@Override
public void bindValues(PreparedStatement ps) throws SQLException {
jdbcValueBinder.bind(ps, entry.getKey(), 1, executionContext.getSession());
}
@Override
public Object getEntity() {
return null;
}
});
entry.setValue(rootIdentity);
}
final JdbcParameter entityIdentity = new JdbcParameterImpl(identifierMapping.getJdbcMapping());
final JdbcParameter rootIdentity = new JdbcParameterImpl(identifierMapping.getJdbcMapping());
final List<Assignment> temporaryTableAssignments = new ArrayList<>(1);
temporaryTableAssignments.add(new Assignment(new ColumnReference((String) null, identifierMapping, sessionFactory), rootIdentity));
final UpdateStatement updateStatement = new UpdateStatement(temporaryTableReference, temporaryTableAssignments, new ComparisonPredicate(new ColumnReference((String) null, TemporaryTable.ENTITY_TABLE_IDENTITY_COLUMN, false, null, null, identifierMapping.getJdbcMapping(), sessionFactory), ComparisonOperator.EQUAL, entityIdentity));
final JdbcUpdate jdbcUpdate = jdbcServices.getJdbcEnvironment().getSqlAstTranslatorFactory().buildUpdateTranslator(sessionFactory, updateStatement).translate(null, executionContext.getQueryOptions());
final JdbcParameterBindings updateBindings = new JdbcParameterBindingsImpl(2);
for (Map.Entry<Object, Object> entry : entityTableToRootIdentity.entrySet()) {
updateBindings.addBinding(entityIdentity, new JdbcParameterBindingImpl(identifierMapping.getJdbcMapping(), entry.getKey()));
updateBindings.addBinding(rootIdentity, new JdbcParameterBindingImpl(identifierMapping.getJdbcMapping(), entry.getValue()));
jdbcServices.getJdbcMutationExecutor().execute(jdbcUpdate, updateBindings, sql -> executionContext.getSession().getJdbcCoordinator().getStatementPreparer().prepareStatement(sql), (integer, preparedStatement) -> {
}, executionContext);
}
} else {
jdbcServices.getJdbcMutationExecutor().execute(jdbcInsert, JdbcParameterBindings.NO_BINDINGS, sql -> executionContext.getSession().getJdbcCoordinator().getStatementPreparer().prepareStatement(sql), (integer, preparedStatement) -> {
}, executionContext);
}
}
use of org.hibernate.id.enhanced.Optimizer in project hibernate-orm by hibernate.
the class OptimizerConcurrencyUnitTest method testConcurrentUsage_singleTenancy.
@Test
public void testConcurrentUsage_singleTenancy() throws InterruptedException {
final int increment = 50;
final int taskCount = 100 * increment;
Optimizer optimizer = buildOptimizer(1, increment);
List<Callable<Long>> tasks = new ArrayList<>();
SourceMock sequence = new SourceMock(1, increment);
assertEquals(0, sequence.getTimesCalled());
assertEquals(-1, sequence.getCurrentValue());
for (int i = 0; i < taskCount; i++) {
tasks.add(new Callable<Long>() {
@Override
public Long call() throws Exception {
return (Long) optimizer.generate(sequence);
}
});
}
ExecutorService executor = Executors.newFixedThreadPool(10);
List<Future<Long>> futures;
try {
futures = executor.invokeAll(tasks);
executor.shutdown();
executor.awaitTermination(10, TimeUnit.SECONDS);
} finally {
executor.shutdownNow();
}
assertThat(futures).allSatisfy(future -> {
assertThat(future).isDone();
assertThatCode(future::get).doesNotThrowAnyException();
});
List<Long> generated = futures.stream().map(this::getDoneFutureValue).collect(Collectors.toList());
assertThat(generated).hasSize(taskCount).containsExactlyInAnyOrderElementsOf(new HashSet<>(generated));
System.out.println("Generated IDs: " + generated);
}
Aggregations