use of org.hibernate.sql.results.jdbc.internal.JdbcValuesResultSetImpl in project hibernate-orm by hibernate.
the class JdbcSelectExecutorStandardImpl method doExecuteQuery.
private <T, R> T doExecuteQuery(JdbcSelect jdbcSelect, JdbcParameterBindings jdbcParameterBindings, ExecutionContext executionContext, RowTransformer<R> rowTransformer, Function<String, PreparedStatement> statementCreator, ResultsConsumer<T, R> resultsConsumer) {
final DeferredResultSetAccess deferredResultSetAccess = new DeferredResultSetAccess(jdbcSelect, jdbcParameterBindings, executionContext, statementCreator);
final JdbcValues jdbcValues = resolveJdbcValuesSource(executionContext.getQueryIdentifier(deferredResultSetAccess.getFinalSql()), jdbcSelect, resultsConsumer.canResultsBeCached(), executionContext, deferredResultSetAccess);
if (rowTransformer == null) {
@SuppressWarnings("unchecked") final TupleTransformer<R> tupleTransformer = (TupleTransformer<R>) executionContext.getQueryOptions().getTupleTransformer();
if (tupleTransformer == null) {
rowTransformer = RowTransformerPassThruImpl.instance();
} else {
final List<DomainResult<?>> domainResults = jdbcValues.getValuesMapping().getDomainResults();
final String[] aliases = new String[domainResults.size()];
for (int i = 0; i < domainResults.size(); i++) {
aliases[i] = domainResults.get(i).getResultVariable();
}
rowTransformer = new RowTransformerTupleTransformerAdapter<>(aliases, tupleTransformer);
}
}
final boolean stats;
long startTime = 0;
final StatisticsImplementor statistics = executionContext.getSession().getFactory().getStatistics();
if (executionContext.hasQueryExecutionToBeAddedToStatistics() && jdbcValues instanceof JdbcValuesResultSetImpl) {
stats = statistics.isStatisticsEnabled();
if (stats) {
startTime = System.nanoTime();
}
} else {
stats = false;
}
/*
* Processing options effectively are only used for entity loading. Here we don't need these values.
*/
final JdbcValuesSourceProcessingOptions processingOptions = new JdbcValuesSourceProcessingOptions() {
@Override
public Object getEffectiveOptionalObject() {
return executionContext.getEntityInstance();
}
@Override
public String getEffectiveOptionalEntityName() {
return null;
}
@Override
public Object getEffectiveOptionalId() {
return executionContext.getEntityId();
}
@Override
public boolean shouldReturnProxies() {
return true;
}
};
final JdbcValuesSourceProcessingStateStandardImpl valuesProcessingState = new JdbcValuesSourceProcessingStateStandardImpl(executionContext, processingOptions, executionContext::registerLoadingEntityEntry);
final RowReader<R> rowReader = ResultsHelper.createRowReader(executionContext, // because the EntityEntrys would already have the desired lock mode
deferredResultSetAccess.usesFollowOnLocking() ? LockOptions.NONE : executionContext.getQueryOptions().getLockOptions(), rowTransformer, jdbcValues);
final RowProcessingStateStandardImpl rowProcessingState = new RowProcessingStateStandardImpl(valuesProcessingState, executionContext, rowReader, jdbcValues);
final T result = resultsConsumer.consume(jdbcValues, executionContext.getSession(), processingOptions, valuesProcessingState, rowProcessingState, rowReader);
if (stats) {
final long endTime = System.nanoTime();
final long milliseconds = TimeUnit.MILLISECONDS.convert(endTime - startTime, TimeUnit.NANOSECONDS);
statistics.queryExecuted(executionContext.getQueryIdentifier(jdbcSelect.getSql()), getResultSize(result), milliseconds);
}
return result;
}
use of org.hibernate.sql.results.jdbc.internal.JdbcValuesResultSetImpl in project hibernate-orm by hibernate.
the class JdbcSelectExecutorStandardImpl method resolveJdbcValuesSource.
private JdbcValues resolveJdbcValuesSource(String queryIdentifier, JdbcSelect jdbcSelect, boolean canBeCached, ExecutionContext executionContext, ResultSetAccess resultSetAccess) {
final SharedSessionContractImplementor session = executionContext.getSession();
final SessionFactoryImplementor factory = session.getFactory();
final boolean queryCacheEnabled = factory.getSessionFactoryOptions().isQueryCacheEnabled();
final List<?> cachedResults;
final CacheMode cacheMode = JdbcExecHelper.resolveCacheMode(executionContext);
final JdbcValuesMappingProducer mappingProducer = jdbcSelect.getJdbcValuesMappingProducer();
final boolean cacheable = queryCacheEnabled && canBeCached && executionContext.getQueryOptions().isResultCachingEnabled() == Boolean.TRUE;
final QueryKey queryResultsCacheKey;
if (cacheable && cacheMode.isGetEnabled()) {
SqlExecLogger.INSTANCE.debugf("Reading Query result cache data per CacheMode#isGetEnabled [%s]", cacheMode.name());
final Set<String> querySpaces = jdbcSelect.getAffectedTableNames();
if (querySpaces == null || querySpaces.size() == 0) {
SqlExecLogger.INSTANCE.tracev("Unexpected querySpaces is {0}", (querySpaces == null ? querySpaces : "empty"));
} else {
SqlExecLogger.INSTANCE.tracev("querySpaces is {0}", querySpaces);
}
final QueryResultsCache queryCache = factory.getCache().getQueryResultsCache(executionContext.getQueryOptions().getResultCacheRegionName());
// todo (6.0) : not sure that it is at all important that we account for QueryResults
// these cached values are "lower level" than that, representing the
// "raw" JDBC values.
//
// todo (6.0) : relatedly ^^, pretty sure that SqlSelections are also irrelevant
queryResultsCacheKey = QueryKey.from(jdbcSelect.getSql(), executionContext.getQueryOptions().getLimit(), executionContext.getQueryParameterBindings(), session);
cachedResults = queryCache.get(// todo (6.0) : QueryCache#get takes the `queryResultsCacheKey` see tat discussion above
queryResultsCacheKey, // atm we do not even collect querySpaces, but we need to
querySpaces, session);
// todo (6.0) : `querySpaces` and `session` are used in QueryCache#get to verify "up-to-dateness" via UpdateTimestampsCache
// better imo to move UpdateTimestampsCache handling here and have QueryCache be a simple access to
// the underlying query result cache region.
//
// todo (6.0) : if we go this route (^^), still beneficial to have an abstraction over different UpdateTimestampsCache-based
// invalidation strategies - QueryCacheInvalidationStrategy
final StatisticsImplementor statistics = factory.getStatistics();
if (statistics.isStatisticsEnabled()) {
if (cachedResults == null) {
statistics.queryCacheMiss(queryIdentifier, queryCache.getRegion().getName());
} else {
statistics.queryCacheHit(queryIdentifier, queryCache.getRegion().getName());
}
}
} else {
SqlExecLogger.INSTANCE.debugf("Skipping reading Query result cache data: cache-enabled = %s, cache-mode = %s", queryCacheEnabled, cacheMode.name());
cachedResults = null;
if (cacheable && cacheMode.isPutEnabled()) {
queryResultsCacheKey = QueryKey.from(jdbcSelect.getSql(), executionContext.getQueryOptions().getLimit(), executionContext.getQueryParameterBindings(), session);
} else {
queryResultsCacheKey = null;
}
}
if (cachedResults == null) {
final JdbcValuesMetadata metadataForCache;
final JdbcValuesMapping jdbcValuesMapping;
if (queryResultsCacheKey == null) {
jdbcValuesMapping = mappingProducer.resolve(resultSetAccess, factory);
metadataForCache = null;
} else {
// If we need to put the values into the cache, we need to be able to capture the JdbcValuesMetadata
final CapturingJdbcValuesMetadata capturingMetadata = new CapturingJdbcValuesMetadata(resultSetAccess);
jdbcValuesMapping = mappingProducer.resolve(capturingMetadata, factory);
metadataForCache = capturingMetadata.resolveMetadataForCache();
}
return new JdbcValuesResultSetImpl(resultSetAccess, queryResultsCacheKey, queryIdentifier, executionContext.getQueryOptions(), jdbcValuesMapping, metadataForCache, executionContext);
} else {
final JdbcValuesMapping jdbcValuesMapping;
if (cachedResults.isEmpty() || !(cachedResults.get(0) instanceof JdbcValuesMetadata)) {
jdbcValuesMapping = mappingProducer.resolve(resultSetAccess, factory);
} else {
jdbcValuesMapping = mappingProducer.resolve((JdbcValuesMetadata) cachedResults.get(0), factory);
}
return new JdbcValuesCacheHit(cachedResults, jdbcValuesMapping);
}
}
use of org.hibernate.sql.results.jdbc.internal.JdbcValuesResultSetImpl in project hibernate-orm by hibernate.
the class OutputsImpl method extractResults.
protected List extractResults(ResultSet resultSet) {
final DirectResultSetAccess resultSetAccess = new DirectResultSetAccess(context.getSession(), jdbcStatement, resultSet);
final ProcedureCallImpl procedureCall = (ProcedureCallImpl) context;
final ResultSetMapping resultSetMapping = procedureCall.getResultSetMapping();
final JavaTypeRegistry javaTypeRegistry = context.getSession().getTypeConfiguration().getJavaTypeRegistry();
procedureCall.getParameterBindings().visitBindings((parameterImplementor, queryParameterBinding) -> {
ProcedureParameter parameter = (ProcedureParameter) parameterImplementor;
if (parameter.getMode() == ParameterMode.INOUT) {
final JavaType<?> basicType = javaTypeRegistry.getDescriptor(parameterImplementor.getParameterType());
if (basicType != null) {
resultSetMapping.addResultBuilder(new ScalarDomainResultBuilder<>(basicType));
} else {
throw new NotYetImplementedFor6Exception(getClass());
}
}
});
final ExecutionContext executionContext = new ExecutionContext() {
private final Callback callback = new CallbackImpl();
@Override
public SharedSessionContractImplementor getSession() {
return OutputsImpl.this.context.getSession();
}
@Override
public QueryOptions getQueryOptions() {
return new QueryOptionsAdapter() {
@Override
public Boolean isReadOnly() {
return false;
}
};
}
@Override
public String getQueryIdentifier(String sql) {
return sql;
}
@Override
public QueryParameterBindings getQueryParameterBindings() {
return QueryParameterBindings.NO_PARAM_BINDINGS;
}
@Override
public Callback getCallback() {
return callback;
}
};
final JdbcValues jdbcValues = new JdbcValuesResultSetImpl(resultSetAccess, null, null, this.context.getQueryOptions(), resultSetMapping.resolve(resultSetAccess, getSessionFactory()), null, executionContext);
final RowReader<Object[]> rowReader = (RowReader<Object[]>) ResultsHelper.createRowReader(executionContext, null, RowTransformerPassThruImpl.INSTANCE, jdbcValues);
/*
* Processing options effectively are only used for entity loading. Here we don't need these values.
*/
final JdbcValuesSourceProcessingOptions processingOptions = new JdbcValuesSourceProcessingOptions() {
@Override
public Object getEffectiveOptionalObject() {
return null;
}
@Override
public String getEffectiveOptionalEntityName() {
return null;
}
@Override
public Serializable getEffectiveOptionalId() {
return null;
}
@Override
public boolean shouldReturnProxies() {
return true;
}
};
final JdbcValuesSourceProcessingStateStandardImpl jdbcValuesSourceProcessingState = new JdbcValuesSourceProcessingStateStandardImpl(executionContext, processingOptions, executionContext::registerLoadingEntityEntry);
try {
final RowProcessingStateStandardImpl rowProcessingState = new RowProcessingStateStandardImpl(jdbcValuesSourceProcessingState, executionContext, rowReader, jdbcValues);
final List results = new ArrayList<>();
while (rowProcessingState.next()) {
results.add(rowReader.readRow(rowProcessingState, processingOptions));
rowProcessingState.finishRowProcessing();
}
return results;
} finally // catch (SQLException e) {
// throw context.getSession().getExceptionConverter().convert( e, "Error processing return rows" );
// }
{
rowReader.finishUp(jdbcValuesSourceProcessingState);
jdbcValuesSourceProcessingState.finishUp();
jdbcValues.finishUp(this.context.getSession());
}
}
Aggregations