use of org.hibernate.engine.ResultSetMappingDefinition in project hibernate-orm by hibernate.
the class NamedQueryRepository method checkNamedQueries.
public Map<String, HibernateException> checkNamedQueries(QueryPlanCache queryPlanCache) {
Map<String, HibernateException> errors = new HashMap<String, HibernateException>();
// Check named HQL queries
log.debugf("Checking %s named HQL queries", namedQueryDefinitionMap.size());
for (NamedQueryDefinition namedQueryDefinition : namedQueryDefinitionMap.values()) {
// this will throw an error if there's something wrong.
try {
log.debugf("Checking named query: %s", namedQueryDefinition.getName());
//TODO: BUG! this currently fails for named queries for non-POJO entities
queryPlanCache.getHQLQueryPlan(namedQueryDefinition.getQueryString(), false, Collections.EMPTY_MAP);
} catch (HibernateException e) {
errors.put(namedQueryDefinition.getName(), e);
}
}
// Check native-sql queries
log.debugf("Checking %s named SQL queries", namedSqlQueryDefinitionMap.size());
for (NamedSQLQueryDefinition namedSQLQueryDefinition : namedSqlQueryDefinitionMap.values()) {
// this will throw an error if there's something wrong.
try {
log.debugf("Checking named SQL query: %s", namedSQLQueryDefinition.getName());
// TODO : would be really nice to cache the spec on the query-def so as to not have to re-calc the hash;
// currently not doable though because of the resultset-ref stuff...
NativeSQLQuerySpecification spec;
if (namedSQLQueryDefinition.getResultSetRef() != null) {
ResultSetMappingDefinition definition = getResultSetMappingDefinition(namedSQLQueryDefinition.getResultSetRef());
if (definition == null) {
throw new MappingException("Unable to find resultset-ref definition: " + namedSQLQueryDefinition.getResultSetRef());
}
spec = new NativeSQLQuerySpecification(namedSQLQueryDefinition.getQueryString(), definition.getQueryReturns(), namedSQLQueryDefinition.getQuerySpaces());
} else {
spec = new NativeSQLQuerySpecification(namedSQLQueryDefinition.getQueryString(), namedSQLQueryDefinition.getQueryReturns(), namedSQLQueryDefinition.getQuerySpaces());
}
queryPlanCache.getNativeSQLQueryPlan(spec);
} catch (HibernateException e) {
errors.put(namedSQLQueryDefinition.getName(), e);
}
}
return errors;
}
use of org.hibernate.engine.ResultSetMappingDefinition in project hibernate-orm by hibernate.
the class NamedQueryBinder method processNamedNativeQuery.
public static void processNamedNativeQuery(final HbmLocalMetadataBuildingContext context, JaxbHbmNamedNativeQueryType namedQueryBinding, String prefix) {
final String queryName = prefix + namedQueryBinding.getName();
final NamedSQLQueryDefinitionBuilder builder = new NamedSQLQueryDefinitionBuilder().setName(queryName).setComment(namedQueryBinding.getComment()).setCacheable(namedQueryBinding.isCacheable()).setCacheMode(namedQueryBinding.getCacheMode()).setCacheRegion(namedQueryBinding.getCacheRegion()).setTimeout(namedQueryBinding.getTimeout()).setReadOnly(namedQueryBinding.isReadOnly()).setFlushMode(namedQueryBinding.getFlushMode()).setFetchSize(namedQueryBinding.getFetchSize()).setCallable(namedQueryBinding.isCallable()).setResultSetRef(namedQueryBinding.getResultsetRef());
final ImplicitResultSetMappingDefinition.Builder implicitResultSetMappingBuilder = new ImplicitResultSetMappingDefinition.Builder(queryName);
boolean foundQuery = false;
for (Object content : namedQueryBinding.getContent()) {
final boolean wasQuery = processNamedQueryContentItem(content, builder, implicitResultSetMappingBuilder, namedQueryBinding, context);
if (wasQuery) {
foundQuery = true;
}
}
if (!foundQuery) {
throw new org.hibernate.boot.MappingException(String.format("Named native query [%s] did not specify query string", namedQueryBinding.getName()), context.getOrigin());
}
if (implicitResultSetMappingBuilder.hasAnyReturns()) {
if (StringHelper.isNotEmpty(namedQueryBinding.getResultsetRef())) {
throw new org.hibernate.boot.MappingException(String.format("Named native query [%s] specified both a resultset-ref and an inline mapping of results", namedQueryBinding.getName()), context.getOrigin());
}
// Building a ResultSet mapping needs access to entity bindings for any entity
// returns it defines. But binding for those entities may have not been
// completed yet. For "normal" ResultSet mappings, this is already handled by
// the fact that MetadataSourceProcessor#processResultSetMappings() is called
// afterQuery all entity hierarchies have been processed. However, here we are in
// the middle of processing named-queries (either top-level or entity-level)
// and have no guarantee that any entity bindings we may need here are bound.
// So we add the second-pass to bind the implicit resultSet mapping.
//
// It is possible to know here whether the second-pass is needed or whether we
// can immediately bind the ResultSet mapping.
// todo : consider implementing this (^^) checking
final ImplicitResultSetMappingDefinition implicitResultSetMappingDefinition = implicitResultSetMappingBuilder.build();
builder.setResultSetRef(implicitResultSetMappingDefinition.getName());
context.getMetadataCollector().addSecondPass(new SecondPass() {
@Override
public void doSecondPass(Map persistentClasses) throws MappingException {
final ResultSetMappingDefinition resultSetMappingDefinition = ResultSetMappingBinder.bind(implicitResultSetMappingDefinition, context);
context.getMetadataCollector().addResultSetMapping(resultSetMappingDefinition);
NativeSQLQueryReturn[] newQueryReturns = resultSetMappingDefinition.getQueryReturns();
final NamedSQLQueryDefinition queryDefinition = context.getMetadataCollector().getNamedNativeQueryDefinition(queryName);
if (queryDefinition != null) {
queryDefinition.addQueryReturns(newQueryReturns);
}
}
});
}
context.getMetadataCollector().addNamedNativeQuery(builder.createNamedQueryDefinition());
}
use of org.hibernate.engine.ResultSetMappingDefinition in project hibernate-orm by hibernate.
the class MappingDocument method processResultSetMappings.
@Override
public void processResultSetMappings() {
for (ResultSetMappingBindingDefinition resultSetMappingBinding : documentRoot.getResultset()) {
final ResultSetMappingDefinition binding = ResultSetMappingBinder.bind(resultSetMappingBinding, this);
getMetadataCollector().addResultSetMapping(binding);
}
}
use of org.hibernate.engine.ResultSetMappingDefinition in project hibernate-orm by hibernate.
the class ResultsetMappingSecondPass method doSecondPass.
@Override
public void doSecondPass(Map persistentClasses) throws MappingException {
//TODO add parameters checkings
if (ann == null)
return;
ResultSetMappingDefinition definition = new ResultSetMappingDefinition(ann.name());
LOG.debugf("Binding result set mapping: %s", definition.getName());
int entityAliasIndex = 0;
for (EntityResult entity : ann.entities()) {
//TODO parameterize lock mode?
List<FieldResult> properties = new ArrayList<FieldResult>();
List<String> propertyNames = new ArrayList<String>();
for (FieldResult field : entity.fields()) {
//use an ArrayList cause we might have several columns per root property
String name = field.name();
if (name.indexOf('.') == -1) {
//regular property
properties.add(field);
propertyNames.add(name);
} else {
/**
* Reorder properties
* 1. get the parent property
* 2. list all the properties following the expected one in the parent property
* 3. calculate the lowest index and insert the property
*/
PersistentClass pc = context.getMetadataCollector().getEntityBinding(entity.entityClass().getName());
if (pc == null) {
throw new MappingException(String.format(Locale.ENGLISH, "Could not resolve entity [%s] referenced in SqlResultSetMapping [%s]", entity.entityClass().getName(), ann.name()));
}
int dotIndex = name.lastIndexOf('.');
String reducedName = name.substring(0, dotIndex);
Iterator parentPropItr = getSubPropertyIterator(pc, reducedName);
List<String> followers = getFollowers(parentPropItr, reducedName, name);
int index = propertyNames.size();
for (String follower : followers) {
int currentIndex = getIndexOfFirstMatchingProperty(propertyNames, follower);
index = currentIndex != -1 && currentIndex < index ? currentIndex : index;
}
propertyNames.add(index, name);
properties.add(index, field);
}
}
Set<String> uniqueReturnProperty = new HashSet<String>();
Map<String, ArrayList<String>> propertyResultsTmp = new HashMap<String, ArrayList<String>>();
for (Object property : properties) {
final FieldResult propertyresult = (FieldResult) property;
final String name = propertyresult.name();
if ("class".equals(name)) {
throw new MappingException("class is not a valid property name to use in a @FieldResult, use @Entity(discriminatorColumn) instead");
}
if (uniqueReturnProperty.contains(name)) {
throw new MappingException("duplicate @FieldResult for property " + name + " on @Entity " + entity.entityClass().getName() + " in " + ann.name());
}
uniqueReturnProperty.add(name);
final String quotingNormalizedColumnName = normalizeColumnQuoting(propertyresult.column());
String key = StringHelper.root(name);
ArrayList<String> intermediateResults = propertyResultsTmp.get(key);
if (intermediateResults == null) {
intermediateResults = new ArrayList<String>();
propertyResultsTmp.put(key, intermediateResults);
}
intermediateResults.add(quotingNormalizedColumnName);
}
Map<String, String[]> propertyResults = new HashMap<String, String[]>();
for (Map.Entry<String, ArrayList<String>> entry : propertyResultsTmp.entrySet()) {
propertyResults.put(entry.getKey(), entry.getValue().toArray(new String[entry.getValue().size()]));
}
if (!BinderHelper.isEmptyAnnotationValue(entity.discriminatorColumn())) {
final String quotingNormalizedName = normalizeColumnQuoting(entity.discriminatorColumn());
propertyResults.put("class", new String[] { quotingNormalizedName });
}
if (propertyResults.isEmpty()) {
propertyResults = java.util.Collections.emptyMap();
}
NativeSQLQueryRootReturn result = new NativeSQLQueryRootReturn("alias" + entityAliasIndex++, entity.entityClass().getName(), propertyResults, LockMode.READ);
definition.addQueryReturn(result);
}
for (ColumnResult column : ann.columns()) {
definition.addQueryReturn(new NativeSQLQueryScalarReturn(normalizeColumnQuoting(column.name()), column.type() != null ? context.getMetadataCollector().getTypeResolver().heuristicType(column.type().getName()) : null));
}
for (ConstructorResult constructorResult : ann.classes()) {
List<NativeSQLQueryScalarReturn> columnReturns = new ArrayList<NativeSQLQueryScalarReturn>();
for (ColumnResult columnResult : constructorResult.columns()) {
columnReturns.add(new NativeSQLQueryScalarReturn(normalizeColumnQuoting(columnResult.name()), columnResult.type() != null ? context.getMetadataCollector().getTypeResolver().heuristicType(columnResult.type().getName()) : null));
}
definition.addQueryReturn(new NativeSQLQueryConstructorReturn(constructorResult.targetClass(), columnReturns));
}
if (isDefault) {
context.getMetadataCollector().addDefaultResultSetMapping(definition);
} else {
context.getMetadataCollector().addResultSetMapping(definition);
}
}
use of org.hibernate.engine.ResultSetMappingDefinition in project hibernate-orm by hibernate.
the class NativeQueryImpl method setResultSetMapping.
@Override
public NativeQuery setResultSetMapping(String name) {
ResultSetMappingDefinition mapping = getProducer().getFactory().getNamedQueryRepository().getResultSetMappingDefinition(name);
if (mapping == null) {
throw new MappingException("Unknown SqlResultSetMapping [" + name + "]");
}
NativeSQLQueryReturn[] returns = mapping.getQueryReturns();
queryReturns.addAll(Arrays.asList(returns));
return this;
}
Aggregations