All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.hibernate.loader.internal.DatabaseSnapshotExecutor Maven / Gradle / Ivy

There is a newer version: 7.0.0.Beta1
Show newest version
/*
 * Hibernate, Relational Persistence for Idiomatic Java
 *
 * License: GNU Lesser General Public License (LGPL), version 2.1 or later
 * See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
 */
package org.hibernate.loader.internal;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.hibernate.LockMode;
import org.hibernate.LockOptions;
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
import org.hibernate.engine.jdbc.spi.JdbcServices;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.metamodel.mapping.EntityIdentifierMapping;
import org.hibernate.metamodel.mapping.EntityMappingType;
import org.hibernate.metamodel.mapping.JdbcMapping;
import org.hibernate.query.ComparisonOperator;
import org.hibernate.query.NavigablePath;
import org.hibernate.query.spi.QueryOptions;
import org.hibernate.query.spi.QueryParameterBindings;
import org.hibernate.sql.ast.Clause;
import org.hibernate.sql.ast.SqlAstTranslatorFactory;
import org.hibernate.sql.ast.spi.SqlAliasBaseManager;
import org.hibernate.sql.ast.spi.SqlExpressionResolver;
import org.hibernate.sql.ast.spi.SqlSelection;
import org.hibernate.sql.ast.tree.expression.ColumnReference;
import org.hibernate.sql.ast.tree.from.TableGroup;
import org.hibernate.sql.ast.tree.from.TableReference;
import org.hibernate.sql.ast.tree.predicate.ComparisonPredicate;
import org.hibernate.sql.ast.tree.select.QuerySpec;
import org.hibernate.sql.ast.tree.select.SelectStatement;
import org.hibernate.sql.exec.internal.JdbcParameterBindingsImpl;
import org.hibernate.sql.exec.internal.JdbcParameterImpl;
import org.hibernate.sql.exec.internal.JdbcSelectExecutorStandardImpl;
import org.hibernate.sql.exec.spi.Callback;
import org.hibernate.sql.exec.spi.ExecutionContext;
import org.hibernate.sql.exec.spi.JdbcParameter;
import org.hibernate.sql.exec.spi.JdbcParameterBinding;
import org.hibernate.sql.exec.spi.JdbcParameterBindings;
import org.hibernate.sql.exec.spi.JdbcSelect;
import org.hibernate.sql.results.internal.RowTransformerPassThruImpl;
import org.hibernate.sql.results.internal.domain.basic.BasicResult;
import org.hibernate.sql.results.spi.DomainResult;

import org.jboss.logging.Logger;

/**
 * @author Steve Ebersole
 */
class DatabaseSnapshotExecutor {
	private static final Logger log = Logger.getLogger( DatabaseSnapshotExecutor.class );

	private final EntityMappingType entityDescriptor;
	private final SessionFactoryImplementor sessionFactory;

	private final JdbcSelect jdbcSelect;
	private final List jdbcParameters;

	DatabaseSnapshotExecutor(
			EntityMappingType entityDescriptor,
			SessionFactoryImplementor sessionFactory) {
		this.entityDescriptor = entityDescriptor;
		this.sessionFactory = sessionFactory;

		final QuerySpec rootQuerySpec = new QuerySpec( true );

		final SqlAliasBaseManager sqlAliasBaseManager = new SqlAliasBaseManager();

		final LoaderSqlAstCreationState state = new LoaderSqlAstCreationState(
				rootQuerySpec,
				sqlAliasBaseManager,
				LockOptions.READ,
				sessionFactory
		);

		final NavigablePath rootPath = new NavigablePath( entityDescriptor.getEntityName() );

		final TableGroup rootTableGroup = entityDescriptor.createRootTableGroup(
				rootPath,
				null,
				null,
				LockMode.NONE,
				sqlAliasBaseManager,
				state.getSqlExpressionResolver(),
				() -> rootQuerySpec::applyPredicate,
				sessionFactory
		);

		rootQuerySpec.getFromClause().addRoot( rootTableGroup );

		jdbcParameters = new ArrayList<>(
				entityDescriptor.getIdentifierMapping().getJdbcTypeCount( sessionFactory.getTypeConfiguration() )
		);
		final List domainResults = new ArrayList<>();

		final NavigablePath idPath = rootPath.append( EntityIdentifierMapping.ROLE_LOCAL_NAME );
		entityDescriptor.getIdentifierMapping().visitColumns(
				(col, tab, jdbcMapping) -> {
					final TableReference tableReference = rootTableGroup.resolveTableReference( tab );

					final JdbcParameter jdbcParameter = new JdbcParameterImpl( jdbcMapping );
					jdbcParameters.add( jdbcParameter );

					final ColumnReference columnReference = (ColumnReference) state.getSqlExpressionResolver()
							.resolveSqlExpression(
									SqlExpressionResolver.createColumnReferenceKey( tableReference, col ),
									s -> new ColumnReference(
											tableReference,
											col,
											jdbcMapping,
											sessionFactory
									)
							);

					rootQuerySpec.applyPredicate(
							new ComparisonPredicate(
									columnReference,
									ComparisonOperator.EQUAL,
									jdbcParameter
							)
					);

					final SqlSelection sqlSelection = state.getSqlExpressionResolver().resolveSqlSelection(
							columnReference,
							jdbcMapping.getJavaTypeDescriptor(),
							sessionFactory.getTypeConfiguration()
					);

					//noinspection unchecked
					domainResults.add(
							new BasicResult(
									sqlSelection.getValuesArrayPosition(),
									null,
									jdbcMapping.getJavaTypeDescriptor()
							)
					);
				}
		);

		entityDescriptor.visitStateArrayContributors(
				contributorMapping -> {
					rootPath.append( contributorMapping.getAttributeName() );
					contributorMapping.visitColumns(
							(columnExpression, containingTableExpression, jdbcMapping) -> {
								final TableReference tableReference = rootTableGroup.resolveTableReference(
										containingTableExpression );

								final ColumnReference columnReference = (ColumnReference) state.getSqlExpressionResolver()
										.resolveSqlExpression(
												SqlExpressionResolver.createColumnReferenceKey(
														tableReference,
														columnExpression
												),
												s -> new ColumnReference(
														tableReference,
														columnExpression,
														jdbcMapping,
														sessionFactory
												)
										);

								final SqlSelection sqlSelection = state.getSqlExpressionResolver()
										.resolveSqlSelection(
												columnReference,
												jdbcMapping.getJavaTypeDescriptor(),
												sessionFactory.getTypeConfiguration()
										);

								//noinspection unchecked
								domainResults.add(
										new BasicResult(
												sqlSelection.getValuesArrayPosition(),
												null,
												jdbcMapping.getJavaTypeDescriptor()
										)
								);
							}
					);
				}
		);

		final SelectStatement selectStatement = new SelectStatement( rootQuerySpec, domainResults );

		final JdbcServices jdbcServices = sessionFactory.getJdbcServices();
		final JdbcEnvironment jdbcEnvironment = jdbcServices.getJdbcEnvironment();
		final SqlAstTranslatorFactory sqlAstTranslatorFactory = jdbcEnvironment.getSqlAstTranslatorFactory();

		jdbcSelect = sqlAstTranslatorFactory.buildSelectTranslator( sessionFactory ).translate( selectStatement );
	}

	Object[] loadDatabaseSnapshot(Object id, SharedSessionContractImplementor session) {
		log.tracef( "Getting current persistent state for `%s#%s`", entityDescriptor.getEntityName(), id );

		final JdbcParameterBindings jdbcParameterBindings = new JdbcParameterBindingsImpl(
				entityDescriptor.getIdentifierMapping().getJdbcTypeCount( sessionFactory.getTypeConfiguration() )
		);

		final Iterator paramItr = jdbcParameters.iterator();

		entityDescriptor.getIdentifierMapping().visitJdbcValues(
				id,
				Clause.WHERE,
				(value, type) -> {
					assert paramItr.hasNext();
					final JdbcParameter parameter = paramItr.next();
					jdbcParameterBindings.addBinding(
							parameter,
							new JdbcParameterBinding() {
								@Override
								public JdbcMapping getBindType() {
									return type;
								}

								@Override
								public Object getBindValue() {
									return value;
								}
							}
					);
				},
				session
		);
		assert !paramItr.hasNext();

		final List list = JdbcSelectExecutorStandardImpl.INSTANCE.list(
				jdbcSelect,
				jdbcParameterBindings,
				new ExecutionContext() {
					@Override
					public SharedSessionContractImplementor getSession() {
						return session;
					}

					@Override
					public QueryOptions getQueryOptions() {
						return QueryOptions.NONE;
					}

					@Override
					public QueryParameterBindings getQueryParameterBindings() {
						return QueryParameterBindings.NO_PARAM_BINDINGS;
					}

					@Override
					public Callback getCallback() {
						return null;
					}
				},
				RowTransformerPassThruImpl.instance()
		);

		if ( list.isEmpty() ) {
			return null;
		}

		final int size = list.size();
		final Object[] values = new Object[size];
		for ( int i = 0; i < size; i++ ) {
			values[i] = list.get( i );
		}

		return values;
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy