Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.hibernate.impl.SQLQueryImpl Maven / Gradle / Ivy
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2010, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.impl;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.io.Serializable;
import org.hibernate.FlushMode;
import org.hibernate.HibernateException;
import org.hibernate.LockMode;
import org.hibernate.Query;
import org.hibernate.QueryException;
import org.hibernate.SQLQuery;
import org.hibernate.ScrollMode;
import org.hibernate.ScrollableResults;
import org.hibernate.MappingException;
import org.hibernate.LockOptions;
import org.hibernate.engine.query.sql.NativeSQLQuerySpecification;
import org.hibernate.engine.ResultSetMappingDefinition;
import org.hibernate.engine.NamedSQLQueryDefinition;
import org.hibernate.engine.QueryParameters;
import org.hibernate.engine.SessionImplementor;
import org.hibernate.engine.query.ParameterMetadata;
import org.hibernate.engine.query.sql.NativeSQLQueryJoinReturn;
import org.hibernate.engine.query.sql.NativeSQLQueryScalarReturn;
import org.hibernate.engine.query.sql.NativeSQLQueryRootReturn;
import org.hibernate.engine.query.sql.NativeSQLQueryReturn;
import org.hibernate.type.Type;
import org.hibernate.util.StringHelper;
/**
* Implementation of the {@link SQLQuery} contract.
*
* @author Max Andersen
* @author Steve Ebersole
*/
public class SQLQueryImpl extends AbstractQueryImpl implements SQLQuery {
private List queryReturns;
private List queryReturnBuilders;
private boolean autoDiscoverTypes;
private Collection querySpaces;
private final boolean callable;
/**
* Constructs a SQLQueryImpl given a sql query defined in the mappings.
*
* @param queryDef The representation of the defined .
* @param session The session to which this SQLQueryImpl belongs.
* @param parameterMetadata Metadata about parameters found in the query.
*/
SQLQueryImpl(NamedSQLQueryDefinition queryDef, SessionImplementor session, ParameterMetadata parameterMetadata) {
super( queryDef.getQueryString(), queryDef.getFlushMode(), session, parameterMetadata );
if ( queryDef.getResultSetRef() != null ) {
ResultSetMappingDefinition definition = session.getFactory()
.getResultSetMapping( queryDef.getResultSetRef() );
if (definition == null) {
throw new MappingException(
"Unable to find resultset-ref definition: " +
queryDef.getResultSetRef()
);
}
this.queryReturns = Arrays.asList( definition.getQueryReturns() );
}
else if ( queryDef.getQueryReturns() != null && queryDef.getQueryReturns().length > 0 ) {
this.queryReturns = Arrays.asList( queryDef.getQueryReturns() );
}
else {
this.queryReturns = new ArrayList();
}
this.querySpaces = queryDef.getQuerySpaces();
this.callable = queryDef.isCallable();
}
SQLQueryImpl(
final String sql,
final String returnAliases[],
final Class returnClasses[],
final LockMode[] lockModes,
final SessionImplementor session,
final Collection querySpaces,
final FlushMode flushMode,
ParameterMetadata parameterMetadata) {
// TODO : this constructor form is *only* used from constructor directly below us; can it go away?
super( sql, flushMode, session, parameterMetadata );
queryReturns = new ArrayList( returnAliases.length );
for ( int i=0; i();
querySpaces = null;
callable = false;
}
private NativeSQLQueryReturn[] getQueryReturns() {
return queryReturns.toArray( new NativeSQLQueryReturn[queryReturns.size()] );
}
public List list() throws HibernateException {
verifyParameters();
before();
Map namedParams = getNamedParams();
NativeSQLQuerySpecification spec = generateQuerySpecification( namedParams );
try {
return getSession().list( spec, getQueryParameters( namedParams ) );
}
finally {
after();
}
}
private NativeSQLQuerySpecification generateQuerySpecification(Map namedParams) {
return new NativeSQLQuerySpecification(
expandParameterLists(namedParams),
getQueryReturns(),
querySpaces
);
}
public ScrollableResults scroll(ScrollMode scrollMode) throws HibernateException {
verifyParameters();
before();
Map namedParams = getNamedParams();
NativeSQLQuerySpecification spec = generateQuerySpecification( namedParams );
QueryParameters qp = getQueryParameters( namedParams );
qp.setScrollMode( scrollMode );
try {
return getSession().scroll( spec, qp );
}
finally {
after();
}
}
public ScrollableResults scroll() throws HibernateException {
return scroll(ScrollMode.SCROLL_INSENSITIVE);
}
public Iterator iterate() throws HibernateException {
throw new UnsupportedOperationException("SQL queries do not currently support iteration");
}
public QueryParameters getQueryParameters(Map namedParams) {
QueryParameters qp = super.getQueryParameters(namedParams);
qp.setCallable(callable);
qp.setAutoDiscoverScalarTypes( autoDiscoverTypes );
return qp;
}
protected void verifyParameters() {
// verifyParameters is called at the start of all execution type methods, so we use that here to perform
// some preparation work.
prepare();
verifyParameters( callable );
boolean noReturns = queryReturns==null || queryReturns.isEmpty();
if ( noReturns ) {
this.autoDiscoverTypes = noReturns;
}
else {
for ( NativeSQLQueryReturn queryReturn : queryReturns ) {
if ( queryReturn instanceof NativeSQLQueryScalarReturn ) {
NativeSQLQueryScalarReturn scalar = (NativeSQLQueryScalarReturn) queryReturn;
if ( scalar.getType() == null ) {
autoDiscoverTypes = true;
break;
}
}
}
}
}
private void prepare() {
if ( queryReturnBuilders != null ) {
if ( ! queryReturnBuilders.isEmpty() ) {
if ( queryReturns != null ) {
queryReturns.clear();
queryReturns = null;
}
queryReturns = new ArrayList();
for ( ReturnBuilder builder : queryReturnBuilders ) {
queryReturns.add( builder.buildReturn() );
}
queryReturnBuilders.clear();
}
queryReturnBuilders = null;
}
}
public String[] getReturnAliases() throws HibernateException {
throw new UnsupportedOperationException("SQL queries do not currently support returning aliases");
}
public Type[] getReturnTypes() throws HibernateException {
throw new UnsupportedOperationException("not yet implemented for SQL queries");
}
public Query setLockMode(String alias, LockMode lockMode) {
throw new UnsupportedOperationException("cannot set the lock mode for a native SQL query");
}
public Query setLockOptions(LockOptions lockOptions) {
throw new UnsupportedOperationException("cannot set lock options for a native SQL query");
}
public LockOptions getLockOptions() {
//we never need to apply locks to the SQL
return null;
}
public SQLQuery addScalar(final String columnAlias, final Type type) {
if ( queryReturnBuilders == null ) {
queryReturnBuilders = new ArrayList();
}
queryReturnBuilders.add(
new ReturnBuilder() {
public NativeSQLQueryReturn buildReturn() {
return new NativeSQLQueryScalarReturn( columnAlias, type );
}
}
);
return this;
}
public SQLQuery addScalar(String columnAlias) {
return addScalar( columnAlias, null );
}
public RootReturn addRoot(String tableAlias, String entityName) {
RootReturnBuilder builder = new RootReturnBuilder( tableAlias, entityName );
if ( queryReturnBuilders == null ) {
queryReturnBuilders = new ArrayList();
}
queryReturnBuilders.add( builder );
return builder;
}
public RootReturn addRoot(String tableAlias, Class entityType) {
return addRoot( tableAlias, entityType.getName() );
}
public SQLQuery addEntity(String entityName) {
return addEntity( StringHelper.unqualify( entityName ), entityName );
}
public SQLQuery addEntity(String alias, String entityName) {
addRoot( alias, entityName );
return this;
}
public SQLQuery addEntity(String alias, String entityName, LockMode lockMode) {
addRoot( alias, entityName ).setLockMode( lockMode );
return this;
}
public SQLQuery addEntity(Class entityType) {
return addEntity( entityType.getName() );
}
public SQLQuery addEntity(String alias, Class entityClass) {
return addEntity( alias, entityClass.getName() );
}
public SQLQuery addEntity(String alias, Class entityClass, LockMode lockMode) {
return addEntity( alias, entityClass.getName(), lockMode );
}
public FetchReturn addFetch(String tableAlias, String ownerTableAlias, String joinPropertyName) {
FetchReturnBuilder builder = new FetchReturnBuilder( tableAlias, ownerTableAlias, joinPropertyName );
if ( queryReturnBuilders == null ) {
queryReturnBuilders = new ArrayList();
}
queryReturnBuilders.add( builder );
return builder;
}
public SQLQuery addJoin(String tableAlias, String ownerTableAlias, String joinPropertyName) {
addFetch( tableAlias, ownerTableAlias, joinPropertyName );
return this;
}
public SQLQuery addJoin(String alias, String path) {
createFetchJoin( alias, path );
return this;
}
private FetchReturn createFetchJoin(String tableAlias, String path) {
int loc = path.indexOf('.');
if ( loc < 0 ) {
throw new QueryException( "not a property path: " + path );
}
final String ownerTableAlias = path.substring( 0, loc );
final String joinedPropertyName = path.substring( loc+1 );
return addFetch( tableAlias, ownerTableAlias, joinedPropertyName );
}
public SQLQuery addJoin(String alias, String path, LockMode lockMode) {
createFetchJoin( alias, path ).setLockMode( lockMode );
return this;
}
public SQLQuery setResultSetMapping(String name) {
ResultSetMappingDefinition mapping = session.getFactory().getResultSetMapping( name );
if ( mapping == null ) {
throw new MappingException( "Unknown SqlResultSetMapping [" + name + "]" );
}
NativeSQLQueryReturn[] returns = mapping.getQueryReturns();
queryReturns.addAll( Arrays.asList( returns ) );
return this;
}
public SQLQuery addSynchronizedQuerySpace(String querySpace) {
if ( querySpaces == null ) {
querySpaces = new ArrayList();
}
querySpaces.add( querySpace );
return this;
}
public SQLQuery addSynchronizedEntityName(String entityName) {
return addQuerySpaces( getSession().getFactory().getEntityPersister( entityName ).getQuerySpaces() );
}
public SQLQuery addSynchronizedEntityClass(Class entityClass) {
return addQuerySpaces( getSession().getFactory().getEntityPersister( entityClass.getName() ).getQuerySpaces() );
}
private SQLQuery addQuerySpaces(Serializable[] spaces) {
if ( spaces != null ) {
if ( querySpaces == null ) {
querySpaces = new ArrayList();
}
querySpaces.addAll( Arrays.asList( (String[]) spaces ) );
}
return this;
}
public int executeUpdate() throws HibernateException {
Map namedParams = getNamedParams();
before();
try {
return getSession().executeNativeUpdate(
generateQuerySpecification( namedParams ),
getQueryParameters( namedParams )
);
}
finally {
after();
}
}
private class RootReturnBuilder implements RootReturn, ReturnBuilder {
private final String alias;
private final String entityName;
private LockMode lockMode = LockMode.READ;
private Map propertyMappings;
private RootReturnBuilder(String alias, String entityName) {
this.alias = alias;
this.entityName = entityName;
}
public RootReturn setLockMode(LockMode lockMode) {
this.lockMode = lockMode;
return this;
}
public RootReturn setDiscriminatorAlias(String alias) {
addProperty( "class", alias );
return this;
}
public RootReturn addProperty(String propertyName, String columnAlias) {
addProperty( propertyName ).addColumnAlias( columnAlias );
return this;
}
public ReturnProperty addProperty(final String propertyName) {
if ( propertyMappings == null ) {
propertyMappings = new HashMap();
}
return new ReturnProperty() {
public ReturnProperty addColumnAlias(String columnAlias) {
String[] columnAliases = propertyMappings.get( propertyName );
if ( columnAliases == null ) {
columnAliases = new String[] { columnAlias };
}
else {
String[] newColumnAliases = new String[columnAliases.length + 1];
System.arraycopy( columnAliases, 0, newColumnAliases, 0, columnAliases.length );
newColumnAliases[columnAliases.length] = columnAlias;
columnAliases = newColumnAliases;
}
propertyMappings.put( propertyName, columnAliases );
return this;
}
};
}
public NativeSQLQueryReturn buildReturn() {
return new NativeSQLQueryRootReturn( alias, entityName, propertyMappings, lockMode );
}
}
private class FetchReturnBuilder implements FetchReturn, ReturnBuilder {
private final String alias;
private String ownerTableAlias;
private final String joinedPropertyName;
private LockMode lockMode = LockMode.READ;
private Map propertyMappings;
private FetchReturnBuilder(String alias, String ownerTableAlias, String joinedPropertyName) {
this.alias = alias;
this.ownerTableAlias = ownerTableAlias;
this.joinedPropertyName = joinedPropertyName;
}
public FetchReturn setLockMode(LockMode lockMode) {
this.lockMode = lockMode;
return this;
}
public FetchReturn addProperty(String propertyName, String columnAlias) {
addProperty( propertyName ).addColumnAlias( columnAlias );
return this;
}
public ReturnProperty addProperty(final String propertyName) {
if ( propertyMappings == null ) {
propertyMappings = new HashMap();
}
return new ReturnProperty() {
public ReturnProperty addColumnAlias(String columnAlias) {
String[] columnAliases = propertyMappings.get( propertyName );
if ( columnAliases == null ) {
columnAliases = new String[] { columnAlias };
}
else {
String[] newColumnAliases = new String[columnAliases.length + 1];
System.arraycopy( columnAliases, 0, newColumnAliases, 0, columnAliases.length );
newColumnAliases[columnAliases.length] = columnAlias;
columnAliases = newColumnAliases;
}
propertyMappings.put( propertyName, columnAliases );
return this;
}
};
}
public NativeSQLQueryReturn buildReturn() {
return new NativeSQLQueryJoinReturn( alias, ownerTableAlias, joinedPropertyName, propertyMappings, lockMode );
}
}
private interface ReturnBuilder {
NativeSQLQueryReturn buildReturn();
}
}