use of org.hibernate.metamodel.mapping.BasicEntityIdentifierMapping in project hibernate-orm by hibernate.
the class SimpleHbmTests method testBinding.
@Test
public void testBinding(ServiceRegistryScope scope) {
final SessionFactoryImplementor sessionFactory = (SessionFactoryImplementor) new MetadataSources(scope.getRegistry()).addResource("org/hibernate/orm/test/bootstrap/binding/hbm/simple/pojo/SimpleEntity.hbm.xml").buildMetadata().buildSessionFactory();
final EntityPersister entityDescriptor = sessionFactory.getRuntimeMetamodels().getMappingMetamodel().findEntityDescriptor(SimpleEntity.class);
final EntityIdentifierMapping identifierMapping = entityDescriptor.getIdentifierMapping();
assertThat(identifierMapping, instanceOf(BasicEntityIdentifierMapping.class));
final BasicEntityIdentifierMapping bid = (BasicEntityIdentifierMapping) identifierMapping;
assertThat(bid.getFetchableName(), is("id"));
assertThat(bid.getPartName(), is(EntityIdentifierMapping.ROLE_LOCAL_NAME));
assertThat(entityDescriptor.getNumberOfAttributeMappings(), is(1));
assertThat(entityDescriptor.getNumberOfDeclaredAttributeMappings(), is(1));
final AttributeMapping nameAttr = entityDescriptor.findAttributeMapping("name");
assertThat(nameAttr, notNullValue());
}
use of org.hibernate.metamodel.mapping.BasicEntityIdentifierMapping 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.metamodel.mapping.BasicEntityIdentifierMapping in project hibernate-orm by hibernate.
the class BaseSqmToSqlAstConverter method visitInsertionTargetPaths.
public AdditionalInsertValues visitInsertionTargetPaths(BiConsumer<Assignable, List<ColumnReference>> targetColumnReferenceConsumer, SqmInsertStatement<?> sqmStatement, EntityPersister entityDescriptor, TableGroup rootTableGroup) {
final List<SqmPath<?>> targetPaths = sqmStatement.getInsertionTargetPaths();
final EntityDiscriminatorMapping discriminatorMapping = entityDescriptor.getDiscriminatorMapping();
IdentifierGenerator identifierGenerator = entityDescriptor.getIdentifierGenerator();
Expression versionExpression = null;
Expression discriminatorExpression = null;
BasicEntityIdentifierMapping identifierMapping = null;
// We use the id property name to null the identifier generator variable if the target paths contain the id
final String identifierPropertyName;
if (identifierGenerator != null) {
identifierPropertyName = entityDescriptor.getIdentifierPropertyName();
} else {
identifierPropertyName = null;
}
final String versionAttributeName;
boolean needsVersionInsert;
if (entityDescriptor.isVersioned()) {
versionAttributeName = entityDescriptor.getVersionMapping().getVersionAttribute().getAttributeName();
needsVersionInsert = true;
} else {
versionAttributeName = null;
needsVersionInsert = false;
}
// Go through all target paths and remember if the target paths contain the version or id attributes
for (int i = 0; i < targetPaths.size(); i++) {
final SqmPath<?> path = targetPaths.get(i);
final String localName = path.getNavigablePath().getLocalName();
if (localName.equals(identifierPropertyName)) {
identifierGenerator = null;
} else if (localName.equals(versionAttributeName)) {
needsVersionInsert = false;
}
final Assignable assignable = (Assignable) path.accept(this);
targetColumnReferenceConsumer.accept(assignable, assignable.getColumnReferences());
}
if (needsVersionInsert) {
final BasicValuedPathInterpretation<?> versionPath = BasicValuedPathInterpretation.from((SqmBasicValuedSimplePath<?>) sqmStatement.getTarget().get(versionAttributeName), this, this, jpaQueryComplianceEnabled);
final List<ColumnReference> targetColumnReferences = versionPath.getColumnReferences();
assert targetColumnReferences.size() == 1;
targetColumnReferenceConsumer.accept(versionPath, targetColumnReferences);
versionExpression = new VersionTypeSeedParameterSpecification(entityDescriptor.getVersionMapping().getJdbcMapping(), entityDescriptor.getVersionJavaType());
}
if (discriminatorMapping != null && discriminatorMapping.isPhysical()) {
final BasicValuedPathInterpretation<?> discriminatorPath = new BasicValuedPathInterpretation<>(new ColumnReference(rootTableGroup.resolveTableReference(discriminatorMapping.getContainingTableExpression()), discriminatorMapping, getCreationContext().getSessionFactory()), rootTableGroup.getNavigablePath().append(discriminatorMapping.getPartName()), discriminatorMapping, rootTableGroup);
targetColumnReferenceConsumer.accept(discriminatorPath, discriminatorPath.getColumnReferences());
discriminatorExpression = new QueryLiteral<>(entityDescriptor.getDiscriminatorValue(), discriminatorMapping);
}
// This uses identity generation, so we don't need to list the column
if (identifierGenerator instanceof PostInsertIdentifierGenerator || identifierGenerator instanceof CompositeNestedGeneratedValueGenerator) {
identifierGenerator = null;
} else if (identifierGenerator != null) {
identifierMapping = (BasicEntityIdentifierMapping) entityDescriptor.getIdentifierMapping();
final BasicValuedPathInterpretation<?> identifierPath = new BasicValuedPathInterpretation<>(new ColumnReference(rootTableGroup.resolveTableReference(identifierMapping.getContainingTableExpression()), identifierMapping, getCreationContext().getSessionFactory()), rootTableGroup.getNavigablePath().append(identifierMapping.getPartName()), identifierMapping, rootTableGroup);
targetColumnReferenceConsumer.accept(identifierPath, identifierPath.getColumnReferences());
}
return new AdditionalInsertValues(versionExpression, discriminatorExpression, identifierGenerator, identifierMapping);
}
use of org.hibernate.metamodel.mapping.BasicEntityIdentifierMapping in project hibernate-orm by hibernate.
the class InsertExecutionDelegate method insertTable.
private void insertTable(String tableExpression, String[] keyColumns, boolean nullableTable, ExecutionContext executionContext) {
final TableReference updatingTableReference = updatingTableGroup.getTableReference(updatingTableGroup.getNavigablePath(), tableExpression, true, true);
final List<Assignment> assignments = assignmentsByTable.get(updatingTableReference);
if (nullableTable && (assignments == null || assignments.isEmpty())) {
// no assignments for this table - skip it
return;
}
final NamedTableReference dmlTargetTableReference = resolveUnionTableReference(updatingTableReference, tableExpression);
final QuerySpec querySpec = new QuerySpec(true);
final TableGroupImpl temporaryTableGroup = new TableGroupImpl(updatingTableGroup.getNavigablePath(), null, new NamedTableReference(insertStatement.getTargetTable().getTableExpression(), updatingTableReference.getIdentificationVariable(), false, sessionFactory), entityDescriptor);
querySpec.getFromClause().addRoot(temporaryTableGroup);
final InsertStatement insertStatement = new InsertStatement(dmlTargetTableReference);
insertStatement.setSourceSelectStatement(querySpec);
if (assignments != null && !assignments.isEmpty()) {
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 String targetKeyColumnName = keyColumns[0];
final AbstractEntityPersister entityPersister = (AbstractEntityPersister) entityDescriptor.getEntityPersister();
final IdentifierGenerator identifierGenerator = entityPersister.getIdentifierGenerator();
final boolean needsKeyInsert;
if (identifierGenerator instanceof PostInsertIdentifierGenerator) {
needsKeyInsert = true;
} else if (identifierGenerator instanceof OptimizableGenerator) {
final Optimizer optimizer = ((OptimizableGenerator) identifierGenerator).getOptimizer();
// If the generator uses an optimizer, we have to generate the identifiers for the new rows
needsKeyInsert = optimizer != null && optimizer.getIncrementSize() > 1;
} else {
needsKeyInsert = false;
}
if (needsKeyInsert && insertStatement.getTargetColumnReferences().stream().noneMatch(c -> targetKeyColumnName.equals(c.getColumnExpression()))) {
final BasicEntityIdentifierMapping identifierMapping = (BasicEntityIdentifierMapping) entityDescriptor.getIdentifierMapping();
insertStatement.addTargetColumnReferences(new ColumnReference(dmlTargetTableReference.getIdentificationVariable(), targetKeyColumnName, false, null, null, identifierMapping.getJdbcMapping(), sessionFactory));
querySpec.getSelectClause().addSqlSelection(new SqlSelectionImpl(1, 0, new ColumnReference(updatingTableReference.getIdentificationVariable(), identifierMapping, sessionFactory)));
}
final JdbcServices jdbcServices = sessionFactory.getJdbcServices();
final JdbcInsert jdbcInsert = jdbcServices.getJdbcEnvironment().getSqlAstTranslatorFactory().buildInsertTranslator(sessionFactory, insertStatement).translate(null, executionContext.getQueryOptions());
jdbcServices.getJdbcMutationExecutor().execute(jdbcInsert, JdbcParameterBindings.NO_BINDINGS, sql -> executionContext.getSession().getJdbcCoordinator().getStatementPreparer().prepareStatement(sql), (integer, preparedStatement) -> {
}, executionContext);
}
use of org.hibernate.metamodel.mapping.BasicEntityIdentifierMapping in project hibernate-orm by hibernate.
the class SimpleDynamicHbmTests method testBinding.
@Test
public void testBinding(ServiceRegistryScope scope) {
final SessionFactoryImplementor sessionFactory = (SessionFactoryImplementor) new MetadataSources(scope.getRegistry()).addResource("org/hibernate/orm/test/bootstrap/binding/hbm/simple/dynamic/SimpleDynamicEntity.hbm.xml").buildMetadata().buildSessionFactory();
try {
final EntityPersister entityDescriptor = sessionFactory.getRuntimeMetamodels().getMappingMetamodel().findEntityDescriptor("SimpleDynamicEntity");
final EntityIdentifierMapping identifierMapping = entityDescriptor.getIdentifierMapping();
assertThat(identifierMapping, instanceOf(BasicEntityIdentifierMapping.class));
final BasicEntityIdentifierMapping bid = (BasicEntityIdentifierMapping) identifierMapping;
assertThat(bid.getFetchableName(), is("id"));
assertThat(bid.getPartName(), is(EntityIdentifierMapping.ROLE_LOCAL_NAME));
assertThat(entityDescriptor.getNumberOfAttributeMappings(), is(1));
assertThat(entityDescriptor.getNumberOfDeclaredAttributeMappings(), is(1));
final AttributeMapping nameAttr = entityDescriptor.findAttributeMapping("name");
assertThat(nameAttr, notNullValue());
sessionFactory.inTransaction(session -> {
session.createQuery("from SimpleDynamicEntity").list();
session.createQuery("select e from SimpleDynamicEntity e").list();
session.createQuery("select e from SimpleDynamicEntity e where e.name = 'abc'").list();
});
} finally {
sessionFactory.close();
}
}
Aggregations