HHH-8159 - Apply fixups indicated by analysis tools

This commit is contained in:
Steve Ebersole 2013-04-23 18:13:41 -05:00
parent 900ad4be11
commit 8c28ba8463
61 changed files with 4083 additions and 1913 deletions

View File

@ -2,6 +2,18 @@
* Defines service registry contracts application are likely to want to utilize for
* configuring Hibernate behavior.
*
* {@link BootstrapServiceRegistry} is the
* Service registries are designed to be hierarchical. This works in 2 fashions. First registries can "hide" or
* "override" services from parent registries. It also allows granular building of registries as services
* become available.
*
* {@link BootstrapServiceRegistry} is the base service registry, intended to be built via
* {@link BootstrapServiceRegistryBuilder} if you need customization. For non-customized
* {@link BootstrapServiceRegistry} usage, the {@link BootstrapServiceRegistryBuilder} and
* {@link BootstrapServiceRegistry} can be bypassed altogether.
*
* Usually the next level in a standard registry set up is the {@link StandardServiceRegistry}, intended to be built
* by the {@link StandardServiceRegistryBuilder} if you need customization. The builder optionally takes the
* {@link BootstrapServiceRegistry} to use as a base; if none is provided a default one is generated assuming sensible
* defaults in Java SE and EE environments, particularly in respect to Class loading.
*/
package org.hibernate.boot.registry;

View File

@ -33,11 +33,22 @@ import org.hibernate.HibernateException;
* @author Steve Ebersole
*/
public class TenantIdentifierMismatchException extends HibernateException{
/**
* Constructs a TenantIdentifierMismatchException.
*
* @param message Message explaining the exception condition
*/
public TenantIdentifierMismatchException(String message) {
super( message );
}
public TenantIdentifierMismatchException(String message, Throwable root) {
super( message, root );
/**
* Constructs a TenantIdentifierMismatchException.
*
* @param message Message explaining the exception condition
* @param cause The underlying cause
*/
public TenantIdentifierMismatchException(String message, Throwable cause) {
super( message, cause );
}
}

View File

@ -23,12 +23,11 @@
*/
package org.hibernate.context.internal;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import javax.transaction.Synchronization;
import javax.transaction.Transaction;
import javax.transaction.TransactionManager;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.jboss.logging.Logger;
@ -36,40 +35,44 @@ import org.hibernate.ConnectionReleaseMode;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.context.spi.AbstractCurrentSessionContext;
import org.hibernate.context.spi.CurrentSessionContext;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.transaction.internal.jta.JtaStatusHelper;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.engine.transaction.jta.platform.spi.JtaPlatform;
import org.hibernate.internal.CoreMessageLogger;
/**
* An implementation of {@link CurrentSessionContext} which scopes the notion
* of a current session to a JTA transaction. Because JTA gives us a nice
* tie-in to clean up after ourselves, this implementation will generate
* Sessions as needed provided a JTA transaction is in effect. If a session
* is not already associated with the current JTA transaction at the time
* {@link #currentSession()} is called, a new session will be opened and it
* will be associated with that JTA transaction.
* <p/>
* Note that the sessions returned from this method are automatically configured with
* both the {@link org.hibernate.cfg.Environment#FLUSH_BEFORE_COMPLETION auto-flush} and
* {@link org.hibernate.cfg.Environment#AUTO_CLOSE_SESSION auto-close} attributes set to
* true, meaning that the Session will be automatically flushed and closed
* as part of the lifecycle for the JTA transaction to which it is associated.
* Additionally, it will also be configured to aggressively release JDBC
* connections after each statement is executed. These settings are governed
* by the {@link #isAutoFlushEnabled()}, {@link #isAutoCloseEnabled()}, and
* {@link #getConnectionReleaseMode()} methods; these are provided (along with
* the {@link #buildOrObtainSession()} method) for easier subclassing for custom
* JTA-based session tracking logic (like maybe long-session semantics).
* An implementation of {@link org.hibernate.context.spi.CurrentSessionContext} which scopes the notion
* of a current session to a JTA transaction. Because JTA gives us a nice tie-in to clean up after
* ourselves, this implementation will generate Sessions as needed provided a JTA transaction is in
* effect. If a session is not already associated with the current JTA transaction at the time
* {@link #currentSession()} is called, a new session will be opened and it will be associated with that
* JTA transaction.
*
* Note that the sessions returned from this method are automatically configured with both the
* {@link org.hibernate.cfg.Environment#FLUSH_BEFORE_COMPLETION auto-flush} and
* {@link org.hibernate.cfg.Environment#AUTO_CLOSE_SESSION auto-close} attributes set to true, meaning
* that the Session will be automatically flushed and closed as part of the lifecycle for the JTA
* transaction to which it is associated. Additionally, it will also be configured to aggressively
* release JDBC connections after each statement is executed. These settings are governed by the
* {@link #isAutoFlushEnabled()}, {@link #isAutoCloseEnabled()}, and {@link #getConnectionReleaseMode()}
* methods; these are provided (along with the {@link #buildOrObtainSession()} method) for easier
* subclassing for custom JTA-based session tracking logic (like maybe long-session semantics).
*
* @author Steve Ebersole
*/
public class JTASessionContext extends AbstractCurrentSessionContext {
private static final CoreMessageLogger LOG = Logger.getMessageLogger(CoreMessageLogger.class, JTASessionContext.class.getName());
private static final CoreMessageLogger LOG = Logger.getMessageLogger(
CoreMessageLogger.class,
JTASessionContext.class.getName()
);
private transient Map<Object, Session> currentSessionMap = new ConcurrentHashMap<Object, Session>();
/**
* Constructs a JTASessionContext
*
* @param factory The factory this context will service
*/
public JTASessionContext(SessionFactoryImplementor factory) {
super( factory );
}
@ -132,24 +135,23 @@ public class JTASessionContext extends AbstractCurrentSessionContext {
}
/**
* Builds a {@link CleanupSynch} capable of cleaning up the the current session map as an after transaction
* Builds a {@link org.hibernate.context.internal.JTASessionContext.CleanupSync} capable of cleaning up the the current session map as an after transaction
* callback.
*
* @param transactionIdentifier The transaction identifier under which the current session is registered.
* @return The cleanup synch.
*/
private CleanupSynch buildCleanupSynch(Object transactionIdentifier) {
return new CleanupSynch( transactionIdentifier, this );
private CleanupSync buildCleanupSynch(Object transactionIdentifier) {
return new CleanupSync( transactionIdentifier, this );
}
/**
* Strictly provided for subclassing purposes; specifically to allow long-session
* support.
* <p/>
* This implementation always just opens a new session.
* support. This implementation always just opens a new session.
*
* @return the built or (re)obtained session.
*/
@SuppressWarnings("deprecation")
protected Session buildOrObtainSession() {
return baseSessionBuilder()
.autoClose( isAutoCloseEnabled() )
@ -186,26 +188,22 @@ public class JTASessionContext extends AbstractCurrentSessionContext {
}
/**
* JTA transaction synch used for cleanup of the internal session map.
* JTA transaction sync used for cleanup of the internal session map.
*/
protected static class CleanupSynch implements Synchronization {
protected static class CleanupSync implements Synchronization {
private Object transactionIdentifier;
private JTASessionContext context;
public CleanupSynch(Object transactionIdentifier, JTASessionContext context) {
public CleanupSync(Object transactionIdentifier, JTASessionContext context) {
this.transactionIdentifier = transactionIdentifier;
this.context = context;
}
/**
* {@inheritDoc}
*/
@Override
public void beforeCompletion() {
}
/**
* {@inheritDoc}
*/
@Override
public void afterCompletion(int i) {
context.currentSessionMap.remove( transactionIdentifier );
}

View File

@ -57,16 +57,20 @@ import org.hibernate.engine.spi.SessionFactoryImplementor;
* @author Steve Ebersole
*/
public class ManagedSessionContext extends AbstractCurrentSessionContext {
private static final ThreadLocal<Map<SessionFactory,Session>> CONTEXT_TL = new ThreadLocal<Map<SessionFactory,Session>>();
private static final ThreadLocal<Map<SessionFactory,Session>> context = new ThreadLocal<Map<SessionFactory,Session>>();
/**
* Constructs a new ManagedSessionContext
*
* @param factory The factory this context will service
*/
public ManagedSessionContext(SessionFactoryImplementor factory) {
super( factory );
}
@Override
public Session currentSession() {
Session current = existingSession( factory() );
final Session current = existingSession( factory() );
if ( current == null ) {
throw new HibernateException( "No session currently bound to execution context" );
}
@ -106,8 +110,8 @@ public class ManagedSessionContext extends AbstractCurrentSessionContext {
* @return The bound session if one, else null.
*/
public static Session unbind(SessionFactory factory) {
final Map<SessionFactory,Session> sessionMap = sessionMap();
Session existing = null;
Map<SessionFactory,Session> sessionMap = sessionMap();
if ( sessionMap != null ) {
existing = sessionMap.remove( factory );
doCleanup();
@ -116,12 +120,12 @@ public class ManagedSessionContext extends AbstractCurrentSessionContext {
}
private static Session existingSession(SessionFactory factory) {
Map sessionMap = sessionMap();
final Map sessionMap = sessionMap();
if ( sessionMap == null ) {
return null;
}
else {
return ( Session ) sessionMap.get( factory );
return (Session) sessionMap.get( factory );
}
}
@ -130,19 +134,19 @@ public class ManagedSessionContext extends AbstractCurrentSessionContext {
}
private static synchronized Map<SessionFactory,Session> sessionMap(boolean createMap) {
Map<SessionFactory,Session> sessionMap = context.get();
Map<SessionFactory,Session> sessionMap = CONTEXT_TL.get();
if ( sessionMap == null && createMap ) {
sessionMap = new HashMap<SessionFactory,Session>();
context.set( sessionMap );
CONTEXT_TL.set( sessionMap );
}
return sessionMap;
}
private static synchronized void doCleanup() {
Map<SessionFactory,Session> sessionMap = sessionMap( false );
final Map<SessionFactory,Session> sessionMap = sessionMap( false );
if ( sessionMap != null ) {
if ( sessionMap.isEmpty() ) {
context.set( null );
CONTEXT_TL.set( null );
}
}
}

View File

@ -42,7 +42,6 @@ import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.context.spi.AbstractCurrentSessionContext;
import org.hibernate.context.spi.CurrentSessionContext;
import org.hibernate.engine.jdbc.LobCreationContext;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.SessionImplementor;
@ -51,39 +50,37 @@ import org.hibernate.event.spi.EventSource;
import org.hibernate.internal.CoreMessageLogger;
/**
* A {@link CurrentSessionContext} impl which scopes the notion of current
* session by the current thread of execution. Unlike the JTA counterpart,
* threads do not give us a nice hook to perform any type of cleanup making
* it questionable for this impl to actually generate Session instances. In
* the interest of usability, it was decided to have this default impl
* actually generate a session upon first request and then clean it up
* after the {@link org.hibernate.Transaction} associated with that session
* is committed/rolled-back. In order for ensuring that happens, the sessions
* generated here are unusable until after {@link Session#beginTransaction()}
* has been called. If <tt>close()</tt> is called on a session managed by
* this class, it will be automatically unbound.
* <p/>
* Additionally, the static {@link #bind} and {@link #unbind} methods are
* provided to allow application code to explicitly control opening and
* closing of these sessions. This, with some from of interception,
* is the preferred approach. It also allows easy framework integration
* and one possible approach for implementing long-sessions.
* <p/>
* The {@link #buildOrObtainSession}, {@link #isAutoCloseEnabled},
* {@link #isAutoFlushEnabled}, {@link #getConnectionReleaseMode}, and
* {@link #buildCleanupSynch} methods are all provided to allow easy
* A {@link org.hibernate.context.spi.CurrentSessionContext} impl which scopes the notion of current
* session by the current thread of execution. Unlike the JTA counterpart, threads do not give us a nice
* hook to perform any type of cleanup making it questionable for this impl to actually generate Session
* instances. In the interest of usability, it was decided to have this default impl actually generate
* a session upon first request and then clean it up after the {@link org.hibernate.Transaction}
* associated with that session is committed/rolled-back. In order for ensuring that happens, the
* sessions generated here are unusable until after {@link Session#beginTransaction()} has been
* called. If <tt>close()</tt> is called on a session managed by this class, it will be automatically
* unbound.
*
* Additionally, the static {@link #bind} and {@link #unbind} methods are provided to allow application
* code to explicitly control opening and closing of these sessions. This, with some from of interception,
* is the preferred approach. It also allows easy framework integration and one possible approach for
* implementing long-sessions.
*
* The {@link #buildOrObtainSession}, {@link #isAutoCloseEnabled}, {@link #isAutoFlushEnabled},
* {@link #getConnectionReleaseMode}, and {@link #buildCleanupSynch} methods are all provided to allow easy
* subclassing (for long-running session scenarios, for example).
*
* @author Steve Ebersole
*/
public class ThreadLocalSessionContext extends AbstractCurrentSessionContext {
private static final CoreMessageLogger LOG = Logger.getMessageLogger(
CoreMessageLogger.class,
ThreadLocalSessionContext.class.getName()
);
private static final CoreMessageLogger LOG = Logger.getMessageLogger(CoreMessageLogger.class,
ThreadLocalSessionContext.class.getName());
private static final Class[] SESSION_PROXY_INTERFACES = new Class[] {
Session.class,
SessionImplementor.class,
EventSource.class,
SessionImplementor.class,
EventSource.class,
TransactionContext.class,
LobCreationContext.class
};
@ -91,11 +88,16 @@ public class ThreadLocalSessionContext extends AbstractCurrentSessionContext {
/**
* A ThreadLocal maintaining current sessions for the given execution thread.
* The actual ThreadLocal variable is a java.util.Map to account for
* the possibility for multiple SessionFactorys being used during execution
* the possibility for multiple SessionFactory instances being used during execution
* of the given thread.
*/
private static final ThreadLocal<Map> context = new ThreadLocal<Map>();
private static final ThreadLocal<Map> CONTEXT_TL = new ThreadLocal<Map>();
/**
* Constructs a ThreadLocal
*
* @param factory The factory this context will service
*/
public ThreadLocalSessionContext(SessionFactoryImplementor factory) {
super( factory );
}
@ -122,10 +124,15 @@ public class ThreadLocalSessionContext extends AbstractCurrentSessionContext {
private boolean needsWrapping(Session session) {
// try to make sure we don't wrap and already wrapped session
return session != null
&& ! Proxy.isProxyClass( session.getClass() )
|| ( Proxy.getInvocationHandler( session ) != null
&& ! ( Proxy.getInvocationHandler( session ) instanceof TransactionProtectionWrapper ) );
if ( session != null ) {
if ( Proxy.isProxyClass( session.getClass() ) ) {
final InvocationHandler invocationHandler = Proxy.getInvocationHandler( session );
if ( invocationHandler != null && TransactionProtectionWrapper.class.isInstance( invocationHandler ) ) {
return false;
}
}
}
return true;
}
/**
@ -138,13 +145,14 @@ public class ThreadLocalSessionContext extends AbstractCurrentSessionContext {
}
/**
* Strictly provided for subclassing purposes; specifically to allow long-session
* Strictly provided for sub-classing purposes; specifically to allow long-session
* support.
* <p/>
* This implementation always just opens a new session.
*
* @return the built or (re)obtained session.
*/
@SuppressWarnings("deprecation")
protected Session buildOrObtainSession() {
return baseSessionBuilder()
.autoClose( isAutoCloseEnabled() )
@ -153,8 +161,8 @@ public class ThreadLocalSessionContext extends AbstractCurrentSessionContext {
.openSession();
}
protected CleanupSynch buildCleanupSynch() {
return new CleanupSynch( factory() );
protected CleanupSync buildCleanupSynch() {
return new CleanupSync( factory() );
}
/**
@ -185,12 +193,12 @@ public class ThreadLocalSessionContext extends AbstractCurrentSessionContext {
}
protected Session wrap(Session session) {
TransactionProtectionWrapper wrapper = new TransactionProtectionWrapper( session );
Session wrapped = ( Session ) Proxy.newProxyInstance(
final TransactionProtectionWrapper wrapper = new TransactionProtectionWrapper( session );
final Session wrapped = (Session) Proxy.newProxyInstance(
Session.class.getClassLoader(),
SESSION_PROXY_INTERFACES,
wrapper
);
wrapper
);
// yick! need this for proper serialization/deserialization handling...
wrapper.setWrapped( wrapped );
return wrapped;
@ -202,13 +210,13 @@ public class ThreadLocalSessionContext extends AbstractCurrentSessionContext {
* @param session The session to bind.
*/
public static void bind(org.hibernate.Session session) {
SessionFactory factory = session.getSessionFactory();
final SessionFactory factory = session.getSessionFactory();
cleanupAnyOrphanedSession( factory );
doBind( session, factory );
}
private static void cleanupAnyOrphanedSession(SessionFactory factory) {
Session orphan = doUnbind( factory, false );
final Session orphan = doUnbind( factory, false );
if ( orphan != null ) {
LOG.alreadySessionBound();
try {
@ -239,7 +247,7 @@ public class ThreadLocalSessionContext extends AbstractCurrentSessionContext {
}
private static Session existingSession(SessionFactory factory) {
Map sessionMap = sessionMap();
final Map sessionMap = sessionMap();
if ( sessionMap == null ) {
return null;
}
@ -247,7 +255,7 @@ public class ThreadLocalSessionContext extends AbstractCurrentSessionContext {
}
protected static Map sessionMap() {
return context.get();
return CONTEXT_TL.get();
}
@SuppressWarnings({"unchecked"})
@ -255,42 +263,38 @@ public class ThreadLocalSessionContext extends AbstractCurrentSessionContext {
Map sessionMap = sessionMap();
if ( sessionMap == null ) {
sessionMap = new HashMap();
context.set( sessionMap );
CONTEXT_TL.set( sessionMap );
}
sessionMap.put( factory, session );
}
private static Session doUnbind(SessionFactory factory, boolean releaseMapIfEmpty) {
Map sessionMap = sessionMap();
Session session = null;
final Map sessionMap = sessionMap();
if ( sessionMap != null ) {
session = ( Session ) sessionMap.remove( factory );
session = (Session) sessionMap.remove( factory );
if ( releaseMapIfEmpty && sessionMap.isEmpty() ) {
context.set( null );
CONTEXT_TL.set( null );
}
}
return session;
}
/**
* JTA transaction synch used for cleanup of the internal session map.
* Transaction sync used for cleanup of the internal session map.
*/
protected static class CleanupSynch implements Synchronization, Serializable {
protected static class CleanupSync implements Synchronization, Serializable {
protected final SessionFactory factory;
public CleanupSynch(SessionFactory factory) {
public CleanupSync(SessionFactory factory) {
this.factory = factory;
}
/**
* {@inheritDoc}
*/
@Override
public void beforeCompletion() {
}
/**
* {@inheritDoc}
*/
@Override
public void afterCompletion(int i) {
unbind( factory );
}
@ -304,9 +308,7 @@ public class ThreadLocalSessionContext extends AbstractCurrentSessionContext {
this.realSession = realSession;
}
/**
* {@inheritDoc}
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
final String methodName = method.getName();
try {
@ -315,13 +317,13 @@ public class ThreadLocalSessionContext extends AbstractCurrentSessionContext {
unbind( realSession.getSessionFactory() );
}
else if ( "toString".equals( methodName )
|| "equals".equals( methodName )
|| "hashCode".equals( methodName )
|| "getStatistics".equals( methodName )
|| "isOpen".equals( methodName )
|| "getListeners".equals( methodName )
) {
|| "equals".equals( methodName )
|| "hashCode".equals( methodName )
|| "getStatistics".equals( methodName )
|| "isOpen".equals( methodName )
|| "getListeners".equals( methodName ) ) {
// allow these to go through the the real session no matter what
LOG.tracef( "Allowing invocation [%s] to proceed to real session", methodName );
}
else if ( !realSession.isOpen() ) {
// essentially, if the real session is closed allow any
@ -329,6 +331,7 @@ public class ThreadLocalSessionContext extends AbstractCurrentSessionContext {
// will complain by throwing an appropriate exception;
// NOTE that allowing close() above has the same basic effect,
// but we capture that there simply to doAfterTransactionCompletion the unbind...
LOG.tracef( "Allowing invocation [%s] to proceed to real (closed) session", methodName );
}
else if ( !realSession.getTransaction().isActive() ) {
// limit the methods available if no transaction is active
@ -339,21 +342,24 @@ public class ThreadLocalSessionContext extends AbstractCurrentSessionContext {
|| "getFactory".equals( methodName )
|| "getSessionFactory".equals( methodName )
|| "getTenantIdentifier".equals( methodName ) ) {
LOG.tracev( "Allowing method [{0}] in non-transacted context", methodName );
LOG.tracef( "Allowing invocation [%s] to proceed to real (non-transacted) session", methodName );
}
else if ( "reconnect".equals( methodName ) || "disconnect".equals( methodName ) ) {
// allow these (deprecated) methods to pass through
LOG.tracef( "Allowing invocation [%s] to proceed to real (non-transacted) session - deprecated methods", methodName );
}
else {
throw new HibernateException( methodName + " is not valid without active transaction" );
}
}
LOG.tracev( "Allowing proxied method [{0}] to proceed to real session", methodName );
LOG.tracef( "Allowing proxy invocation [%s] to proceed to real session", methodName );
return method.invoke( realSession, args );
}
catch ( InvocationTargetException e ) {
if (e.getTargetException() instanceof RuntimeException) throw (RuntimeException)e.getTargetException();
throw e;
if (e.getTargetException() instanceof RuntimeException) {
throw (RuntimeException)e.getTargetException();
}
throw e;
}
}

View File

@ -0,0 +1,4 @@
/**
* Internal implementations and support around "current session" handling.
*/
package org.hibernate.context.internal;

View File

@ -0,0 +1,4 @@
/**
* Defines support for "current session" feature.
*/
package org.hibernate.context;

View File

@ -41,6 +41,11 @@ public abstract class AbstractCurrentSessionContext implements CurrentSessionCon
this.factory = factory;
}
/**
* Access to the SessionFactory
*
* @return The SessionFactory being serviced by this context
*/
public SessionFactoryImplementor factory() {
return factory;
}

View File

@ -0,0 +1,4 @@
/**
* SPI level contracts around "current session" support.
*/
package org.hibernate.context.spi;

View File

@ -1,10 +1,10 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
* Copyright (c) 2008, 2013, 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 Middleware LLC.
* 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
@ -20,7 +20,6 @@
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*
*/
package org.hibernate.criterion;
import org.hibernate.Criteria;
@ -37,7 +36,7 @@ import org.hibernate.type.CollectionType;
import org.hibernate.type.Type;
/**
* Implementation of AbstractEmptinessExpression.
* Base expression implementation for (not) emptiness checking of collection properties
*
* @author Steve Ebersole
*/
@ -51,43 +50,50 @@ public abstract class AbstractEmptinessExpression implements Criterion {
this.propertyName = propertyName;
}
/**
* Should empty rows be excluded?
*
* @return {@code true} Indicates the expression should be 'exists'; {@code false} indicates 'not exists'
*/
protected abstract boolean excludeEmpty();
@Override
public final String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException {
String entityName = criteriaQuery.getEntityName( criteria, propertyName );
String actualPropertyName = criteriaQuery.getPropertyName( propertyName );
String sqlAlias = criteriaQuery.getSQLAlias( criteria, propertyName );
final String entityName = criteriaQuery.getEntityName( criteria, propertyName );
final String actualPropertyName = criteriaQuery.getPropertyName( propertyName );
final String sqlAlias = criteriaQuery.getSQLAlias( criteria, propertyName );
SessionFactoryImplementor factory = criteriaQuery.getFactory();
QueryableCollection collectionPersister = getQueryableCollection( entityName, actualPropertyName, factory );
final SessionFactoryImplementor factory = criteriaQuery.getFactory();
final QueryableCollection collectionPersister = getQueryableCollection( entityName, actualPropertyName, factory );
String[] collectionKeys = collectionPersister.getKeyColumnNames();
String[] ownerKeys = ( ( Loadable ) factory.getEntityPersister( entityName ) ).getIdentifierColumnNames();
final String[] collectionKeys = collectionPersister.getKeyColumnNames();
final String[] ownerKeys = ( (Loadable) factory.getEntityPersister( entityName ) ).getIdentifierColumnNames();
String innerSelect = "(select 1 from " + collectionPersister.getTableName()
+ " where "
+ new ConditionFragment().setTableAlias( sqlAlias ).setCondition( ownerKeys, collectionKeys ).toFragmentString()
+ ")";
final String innerSelect = "(select 1 from " + collectionPersister.getTableName() + " where "
+ new ConditionFragment().setTableAlias( sqlAlias ).setCondition( ownerKeys, collectionKeys ).toFragmentString()
+ ")";
return excludeEmpty()
? "exists " + innerSelect
: "not exists " + innerSelect;
? "exists " + innerSelect
: "not exists " + innerSelect;
}
protected QueryableCollection getQueryableCollection(String entityName, String propertyName, SessionFactoryImplementor factory)
throws HibernateException {
PropertyMapping ownerMapping = ( PropertyMapping ) factory.getEntityPersister( entityName );
Type type = ownerMapping.toType( propertyName );
protected QueryableCollection getQueryableCollection(
String entityName,
String propertyName,
SessionFactoryImplementor factory) throws HibernateException {
final PropertyMapping ownerMapping = (PropertyMapping) factory.getEntityPersister( entityName );
final Type type = ownerMapping.toType( propertyName );
if ( !type.isCollectionType() ) {
throw new MappingException(
"Property path [" + entityName + "." + propertyName + "] does not reference a collection"
"Property path [" + entityName + "." + propertyName + "] does not reference a collection"
);
}
String role = ( ( CollectionType ) type ).getRole();
final String role = ( (CollectionType) type ).getRole();
try {
return ( QueryableCollection ) factory.getCollectionPersister( role );
return (QueryableCollection) factory.getCollectionPersister( role );
}
catch ( ClassCastException cce ) {
throw new QueryException( "collection role is not queryable: " + role );
@ -97,11 +103,13 @@ public abstract class AbstractEmptinessExpression implements Criterion {
}
}
@Override
public final TypedValue[] getTypedValues(Criteria criteria, CriteriaQuery criteriaQuery)
throws HibernateException {
throws HibernateException {
return NO_VALUES;
}
@Override
public final String toString() {
return propertyName + ( excludeEmpty() ? " is not empty" : " is empty" );
}

View File

@ -52,13 +52,7 @@ public class AggregateProjection extends SimpleProjection {
return propertyName;
}
public String toString() {
return functionName + "(" + propertyName + ')';
}
/**
* {@inheritDoc}
*/
@Override
public Type[] getTypes(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException {
return new Type[] {
getFunction( criteriaQuery ).getReturnType(
@ -68,9 +62,7 @@ public class AggregateProjection extends SimpleProjection {
};
}
/**
* {@inheritDoc}
*/
@Override
public String toSqlString(Criteria criteria, int loc, CriteriaQuery criteriaQuery) throws HibernateException {
final String functionFragment = getFunction( criteriaQuery ).render(
criteriaQuery.getType( criteria, getPropertyName() ),
@ -85,7 +77,7 @@ public class AggregateProjection extends SimpleProjection {
}
protected SQLFunction getFunction(String functionName, CriteriaQuery criteriaQuery) {
SQLFunction function = criteriaQuery.getFactory()
final SQLFunction function = criteriaQuery.getFactory()
.getSqlFunctionRegistry()
.findSQLFunction( functionName );
if ( function == null ) {
@ -101,4 +93,10 @@ public class AggregateProjection extends SimpleProjection {
protected List buildFunctionParameterList(String column) {
return Collections.singletonList( column );
}
@Override
public String toString() {
return functionName + "(" + propertyName + ')';
}
}

View File

@ -1,10 +1,10 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
* Copyright (c) 2008, 2013, 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 Middleware LLC.
* 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
@ -20,7 +20,6 @@
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*
*/
package org.hibernate.criterion;
import org.hibernate.Criteria;
@ -28,71 +27,80 @@ import org.hibernate.HibernateException;
import org.hibernate.type.Type;
/**
* Represents a projection that specifies an alias
*
* @author Gavin King
*/
public class AliasedProjection implements EnhancedProjection {
private final Projection projection;
private final String alias;
public String toString() {
return projection.toString() + " as " + alias;
}
protected AliasedProjection(Projection projection, String alias) {
this.projection = projection;
this.alias = alias;
}
public String toSqlString(Criteria criteria, int position, CriteriaQuery criteriaQuery)
throws HibernateException {
return projection.toSqlString(criteria, position, criteriaQuery);
@Override
public String toSqlString(Criteria criteria, int position, CriteriaQuery criteriaQuery) throws HibernateException {
return projection.toSqlString( criteria, position, criteriaQuery );
}
@Override
public String toGroupSqlString(Criteria criteria, CriteriaQuery criteriaQuery) {
return projection.toGroupSqlString(criteria, criteriaQuery);
return projection.toGroupSqlString( criteria, criteriaQuery );
}
public Type[] getTypes(Criteria criteria, CriteriaQuery criteriaQuery)
throws HibernateException {
return projection.getTypes(criteria, criteriaQuery);
@Override
public Type[] getTypes(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException {
return projection.getTypes( criteria, criteriaQuery );
}
@Override
public String[] getColumnAliases(int loc) {
return projection.getColumnAliases(loc);
return projection.getColumnAliases( loc );
}
@Override
public String[] getColumnAliases(int loc, Criteria criteria, CriteriaQuery criteriaQuery) {
return projection instanceof EnhancedProjection ?
( ( EnhancedProjection ) projection ).getColumnAliases( loc, criteria, criteriaQuery ) :
getColumnAliases( loc );
return projection instanceof EnhancedProjection
? ( (EnhancedProjection) projection ).getColumnAliases( loc, criteria, criteriaQuery )
: getColumnAliases( loc );
}
public Type[] getTypes(String alias, Criteria criteria, CriteriaQuery criteriaQuery)
throws HibernateException {
return this.alias.equals(alias) ?
getTypes(criteria, criteriaQuery) :
null;
@Override
public Type[] getTypes(String alias, Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException {
return this.alias.equals( alias )
? getTypes( criteria, criteriaQuery )
: null;
}
@Override
public String[] getColumnAliases(String alias, int loc) {
return this.alias.equals(alias) ?
getColumnAliases(loc) :
null;
return this.alias.equals( alias )
? getColumnAliases( loc )
: null;
}
@Override
public String[] getColumnAliases(String alias, int loc, Criteria criteria, CriteriaQuery criteriaQuery) {
return this.alias.equals(alias) ?
getColumnAliases( loc, criteria, criteriaQuery ) :
null;
return this.alias.equals( alias )
? getColumnAliases( loc, criteria, criteriaQuery )
: null;
}
@Override
public String[] getAliases() {
return new String[]{ alias };
return new String[] { alias };
}
@Override
public boolean isGrouped() {
return projection.isGrouped();
}
@Override
public String toString() {
return projection.toString() + " as " + alias;
}
}

View File

@ -23,14 +23,18 @@
*/
package org.hibernate.criterion;
/**
* An avg() projection
*
* @author Gavin King
*/
public class AvgProjection extends AggregateProjection {
/**
* Constructs the AvgProjection
*
* @param propertyName The name of the property to average
*/
public AvgProjection(String propertyName) {
super("avg", propertyName);
super( "avg", propertyName );
}
}

View File

@ -1,10 +1,10 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
* Copyright (c) 2008, 2013, 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 Middleware LLC.
* 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
@ -20,9 +20,9 @@
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*
*/
package org.hibernate.criterion;
import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.engine.spi.TypedValue;
@ -30,10 +30,10 @@ import org.hibernate.internal.util.StringHelper;
/**
* Constrains a property to between two values
*
* @author Gavin King
*/
public class BetweenExpression implements Criterion {
private final String propertyName;
private final Object lo;
private final Object hi;
@ -44,24 +44,22 @@ public class BetweenExpression implements Criterion {
this.hi = hi;
}
public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery)
throws HibernateException {
return StringHelper.join(
" and ",
StringHelper.suffix( criteriaQuery.findColumns(propertyName, criteria), " between ? and ?" )
);
//TODO: get SQL rendering out of this package!
@Override
public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException {
final String[] columns = criteriaQuery.findColumns( propertyName, criteria );
final String[] expressions = StringHelper.suffix( columns, " between ? and ?" );
return StringHelper.join( " and ", expressions );
}
public TypedValue[] getTypedValues(Criteria criteria, CriteriaQuery criteriaQuery)
throws HibernateException {
@Override
public TypedValue[] getTypedValues(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException {
return new TypedValue[] {
criteriaQuery.getTypedValue(criteria, propertyName, lo),
criteriaQuery.getTypedValue(criteria, propertyName, hi)
criteriaQuery.getTypedValue( criteria, propertyName, lo ),
criteriaQuery.getTypedValue( criteria, propertyName, hi )
};
}
@Override
public String toString() {
return propertyName + " between " + lo + " and " + hi;
}

View File

@ -24,10 +24,22 @@
package org.hibernate.criterion;
/**
* Defines a conjunction (AND series).
*
* @author Gavin King
* @author Steve Ebersole
*
* @see Disjunction
*/
public class Conjunction extends Junction {
/**
* Constructs a Conjunction
*/
public Conjunction() {
super( Nature.AND );
}
protected Conjunction(Criterion... criterion) {
super( Nature.AND, criterion );
}
}

View File

@ -29,16 +29,50 @@ import java.util.List;
import org.hibernate.Criteria;
/**
* A count
* A count projection
*
* @author Gavin King
*/
public class CountProjection extends AggregateProjection {
private boolean distinct;
/**
* Constructs the count projection.
*
* @param prop The property name
*
* @see Projections#count(String)
* @see Projections#countDistinct(String)
*/
protected CountProjection(String prop) {
super("count", prop);
super( "count", prop );
}
@Override
protected List buildFunctionParameterList(Criteria criteria, CriteriaQuery criteriaQuery) {
final String[] cols = criteriaQuery.getColumns( propertyName, criteria );
return ( distinct ? buildCountDistinctParameterList( cols ) : Arrays.asList( cols ) );
}
@SuppressWarnings("unchecked")
private List buildCountDistinctParameterList(String[] cols) {
final List params = new ArrayList( cols.length + 1 );
params.add( "distinct" );
params.addAll( Arrays.asList( cols ) );
return params;
}
/**
* Sets the count as being distinct
*
* @return {@code this}, for method chaining
*/
public CountProjection setDistinct() {
distinct = true;
return this;
}
@Override
public String toString() {
if ( distinct ) {
return "distinct " + super.toString();
@ -48,20 +82,4 @@ public class CountProjection extends AggregateProjection {
}
}
protected List buildFunctionParameterList(Criteria criteria, CriteriaQuery criteriaQuery) {
String cols[] = criteriaQuery.getColumns( propertyName, criteria );
return ( distinct ? buildCountDistinctParameterList( cols ) : Arrays.asList( cols ) );
}
private List buildCountDistinctParameterList(String[] cols) {
List params = new ArrayList( cols.length + 1 );
params.add( "distinct" );
params.addAll( Arrays.asList( cols ) );
return params;
}
public CountProjection setDistinct() {
distinct = true;
return this;
}
}

View File

@ -1,10 +1,10 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
* Copyright (c) 2008, 2013, 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 Middleware LLC.
* 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
@ -20,9 +20,9 @@
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*
*/
package org.hibernate.criterion;
import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.engine.spi.SessionFactoryImplementor;
@ -38,93 +38,183 @@ import org.hibernate.type.Type;
* @author Gavin King
*/
public interface CriteriaQuery {
/**
* Provides access to the SessionFactory
*
* @return The SessionFactory
*/
public SessionFactoryImplementor getFactory();
/**
* Get the names of the columns mapped by a property path,
* ignoring projection aliases
* @throws org.hibernate.QueryException if the property maps to more than 1 column
* Resolve a property path to the name of the column it maps to. Ignores projection aliases.
*
* @param criteria The overall criteria
* @param propertyPath The property path to resolve
*
* @return The column name
*
* @throws HibernateException if the property maps to more than 1 column, or if the property could not be resolved
*
* @see #getColumns
*/
public String getColumn(Criteria criteria, String propertyPath)
throws HibernateException;
public String getColumn(Criteria criteria, String propertyPath) throws HibernateException;
/**
* Get the names of the columns mapped by a property path,
* ignoring projection aliases
* Resolve a property path to the names of the columns it maps to. Ignores projection aliases
*
* @param criteria The criteria
* @param propertyPath The property path to resolve
*
* @return The column names
*
* @throws HibernateException if the property maps to more than 1 column, or if the property could not be resolved
*/
public String[] getColumns(String propertyPath, Criteria criteria)
throws HibernateException;
public String[] getColumns(String propertyPath, Criteria criteria) throws HibernateException;
/**
* Get the names of the columns mapped by a property path; if the
* property path is not found in criteria, try the "outer" query.
* Projection aliases are ignored.
* Get the names of the columns mapped by a property path; if the property path is not found in criteria, try
* the "outer" query. Projection aliases are ignored.
*
* @param criteria The criteria
* @param propertyPath The property path to resolve
*
* @return The column names
*
* @throws HibernateException if the property could not be resolved
*/
public String[] findColumns(String propertyPath, Criteria criteria)
throws HibernateException;
public String[] findColumns(String propertyPath, Criteria criteria) throws HibernateException;
/**
* Get the type of a property path, ignoring projection aliases
* Get the type of a property path.
*
* @param criteria The criteria
* @param propertyPath The property path to resolve
*
* @return The type
*
* @throws HibernateException if the property could not be resolved
*/
public Type getType(Criteria criteria, String propertyPath)
throws HibernateException;
public Type getType(Criteria criteria, String propertyPath) throws HibernateException;
/**
* Get the names of the columns mapped by a property path
* Get the names of the columns mapped by a property path. Here, the property path can refer to
* a projection alias.
*
* @param criteria The criteria
* @param propertyPath The property path to resolve or projection alias
*
* @return The column names
*
* @throws HibernateException if the property/alias could not be resolved
*/
public String[] getColumnsUsingProjection(Criteria criteria, String propertyPath)
throws HibernateException;
public String[] getColumnsUsingProjection(Criteria criteria, String propertyPath) throws HibernateException;
/**
* Get the type of a property path
* Get the type of a property path. Here, the property path can refer to a projection alias.
*
* @param criteria The criteria
* @param propertyPath The property path to resolve or projection alias
*
* @return The type
*
* @throws HibernateException if the property/alias could not be resolved
*/
public Type getTypeUsingProjection(Criteria criteria, String propertyPath)
throws HibernateException;
public Type getTypeUsingProjection(Criteria criteria, String propertyPath) throws HibernateException;
/**
* Get the a typed value for the given property value.
* Build a typed-value for the property/value combo. Essentially the same as manually building a TypedValue
* using the given value and the resolved type using {@link #getTypeUsingProjection}.
*
* @param criteria The criteria query
* @param propertyPath The property path/alias to resolve to type.
* @param value The value
*
* @return The TypedValue
*
* @throws HibernateException if the property/alias could not be resolved
*/
public TypedValue getTypedValue(Criteria criteria, String propertyPath, Object value)
throws HibernateException;
public TypedValue getTypedValue(Criteria criteria, String propertyPath, Object value) throws HibernateException;
/**
* Get the entity name of an entity
*
* @param criteria The criteria
*
* @return The entity name
*/
public String getEntityName(Criteria criteria);
/**
* Get the entity name of an entity, taking into account
* the qualifier of the property path
* Get the entity name of an entity, taking into account the qualifier of the property path
*
* @param criteria The criteria
* @param propertyPath The property path that (supposedly) references an entity
*
* @return The entity name
*/
public String getEntityName(Criteria criteria, String propertyPath);
/**
* Get the root table alias of an entity
*
* @param criteria The criteria
*
* @return The SQL table alias for the given criteria
*/
public String getSQLAlias(Criteria subcriteria);
public String getSQLAlias(Criteria criteria);
/**
* Get the root table alias of an entity, taking into account
* the qualifier of the property path
*
* @param criteria The criteria
* @param propertyPath The property path whose SQL alias should be returned.
*
* @return The SQL table alias for the given criteria
*/
public String getSQLAlias(Criteria criteria, String propertyPath);
/**
* Get the property name, given a possibly qualified property name
*
* @param propertyName The (possibly qualified) property name
*
* @return The simple property name
*/
public String getPropertyName(String propertyName);
/**
* Get the identifier column names of this entity
*
* @param criteria The criteria
*
* @return The identifier column names
*/
public String[] getIdentifierColumns(Criteria subcriteria);
public String[] getIdentifierColumns(Criteria criteria);
/**
* Get the identifier type of this entity
*
* @param criteria The criteria
*
* @return The identifier type.
*/
public Type getIdentifierType(Criteria subcriteria);
public Type getIdentifierType(Criteria criteria);
public TypedValue getTypedIdentifierValue(Criteria subcriteria, Object value);
/**
* Build a TypedValue for the given identifier value.
*
* @param criteria The criteria whose identifier is referenced.
* @param value The identifier value
*
* @return The TypedValue
*/
public TypedValue getTypedIdentifierValue(Criteria criteria, Object value);
/**
* Generate a unique SQL alias
*
* @return The generated alias
*/
public String generateSQLAlias();
}

View File

@ -1,10 +1,10 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
* Copyright (c) 2008, 2013, 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 Middleware LLC.
* 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
@ -20,9 +20,9 @@
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*
*/
package org.hibernate.criterion;
import org.hibernate.sql.JoinType;
import org.hibernate.transform.AliasToEntityMapResultTransformer;
import org.hibernate.transform.DistinctRootEntityResultTransformer;
@ -31,6 +31,8 @@ import org.hibernate.transform.ResultTransformer;
import org.hibernate.transform.RootEntityResultTransformer;
/**
* Commonality between different types of Criteria.
*
* @author Gavin King
*/
public interface CriteriaSpecification {
@ -62,24 +64,27 @@ public interface CriteriaSpecification {
/**
* Specifies joining to an entity based on an inner join.
* @deprecated use {@link JoinType#INNER_JOIN}
*
* @deprecated use {@link org.hibernate.sql.JoinType#INNER_JOIN}
*/
@Deprecated
public static final int INNER_JOIN = org.hibernate.sql.JoinFragment.INNER_JOIN;
public static final int INNER_JOIN = JoinType.INNER_JOIN.getJoinTypeValue();
/**
* Specifies joining to an entity based on a full join.
* @deprecated use {@link JoinType#FULL_JOIN}
*
* @deprecated use {@link org.hibernate.sql.JoinType#FULL_JOIN}
*/
@Deprecated
public static final int FULL_JOIN = org.hibernate.sql.JoinFragment.FULL_JOIN;
public static final int FULL_JOIN = JoinType.FULL_JOIN.getJoinTypeValue();
/**
* Specifies joining to an entity based on a left outer join.
* @deprecated use {@link JoinType#LEFT_OUTER_JOIN}
*
* @deprecated use {@link org.hibernate.sql.JoinType#LEFT_OUTER_JOIN}
*/
@Deprecated
public static final int LEFT_JOIN = org.hibernate.sql.JoinFragment.LEFT_OUTER_JOIN;
public static final int LEFT_JOIN = JoinType.LEFT_OUTER_JOIN.getJoinTypeValue();
}

View File

@ -1,10 +1,10 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
* Copyright (c) 2008, 2013, 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 Middleware LLC.
* 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
@ -20,14 +20,13 @@
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*
*/
package org.hibernate.criterion;
import java.io.Serializable;
import org.hibernate.Criteria;
import org.hibernate.FetchMode;
import org.hibernate.HibernateException;
import org.hibernate.LockMode;
import org.hibernate.Session;
import org.hibernate.engine.spi.SessionImplementor;
@ -36,29 +35,36 @@ import org.hibernate.sql.JoinType;
import org.hibernate.transform.ResultTransformer;
/**
* Some applications need to create criteria queries in "detached
* mode", where the Hibernate session is not available. This class
* may be instantiated anywhere, and then a <literal>Criteria</literal>
* may be obtained by passing a session to
* <literal>getExecutableCriteria()</literal>. All methods have the
* same semantics and behavior as the corresponding methods of the
* <literal>Criteria</literal> interface.
* Models a detached form of a Criteria (not associated with a Session).
*
* Some applications need to create criteria queries in "detached mode", where the Hibernate Session is
* not available. Applications would create a DetachableCriteria to describe the query, and then later
* associated it with a Session to obtain the "executable" Criteria:
* <code>
* DetachedCriteria detached = new DetachedCriteria();
* ...
* Criteria criteria = detached.getExecutableCriteria( session );
* ...
* criteria.list();
* </code>
*
* All methods have the same semantics and behavior as the corresponding methods of the Criteria interface.
*
* @author Gavin King
*
* @see org.hibernate.Criteria
* @author Gavin King
*/
public class DetachedCriteria implements CriteriaSpecification, Serializable {
private final CriteriaImpl impl;
private final Criteria criteria;
protected DetachedCriteria(String entityName) {
impl = new CriteriaImpl(entityName, null);
impl = new CriteriaImpl( entityName, null );
criteria = impl;
}
protected DetachedCriteria(String entityName, String alias) {
impl = new CriteriaImpl(entityName, alias, null);
impl = new CriteriaImpl( entityName, alias, null );
criteria = impl;
}
@ -68,154 +74,373 @@ public class DetachedCriteria implements CriteriaSpecification, Serializable {
}
/**
* Get an executable instance of <literal>Criteria</literal>,
* to actually run the query.
* Get an executable instance of Criteria to actually run the query.
*
* @param session The session to associate the built Criteria with
*
* @return The "executable" Criteria
*/
public Criteria getExecutableCriteria(Session session) {
impl.setSession( ( SessionImplementor ) session );
impl.setSession( (SessionImplementor) session );
return impl;
}
public static DetachedCriteria forEntityName(String entityName) {
return new DetachedCriteria(entityName);
}
public static DetachedCriteria forEntityName(String entityName, String alias) {
return new DetachedCriteria(entityName, alias);
}
public static DetachedCriteria forClass(Class clazz) {
return new DetachedCriteria( clazz.getName() );
}
public static DetachedCriteria forClass(Class clazz, String alias) {
return new DetachedCriteria( clazz.getName() , alias );
}
public DetachedCriteria add(Criterion criterion) {
criteria.add(criterion);
return this;
}
public DetachedCriteria addOrder(Order order) {
criteria.addOrder(order);
return this;
}
public DetachedCriteria createAlias(String associationPath, String alias)
throws HibernateException {
criteria.createAlias(associationPath, alias);
return this;
}
public DetachedCriteria createCriteria(String associationPath, String alias)
throws HibernateException {
return new DetachedCriteria( impl, criteria.createCriteria(associationPath, alias) );
}
public DetachedCriteria createCriteria(String associationPath)
throws HibernateException {
return new DetachedCriteria( impl, criteria.createCriteria(associationPath) );
}
/**
* Obtain the alias associated with this DetachedCriteria
*
* @return The alias
*/
public String getAlias() {
return criteria.getAlias();
}
public DetachedCriteria setFetchMode(String associationPath, FetchMode mode)
throws HibernateException {
criteria.setFetchMode(associationPath, mode);
return this;
}
public DetachedCriteria setProjection(Projection projection) {
criteria.setProjection(projection);
return this;
}
public DetachedCriteria setResultTransformer(ResultTransformer resultTransformer) {
criteria.setResultTransformer(resultTransformer);
return this;
}
public String toString() {
return "DetachableCriteria(" + criteria.toString() + ')';
}
/**
* Retrieve the CriteriaImpl used internally to hold the DetachedCriteria state
*
* @return The internally maintained CriteriaImpl
*/
CriteriaImpl getCriteriaImpl() {
return impl;
}
public DetachedCriteria createAlias(String associationPath, String alias, JoinType joinType) throws HibernateException {
criteria.createAlias(associationPath, alias, joinType);
return this;
}
/**
* Static builder to create a DetachedCriteria for the given entity.
*
* @param entityName The name of the entity to create a DetachedCriteria for
*
* @return The DetachedCriteria
*/
@SuppressWarnings("UnusedDeclaration")
public static DetachedCriteria forEntityName(String entityName) {
return new DetachedCriteria( entityName );
}
public DetachedCriteria createAlias(String associationPath, String alias, JoinType joinType, Criterion withClause) throws HibernateException {
criteria.createAlias(associationPath, alias, joinType, withClause);
/**
* Static builder to create a DetachedCriteria for the given entity.
*
* @param entityName The name of the entity to create a DetachedCriteria for
* @param alias The alias to apply to the entity
*
* @return The DetachedCriteria
*/
@SuppressWarnings("UnusedDeclaration")
public static DetachedCriteria forEntityName(String entityName, String alias) {
return new DetachedCriteria( entityName, alias );
}
/**
* Static builder to create a DetachedCriteria for the given entity, by its Class.
*
* @param clazz The entity class
*
* @return The DetachedCriteria
*/
public static DetachedCriteria forClass(Class clazz) {
return new DetachedCriteria( clazz.getName() );
}
/**
* Static builder to create a DetachedCriteria for the given entity, by its Class.
*
* @param clazz The entity class
* @param alias The alias to apply to the entity
*
* @return The DetachedCriteria
*/
public static DetachedCriteria forClass(Class clazz, String alias) {
return new DetachedCriteria( clazz.getName() , alias );
}
/**
* Add a restriction
*
* @param criterion The restriction
*
* @return {@code this}, for method chaining
*/
public DetachedCriteria add(Criterion criterion) {
criteria.add( criterion );
return this;
}
public DetachedCriteria createCriteria(String associationPath, JoinType joinType) throws HibernateException {
return new DetachedCriteria(impl, criteria.createCriteria(associationPath, joinType));
}
public DetachedCriteria createCriteria(String associationPath, String alias, JoinType joinType) throws HibernateException {
return new DetachedCriteria(impl, criteria.createCriteria(associationPath, alias, joinType));
}
public DetachedCriteria createCriteria(String associationPath, String alias, JoinType joinType, Criterion withClause) throws HibernateException {
return new DetachedCriteria(impl, criteria.createCriteria(associationPath, alias, joinType, withClause));
/**
* Adds an ordering
*
* @param order The ordering
*
* @return {@code this}, for method chaining
*/
public DetachedCriteria addOrder(Order order) {
criteria.addOrder( order );
return this;
}
/**
* Set the fetch mode for a given association
*
* @param associationPath The association path
* @param mode The fetch mode to apply
*
* @return {@code this}, for method chaining
*/
public DetachedCriteria setFetchMode(String associationPath, FetchMode mode) {
criteria.setFetchMode( associationPath, mode );
return this;
}
/**
* Set the projection to use.
*
* @param projection The projection to use
*
* @return {@code this}, for method chaining
*/
public DetachedCriteria setProjection(Projection projection) {
criteria.setProjection( projection );
return this;
}
/**
* Set the result transformer to use.
*
* @param resultTransformer The result transformer to use
*
* @return {@code this}, for method chaining
*/
public DetachedCriteria setResultTransformer(ResultTransformer resultTransformer) {
criteria.setResultTransformer( resultTransformer );
return this;
}
/**
* Creates an association path alias within this DetachedCriteria. The alias can then be used in further
* alias creations or restrictions, etc.
*
* @param associationPath The association path
* @param alias The alias to apply to that association path
*
* @return {@code this}, for method chaining
*/
public DetachedCriteria createAlias(String associationPath, String alias) {
criteria.createAlias( associationPath, alias );
return this;
}
/**
* Creates an association path alias within this DetachedCriteria specifying the type of join. The alias
* can then be used in further alias creations or restrictions, etc.
*
* @param associationPath The association path
* @param alias The alias to apply to that association path
* @param joinType The type of join to use
*
* @return {@code this}, for method chaining
*/
public DetachedCriteria createAlias(String associationPath, String alias, JoinType joinType) {
criteria.createAlias( associationPath, alias, joinType );
return this;
}
/**
* Creates an association path alias within this DetachedCriteria specifying the type of join. The alias
* can then be used in further alias creations or restrictions, etc.
*
* @param associationPath The association path
* @param alias The alias to apply to that association path
* @param joinType The type of join to use
* @param withClause An additional restriction on the join
*
* @return {@code this}, for method chaining
*/
public DetachedCriteria createAlias(String associationPath, String alias, JoinType joinType, Criterion withClause) {
criteria.createAlias( associationPath, alias, joinType, withClause );
return this;
}
/**
* Deprecated!
*
* @param associationPath The association path
* @param alias The alias to apply to that association path
* @param joinType The type of join to use
*
* @return {@code this}, for method chaining
*
* @deprecated use {@link #createAlias(String, String, JoinType)}
*/
@Deprecated
public DetachedCriteria createAlias(String associationPath, String alias, int joinType) throws HibernateException {
return createAlias( associationPath, alias, JoinType.parse( joinType ) );
}
public DetachedCriteria createAlias(String associationPath, String alias, int joinType) {
return createAlias( associationPath, alias, JoinType.parse( joinType ) );
}
/**
* Deprecated!
*
* @param associationPath The association path
* @param alias The alias to apply to that association path
* @param joinType The type of join to use
* @param withClause An additional restriction on the join
*
* @return {@code this}, for method chaining
*
* @deprecated use {@link #createAlias(String, String, JoinType, Criterion)}
*/
@Deprecated
public DetachedCriteria createAlias(String associationPath, String alias, int joinType, Criterion withClause) throws HibernateException {
public DetachedCriteria createAlias(String associationPath, String alias, int joinType, Criterion withClause) {
return createAlias( associationPath, alias, JoinType.parse( joinType ), withClause );
}
/**
* Creates an nested DetachedCriteria representing the association path.
*
* @param associationPath The association path
* @param alias The alias to apply to that association path
*
* @return the newly created, nested DetachedCriteria
*/
public DetachedCriteria createCriteria(String associationPath, String alias) {
return new DetachedCriteria( impl, criteria.createCriteria( associationPath, alias ) );
}
/**
* Creates an nested DetachedCriteria representing the association path.
*
* @param associationPath The association path
*
* @return the newly created, nested DetachedCriteria
*/
public DetachedCriteria createCriteria(String associationPath) {
return new DetachedCriteria( impl, criteria.createCriteria( associationPath ) );
}
/**
* Creates an nested DetachedCriteria representing the association path, specifying the type of join to use.
*
* @param associationPath The association path
* @param joinType The type of join to use
*
* @return the newly created, nested DetachedCriteria
*/
public DetachedCriteria createCriteria(String associationPath, JoinType joinType) {
return new DetachedCriteria( impl, criteria.createCriteria( associationPath, joinType ) );
}
/**
* Creates an nested DetachedCriteria representing the association path, specifying the type of join to use.
*
* @param associationPath The association path
* @param alias The alias to associate with this "join".
* @param joinType The type of join to use
*
* @return the newly created, nested DetachedCriteria
*/
public DetachedCriteria createCriteria(String associationPath, String alias, JoinType joinType) {
return new DetachedCriteria( impl, criteria.createCriteria( associationPath, alias, joinType ) );
}
/**
* Creates an nested DetachedCriteria representing the association path, specifying the type of join to use and
* an additional join restriction.
*
* @param associationPath The association path
* @param alias The alias to associate with this "join".
* @param joinType The type of join to use
* @param withClause The additional join restriction
*
* @return the newly created, nested DetachedCriteria
*/
public DetachedCriteria createCriteria(String associationPath, String alias, JoinType joinType, Criterion withClause) {
return new DetachedCriteria(impl, criteria.createCriteria( associationPath, alias, joinType, withClause ) );
}
/**
* Deprecated!
*
* @param associationPath The association path
* @param joinType The type of join to use
*
* @return the newly created, nested DetachedCriteria
*
* @deprecated use {@link #createCriteria(String, JoinType)}
*/
@Deprecated
public DetachedCriteria createCriteria(String associationPath, int joinType) throws HibernateException {
return createCriteria( associationPath, JoinType.parse( joinType ) );
}
public DetachedCriteria createCriteria(String associationPath, int joinType) {
return createCriteria( associationPath, JoinType.parse( joinType ) );
}
/**
* Deprecated!
*
* @param associationPath The association path
* @param alias The alias
* @param joinType The type of join to use
*
* @return the newly created, nested DetachedCriteria
*
* @deprecated use {@link #createCriteria(String, String, JoinType)}
*/
@Deprecated
public DetachedCriteria createCriteria(String associationPath, String alias, int joinType) throws HibernateException {
return createCriteria( associationPath, alias, JoinType.parse( joinType ) );
}
public DetachedCriteria createCriteria(String associationPath, String alias, int joinType) {
return createCriteria( associationPath, alias, JoinType.parse( joinType ) );
}
/**
* Deprecated!
*
* @param associationPath The association path
* @param alias The alias to associate with this "join".
* @param joinType The type of join to use
* @param withClause The additional join restriction
*
* @return the newly created, nested DetachedCriteria
*
* @deprecated use {@link #createCriteria(String, String, JoinType, Criterion)}
*/
@Deprecated
public DetachedCriteria createCriteria(String associationPath, String alias, int joinType, Criterion withClause) throws HibernateException {
public DetachedCriteria createCriteria(String associationPath, String alias, int joinType, Criterion withClause) {
return createCriteria( associationPath, alias, JoinType.parse( joinType ), withClause );
}
/**
* Set the SQL comment to use.
*
* @param comment The SQL comment to use
*
* @return {@code this}, for method chaining
*/
public DetachedCriteria setComment(String comment) {
criteria.setComment(comment);
return this;
}
criteria.setComment( comment );
return this;
}
public DetachedCriteria setLockMode(LockMode lockMode) {
criteria.setLockMode(lockMode);
return this;
}
/**
* Set the lock mode to use.
*
* @param lockMode The lock mode to use
*
* @return {@code this}, for method chaining
*/
public DetachedCriteria setLockMode(LockMode lockMode) {
criteria.setLockMode( lockMode );
return this;
}
/**
* Set an alias-specific lock mode. The specified lock mode applies only to that alias.
*
* @param alias The alias to apply the lock to
* @param lockMode The lock mode to use.
*
* @return {@code this}, for method chaining
*/
public DetachedCriteria setLockMode(String alias, LockMode lockMode) {
criteria.setLockMode( alias, lockMode );
return this;
}
@Override
public String toString() {
return "DetachableCriteria(" + criteria.toString() + ')';
}
public DetachedCriteria setLockMode(String alias, LockMode lockMode) {
criteria.setLockMode(alias, lockMode);
return this;
}
}

View File

@ -24,10 +24,22 @@
package org.hibernate.criterion;
/**
* Defines a disjunction (OR series).
*
* @author Gavin King
* @author Steve Ebersole
*
* @see Conjunction
*/
public class Disjunction extends Junction {
/**
* Constructs a Disjunction
*/
protected Disjunction() {
super( Nature.OR );
}
protected Disjunction(Criterion[] conditions) {
super( Nature.OR, conditions );
}
}

View File

@ -1,10 +1,10 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
* Copyright (c) 2008, 2013, 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 Middleware LLC.
* 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
@ -20,73 +20,85 @@
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*
*/
package org.hibernate.criterion;
import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.type.Type;
/**
* A wrappedProjection that is a wrapper around other projections to apply distinction.
*
* @author Gavin King
*/
public class Distinct implements EnhancedProjection {
private final Projection wrappedProjection;
private final Projection projection;
public Distinct(Projection proj) {
this.projection = proj;
/**
* Constructs a Distinct
*
* @param wrappedProjection The wrapped projection
*/
public Distinct(Projection wrappedProjection) {
this.wrappedProjection = wrappedProjection;
}
public String toSqlString(Criteria criteria, int position, CriteriaQuery criteriaQuery)
throws HibernateException {
return "distinct " + projection.toSqlString(criteria, position, criteriaQuery);
@Override
public String toSqlString(Criteria criteria, int position, CriteriaQuery criteriaQuery) {
return "distinct " + wrappedProjection.toSqlString( criteria, position, criteriaQuery );
}
public String toGroupSqlString(Criteria criteria, CriteriaQuery criteriaQuery)
throws HibernateException {
return projection.toGroupSqlString(criteria, criteriaQuery);
@Override
public String toGroupSqlString(Criteria criteria, CriteriaQuery criteriaQuery) {
return wrappedProjection.toGroupSqlString( criteria, criteriaQuery );
}
public Type[] getTypes(Criteria criteria, CriteriaQuery criteriaQuery)
throws HibernateException {
return projection.getTypes(criteria, criteriaQuery);
@Override
public Type[] getTypes(Criteria criteria, CriteriaQuery criteriaQuery) {
return wrappedProjection.getTypes( criteria, criteriaQuery );
}
public Type[] getTypes(String alias, Criteria criteria, CriteriaQuery criteriaQuery)
throws HibernateException {
return projection.getTypes(alias, criteria, criteriaQuery);
@Override
public Type[] getTypes(String alias, Criteria criteria, CriteriaQuery criteriaQuery) {
return wrappedProjection.getTypes( alias, criteria, criteriaQuery );
}
@Override
public String[] getColumnAliases(int loc) {
return projection.getColumnAliases(loc);
return wrappedProjection.getColumnAliases( loc );
}
@Override
public String[] getColumnAliases(int loc, Criteria criteria, CriteriaQuery criteriaQuery) {
return projection instanceof EnhancedProjection ?
( ( EnhancedProjection ) projection ).getColumnAliases( loc, criteria, criteriaQuery ) :
getColumnAliases( loc );
return wrappedProjection instanceof EnhancedProjection
? ( (EnhancedProjection) wrappedProjection).getColumnAliases( loc, criteria, criteriaQuery )
: getColumnAliases( loc );
}
@Override
public String[] getColumnAliases(String alias, int loc) {
return projection.getColumnAliases(alias, loc);
return wrappedProjection.getColumnAliases( alias, loc );
}
@Override
public String[] getColumnAliases(String alias, int loc, Criteria criteria, CriteriaQuery criteriaQuery) {
return projection instanceof EnhancedProjection ?
( ( EnhancedProjection ) projection ).getColumnAliases( alias, loc, criteria, criteriaQuery ) :
getColumnAliases( alias, loc );
return wrappedProjection instanceof EnhancedProjection
? ( (EnhancedProjection) wrappedProjection).getColumnAliases( alias, loc, criteria, criteriaQuery )
: getColumnAliases( alias, loc );
}
@Override
public String[] getAliases() {
return projection.getAliases();
return wrappedProjection.getAliases();
}
@Override
public boolean isGrouped() {
return projection.isGrouped();
return wrappedProjection.isGrouped();
}
@Override
public String toString() {
return "distinct " + projection.toString();
return "distinct " + wrappedProjection.toString();
}
}

View File

@ -1,10 +1,10 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
* Copyright (c) 2008, 2013, 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 Middleware LLC.
* 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
@ -20,22 +20,28 @@
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*
*/
package org.hibernate.criterion;
/**
* An expression asserting that a collection property is empty
*
* @author Gavin King
*/
public class EmptyExpression extends AbstractEmptinessExpression implements Criterion {
/**
* Constructs an EmptyExpression
*
* @param propertyName The collection property name
*
* @see Restrictions#isEmpty
*/
protected EmptyExpression(String propertyName) {
super( propertyName );
}
@Override
protected boolean excludeEmpty() {
return false;
}
}

View File

@ -1,10 +1,10 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
* Copyright (c) 2008, 2013, 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 Middleware LLC.
* 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
@ -20,9 +20,9 @@
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*
*/
package org.hibernate.criterion;
import org.hibernate.Criteria;
/**

View File

@ -22,6 +22,7 @@
* Boston, MA 02110-1301 USA
*/
package org.hibernate.criterion;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashSet;
@ -30,7 +31,6 @@ import java.util.Set;
import org.hibernate.Criteria;
import org.hibernate.EntityMode;
import org.hibernate.HibernateException;
import org.hibernate.engine.spi.TypedValue;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.persister.entity.EntityPersister;
@ -39,6 +39,7 @@ import org.hibernate.type.Type;
/**
* Support for query by example.
*
* <pre>
* List results = session.createCriteria(Parent.class)
* .add( Example.create(parent).ignoreCase() )
@ -46,68 +47,57 @@ import org.hibernate.type.Type;
* .add( Example.create( parent.getChild() ) )
* .list();
* </pre>
* "Examples" may be mixed and matched with "Expressions" in the same <tt>Criteria</tt>.
*
* "Examples" may be mixed and matched with "Expressions" in the same Criteria.
*
* @see org.hibernate.Criteria
* @author Gavin King
*/
public class Example implements Criterion {
private final Object entity;
private final Set excludedProperties = new HashSet();
private final Object exampleEntity;
private PropertySelector selector;
private boolean isLikeEnabled;
private Character escapeCharacter;
private boolean isIgnoreCaseEnabled;
private MatchMode matchMode;
private final Set<String> excludedProperties = new HashSet<String>();
/**
* A strategy for choosing property values for inclusion in the query
* criteria
* Create a new Example criterion instance, which includes all non-null properties by default
*
* @param exampleEntity The example bean to use.
*
* @return a new instance of Example
*/
public static interface PropertySelector extends Serializable {
public boolean include(Object propertyValue, String propertyName, Type type);
}
private static final PropertySelector NOT_NULL = new NotNullPropertySelector();
private static final PropertySelector ALL = new AllPropertySelector();
private static final PropertySelector NOT_NULL_OR_ZERO = new NotNullOrZeroPropertySelector();
static final class AllPropertySelector implements PropertySelector {
public boolean include(Object object, String propertyName, Type type) {
return true;
}
private Object readResolve() {
return ALL;
}
}
static final class NotNullPropertySelector implements PropertySelector {
public boolean include(Object object, String propertyName, Type type) {
return object!=null;
}
private Object readResolve() {
return NOT_NULL;
}
}
static final class NotNullOrZeroPropertySelector implements PropertySelector {
public boolean include(Object object, String propertyName, Type type) {
return object!=null && (
!(object instanceof Number) || ( (Number) object ).longValue()!=0
);
}
private Object readResolve() {
return NOT_NULL_OR_ZERO;
public static Example create(Object exampleEntity) {
if ( exampleEntity == null ) {
throw new NullPointerException( "null example entity" );
}
return new Example( exampleEntity, NotNullPropertySelector.INSTANCE );
}
/**
* Set escape character for "like" clause
* Allow subclasses to instantiate as needed.
*
* @param exampleEntity The example bean
* @param selector The property selector to use
*/
protected Example(Object exampleEntity, PropertySelector selector) {
this.exampleEntity = exampleEntity;
this.selector = selector;
}
/**
* Set escape character for "like" clause if like matching was enabled
*
* @param escapeCharacter The escape character
*
* @return {@code this}, for method chaining
*
* @see #enableLike
*/
public Example setEscapeCharacter(Character escapeCharacter) {
this.escapeCharacter = escapeCharacter;
@ -115,7 +105,47 @@ public class Example implements Criterion {
}
/**
* Set the property selector
* Use the "like" operator for all string-valued properties. This form implicitly uses {@link MatchMode#EXACT}
*
* @return {@code this}, for method chaining
*/
public Example enableLike() {
return enableLike( MatchMode.EXACT );
}
/**
* Use the "like" operator for all string-valued properties
*
* @param matchMode The match mode to use.
*
* @return {@code this}, for method chaining
*/
public Example enableLike(MatchMode matchMode) {
this.isLikeEnabled = true;
this.matchMode = matchMode;
return this;
}
/**
* Ignore case for all string-valued properties
*
* @return {@code this}, for method chaining
*/
public Example ignoreCase() {
this.isIgnoreCaseEnabled = true;
return this;
}
/**
* Set the property selector to use.
*
* The property selector operates separate from excluding a property.
*
* @param selector The selector to use
*
* @return {@code this}, for method chaining
*
* @see #excludeProperty
*/
public Example setPropertySelector(PropertySelector selector) {
this.selector = selector;
@ -123,95 +153,63 @@ public class Example implements Criterion {
}
/**
* Exclude zero-valued properties
* Exclude zero-valued properties.
*
* Equivalent to calling {@link #setPropertySelector} passing in {@link NotNullOrZeroPropertySelector#INSTANCE}
*
* @return {@code this}, for method chaining
*
* @see #setPropertySelector
*/
public Example excludeZeroes() {
setPropertySelector(NOT_NULL_OR_ZERO);
setPropertySelector( NotNullOrZeroPropertySelector.INSTANCE );
return this;
}
/**
* Don't exclude null or zero-valued properties
* Include all properties.
*
* Equivalent to calling {@link #setPropertySelector} passing in {@link AllPropertySelector#INSTANCE}
*
* @return {@code this}, for method chaining
*
* @see #setPropertySelector
*/
public Example excludeNone() {
setPropertySelector(ALL);
setPropertySelector( AllPropertySelector.INSTANCE );
return this;
}
/**
* Use the "like" operator for all string-valued properties
*/
public Example enableLike(MatchMode matchMode) {
isLikeEnabled = true;
this.matchMode = matchMode;
return this;
}
/**
* Use the "like" operator for all string-valued properties
*/
public Example enableLike() {
return enableLike(MatchMode.EXACT);
}
/**
* Ignore case for all string-valued properties
*/
public Example ignoreCase() {
isIgnoreCaseEnabled = true;
return this;
}
/**
* Exclude a particular named property
* Exclude a particular property by name.
*
* @param name The name of the property to exclude
*
* @return {@code this}, for method chaining
*
* @see #setPropertySelector
*/
public Example excludeProperty(String name) {
excludedProperties.add(name);
excludedProperties.add( name );
return this;
}
/**
* Create a new instance, which includes all non-null properties
* by default
* @param entity
* @return a new instance of <tt>Example</tt>
*/
public static Example create(Object entity) {
if (entity==null) throw new NullPointerException("null example");
return new Example(entity, NOT_NULL);
}
@Override
public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery) {
final StringBuilder buf = new StringBuilder().append( '(' );
final EntityPersister meta = criteriaQuery.getFactory().getEntityPersister(
criteriaQuery.getEntityName( criteria )
);
final String[] propertyNames = meta.getPropertyNames();
final Type[] propertyTypes = meta.getPropertyTypes();
protected Example(Object entity, PropertySelector selector) {
this.entity = entity;
this.selector = selector;
}
final Object[] propertyValues = meta.getPropertyValues( exampleEntity );
for ( int i=0; i<propertyNames.length; i++ ) {
final Object propertyValue = propertyValues[i];
final String propertyName = propertyNames[i];
public String toString() {
return "example (" + entity + ')';
}
private boolean isPropertyIncluded(Object value, String name, Type type) {
return !excludedProperties.contains(name) &&
!type.isAssociationType() &&
selector.include(value, name, type);
}
public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery)
throws HibernateException {
StringBuilder buf = new StringBuilder().append('(');
EntityPersister meta = criteriaQuery.getFactory().getEntityPersister( criteriaQuery.getEntityName(criteria) );
String[] propertyNames = meta.getPropertyNames();
Type[] propertyTypes = meta.getPropertyTypes();
//TODO: get all properties, not just the fetched ones!
Object[] propertyValues = meta.getPropertyValues( entity );
for (int i=0; i<propertyNames.length; i++) {
Object propertyValue = propertyValues[i];
String propertyName = propertyNames[i];
boolean isPropertyIncluded = i!=meta.getVersionProperty() &&
isPropertyIncluded( propertyValue, propertyName, propertyTypes[i] );
if (isPropertyIncluded) {
final boolean isVersionProperty = i == meta.getVersionProperty();
if ( ! isVersionProperty && isPropertyIncluded( propertyValue, propertyName, propertyTypes[i] ) ) {
if ( propertyTypes[i].isComponentType() ) {
appendComponentCondition(
propertyName,
@ -233,61 +231,72 @@ public class Example implements Criterion {
}
}
}
if ( buf.length()==1 ) buf.append("1=1"); //yuck!
return buf.append(')').toString();
if ( buf.length()==1 ) {
buf.append( "1=1" );
}
return buf.append( ')' ).toString();
}
private static final Object[] TYPED_VALUES = new TypedValue[0];
@SuppressWarnings("SimplifiableIfStatement")
private boolean isPropertyIncluded(Object value, String name, Type type) {
if ( excludedProperties.contains( name ) ) {
// was explicitly excluded
return false;
}
public TypedValue[] getTypedValues(Criteria criteria, CriteriaQuery criteriaQuery)
throws HibernateException {
if ( type.isAssociationType() ) {
// associations are implicitly excluded
return false;
}
EntityPersister meta = criteriaQuery.getFactory()
.getEntityPersister( criteriaQuery.getEntityName(criteria) );
String[] propertyNames = meta.getPropertyNames();
Type[] propertyTypes = meta.getPropertyTypes();
//TODO: get all properties, not just the fetched ones!
Object[] values = meta.getPropertyValues( entity );
List list = new ArrayList();
for (int i=0; i<propertyNames.length; i++) {
Object value = values[i];
Type type = propertyTypes[i];
String name = propertyNames[i];
return selector.include( value, name, type );
}
boolean isPropertyIncluded = i!=meta.getVersionProperty() &&
isPropertyIncluded(value, name, type);
@Override
public TypedValue[] getTypedValues(Criteria criteria, CriteriaQuery criteriaQuery) {
final EntityPersister meta = criteriaQuery.getFactory().getEntityPersister(
criteriaQuery.getEntityName( criteria )
);
final String[] propertyNames = meta.getPropertyNames();
final Type[] propertyTypes = meta.getPropertyTypes();
if (isPropertyIncluded) {
final Object[] values = meta.getPropertyValues( exampleEntity );
final List<TypedValue> list = new ArrayList<TypedValue>();
for ( int i=0; i<propertyNames.length; i++ ) {
final Object value = values[i];
final Type type = propertyTypes[i];
final String name = propertyNames[i];
final boolean isVersionProperty = i == meta.getVersionProperty();
if ( ! isVersionProperty && isPropertyIncluded( value, name, type ) ) {
if ( propertyTypes[i].isComponentType() ) {
addComponentTypedValues(name, value, (CompositeType) type, list, criteria, criteriaQuery);
addComponentTypedValues( name, value, (CompositeType) type, list, criteria, criteriaQuery );
}
else {
addPropertyTypedValue(value, type, list);
addPropertyTypedValue( value, type, list );
}
}
}
return (TypedValue[]) list.toArray(TYPED_VALUES);
return list.toArray( new TypedValue[ list.size() ] );
}
private EntityMode getEntityMode(Criteria criteria, CriteriaQuery criteriaQuery) {
EntityPersister meta = criteriaQuery.getFactory()
.getEntityPersister( criteriaQuery.getEntityName(criteria) );
EntityMode result = meta.getEntityMode();
if ( ! meta.getEntityMetamodel().getTuplizer().isInstance( entity ) ) {
throw new ClassCastException( entity.getClass().getName() );
}
return result;
}
protected void addPropertyTypedValue(Object value, Type type, List list) {
if ( value!=null ) {
protected void addPropertyTypedValue(Object value, Type type, List<TypedValue> list) {
if ( value != null ) {
if ( value instanceof String ) {
String string = (String) value;
if (isIgnoreCaseEnabled) string = string.toLowerCase();
if (isLikeEnabled) string = matchMode.toMatchString(string);
if ( isIgnoreCaseEnabled ) {
string = string.toLowerCase();
}
if ( isLikeEnabled ) {
string = matchMode.toMatchString( string );
}
value = string;
}
list.add( new TypedValue(type, value, null) );
list.add( new TypedValue( type, value ) );
}
}
@ -295,101 +304,197 @@ public class Example implements Criterion {
String path,
Object component,
CompositeType type,
List list,
List<TypedValue> list,
Criteria criteria,
CriteriaQuery criteriaQuery)
throws HibernateException {
if (component!=null) {
String[] propertyNames = type.getPropertyNames();
Type[] subtypes = type.getSubtypes();
Object[] values = type.getPropertyValues( component, getEntityMode(criteria, criteriaQuery) );
for (int i=0; i<propertyNames.length; i++) {
Object value = values[i];
Type subtype = subtypes[i];
String subpath = StringHelper.qualify( path, propertyNames[i] );
if ( isPropertyIncluded(value, subpath, subtype) ) {
CriteriaQuery criteriaQuery) {
if ( component != null ) {
final String[] propertyNames = type.getPropertyNames();
final Type[] subtypes = type.getSubtypes();
final Object[] values = type.getPropertyValues( component, getEntityMode( criteria, criteriaQuery ) );
for ( int i=0; i<propertyNames.length; i++ ) {
final Object value = values[i];
final Type subtype = subtypes[i];
final String subpath = StringHelper.qualify( path, propertyNames[i] );
if ( isPropertyIncluded( value, subpath, subtype ) ) {
if ( subtype.isComponentType() ) {
addComponentTypedValues(subpath, value, (CompositeType) subtype, list, criteria, criteriaQuery);
addComponentTypedValues( subpath, value, (CompositeType) subtype, list, criteria, criteriaQuery );
}
else {
addPropertyTypedValue(value, subtype, list);
addPropertyTypedValue( value, subtype, list );
}
}
}
}
}
private EntityMode getEntityMode(Criteria criteria, CriteriaQuery criteriaQuery) {
final EntityPersister meta = criteriaQuery.getFactory().getEntityPersister(
criteriaQuery.getEntityName( criteria )
);
final EntityMode result = meta.getEntityMode();
if ( ! meta.getEntityMetamodel().getTuplizer().isInstance( exampleEntity ) ) {
throw new ClassCastException( exampleEntity.getClass().getName() );
}
return result;
}
protected void appendPropertyCondition(
String propertyName,
Object propertyValue,
Criteria criteria,
CriteriaQuery cq,
StringBuilder buf)
throws HibernateException {
Criterion crit;
if ( propertyValue!=null ) {
boolean isString = propertyValue instanceof String;
String propertyName,
Object propertyValue,
Criteria criteria,
CriteriaQuery cq,
StringBuilder buf) {
final Criterion condition;
if ( propertyValue != null ) {
final boolean isString = propertyValue instanceof String;
if ( isLikeEnabled && isString ) {
crit = new LikeExpression(
condition = new LikeExpression(
propertyName,
( String ) propertyValue,
(String) propertyValue,
matchMode,
escapeCharacter,
isIgnoreCaseEnabled
);
}
else {
crit = new SimpleExpression( propertyName, propertyValue, "=", isIgnoreCaseEnabled && isString );
condition = new SimpleExpression( propertyName, propertyValue, "=", isIgnoreCaseEnabled && isString );
}
}
else {
crit = new NullExpression(propertyName);
condition = new NullExpression(propertyName);
}
final String conditionFragment = condition.toSqlString( criteria, cq );
if ( conditionFragment.trim().length() > 0 ) {
if ( buf.length() > 1 ) {
buf.append( " and " );
}
buf.append( conditionFragment );
}
String critCondition = crit.toSqlString(criteria, cq);
if ( buf.length()>1 && critCondition.trim().length()>0 ) buf.append(" and ");
buf.append(critCondition);
}
protected void appendComponentCondition(
String path,
Object component,
CompositeType type,
Criteria criteria,
CriteriaQuery criteriaQuery,
StringBuilder buf)
throws HibernateException {
if (component!=null) {
String[] propertyNames = type.getPropertyNames();
Object[] values = type.getPropertyValues( component, getEntityMode(criteria, criteriaQuery) );
Type[] subtypes = type.getSubtypes();
for (int i=0; i<propertyNames.length; i++) {
String subpath = StringHelper.qualify( path, propertyNames[i] );
Object value = values[i];
if ( isPropertyIncluded( value, subpath, subtypes[i] ) ) {
Type subtype = subtypes[i];
String path,
Object component,
CompositeType type,
Criteria criteria,
CriteriaQuery criteriaQuery,
StringBuilder buf) {
if ( component != null ) {
final String[] propertyNames = type.getPropertyNames();
final Object[] values = type.getPropertyValues( component, getEntityMode( criteria, criteriaQuery ) );
final Type[] subtypes = type.getSubtypes();
for ( int i=0; i<propertyNames.length; i++ ) {
final String subPath = StringHelper.qualify( path, propertyNames[i] );
final Object value = values[i];
if ( isPropertyIncluded( value, subPath, subtypes[i] ) ) {
final Type subtype = subtypes[i];
if ( subtype.isComponentType() ) {
appendComponentCondition(
subpath,
value,
(CompositeType) subtype,
criteria,
criteriaQuery,
buf
subPath,
value,
(CompositeType) subtype,
criteria,
criteriaQuery,
buf
);
}
else {
appendPropertyCondition(
subpath,
value,
criteria,
criteriaQuery,
buf
subPath,
value,
criteria,
criteriaQuery,
buf
);
}
}
}
}
}
@Override
public String toString() {
return "example (" + exampleEntity + ')';
}
// PropertySelector definitions ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/**
* A strategy for choosing property values for inclusion in the query criteria. Note that
* property selection (for inclusion) operates separately from excluding a property. Excluded
* properties are not even passed in to the PropertySelector for consideration.
*/
public static interface PropertySelector extends Serializable {
/**
* Determine whether the given property should be used in the criteria.
*
* @param propertyValue The property value (from the example bean)
* @param propertyName The name of the property
* @param type The type of the property
*
* @return {@code true} indicates the property should be included; {@code false} indiates it should not.
*/
public boolean include(Object propertyValue, String propertyName, Type type);
}
/**
* Property selector that includes all properties
*/
public static final class AllPropertySelector implements PropertySelector {
/**
* Singleton access
*/
public static final AllPropertySelector INSTANCE = new AllPropertySelector();
@Override
public boolean include(Object object, String propertyName, Type type) {
return true;
}
private Object readResolve() {
return INSTANCE;
}
}
/**
* Property selector that includes only properties that are not {@code null}
*/
public static final class NotNullPropertySelector implements PropertySelector {
/**
* Singleton access
*/
public static final NotNullPropertySelector INSTANCE = new NotNullPropertySelector();
@Override
public boolean include(Object object, String propertyName, Type type) {
return object!=null;
}
private Object readResolve() {
return INSTANCE;
}
}
/**
* Property selector that includes only properties that are not {@code null} and non-zero (if numeric)
*/
public static final class NotNullOrZeroPropertySelector implements PropertySelector {
/**
* Singleton access
*/
public static final NotNullOrZeroPropertySelector INSTANCE = new NotNullOrZeroPropertySelector();
@Override
public boolean include(Object object, String propertyName, Type type) {
return object != null
&& ( !(object instanceof Number) || ( (Number) object ).longValue()!=0
);
}
private Object readResolve() {
return INSTANCE;
}
}
}

View File

@ -1,10 +1,10 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
* Copyright (c) 2008, 2013, 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 Middleware LLC.
* 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
@ -20,21 +20,32 @@
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*
*/
package org.hibernate.criterion;
import org.hibernate.Criteria;
/**
* Expression that checks the existence of rows in a sub-query
*
* @author Gavin King
*/
public class ExistsSubqueryExpression extends SubqueryExpression {
/**
* Constructs the ExistsSubqueryExpression
*
* @param quantifier The "exists"/"not exists" sub-query quantifier
* @param dc The DetachedCriteria representing the sub-query
*
* @see Subqueries#exists
* @see Subqueries#notExists
*/
protected ExistsSubqueryExpression(String quantifier, DetachedCriteria dc) {
super( null, quantifier, dc );
}
@Override
protected String toLeftSqlString(Criteria criteria, CriteriaQuery outerQuery) {
return "";
}
protected ExistsSubqueryExpression(String quantifier, DetachedCriteria dc) {
super(null, quantifier, dc);
}
}

View File

@ -1,10 +1,10 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
* Copyright (c) 2008, 2013, 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 Middleware LLC.
* 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
@ -20,66 +20,72 @@
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*
*/
package org.hibernate.criterion;
import org.hibernate.internal.util.collections.ArrayHelper;
import org.hibernate.type.Type;
/**
* @deprecated Use <tt>Restrictions</tt>.
* @see Restrictions
* Factory for Criterion objects. Deprecated!
*
* @author Gavin King
*
* @see Restrictions
*
* @deprecated Use {@link Restrictions} instead
*/
@Deprecated
public final class Expression extends Restrictions {
/**
* Apply a constraint expressed in SQL, with JDBC parameters. Any occurrences of <tt>{alias}</tt> will be
* replaced by the table alias.
*
* @param sql The sql
* @param values The parameter values
* @param types The parameter types
*
* @return Criterion
*
* @deprecated use {@link org.hibernate.criterion.Restrictions#sqlRestriction(String, Object[], Type[])}
*/
@Deprecated
public static Criterion sql(String sql, Object[] values, Type[] types) {
return new SQLCriterion( sql, values, types );
}
/**
* Apply a constraint expressed in SQL, with a JDBC parameter. Any occurrences of <tt>{alias}</tt> will be
* replaced by the table alias.
*
* @param sql The sql
* @param value The parameter value
* @param type The parameter type
*
* @return Criterion
*
* @deprecated use {@link org.hibernate.criterion.Restrictions#sqlRestriction(String, Object, Type)}
*/
@Deprecated
public static Criterion sql(String sql, Object value, Type type) {
return new SQLCriterion( sql, value, type );
}
/**
* Apply a constraint expressed in SQL with no parameters. Any occurrences of <tt>{alias}</tt> will be
* replaced by the table alias.
*
* @param sql The sql
*
* @return Criterion
*
* @deprecated use {@link org.hibernate.criterion.Restrictions#sqlRestriction(String)}
*/
@Deprecated
public static Criterion sql(String sql) {
return new SQLCriterion( sql );
}
private Expression() {
//cannot be instantiated
}
/**
* Apply a constraint expressed in SQL, with the given JDBC
* parameters. Any occurrences of <tt>{alias}</tt> will be
* replaced by the table alias.
*
* @deprecated use {@link org.hibernate.criterion.Restrictions#sqlRestriction(String, Object[], Type[])}
* @param sql
* @param values
* @param types
* @return Criterion
*/
@Deprecated
public static Criterion sql(String sql, Object[] values, Type[] types) {
return new SQLCriterion(sql, values, types);
}
/**
* Apply a constraint expressed in SQL, with the given JDBC
* parameter. Any occurrences of <tt>{alias}</tt> will be replaced
* by the table alias.
*
* @deprecated use {@link org.hibernate.criterion.Restrictions#sqlRestriction(String, Object, Type)}
* @param sql
* @param value
* @param type
* @return Criterion
*/
@Deprecated
public static Criterion sql(String sql, Object value, Type type) {
return new SQLCriterion(sql, new Object[] { value }, new Type[] { type } );
}
/**
* Apply a constraint expressed in SQL. Any occurrences of <tt>{alias}</tt>
* will be replaced by the table alias.
*
* @deprecated use {@link org.hibernate.criterion.Restrictions#sqlRestriction(String)}
* @param sql
* @return Criterion
*/
@Deprecated
public static Criterion sql(String sql) {
return new SQLCriterion(sql, ArrayHelper.EMPTY_OBJECT_ARRAY, ArrayHelper.EMPTY_TYPE_ARRAY);
}
}

View File

@ -1,10 +1,10 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
* Copyright (c) 2008, 2013, 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 Middleware LLC.
* 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
@ -20,46 +20,49 @@
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*
*/
package org.hibernate.criterion;
import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.engine.spi.TypedValue;
import org.hibernate.internal.util.StringHelper;
/**
* An identifier constraint
*
* @author Gavin King
*/
public class IdentifierEqExpression implements Criterion {
private final Object value;
/**
* Constructs an IdentifierEqExpression
*
* @param value The identifier value
*
* @see Restrictions#idEq
*/
protected IdentifierEqExpression(Object value) {
this.value = value;
}
public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery)
throws HibernateException {
@Override
public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery) {
final String[] columns = criteriaQuery.getIdentifierColumns( criteria );
String[] columns = criteriaQuery.getIdentifierColumns(criteria);
String result = StringHelper.join(
" and ",
StringHelper.suffix( columns, " = ?" )
);
if (columns.length>1) result = '(' + result + ')';
String result = StringHelper.join( " and ", StringHelper.suffix( columns, " = ?" ) );
if ( columns.length > 1) {
result = '(' + result + ')';
}
return result;
//TODO: get SQL rendering out of this package!
}
public TypedValue[] getTypedValues(Criteria criteria, CriteriaQuery criteriaQuery)
throws HibernateException {
return new TypedValue[] { criteriaQuery.getTypedIdentifierValue(criteria, value) };
@Override
public TypedValue[] getTypedValues(Criteria criteria, CriteriaQuery criteriaQuery) {
return new TypedValue[] { criteriaQuery.getTypedIdentifierValue( criteria, value ) };
}
@Override
public String toString() {
return "id = " + value;
}

View File

@ -1,10 +1,10 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
* Copyright (c) 2008, 2013, 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 Middleware LLC.
* 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
@ -20,66 +20,77 @@
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*
*/
package org.hibernate.criterion;
import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.type.Type;
/**
* A property value, or grouped property value
*
* @author Gavin King
*/
public class IdentifierProjection extends SimpleProjection {
private boolean grouped;
protected IdentifierProjection(boolean grouped) {
/**
* Constructs a non-grouped identifier projection
*
* @see Projections#id
*/
protected IdentifierProjection() {
this( false );
}
/**
*
* Not used externally
*/
private IdentifierProjection(boolean grouped) {
this.grouped = grouped;
}
protected IdentifierProjection() {
this(false);
@Override
public Type[] getTypes(Criteria criteria, CriteriaQuery criteriaQuery) {
return new Type[] { criteriaQuery.getIdentifierType( criteria ) };
}
public String toString() {
return "id";
}
public Type[] getTypes(Criteria criteria, CriteriaQuery criteriaQuery)
throws HibernateException {
return new Type[] { criteriaQuery.getIdentifierType(criteria) };
}
public String toSqlString(Criteria criteria, int position, CriteriaQuery criteriaQuery)
throws HibernateException {
StringBuilder buf = new StringBuilder();
String[] cols = criteriaQuery.getIdentifierColumns(criteria);
@Override
public String toSqlString(Criteria criteria, int position, CriteriaQuery criteriaQuery) {
final StringBuilder buf = new StringBuilder();
final String[] cols = criteriaQuery.getIdentifierColumns( criteria );
for ( int i=0; i<cols.length; i++ ) {
buf.append( cols[i] )
.append(" as y")
.append(position + i)
.append('_');
if (i < cols.length -1)
buf.append(", ");
.append( " as y" )
.append( position + i )
.append( '_' );
if ( i < cols.length -1 ) {
buf.append( ", " );
}
}
return buf.toString();
}
@Override
public boolean isGrouped() {
return grouped;
}
public String toGroupSqlString(Criteria criteria, CriteriaQuery criteriaQuery)
throws HibernateException {
if (!grouped) {
return super.toGroupSqlString(criteria, criteriaQuery);
@Override
public String toGroupSqlString(Criteria criteria, CriteriaQuery criteriaQuery) {
if ( !grouped ) {
return super.toGroupSqlString( criteria, criteriaQuery );
}
else {
return StringHelper.join( ", ", criteriaQuery.getIdentifierColumns(criteria) );
return StringHelper.join( ", ", criteriaQuery.getIdentifierColumns( criteria ) );
}
}
@Override
public String toString() {
return "id";
}
}

View File

@ -32,13 +32,15 @@ import org.hibernate.dialect.PostgreSQLDialect;
import org.hibernate.engine.spi.TypedValue;
/**
* A case-insensitive "like"
* A case-insensitive "like".
*
* @author Gavin King
*
* @deprecated Prefer {@link LikeExpression} which now has case-insensitivity capability.
*/
@Deprecated
@SuppressWarnings({"deprecation", "UnusedDeclaration"})
public class IlikeExpression implements Criterion {
private final String propertyName;
private final Object value;
@ -51,10 +53,10 @@ public class IlikeExpression implements Criterion {
this( propertyName, matchMode.toMatchString( value ) );
}
public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery)
throws HibernateException {
Dialect dialect = criteriaQuery.getFactory().getDialect();
String[] columns = criteriaQuery.findColumns( propertyName, criteria );
@Override
public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery) {
final Dialect dialect = criteriaQuery.getFactory().getDialect();
final String[] columns = criteriaQuery.findColumns( propertyName, criteria );
if ( columns.length != 1 ) {
throw new HibernateException( "ilike may only be used with single-column properties" );
}
@ -64,12 +66,10 @@ public class IlikeExpression implements Criterion {
else {
return dialect.getLowercaseFunction() + '(' + columns[0] + ") like ?";
}
//TODO: get SQL rendering out of this package!
}
public TypedValue[] getTypedValues(Criteria criteria, CriteriaQuery criteriaQuery)
throws HibernateException {
@Override
public TypedValue[] getTypedValues(Criteria criteria, CriteriaQuery criteriaQuery) {
return new TypedValue[] {
criteriaQuery.getTypedValue(
criteria,
@ -79,6 +79,7 @@ public class IlikeExpression implements Criterion {
};
}
@Override
public String toString() {
return propertyName + " ilike " + value;
}

View File

@ -22,11 +22,11 @@
* Boston, MA 02110-1301 USA
*/
package org.hibernate.criterion;
import java.util.ArrayList;
import org.hibernate.Criteria;
import org.hibernate.EntityMode;
import org.hibernate.HibernateException;
import org.hibernate.engine.spi.TypedValue;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.type.CompositeType;
@ -34,70 +34,80 @@ import org.hibernate.type.Type;
/**
* Constrains the property to a specified list of values
*
* @author Gavin King
*/
public class InExpression implements Criterion {
private final String propertyName;
private final Object[] values;
/**
* Constructs an InExpression
*
* @param propertyName The property name to check
* @param values The values to check against
*
* @see Restrictions#in(String, java.util.Collection)
* @see Restrictions#in(String, Object[])
*/
protected InExpression(String propertyName, Object[] values) {
this.propertyName = propertyName;
this.values = values;
}
public String toSqlString( Criteria criteria, CriteriaQuery criteriaQuery )
throws HibernateException {
String[] columns = criteriaQuery.findColumns(propertyName, criteria);
if ( criteriaQuery.getFactory().getDialect()
.supportsRowValueConstructorSyntaxInInList() || columns.length<=1) {
@Override
public String toSqlString( Criteria criteria, CriteriaQuery criteriaQuery ) {
final String[] columns = criteriaQuery.findColumns( propertyName, criteria );
if ( criteriaQuery.getFactory().getDialect().supportsRowValueConstructorSyntaxInInList() || columns.length <= 1 ) {
String singleValueParam = StringHelper.repeat( "?, ", columns.length - 1 ) + "?";
if ( columns.length > 1 ) {
singleValueParam = '(' + singleValueParam + ')';
}
final String params = values.length > 0
? StringHelper.repeat( singleValueParam + ", ", values.length - 1 ) + singleValueParam
: "";
String cols = StringHelper.join( ", ", columns );
if ( columns.length > 1 ) {
cols = '(' + cols + ')';
}
return cols + " in (" + params + ')';
}
else {
String cols = " ( " + StringHelper.join( " = ? and ", columns ) + "= ? ) ";
cols = values.length > 0
? StringHelper.repeat( cols + "or ", values.length - 1 ) + cols
: "";
cols = " ( " + cols + " ) ";
return cols;
}
}
String singleValueParam = StringHelper.repeat( "?, ",
columns.length - 1 )
+ "?";
if ( columns.length > 1 )
singleValueParam = '(' + singleValueParam + ')';
String params = values.length > 0 ? StringHelper.repeat(
singleValueParam + ", ", values.length - 1 )
+ singleValueParam : "";
String cols = StringHelper.join( ", ", columns );
if ( columns.length > 1 )
cols = '(' + cols + ')';
return cols + " in (" + params + ')';
} else {
String cols = " ( " + StringHelper.join( " = ? and ", columns ) + "= ? ) ";
cols = values.length > 0 ? StringHelper.repeat( cols
+ "or ", values.length - 1 )
+ cols : "";
cols = " ( " + cols + " ) ";
return cols;
}
}
public TypedValue[] getTypedValues(Criteria criteria, CriteriaQuery criteriaQuery)
throws HibernateException {
ArrayList list = new ArrayList();
Type type = criteriaQuery.getTypeUsingProjection(criteria, propertyName);
@Override
public TypedValue[] getTypedValues(Criteria criteria, CriteriaQuery criteriaQuery) {
final ArrayList<TypedValue> list = new ArrayList<TypedValue>();
final Type type = criteriaQuery.getTypeUsingProjection( criteria, propertyName );
if ( type.isComponentType() ) {
CompositeType actype = (CompositeType) type;
Type[] types = actype.getSubtypes();
for ( int j=0; j<values.length; j++ ) {
for ( int i=0; i<types.length; i++ ) {
Object subval = values[j]==null ?
null :
actype.getPropertyValues( values[j], EntityMode.POJO )[i];
list.add( new TypedValue( types[i], subval, EntityMode.POJO ) );
final CompositeType compositeType = (CompositeType) type;
final Type[] subTypes = compositeType.getSubtypes();
for ( Object value : values ) {
for ( int i = 0; i < subTypes.length; i++ ) {
final Object subValue = value == null
? null
: compositeType.getPropertyValues( value, EntityMode.POJO )[i];
list.add( new TypedValue( subTypes[i], subValue ) );
}
}
}
else {
for ( int j=0; j<values.length; j++ ) {
list.add( new TypedValue( type, values[j], EntityMode.POJO ) );
for ( Object value : values ) {
list.add( new TypedValue( type, value ) );
}
}
return (TypedValue[]) list.toArray( new TypedValue[ list.size() ] );
return list.toArray( new TypedValue[ list.size() ] );
}
@Override
public String toString() {
return propertyName + " in (" + StringHelper.toString(values) + ')';
}

View File

@ -1,10 +1,10 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
* Copyright (c) 2008, 2013, 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 Middleware LLC.
* 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
@ -20,9 +20,9 @@
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*
*/
package org.hibernate.criterion;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
@ -38,6 +38,7 @@ import org.hibernate.internal.util.StringHelper;
* associative logical operator
*
* @author Gavin King
* @author Steve Ebersole
*/
public class Junction implements Criterion {
private final Nature nature;
@ -47,6 +48,18 @@ public class Junction implements Criterion {
this.nature = nature;
}
protected Junction(Nature nature, Criterion... criterion) {
this( nature );
Collections.addAll( conditions, criterion );
}
/**
* Adds a criterion to the junction (and/or)
*
* @param criterion The criterion to add
*
* @return {@code this}, for method chaining
*/
public Junction add(Criterion criterion) {
conditions.add( criterion );
return this;
@ -56,15 +69,20 @@ public class Junction implements Criterion {
return nature;
}
/**
* Access the conditions making up the junction
*
* @return the criterion
*/
public Iterable<Criterion> conditions() {
return conditions;
}
@Override
public TypedValue[] getTypedValues(Criteria crit, CriteriaQuery criteriaQuery) throws HibernateException {
ArrayList<TypedValue> typedValues = new ArrayList<TypedValue>();
final ArrayList<TypedValue> typedValues = new ArrayList<TypedValue>();
for ( Criterion condition : conditions ) {
TypedValue[] subValues = condition.getTypedValues( crit, criteriaQuery );
final TypedValue[] subValues = condition.getTypedValues( crit, criteriaQuery );
Collections.addAll( typedValues, subValues );
}
return typedValues.toArray( new TypedValue[ typedValues.size() ] );
@ -76,15 +94,18 @@ public class Junction implements Criterion {
return "1=1";
}
StringBuilder buffer = new StringBuilder().append( '(' );
Iterator itr = conditions.iterator();
final StringBuilder buffer = new StringBuilder().append( '(' );
final Iterator itr = conditions.iterator();
while ( itr.hasNext() ) {
buffer.append( ( (Criterion) itr.next() ).toSqlString( crit, criteriaQuery ) );
if ( itr.hasNext() ) {
buffer.append(' ').append( nature.getOperator() ).append(' ');
buffer.append( ' ' )
.append( nature.getOperator() )
.append( ' ' );
}
}
return buffer.append(')').toString();
return buffer.append( ')' ).toString();
}
@Override
@ -92,11 +113,24 @@ public class Junction implements Criterion {
return '(' + StringHelper.join( ' ' + nature.getOperator() + ' ', conditions.iterator() ) + ')';
}
/**
* The type of junction
*/
public static enum Nature {
/**
* An AND
*/
AND,
OR
;
/**
* An OR
*/
OR;
/**
* The corresponding SQL operator
*
* @return SQL operator
*/
public String getOperator() {
return name().toLowerCase();
}

View File

@ -1,10 +1,10 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
* Copyright (c) 2008, 2013, 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 Middleware LLC.
* 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
@ -20,9 +20,9 @@
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*
*/
package org.hibernate.criterion;
import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.dialect.Dialect;
@ -51,16 +51,12 @@ public class LikeExpression implements Criterion {
this.ignoreCase = ignoreCase;
}
protected LikeExpression(
String propertyName,
String value) {
protected LikeExpression(String propertyName, String value) {
this( propertyName, value, null, false );
}
protected LikeExpression(
String propertyName,
String value,
MatchMode matchMode) {
@SuppressWarnings("UnusedDeclaration")
protected LikeExpression(String propertyName, String value, MatchMode matchMode) {
this( propertyName, matchMode.toMatchString( value ) );
}
@ -73,16 +69,16 @@ public class LikeExpression implements Criterion {
this( propertyName, matchMode.toMatchString( value ), escapeChar, ignoreCase );
}
public String toSqlString(
Criteria criteria,
CriteriaQuery criteriaQuery) throws HibernateException {
Dialect dialect = criteriaQuery.getFactory().getDialect();
String[] columns = criteriaQuery.findColumns(propertyName, criteria);
@Override
public String toSqlString(Criteria criteria,CriteriaQuery criteriaQuery) {
final Dialect dialect = criteriaQuery.getFactory().getDialect();
final String[] columns = criteriaQuery.findColumns( propertyName, criteria );
if ( columns.length != 1 ) {
throw new HibernateException( "Like may only be used with single-column properties" );
}
String escape = escapeChar == null ? "" : " escape \'" + escapeChar + "\'";
String column = columns[0];
final String escape = escapeChar == null ? "" : " escape \'" + escapeChar + "\'";
final String column = columns[0];
if ( ignoreCase ) {
if ( dialect.supportsCaseInsensitiveLike() ) {
return column +" " + dialect.getCaseInsensitiveLike() + " ?" + escape;
@ -96,11 +92,10 @@ public class LikeExpression implements Criterion {
}
}
public TypedValue[] getTypedValues(
Criteria criteria,
CriteriaQuery criteriaQuery) throws HibernateException {
return new TypedValue[] {
criteriaQuery.getTypedValue( criteria, propertyName, ignoreCase ? value.toString().toLowerCase() : value.toString() )
};
@Override
public TypedValue[] getTypedValues(Criteria criteria, CriteriaQuery criteriaQuery) {
final String matchValue = ignoreCase ? value.toString().toLowerCase() : value.toString();
return new TypedValue[] { criteriaQuery.getTypedValue( criteria, propertyName, matchValue ) };
}
}

View File

@ -1,10 +1,10 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
* Copyright (c) 2008, 2013, 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 Middleware LLC.
* 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
@ -20,19 +20,18 @@
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*
*/
package org.hibernate.criterion;
import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.engine.spi.TypedValue;
/**
* Superclass of binary logical expressions
*
* @author Gavin King
*/
public class LogicalExpression implements Criterion {
private final Criterion lhs;
private final Criterion rhs;
private final String op;
@ -43,33 +42,33 @@ public class LogicalExpression implements Criterion {
this.op = op;
}
public TypedValue[] getTypedValues(Criteria criteria, CriteriaQuery criteriaQuery)
throws HibernateException {
@Override
public TypedValue[] getTypedValues(Criteria criteria, CriteriaQuery criteriaQuery) {
final TypedValue[] lhsTypedValues = lhs.getTypedValues( criteria, criteriaQuery );
final TypedValue[] rhsTypedValues = rhs.getTypedValues( criteria, criteriaQuery );
TypedValue[] lhstv = lhs.getTypedValues(criteria, criteriaQuery);
TypedValue[] rhstv = rhs.getTypedValues(criteria, criteriaQuery);
TypedValue[] result = new TypedValue[ lhstv.length + rhstv.length ];
System.arraycopy(lhstv, 0, result, 0, lhstv.length);
System.arraycopy(rhstv, 0, result, lhstv.length, rhstv.length);
final TypedValue[] result = new TypedValue[ lhsTypedValues.length + rhsTypedValues.length ];
System.arraycopy( lhsTypedValues, 0, result, 0, lhsTypedValues.length );
System.arraycopy( rhsTypedValues, 0, result, lhsTypedValues.length, rhsTypedValues.length );
return result;
}
public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery)
throws HibernateException {
return '(' +
lhs.toSqlString(criteria, criteriaQuery) +
' ' +
getOp() +
' ' +
rhs.toSqlString(criteria, criteriaQuery) +
')';
@Override
public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery) {
return '('
+ lhs.toSqlString( criteria, criteriaQuery )
+ ' '
+ getOp()
+ ' '
+ rhs.toSqlString( criteria, criteriaQuery )
+ ')';
}
public String getOp() {
return op;
}
@Override
public String toString() {
return lhs.toString() + ' ' + getOp() + ' ' + rhs.toString();
}

View File

@ -1,10 +1,10 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
* Copyright (c) 2008, 2013, 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 Middleware LLC.
* 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
@ -20,7 +20,6 @@
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*
*/
package org.hibernate.criterion;
@ -36,6 +35,7 @@ public enum MatchMode {
* Match the entire string to the pattern
*/
EXACT {
@Override
public String toMatchString(String pattern) {
return pattern;
}
@ -45,6 +45,7 @@ public enum MatchMode {
* Match the start of the string to the pattern
*/
START {
@Override
public String toMatchString(String pattern) {
return pattern + '%';
}
@ -54,6 +55,7 @@ public enum MatchMode {
* Match the end of the string to the pattern
*/
END {
@Override
public String toMatchString(String pattern) {
return '%' + pattern;
}
@ -63,13 +65,18 @@ public enum MatchMode {
* Match the pattern anywhere in the string
*/
ANYWHERE {
@Override
public String toMatchString(String pattern) {
return '%' + pattern + '%';
}
};
/**
* convert the pattern, by appending/prepending "%"
* Convert the pattern, by appending/prepending "%"
*
* @param pattern The pattern for convert according to the mode
*
* @return The converted pattern
*/
public abstract String toMatchString(String pattern);

View File

@ -28,27 +28,37 @@ import java.util.concurrent.ConcurrentHashMap;
import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.engine.spi.TypedValue;
/**
* An expression pertaining to an entity's defined natural identifier
*
* @author Gavin King
* @see Session#byNaturalId(Class)
* @see Session#byNaturalId(String)
* @see Session#bySimpleNaturalId(Class)
* @see Session#bySimpleNaturalId(String)
*
* @see org.hibernate.Session#byNaturalId(Class)
* @see org.hibernate.Session#byNaturalId(String)
* @see org.hibernate.Session#bySimpleNaturalId(Class)
* @see org.hibernate.Session#bySimpleNaturalId(String)
*/
public class NaturalIdentifier implements Criterion {
private final Conjunction conjunction = new Conjunction();
@Override
public TypedValue[] getTypedValues(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException {
return conjunction.getTypedValues( criteria, criteriaQuery );
}
@Override
public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException {
return conjunction.toSqlString( criteria, criteriaQuery );
}
/**
* Get a map of set of the natural identifier values set on this criterion (for composite natural identifiers
* this need not be the full set of properties).
*
* @return The value map.
*/
public Map<String, Object> getNaturalIdValues() {
final Map<String, Object> naturalIdValueMap = new ConcurrentHashMap<String, Object>();
for ( Criterion condition : conjunction.conditions() ) {
@ -65,6 +75,14 @@ public class NaturalIdentifier implements Criterion {
return naturalIdValueMap;
}
/**
* Set a natural identifier value for this expression
*
* @param property The specific property name
* @param value The value to use
*
* @return {@code this}, for method chaining
*/
public NaturalIdentifier set(String property, Object value) {
conjunction.add( Restrictions.eq( property, value ) );
return this;

View File

@ -1,10 +1,10 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
* Copyright (c) 2008, 2013, 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 Middleware LLC.
* 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
@ -20,20 +20,27 @@
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*
*/
package org.hibernate.criterion;
/**
* An expression asserting that a collection property is empty
*
* @author Gavin King
*/
public class NotEmptyExpression extends AbstractEmptinessExpression implements Criterion {
/**
* Constructs an EmptyExpression
*
* @param propertyName The collection property name
*
* @see Restrictions#isNotEmpty
*/
protected NotEmptyExpression(String propertyName) {
super( propertyName );
}
@Override
protected boolean excludeEmpty() {
return true;
}

View File

@ -28,29 +28,37 @@ import org.hibernate.HibernateException;
import org.hibernate.engine.spi.TypedValue;
/**
* Negates another criterion
* A criterion that is a wrapper for another, negating the wrapped one.
*
* @author Gavin King
* @author Brett Meyer
*/
public class NotExpression implements Criterion {
private Criterion criterion;
/**
* Constructs a NotExpression
*
* @param criterion The expression to wrap and negate
*
* @see Restrictions#not
*/
protected NotExpression(Criterion criterion) {
this.criterion = criterion;
}
@Override
public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException {
return criteriaQuery.getFactory().getDialect().getNotExpression(
criterion.toSqlString( criteria, criteriaQuery ) );
criterion.toSqlString( criteria, criteriaQuery )
);
}
public TypedValue[] getTypedValues(
Criteria criteria, CriteriaQuery criteriaQuery)
throws HibernateException {
return criterion.getTypedValues(criteria, criteriaQuery);
@Override
public TypedValue[] getTypedValues(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException {
return criterion.getTypedValues( criteria, criteriaQuery );
}
@Override
public String toString() {
return "not " + criterion.toString();
}

View File

@ -1,10 +1,10 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
* Copyright (c) 2008, 2013, 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 Middleware LLC.
* 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
@ -20,9 +20,9 @@
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*
*/
package org.hibernate.criterion;
import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.engine.spi.TypedValue;
@ -30,36 +30,37 @@ import org.hibernate.internal.util.StringHelper;
/**
* Constrains a property to be non-null
*
* @author Gavin King
*/
public class NotNullExpression implements Criterion {
private static final TypedValue[] NO_VALUES = new TypedValue[0];
private final String propertyName;
private static final TypedValue[] NO_VALUES = new TypedValue[0];
protected NotNullExpression(String propertyName) {
this.propertyName = propertyName;
}
public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery)
throws HibernateException {
String[] columns = criteriaQuery.findColumns(propertyName, criteria);
@Override
public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException {
final String[] columns = criteriaQuery.findColumns( propertyName, criteria );
String result = StringHelper.join(
" or ",
StringHelper.suffix( columns, " is not null" )
);
if (columns.length>1) result = '(' + result + ')';
if ( columns.length > 1 ) {
result = '(' + result + ')';
}
return result;
//TODO: get SQL rendering out of this package!
}
public TypedValue[] getTypedValues(Criteria criteria, CriteriaQuery criteriaQuery)
throws HibernateException {
@Override
public TypedValue[] getTypedValues(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException {
return NO_VALUES;
}
@Override
public String toString() {
return propertyName + " is not null";
}

View File

@ -30,36 +30,44 @@ import org.hibernate.internal.util.StringHelper;
/**
* Constrains a property to be null
*
* @author Gavin King
*/
public class NullExpression implements Criterion {
private static final TypedValue[] NO_VALUES = new TypedValue[0];
private final String propertyName;
private static final TypedValue[] NO_VALUES = new TypedValue[0];
/**
* Constructs a NullExpression
*
* @param propertyName The name of the property to check for null
*
* @see Restrictions#isNull
*/
protected NullExpression(String propertyName) {
this.propertyName = propertyName;
}
public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery)
throws HibernateException {
String[] columns = criteriaQuery.findColumns(propertyName, criteria);
@Override
public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException {
final String[] columns = criteriaQuery.findColumns( propertyName, criteria );
String result = StringHelper.join(
" and ",
StringHelper.suffix( columns, " is null" )
);
if (columns.length>1) result = '(' + result + ')';
if ( columns.length > 1 ) {
result = '(' + result + ')';
}
return result;
//TODO: get SQL rendering out of this package!
}
public TypedValue[] getTypedValues(Criteria criteria, CriteriaQuery criteriaQuery)
throws HibernateException {
@Override
public TypedValue[] getTypedValues(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException {
return NO_VALUES;
}
@Override
public String toString() {
return propertyName + " is null";
}

View File

@ -1,10 +1,10 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
* Copyright (c) 2008, 2013, 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 Middleware LLC.
* 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
@ -20,24 +20,22 @@
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*
*/
package org.hibernate.criterion;
import java.io.Serializable;
import java.sql.Types;
import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.NullPrecedence;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.type.Type;
/**
* Represents an order imposed upon a <tt>Criteria</tt> result set
* Represents an ordering imposed upon the results of a Criteria
*
* @author Gavin King
* @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com)
* @author Brett Meyer
*/
public class Order implements Serializable {
private boolean ascending;
@ -45,22 +43,33 @@ public class Order implements Serializable {
private String propertyName;
private NullPrecedence nullPrecedence;
public String toString() {
return propertyName + ' ' + ( ascending ? "asc" : "desc" ) + ( nullPrecedence != null ? ' ' + nullPrecedence.name().toLowerCase() : "" );
}
public Order ignoreCase() {
ignoreCase = true;
return this;
}
public Order nulls(NullPrecedence nullPrecedence) {
this.nullPrecedence = nullPrecedence;
return this;
/**
* Ascending order
*
* @param propertyName The property to order on
*
* @return The build Order instance
*/
public static Order asc(String propertyName) {
return new Order( propertyName, true );
}
/**
* Constructor for Order.
* Descending order.
*
* @param propertyName The property to order on
*
* @return The build Order instance
*/
public static Order desc(String propertyName) {
return new Order( propertyName, false );
}
/**
* Constructor for Order. Order instances are generally created by factory methods.
*
* @see #asc
* @see #desc
*/
protected Order(String propertyName, boolean ascending) {
this.propertyName = propertyName;
@ -68,74 +77,96 @@ public class Order implements Serializable {
}
/**
* Render the SQL fragment
* Should this ordering ignore case? Has no effect on non-character properties.
*
* @return {@code this}, for method chaining
*/
public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery)
throws HibernateException {
String[] columns = criteriaQuery.getColumnsUsingProjection(criteria, propertyName);
Type type = criteriaQuery.getTypeUsingProjection(criteria, propertyName);
StringBuilder fragment = new StringBuilder();
for ( int i=0; i<columns.length; i++ ) {
final StringBuilder expression = new StringBuilder();
SessionFactoryImplementor factory = criteriaQuery.getFactory();
boolean lower = false;
if ( ignoreCase ) {
int sqlType = type.sqlTypes( factory )[i];
lower = sqlType == Types.VARCHAR
|| sqlType == Types.CHAR
|| sqlType == Types.LONGVARCHAR;
}
public Order ignoreCase() {
ignoreCase = true;
return this;
}
if (lower) {
expression.append( factory.getDialect().getLowercaseFunction() ).append('(');
}
expression.append( columns[i] );
if (lower) expression.append(')');
fragment.append(
factory.getDialect()
.renderOrderByElement(
expression.toString(),
null,
ascending ? "asc" : "desc",
nullPrecedence != null ? nullPrecedence : factory.getSettings().getDefaultNullPrecedence()
)
);
if ( i<columns.length-1 ) fragment.append(", ");
}
return fragment.toString();
/**
* Defines precedence for nulls.
*
* @param nullPrecedence The null precedence to use
*
* @return {@code this}, for method chaining
*/
public Order nulls(NullPrecedence nullPrecedence) {
this.nullPrecedence = nullPrecedence;
return this;
}
public String getPropertyName() {
return propertyName;
}
@SuppressWarnings("UnusedDeclaration")
public boolean isAscending() {
return ascending;
}
@SuppressWarnings("UnusedDeclaration")
public boolean isIgnoreCase() {
return ignoreCase;
}
/**
* Ascending order
*
* @param propertyName
* @return Order
*/
public static Order asc(String propertyName) {
return new Order(propertyName, true);
}
/**
* Descending order
* Render the SQL fragment
*
* @param propertyName
* @return Order
* @param criteria The criteria
* @param criteriaQuery The overall query
*
* @return The ORDER BY fragment for this ordering
*/
public static Order desc(String propertyName) {
return new Order(propertyName, false);
public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery) {
final String[] columns = criteriaQuery.getColumnsUsingProjection( criteria, propertyName );
final Type type = criteriaQuery.getTypeUsingProjection( criteria, propertyName );
final SessionFactoryImplementor factory = criteriaQuery.getFactory();
final int[] sqlTypes = type.sqlTypes( factory );
final StringBuilder fragment = new StringBuilder();
for ( int i=0; i<columns.length; i++ ) {
final StringBuilder expression = new StringBuilder();
boolean lower = false;
if ( ignoreCase ) {
int sqlType = sqlTypes[i];
lower = sqlType == Types.VARCHAR
|| sqlType == Types.CHAR
|| sqlType == Types.LONGVARCHAR;
}
if ( lower ) {
expression.append( factory.getDialect().getLowercaseFunction() )
.append( '(' );
}
expression.append( columns[i] );
if ( lower ) {
expression.append( ')' );
}
fragment.append(
factory.getDialect().renderOrderByElement(
expression.toString(),
null,
ascending ? "asc" : "desc",
nullPrecedence != null ? nullPrecedence : factory.getSettings().getDefaultNullPrecedence()
)
);
if ( i < columns.length-1 ) {
fragment.append( ", " );
}
}
return fragment.toString();
}
@Override
public String toString() {
return propertyName + ' '
+ ( ascending ? "asc" : "desc" )
+ ( nullPrecedence != null ? ' ' + nullPrecedence.name().toLowerCase() : "" );
}
}

View File

@ -1,10 +1,10 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
* Copyright (c) 2008, 2013, 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 Middleware LLC.
* 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
@ -20,9 +20,9 @@
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*
*/
package org.hibernate.criterion;
import java.io.Serializable;
import org.hibernate.Criteria;
@ -36,6 +36,7 @@ import org.hibernate.type.Type;
*
* @author Gavin King
* @author Steve Ebersole
*
* @see Projections
* @see Criteria
*/

View File

@ -1,10 +1,10 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
* Copyright (c) 2008, 2013, 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 Middleware LLC.
* 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
@ -20,159 +20,223 @@
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*
*/
package org.hibernate.criterion;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.internal.util.collections.ArrayHelper;
import org.hibernate.type.Type;
/**
* A projection that wraps other projections to allow selecting multiple values.
*
* @author Gavin King
*/
public class ProjectionList implements EnhancedProjection {
private List<Projection> elements = new ArrayList<Projection>();
private List elements = new ArrayList();
protected ProjectionList() {}
/**
* Constructs a ProjectionList
*
* @see Projections#projectionList()
*/
protected ProjectionList() {
}
/**
* Lol
*
* @return duh
*
* @deprecated an instance factory method does not make sense
*
* @see Projections#projectionList()
*/
@Deprecated
public ProjectionList create() {
return new ProjectionList();
}
public ProjectionList add(Projection proj) {
elements.add(proj);
/**
* Add a projection to this list of projections
*
* @param projection The projection to add
*
* @return {@code this}, for method chaining
*/
public ProjectionList add(Projection projection) {
elements.add( projection );
return this;
}
/**
* Adds a projection to this list of projections after wrapping it with an alias
*
* @param projection The projection to add
* @param alias The alias to apply to the projection
*
* @return {@code this}, for method chaining
*
* @see Projections#alias
*/
public ProjectionList add(Projection projection, String alias) {
return add( Projections.alias( projection, alias ) );
}
public Type[] getTypes(Criteria criteria, CriteriaQuery criteriaQuery)
throws HibernateException {
List types = new ArrayList( getLength() );
for ( int i=0; i<getLength(); i++ ) {
Type[] elemTypes = getProjection(i).getTypes(criteria, criteriaQuery);
ArrayHelper.addAll(types, elemTypes);
}
return ArrayHelper.toTypeArray(types);
}
public String toSqlString(Criteria criteria, int loc, CriteriaQuery criteriaQuery)
throws HibernateException {
StringBuilder buf = new StringBuilder();
for ( int i=0; i<getLength(); i++ ) {
Projection proj = getProjection(i);
buf.append( proj.toSqlString(criteria, loc, criteriaQuery) );
loc += getColumnAliases(loc, criteria, criteriaQuery, proj ).length;
if ( i<elements.size()-1 ) buf.append(", ");
}
return buf.toString();
}
public String toGroupSqlString(Criteria criteria, CriteriaQuery criteriaQuery)
throws HibernateException {
StringBuilder buf = new StringBuilder();
for ( int i=0; i<getLength(); i++ ) {
Projection proj = getProjection(i);
if ( proj.isGrouped() ) {
buf.append( proj.toGroupSqlString(criteria, criteriaQuery) )
.append(", ");
@Override
public boolean isGrouped() {
for ( Projection projection : elements ) {
if ( projection.isGrouped() ) {
return true;
}
}
if ( buf.length()>2 ) buf.setLength( buf.length()-2 ); //pull off the last ", "
return false;
}
@Override
public Type[] getTypes(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException {
final List<Type> types = new ArrayList<Type>( getLength() );
for ( Projection projection : elements ) {
final Type[] elemTypes = projection.getTypes( criteria, criteriaQuery );
Collections.addAll( types, elemTypes );
}
return types.toArray( new Type[types.size()] );
}
@Override
public String toSqlString(Criteria criteria, int loc, CriteriaQuery criteriaQuery) throws HibernateException {
final StringBuilder buf = new StringBuilder();
String separator = "";
for ( Projection projection : elements ) {
buf.append( separator ).append( projection.toSqlString( criteria, loc, criteriaQuery ) );
loc += getColumnAliases( loc, criteria, criteriaQuery, projection ).length;
separator = ", ";
}
return buf.toString();
}
public String[] getColumnAliases(int loc) {
List result = new ArrayList( getLength() );
for ( int i=0; i<getLength(); i++ ) {
String[] colAliases = getProjection(i).getColumnAliases(loc);
ArrayHelper.addAll(result, colAliases);
loc+=colAliases.length;
@Override
public String toGroupSqlString(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException {
final StringBuilder buf = new StringBuilder();
String separator = "";
for ( Projection projection : elements ) {
if ( ! projection.isGrouped() ) {
continue;
}
buf.append( separator ).append( projection.toGroupSqlString( criteria, criteriaQuery ) );
separator = ", ";
}
return ArrayHelper.toStringArray(result);
return buf.toString();
}
public String[] getColumnAliases(int loc, Criteria criteria, CriteriaQuery criteriaQuery) {
List result = new ArrayList( getLength() );
for ( int i=0; i<getLength(); i++ ) {
String[] colAliases = getColumnAliases( loc, criteria, criteriaQuery, getProjection( i ) );
ArrayHelper.addAll(result, colAliases);
loc+=colAliases.length;
@Override
public String[] getColumnAliases(final int loc) {
int position = loc;
final List<String> result = new ArrayList<String>( getLength() );
for ( Projection projection : elements ) {
final String[] aliases = projection.getColumnAliases( position );
Collections.addAll( result, aliases );
position += aliases.length;
}
return ArrayHelper.toStringArray(result);
return result.toArray( new String[ result.size() ] );
}
public String[] getColumnAliases(String alias, int loc) {
for ( int i=0; i<getLength(); i++ ) {
String[] result = getProjection(i).getColumnAliases(alias, loc);
if (result!=null) return result;
loc += getProjection(i).getColumnAliases(loc).length;
@Override
public String[] getColumnAliases(final int loc, Criteria criteria, CriteriaQuery criteriaQuery) {
int position = loc;
final List<String> result = new ArrayList<String>( getLength() );
for ( Projection projection : elements ) {
final String[] aliases = getColumnAliases( position, criteria, criteriaQuery, projection );
Collections.addAll( result, aliases );
position += aliases.length;
}
return result.toArray( new String[result.size()] );
}
@Override
public String[] getColumnAliases(String alias, final int loc) {
int position = loc;
for ( Projection projection : elements ) {
final String[] aliases = projection.getColumnAliases( alias, position );
if ( aliases != null ) {
return aliases;
}
position += projection.getColumnAliases( position ).length;
}
return null;
}
@Override
public String[] getColumnAliases(String alias, int loc, Criteria criteria, CriteriaQuery criteriaQuery) {
for ( int i=0; i<getLength(); i++ ) {
String[] result = getColumnAliases( alias, loc, criteria, criteriaQuery, getProjection(i) );
if (result!=null) return result;
loc += getColumnAliases( loc, criteria, criteriaQuery, getProjection( i ) ).length;
int position = loc;
for ( Projection projection : elements ) {
final String[] aliases = getColumnAliases( alias, position, criteria, criteriaQuery, projection );
if ( aliases != null ) {
return aliases;
}
position += getColumnAliases( position, criteria, criteriaQuery, projection ).length;
}
return null;
}
private static String[] getColumnAliases(int loc, Criteria criteria, CriteriaQuery criteriaQuery, Projection projection) {
return projection instanceof EnhancedProjection ?
( ( EnhancedProjection ) projection ).getColumnAliases( loc, criteria, criteriaQuery ) :
projection.getColumnAliases( loc );
return projection instanceof EnhancedProjection
? ( (EnhancedProjection) projection ).getColumnAliases( loc, criteria, criteriaQuery )
: projection.getColumnAliases( loc );
}
private static String[] getColumnAliases(String alias, int loc, Criteria criteria, CriteriaQuery criteriaQuery, Projection projection) {
return projection instanceof EnhancedProjection ?
( ( EnhancedProjection ) projection ).getColumnAliases( alias, loc, criteria, criteriaQuery ) :
projection.getColumnAliases( alias, loc );
return projection instanceof EnhancedProjection
? ( (EnhancedProjection) projection ).getColumnAliases( alias, loc, criteria, criteriaQuery )
: projection.getColumnAliases( alias, loc );
}
@Override
public Type[] getTypes(String alias, Criteria criteria, CriteriaQuery criteriaQuery) {
for ( int i=0; i<getLength(); i++ ) {
Type[] result = getProjection(i).getTypes(alias, criteria, criteriaQuery);
if (result!=null) return result;
for ( Projection projection : elements ) {
final Type[] types = projection.getTypes( alias, criteria, criteriaQuery );
if ( types != null ) {
return types;
}
}
return null;
}
@Override
public String[] getAliases() {
List result = new ArrayList( getLength() );
for ( int i=0; i<getLength(); i++ ) {
String[] aliases = getProjection(i).getAliases();
ArrayHelper.addAll( result, aliases );
final List<String> result = new ArrayList<String>( getLength() );
for ( Projection projection : elements ) {
final String[] aliases = projection.getAliases();
Collections.addAll( result, aliases );
}
return ArrayHelper.toStringArray(result);
return result.toArray( new String[result.size()] );
}
/**
* Access a wrapped projection by index
*
* @param i The index of the projection to return
*
* @return The projection
*/
@SuppressWarnings("UnusedDeclaration")
public Projection getProjection(int i) {
return (Projection) elements.get(i);
return elements.get( i );
}
public int getLength() {
return elements.size();
}
@Override
public String toString() {
return elements.toString();
}
public boolean isGrouped() {
for ( int i=0; i<getLength(); i++ ) {
if ( getProjection(i).isGrouped() ) return true;
}
return false;
}
}

View File

@ -1,10 +1,10 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
* Copyright (c) 2008, 2013, 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 Middleware LLC.
* 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
@ -20,38 +20,81 @@
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*
*/
package org.hibernate.criterion;
import org.hibernate.type.Type;
/**
* The <tt>criterion</tt> package may be used by applications as a framework for building
* new kinds of <tt>Projection</tt>. However, it is intended that most applications will
* simply use the built-in projection types via the static factory methods of this class.<br/>
* <br/>
* simply use the built-in projection types via the static factory methods of this class.
*
* The factory methods that take an alias allow the projected value to be referred to by
* criterion and order instances.
*
* @see org.hibernate.Criteria
* @see Restrictions factory methods for <tt>Criterion</tt> instances
* See also the {@link Restrictions} factory methods for generating {@link Criterion} instances
*
* @author Gavin King
* @author Steve Ebersole
*
* @see org.hibernate.Criteria
*/
public final class Projections {
private Projections() {
//cannot be instantiated
}
/**
* Create a distinct projection from a projection
* A property value projection
*
* @param propertyName The name of the property whose values should be projected
*
* @return The property projection
*
* @see PropertyProjection
*/
public static Projection distinct(Projection proj) {
return new Distinct(proj);
public static PropertyProjection property(String propertyName) {
return new PropertyProjection( propertyName );
}
/**
* Create a new projection list
* A grouping property value projection
*
* @param propertyName The name of the property to group
*
* @return The grouped projection
*
* @see PropertyProjection
*/
public static PropertyProjection groupProperty(String propertyName) {
return new PropertyProjection( propertyName, true );
}
/**
* An identifier value projection.
*
* @return The identifier projection
*
* @see IdentifierProjection
*/
public static IdentifierProjection id() {
return new IdentifierProjection();
}
/**
* Create a distinct projection from a projection.
*
* @param projection The project to treat distinctly
*
* @return The distinct projection
*
* @see Distinct
*/
public static Projection distinct(Projection projection) {
return new Distinct( projection );
}
/**
* Create a new projection list.
*
* @return The projection list
*/
public static ProjectionList projectionList() {
return new ProjectionList();
@ -59,92 +102,141 @@ public final class Projections {
/**
* The query row count, ie. <tt>count(*)</tt>
*
* @return The projection representing the row count
*
* @see RowCountProjection
*/
public static Projection rowCount() {
return new RowCountProjection();
}
/**
* A property value count
* A property value count projection
*
* @param propertyName The name of the property to count over
*
* @return The count projection
*
* @see CountProjection
*/
public static CountProjection count(String propertyName) {
return new CountProjection(propertyName);
return new CountProjection( propertyName );
}
/**
* A distinct property value count
* A distinct property value count projection
*
* @param propertyName The name of the property to count over
*
* @return The count projection
*
* @see CountProjection
*/
public static CountProjection countDistinct(String propertyName) {
return new CountProjection(propertyName).setDistinct();
return new CountProjection( propertyName ).setDistinct();
}
/**
* A property maximum value
* A property maximum value projection
*
* @param propertyName The property for which to find the max
*
* @return the max projection
*
* @see AggregateProjection
*/
public static AggregateProjection max(String propertyName) {
return new AggregateProjection("max", propertyName);
return new AggregateProjection( "max", propertyName );
}
/**
* A property minimum value
* A property minimum value projection
*
* @param propertyName The property for which to find the min
*
* @return the min projection
*
* @see AggregateProjection
*/
public static AggregateProjection min(String propertyName) {
return new AggregateProjection("min", propertyName);
return new AggregateProjection( "min", propertyName );
}
/**
* A property average value
* A property average value projection
*
* @param propertyName The property over which to find the average
*
* @return the avg projection
*
* @see AvgProjection
*/
public static AggregateProjection avg(String propertyName) {
return new AvgProjection(propertyName);
return new AvgProjection( propertyName );
}
/**
* A property value sum
* A property value sum projection
*
* @param propertyName The property over which to sum
*
* @return the sum projection
*
* @see AggregateProjection
*/
public static AggregateProjection sum(String propertyName) {
return new AggregateProjection("sum", propertyName);
}
/**
* A SQL projection, a typed select clause fragment
*/
public static Projection sqlProjection(String sql, String[] columnAliases, Type[] types) {
return new SQLProjection(sql, columnAliases, types);
}
/**
* A grouping SQL projection, specifying both select clause and group by clause fragments
*/
public static Projection sqlGroupProjection(String sql, String groupBy, String[] columnAliases, Type[] types) {
return new SQLProjection(sql, groupBy, columnAliases, types);
}
/**
* A grouping property value
*/
public static PropertyProjection groupProperty(String propertyName) {
return new PropertyProjection(propertyName, true);
}
/**
* A projected property value
*/
public static PropertyProjection property(String propertyName) {
return new PropertyProjection(propertyName);
}
/**
* A projected identifier value
*/
public static IdentifierProjection id() {
return new IdentifierProjection();
return new AggregateProjection( "sum", propertyName );
}
/**
* Assign an alias to a projection, by wrapping it
*
* @param projection The projection to be aliased
* @param alias The alias to apply
*
* @return The aliased projection
*
* @see AliasedProjection
*/
public static Projection alias(Projection projection, String alias) {
return new AliasedProjection(projection, alias);
return new AliasedProjection( projection, alias );
}
/**
* A SQL projection, a typed select clause fragment
*
* @param sql The SQL fragment
* @param columnAliases The column aliases
* @param types The resulting types
*
* @return The SQL projection
*
* @see SQLProjection
*/
public static Projection sqlProjection(String sql, String[] columnAliases, Type[] types) {
return new SQLProjection( sql, columnAliases, types );
}
/**
* A grouping SQL projection, specifying both select clause and group by clause fragments
*
* @param sql The SQL SELECT fragment
* @param groupBy The SQL GROUP BY fragment
* @param columnAliases The column aliases
* @param types The resulting types
*
* @return The SQL projection
*
* @see SQLProjection
*/
@SuppressWarnings("UnusedDeclaration")
public static Projection sqlGroupProjection(String sql, String groupBy, String[] columnAliases, Type[] types) {
return new SQLProjection(sql, groupBy, columnAliases, types);
}
private Projections() {
//cannot be instantiated
}
}

View File

@ -1,3 +1,26 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2013, 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.criterion;
import org.hibernate.Criteria;
@ -5,6 +28,7 @@ import org.hibernate.internal.util.StringHelper;
/**
* A comparison between several properties value in the outer query and the result of a multicolumn subquery.
*
* @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com)
*/
public class PropertiesSubqueryExpression extends SubqueryExpression {
@ -17,7 +41,7 @@ public class PropertiesSubqueryExpression extends SubqueryExpression {
@Override
protected String toLeftSqlString(Criteria criteria, CriteriaQuery outerQuery) {
StringBuilder left = new StringBuilder( "(" );
final StringBuilder left = new StringBuilder( "(" );
final String[] sqlColumnNames = new String[propertyNames.length];
for ( int i = 0; i < sqlColumnNames.length; ++i ) {
sqlColumnNames[i] = outerQuery.getColumn( criteria, propertyNames[i] );

View File

@ -1,10 +1,10 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
* Copyright (c) 2008, 2013, 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 Middleware LLC.
* 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
@ -20,244 +20,737 @@
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*
*/
package org.hibernate.criterion;
import java.util.Collection;
/**
* A factory for property-specific criterion and projection instances
*
* @author Gavin King
* @author Steve Ebersole
*/
public class Property extends PropertyProjection {
//private String propertyName;
/**
* Factory for Property instances.
*
* @param propertyName The name of the property.
*
* @return The Property instance
*/
public static Property forName(String propertyName) {
return new Property( propertyName );
}
/**
* Constructs a Property. non-private to allow subclassing.
*
* @param propertyName The property name.
*/
protected Property(String propertyName) {
super(propertyName);
super( propertyName );
}
/**
* Creates a BETWEEN restriction for this property between the given min and max
*
* @param min The minimum
* @param max The maximum
*
* @return The BETWEEN restriction
*
* @see Restrictions#between(String, Object, Object)
*/
public Criterion between(Object min, Object max) {
return Restrictions.between(getPropertyName(), min, max);
return Restrictions.between( getPropertyName(), min, max );
}
/**
* Creates an IN restriction for this property based on the given list of literals
*
* @param values The literal values
*
* @return The IN restriction
*
* @see Restrictions#in(String, Collection)
*/
public Criterion in(Collection values) {
return Restrictions.in(getPropertyName(), values);
return Restrictions.in( getPropertyName(), values );
}
/**
* Creates an IN restriction for this property based on the given list of literals
*
* @param values The literal values
*
* @return The IN restriction
*
* @see Restrictions#in(String, Object[])
*/
public Criterion in(Object[] values) {
return Restrictions.in(getPropertyName(), values);
return Restrictions.in( getPropertyName(), values );
}
/**
* Creates a LIKE restriction for this property
*
* @param value The value to like compare with
*
* @return The LIKE restriction
*
* @see Restrictions#like(String, Object)
*/
public SimpleExpression like(Object value) {
return Restrictions.like(getPropertyName(), value);
return Restrictions.like( getPropertyName(), value );
}
/**
* Creates a LIKE restriction for this property
*
* @param value The value to like compare with
* @param matchMode The match mode to apply to the LIKE
*
* @return The LIKE restriction
*
* @see Restrictions#like(String, String, MatchMode)
*/
public SimpleExpression like(String value, MatchMode matchMode) {
return Restrictions.like(getPropertyName(), value, matchMode);
return Restrictions.like( getPropertyName(), value, matchMode );
}
/**
* Creates an equality restriction.
*
* @param value The value to check against
*
* @return The equality restriction.
*
* @see Restrictions#eq(String, Object)
*/
public SimpleExpression eq(Object value) {
return Restrictions.eq(getPropertyName(), value);
return Restrictions.eq( getPropertyName(), value );
}
/**
* Creates an equality restriction capable of also rendering as IS NULL if the given value is {@code null}
*
* @param value The value to check against
*
* @return The equality restriction.
*
* @see Restrictions#eqOrIsNull(String, Object)
* @see #eq
* @see #isNull
*/
@SuppressWarnings("UnusedDeclaration")
public Criterion eqOrIsNull(Object value) {
return Restrictions.eqOrIsNull(getPropertyName(), value);
return Restrictions.eqOrIsNull( getPropertyName(), value );
}
/**
* Creates an non-equality restriction.
*
* @param value The value to check against
*
* @return The non-equality restriction.
*
* @see Restrictions#ne(String, Object)
*/
public SimpleExpression ne(Object value) {
return Restrictions.ne(getPropertyName(), value);
return Restrictions.ne( getPropertyName(), value );
}
/**
* Creates an non-equality restriction capable of also rendering as IS NOT NULL if the given value is {@code null}
*
* @param value The value to check against
*
* @return The non-equality restriction.
*
* @see Restrictions#neOrIsNotNull(String, Object)
* @see #ne
* @see #isNotNull
*/
@SuppressWarnings("UnusedDeclaration")
public Criterion neOrIsNotNull(Object value) {
return Restrictions.neOrIsNotNull(getPropertyName(), value);
return Restrictions.neOrIsNotNull( getPropertyName(), value );
}
/**
* Create a greater-than restriction based on this property
*
* @param value The value to check against
*
* @return The greater-than restriction
*
* @see Restrictions#gt(String, Object)
*/
public SimpleExpression gt(Object value) {
return Restrictions.gt(getPropertyName(), value);
return Restrictions.gt( getPropertyName(), value );
}
/**
* Create a less-than restriction based on this property
*
* @param value The value to check against
*
* @return The less-than restriction
*
* @see Restrictions#lt(String, Object)
*/
public SimpleExpression lt(Object value) {
return Restrictions.lt(getPropertyName(), value);
return Restrictions.lt( getPropertyName(), value );
}
/**
* Create a less-than-or-equal-to restriction based on this property
*
* @param value The value to check against
*
* @return The less-than-or-equal-to restriction
*
* @see Restrictions#le(String, Object)
*/
public SimpleExpression le(Object value) {
return Restrictions.le(getPropertyName(), value);
return Restrictions.le( getPropertyName(), value );
}
/**
* Create a greater-than-or-equal-to restriction based on this property
*
* @param value The value to check against
*
* @return The greater-than-or-equal-to restriction
*
* @see Restrictions#ge(String, Object)
*/
public SimpleExpression ge(Object value) {
return Restrictions.ge(getPropertyName(), value);
return Restrictions.ge( getPropertyName(), value );
}
/**
* Creates an equality restriction between 2 properties
*
* @param other The other property to compare against
*
* @return The restriction
*
* @see Restrictions#eqProperty(String, String)
*/
@SuppressWarnings("UnusedDeclaration")
public PropertyExpression eqProperty(Property other) {
return Restrictions.eqProperty( getPropertyName(), other.getPropertyName() );
}
public PropertyExpression neProperty(Property other) {
return Restrictions.neProperty( getPropertyName(), other.getPropertyName() );
}
public PropertyExpression leProperty(Property other) {
return Restrictions.leProperty( getPropertyName(), other.getPropertyName() );
}
public PropertyExpression geProperty(Property other) {
return Restrictions.geProperty( getPropertyName(), other.getPropertyName() );
}
public PropertyExpression ltProperty(Property other) {
return Restrictions.ltProperty( getPropertyName(), other.getPropertyName() );
}
public PropertyExpression gtProperty(Property other) {
return Restrictions.gtProperty( getPropertyName(), other.getPropertyName() );
}
/**
* Creates an equality restriction between 2 properties
*
* @param other The other property to compare against
*
* @return The restriction
*
* @see Restrictions#eqProperty(String, String)
*/
@SuppressWarnings("UnusedDeclaration")
public PropertyExpression eqProperty(String other) {
return Restrictions.eqProperty( getPropertyName(), other );
}
/**
* Creates an non-equality restriction between 2 properties
*
* @param other The other property to compare against
*
* @return The restriction
*
* @see Restrictions#neProperty(String, String)
*/
@SuppressWarnings("UnusedDeclaration")
public PropertyExpression neProperty(Property other) {
return Restrictions.neProperty( getPropertyName(), other.getPropertyName() );
}
/**
* Creates an non-equality restriction between 2 properties
*
* @param other The other property to compare against
*
* @return The restriction
*
* @see Restrictions#neProperty(String, String)
*/
@SuppressWarnings("UnusedDeclaration")
public PropertyExpression neProperty(String other) {
return Restrictions.neProperty( getPropertyName(), other );
}
/**
* Creates an less-than-or-equal-to restriction between 2 properties
*
* @param other The other property to compare against
*
* @return The restriction
*
* @see Restrictions#leProperty(String, String)
*/
@SuppressWarnings("UnusedDeclaration")
public PropertyExpression leProperty(Property other) {
return Restrictions.leProperty( getPropertyName(), other.getPropertyName() );
}
/**
* Creates an less-than-or-equal-to restriction between 2 properties
*
* @param other The other property to compare against
*
* @return The restriction
*
* @see Restrictions#leProperty(String, String)
*/
@SuppressWarnings("UnusedDeclaration")
public PropertyExpression leProperty(String other) {
return Restrictions.leProperty( getPropertyName(), other );
}
/**
* Creates an greater-than-or-equal-to restriction between 2 properties
*
* @param other The other property to compare against
*
* @return The restriction
*
* @see Restrictions#geProperty(String, String)
*/
@SuppressWarnings("UnusedDeclaration")
public PropertyExpression geProperty(Property other) {
return Restrictions.geProperty( getPropertyName(), other.getPropertyName() );
}
/**
* Creates an greater-than-or-equal-to restriction between 2 properties
*
* @param other The other property to compare against
*
* @return The restriction
*
* @see Restrictions#geProperty(String, String)
*/
@SuppressWarnings("UnusedDeclaration")
public PropertyExpression geProperty(String other) {
return Restrictions.geProperty( getPropertyName(), other );
}
/**
* Creates an less-than restriction between 2 properties
*
* @param other The other property to compare against
*
* @return The restriction
*
* @see Restrictions#ltProperty(String, String)
*/
@SuppressWarnings("UnusedDeclaration")
public PropertyExpression ltProperty(Property other) {
return Restrictions.ltProperty( getPropertyName(), other.getPropertyName() );
}
/**
* Creates an less-than restriction between 2 properties
*
* @param other The other property to compare against
*
* @return The restriction
*
* @see Restrictions#ltProperty(String, String)
*/
@SuppressWarnings("UnusedDeclaration")
public PropertyExpression ltProperty(String other) {
return Restrictions.ltProperty( getPropertyName(), other );
}
/**
* Creates an greater-than restriction between 2 properties
*
* @param other The other property to compare against
*
* @return The restriction
*
* @see Restrictions#geProperty(String, String)
*/
@SuppressWarnings("UnusedDeclaration")
public PropertyExpression gtProperty(Property other) {
return Restrictions.gtProperty( getPropertyName(), other.getPropertyName() );
}
/**
* Creates an greater-than restriction between 2 properties
*
* @param other The other property to compare against
*
* @return The restriction
*
* @see Restrictions#geProperty(String, String)
*/
@SuppressWarnings("UnusedDeclaration")
public PropertyExpression gtProperty(String other) {
return Restrictions.gtProperty( getPropertyName(), other );
}
/**
* Creates a NULL restriction
*
* @return The restriction
*
* @see Restrictions#isNull(String)
*/
public Criterion isNull() {
return Restrictions.isNull(getPropertyName());
}
public Criterion isNotNull() {
return Restrictions.isNotNull(getPropertyName());
}
public Criterion isEmpty() {
return Restrictions.isEmpty(getPropertyName());
}
public Criterion isNotEmpty() {
return Restrictions.isNotEmpty(getPropertyName());
}
public CountProjection count() {
return Projections.count(getPropertyName());
}
public AggregateProjection max() {
return Projections.max(getPropertyName());
}
public AggregateProjection min() {
return Projections.min(getPropertyName());
}
public AggregateProjection avg() {
return Projections.avg(getPropertyName());
}
/*public PropertyProjection project() {
return Projections.property(getPropertyName());
}*/
public PropertyProjection group() {
return Projections.groupProperty(getPropertyName());
}
public Order asc() {
return Order.asc(getPropertyName());
}
public Order desc() {
return Order.desc(getPropertyName());
}
public static Property forName(String propertyName) {
return new Property(propertyName);
return Restrictions.isNull( getPropertyName() );
}
/**
* Get a component attribute of this property
* Creates a NOT NULL restriction
*
* @return The restriction
*
* @see Restrictions#isNotNull(String)
*/
public Criterion isNotNull() {
return Restrictions.isNotNull( getPropertyName() );
}
/**
* Creates a restriction to check that a collection is empty
*
* @return The restriction
*
* @see Restrictions#isEmpty(String)
*/
public Criterion isEmpty() {
return Restrictions.isEmpty( getPropertyName() );
}
/**
* Creates a restriction to check that a collection is not empty
*
* @return The restriction
*
* @see Restrictions#isNotEmpty(String)
*/
public Criterion isNotEmpty() {
return Restrictions.isNotEmpty( getPropertyName() );
}
/**
* Creates a property count projection
*
* @return The projection
*
* @see Projections#count
*/
public CountProjection count() {
return Projections.count( getPropertyName() );
}
/**
* Creates a property max projection
*
* @return The projection
*
* @see Projections#max
*/
public AggregateProjection max() {
return Projections.max( getPropertyName() );
}
/**
* Creates a property min projection
*
* @return The projection
*
* @see Projections#min
*/
public AggregateProjection min() {
return Projections.min( getPropertyName() );
}
/**
* Creates a property avg projection
*
* @return The projection
*
* @see Projections#avg
*/
public AggregateProjection avg() {
return Projections.avg( getPropertyName() );
}
/**
* Creates a projection for this property as a group expression
*
* @return The group projection
*
* @see Projections#groupProperty
*/
public PropertyProjection group() {
return Projections.groupProperty( getPropertyName() );
}
/**
* Creates an ascending ordering for this property
*
* @return The order
*/
public Order asc() {
return Order.asc( getPropertyName() );
}
/**
* Creates a descending ordering for this property
*
* @return The order
*/
public Order desc() {
return Order.desc( getPropertyName() );
}
/**
* Get a component attribute of this property.
*
* @param propertyName The sub property name
*
* @return The property
*/
public Property getProperty(String propertyName) {
return forName( getPropertyName() + '.' + propertyName );
}
/**
* Creates a sub-query equality expression for this property
*
* @param subselect The sub-query
*
* @return The expression
*
* @see Subqueries#propertyEq(String, DetachedCriteria)
*/
public Criterion eq(DetachedCriteria subselect) {
return Subqueries.propertyEq( getPropertyName(), subselect );
}
/**
* Creates a sub-query non-equality expression for this property
*
* @param subselect The sub-query
*
* @return The expression
*
* @see Subqueries#propertyNe(String, DetachedCriteria)
*/
public Criterion ne(DetachedCriteria subselect) {
return Subqueries.propertyNe( getPropertyName(), subselect );
}
/**
* Creates a sub-query less-than expression for this property
*
* @param subselect The sub-query
*
* @return The expression
*
* @see Subqueries#propertyLt(String, DetachedCriteria)
*/
public Criterion lt(DetachedCriteria subselect) {
return Subqueries.propertyLt( getPropertyName(), subselect );
}
/**
* Creates a sub-query less-than-or-equal-to expression for this property
*
* @param subselect The sub-query
*
* @return The expression
*
* @see Subqueries#propertyLe(String, DetachedCriteria)
*/
public Criterion le(DetachedCriteria subselect) {
return Subqueries.propertyLe( getPropertyName(), subselect );
}
/**
* Creates a sub-query greater-than expression for this property
*
* @param subselect The sub-query
*
* @return The expression
*
* @see Subqueries#propertyGt(String, DetachedCriteria)
*/
public Criterion gt(DetachedCriteria subselect) {
return Subqueries.propertyGt( getPropertyName(), subselect );
}
/**
* Creates a sub-query greater-than-or-equal-to expression for this property
*
* @param subselect The sub-query
*
* @return The expression
*
* @see Subqueries#propertyGe(String, DetachedCriteria)
*/
public Criterion ge(DetachedCriteria subselect) {
return Subqueries.propertyGe( getPropertyName(), subselect );
}
/**
* Creates a sub-query NOT IN expression for this property. I.e., {@code [prop] NOT IN [subquery]}
*
* @param subselect The sub-query
*
* @return The expression
*
* @see Subqueries#propertyNotIn(String, DetachedCriteria)
*/
@SuppressWarnings("UnusedDeclaration")
public Criterion notIn(DetachedCriteria subselect) {
return Subqueries.propertyNotIn( getPropertyName(), subselect );
}
/**
* Creates a sub-query IN expression for this property. I.e., {@code [prop] IN [subquery]}
*
* @param subselect The sub-query
*
* @return The expression
*
* @see Subqueries#propertyIn(String, DetachedCriteria)
*/
public Criterion in(DetachedCriteria subselect) {
return Subqueries.propertyIn( getPropertyName(), subselect );
}
/**
* Creates a equals-all sub-query expression for this property. I.e., {@code [prop] = ALL [subquery]}
*
* @param subselect The sub-query
*
* @return The expression
*
* @see Subqueries#propertyEqAll(String, DetachedCriteria)
*/
public Criterion eqAll(DetachedCriteria subselect) {
return Subqueries.propertyEqAll( getPropertyName(), subselect );
}
/**
* Creates a greater-than-all sub-query expression for this property. I.e., {@code [prop] > ALL [subquery]}
*
* @param subselect The sub-query
*
* @return The expression
*
* @see Subqueries#propertyGtAll(String, DetachedCriteria)
*/
@SuppressWarnings("UnusedDeclaration")
public Criterion gtAll(DetachedCriteria subselect) {
return Subqueries.propertyGtAll( getPropertyName(), subselect );
}
/**
* Creates a less-than-all sub-query expression for this property. I.e., {@code [prop] < ALL [subquery]}
*
* @param subselect The sub-query
*
* @return The expression
*
* @see Subqueries#propertyLtAll(String, DetachedCriteria)
*/
@SuppressWarnings("UnusedDeclaration")
public Criterion ltAll(DetachedCriteria subselect) {
return Subqueries.propertyLtAll( getPropertyName(), subselect );
}
/**
* Creates a less-than-or-equal-to-all sub-query expression for this property. I.e., {@code [prop] <= ALL [subquery]}
*
* @param subselect The sub-query
*
* @return The expression
*
* @see Subqueries#propertyLeAll(String, DetachedCriteria)
*/
@SuppressWarnings("UnusedDeclaration")
public Criterion leAll(DetachedCriteria subselect) {
return Subqueries.propertyLeAll( getPropertyName(), subselect );
}
/**
* Creates a greater-than-or-equal-to-all sub-query expression for this property. I.e., {@code [prop] >= ALL [subquery]}
*
* @param subselect The sub-query
*
* @return The expression
*
* @see Subqueries#propertyGeAll(String, DetachedCriteria)
*/
@SuppressWarnings("UnusedDeclaration")
public Criterion geAll(DetachedCriteria subselect) {
return Subqueries.propertyGeAll( getPropertyName(), subselect );
}
/**
* Creates a greater-than-some sub-query expression for this property. I.e., {@code [prop] > SOME [subquery]}
*
* @param subselect The sub-query
*
* @return The expression
*
* @see Subqueries#propertyGtSome(String, DetachedCriteria)
*/
@SuppressWarnings("UnusedDeclaration")
public Criterion gtSome(DetachedCriteria subselect) {
return Subqueries.propertyGtSome( getPropertyName(), subselect );
}
/**
* Creates a less-than-some sub-query expression for this property. I.e., {@code [prop] < SOME [subquery]}
*
* @param subselect The sub-query
*
* @return The expression
*
* @see Subqueries#propertyLtSome(String, DetachedCriteria)
*/
@SuppressWarnings("UnusedDeclaration")
public Criterion ltSome(DetachedCriteria subselect) {
return Subqueries.propertyLtSome( getPropertyName(), subselect );
}
/**
* Creates a less-than-or-equal-to-some sub-query expression for this property. I.e., {@code [prop] <= SOME [subquery]}
*
* @param subselect The sub-query
*
* @return The expression
*
* @see Subqueries#propertyLeSome(String, DetachedCriteria)
*/
@SuppressWarnings("UnusedDeclaration")
public Criterion leSome(DetachedCriteria subselect) {
return Subqueries.propertyLeSome( getPropertyName(), subselect );
}
/**
* Creates a greater-than-or-equal-to-some sub-query expression for this property. I.e., {@code [prop] >= SOME [subquery]}
*
* @param subselect The sub-query
*
* @return The expression
*
* @see Subqueries#propertyGeSome(String, DetachedCriteria)
*/
@SuppressWarnings("UnusedDeclaration")
public Criterion geSome(DetachedCriteria subselect) {
return Subqueries.propertyGeSome( getPropertyName(), subselect );
}

View File

@ -1,10 +1,10 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
* Copyright (c) 2008, 2013, 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 Middleware LLC.
* 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
@ -20,9 +20,9 @@
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*
*/
package org.hibernate.criterion;
import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.engine.spi.TypedValue;
@ -30,46 +30,48 @@ import org.hibernate.internal.util.StringHelper;
/**
* superclass for comparisons between two properties (with SQL binary operators)
*
* @author Gavin King
*/
public class PropertyExpression implements Criterion {
private static final TypedValue[] NO_TYPED_VALUES = new TypedValue[0];
private final String propertyName;
private final String otherPropertyName;
private final String op;
private static final TypedValue[] NO_TYPED_VALUES = new TypedValue[0];
protected PropertyExpression(String propertyName, String otherPropertyName, String op) {
this.propertyName = propertyName;
this.otherPropertyName = otherPropertyName;
this.op = op;
}
public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery)
throws HibernateException {
String[] xcols = criteriaQuery.findColumns(propertyName, criteria);
String[] ycols = criteriaQuery.findColumns(otherPropertyName, criteria);
String result = StringHelper.join(
" and ",
StringHelper.add( xcols, getOp(), ycols )
);
if (xcols.length>1) result = '(' + result + ')';
return result;
//TODO: get SQL rendering out of this package!
}
public TypedValue[] getTypedValues(Criteria criteria, CriteriaQuery criteriaQuery)
throws HibernateException {
return NO_TYPED_VALUES;
}
public String toString() {
return propertyName + getOp() + otherPropertyName;
}
public String getOp() {
return op;
}
@Override
public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException {
final String[] lhsColumns = criteriaQuery.findColumns( propertyName, criteria );
final String[] rhsColumns = criteriaQuery.findColumns( otherPropertyName, criteria );
final String[] comparisons = StringHelper.add( lhsColumns, getOp(), rhsColumns );
if ( comparisons.length > 1 ) {
return '(' + StringHelper.join( " and ", comparisons ) + ')';
}
else {
return comparisons[0];
}
}
@Override
public TypedValue[] getTypedValues(Criteria criteria, CriteriaQuery criteriaQuery) {
return NO_TYPED_VALUES;
}
@Override
public String toString() {
return propertyName + getOp() + otherPropertyName;
}
}

View File

@ -30,10 +30,11 @@ import org.hibernate.type.Type;
/**
* A property value, or grouped property value
*
* @author Gavin King
* @author Steve Ebersole
*/
public class PropertyProjection extends SimpleProjection {
private String propertyName;
private boolean grouped;
@ -46,46 +47,49 @@ public class PropertyProjection extends SimpleProjection {
this(prop, false);
}
public String getPropertyName() {
return propertyName;
}
public String toString() {
return propertyName;
}
public Type[] getTypes(Criteria criteria, CriteriaQuery criteriaQuery)
throws HibernateException {
return new Type[] { criteriaQuery.getType(criteria, propertyName) };
}
public String toSqlString(Criteria criteria, int position, CriteriaQuery criteriaQuery)
throws HibernateException {
StringBuilder buf = new StringBuilder();
String[] cols = criteriaQuery.getColumns( propertyName, criteria );
for ( int i=0; i<cols.length; i++ ) {
buf.append( cols[i] )
.append(" as y")
.append(position + i)
.append('_');
if (i < cols.length -1)
buf.append(", ");
}
return buf.toString();
}
@Override
public boolean isGrouped() {
return grouped;
}
public String toGroupSqlString(Criteria criteria, CriteriaQuery criteriaQuery)
throws HibernateException {
if (!grouped) {
return super.toGroupSqlString(criteria, criteriaQuery);
public String getPropertyName() {
return propertyName;
}
@Override
public Type[] getTypes(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException {
return new Type[] { criteriaQuery.getType( criteria, propertyName ) };
}
@Override
public String toSqlString(Criteria criteria, int position, CriteriaQuery criteriaQuery) throws HibernateException {
final StringBuilder buf = new StringBuilder();
final String[] cols = criteriaQuery.getColumns( propertyName, criteria );
for ( int i=0; i<cols.length; i++ ) {
buf.append( cols[i] )
.append( " as y" )
.append( position + i )
.append( '_' );
if (i < cols.length -1) {
buf.append( ", " );
}
}
return buf.toString();
}
@Override
public String toGroupSqlString(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException {
if ( !grouped ) {
return super.toGroupSqlString( criteria, criteriaQuery );
}
else {
return StringHelper.join( ", ", criteriaQuery.getColumns( propertyName, criteria ) );
}
}
@Override
public String toString() {
return propertyName;
}
}

View File

@ -1,10 +1,10 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
* Copyright (c) 2008, 2013, 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 Middleware LLC.
* 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
@ -20,26 +20,28 @@
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*
*/
package org.hibernate.criterion;
import org.hibernate.Criteria;
/**
* A comparison between a property value in the outer query and the
* result of a subquery
* A comparison between a property value in the outer query and the result of a subquery
*
* @author Gavin King
* @author Steve Ebersole
*/
public class PropertySubqueryExpression extends SubqueryExpression {
private String propertyName;
protected PropertySubqueryExpression(String propertyName, String op, String quantifier, DetachedCriteria dc) {
super(op, quantifier, dc);
super( op, quantifier, dc );
this.propertyName = propertyName;
}
@Override
protected String toLeftSqlString(Criteria criteria, CriteriaQuery criteriaQuery) {
return criteriaQuery.getColumn(criteria, propertyName);
return criteriaQuery.getColumn( criteria, propertyName );
}
}

View File

@ -1,10 +1,10 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
* Copyright (c) 2008, 2013, 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 Middleware LLC.
* 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
@ -20,16 +20,12 @@
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*
*/
package org.hibernate.criterion;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
import org.hibernate.Session;
import org.hibernate.internal.util.collections.ArrayHelper;
import org.hibernate.type.Type;
/**
@ -37,105 +33,130 @@ import org.hibernate.type.Type;
* new kinds of <tt>Criterion</tt>. However, it is intended that most applications will
* simply use the built-in criterion types via the static factory methods of this class.
*
* @see org.hibernate.Criteria
* @see Projections factory methods for <tt>Projection</tt> instances
* See also the {@link Projections} factory methods for generating {@link Projection} instances
*
* @author Gavin King
* @author Steve Ebersole
*
* @see org.hibernate.Criteria
*/
public class Restrictions {
Restrictions() {
//cannot be instantiated
}
/**
* Apply an "equal" constraint to the identifier property
* @param value
*
* @param value The value to use in comparison
*
* @return Criterion
*
* @see IdentifierEqExpression
*/
public static Criterion idEq(Object value) {
return new IdentifierEqExpression(value);
return new IdentifierEqExpression( value );
}
/**
* Apply an "equal" constraint to the named property
* @param propertyName
* @param value
*
* @param propertyName The name of the property
* @param value The value to use in comparison
*
* @return SimpleExpression
*
* @see SimpleExpression
*/
public static SimpleExpression eq(String propertyName, Object value) {
return new SimpleExpression(propertyName, value, "=");
}
/**
* Apply an "equal" constraint to the named property. If the value
* is null, instead apply "is null".
* @param propertyName
* @param value
* @return Criterion
*/
public static Criterion eqOrIsNull(String propertyName, Object value) {
if (value == null) {
return isNull(propertyName);
}
return new SimpleExpression(propertyName, value, "=");
}
/**
* Apply a "not equal" constraint to the named property
* @param propertyName
* @param value
* @return SimpleExpression
*/
public static SimpleExpression ne(String propertyName, Object value) {
return new SimpleExpression(propertyName, value, "<>");
}
/**
* Apply a "not equal" constraint to the named property. If the value
* is null, instead apply "is not null".
* @param propertyName
* @param value
* @return Criterion
*/
public static Criterion neOrIsNotNull(String propertyName, Object value) {
if (value == null) {
return isNotNull(propertyName);
}
return new SimpleExpression(propertyName, value, "<>");
}
/**
* Apply a "like" constraint to the named property
* @param propertyName
* @param value
* @return Criterion
*/
public static SimpleExpression like(String propertyName, Object value) {
return new SimpleExpression(propertyName, value, " like ");
}
/**
* Apply a "like" constraint to the named property
* @param propertyName
* @param value
* @return Criterion
*/
public static SimpleExpression like(String propertyName, String value, MatchMode matchMode) {
return new SimpleExpression(propertyName, matchMode.toMatchString(value), " like " );
return new SimpleExpression( propertyName, value, "=" );
}
/**
* A case-insensitive "like", similar to Postgres <tt>ilike</tt>
* operator
* Apply an "equal" constraint to the named property. If the value
* is null, instead apply "is null".
*
* @param propertyName
* @param value
* @return Criterion
* @param propertyName The name of the property
* @param value The value to use in comparison
*
* @return The Criterion
*
* @see #eq
* @see #isNull
*/
public static Criterion ilike(String propertyName, String value, MatchMode matchMode) {
return new LikeExpression(propertyName, value, matchMode, null, true);
public static Criterion eqOrIsNull(String propertyName, Object value) {
return value == null
? isNull( propertyName )
: eq( propertyName, value );
}
/**
* A case-insensitive "like", similar to Postgres <tt>ilike</tt>
* operator
* Apply a "not equal" constraint to the named property
*
* @param propertyName
* @param value
* @return Criterion
* @param propertyName The name of the property
* @param value The value to use in comparison
*
* @return The Criterion
* @see SimpleExpression
*/
public static SimpleExpression ne(String propertyName, Object value) {
return new SimpleExpression( propertyName, value, "<>" );
}
/**
* Apply a "not equal" constraint to the named property. If the value
* is null, instead apply "is not null".
*
* @param propertyName The name of the property
* @param value The value to use in comparison
*
* @return The Criterion
*
* @see #ne
* @see #isNotNull
*/
public static Criterion neOrIsNotNull(String propertyName, Object value) {
return value == null
? isNotNull( propertyName )
: ne( propertyName, value );
}
/**
* Apply a "like" constraint to the named property
*
* @param propertyName The name of the property
* @param value The value to use in comparison
*
* @return The Criterion
*
* @see SimpleExpression
*/
public static SimpleExpression like(String propertyName, Object value) {
// todo : update this to use LikeExpression
return new SimpleExpression( propertyName, value, " like " );
}
/**
* Apply a "like" constraint to the named property using the provided match mode
*
* @param propertyName The name of the property
* @param value The value to use in comparison
* @param matchMode The match mode to use in comparison
*
* @return The Criterion
*
* @see SimpleExpression
*/
public static SimpleExpression like(String propertyName, String value, MatchMode matchMode) {
// todo : update this to use LikeExpression
return new SimpleExpression( propertyName, matchMode.toMatchString( value ), " like " );
}
/**
* A case-insensitive "like" (similar to Postgres <tt>ilike</tt> operator)
*
* @param propertyName The name of the property
* @param value The value to use in comparison
*
* @return The Criterion
*
* @see LikeExpression
*/
public static Criterion ilike(String propertyName, Object value) {
if ( value == null ) {
@ -144,126 +165,239 @@ public class Restrictions {
return ilike( propertyName, value.toString(), MatchMode.EXACT );
}
/**
* A case-insensitive "like" (similar to Postgres <tt>ilike</tt> operator) using the provided match mode
*
* @param propertyName The name of the property
* @param value The value to use in comparison
* @param matchMode The match mode to use in comparison
*
* @return The Criterion
*
* @see LikeExpression
*/
public static Criterion ilike(String propertyName, String value, MatchMode matchMode) {
if ( value == null ) {
throw new IllegalArgumentException( "Comparison value passed to ilike cannot be null" );
}
return new LikeExpression( propertyName, value, matchMode, null, true );
}
/**
* Apply a "greater than" constraint to the named property
* @param propertyName
* @param value
* @return Criterion
*
* @param propertyName The name of the property
* @param value The value to use in comparison
*
* @return The Criterion
*
* @see SimpleExpression
*/
public static SimpleExpression gt(String propertyName, Object value) {
return new SimpleExpression(propertyName, value, ">");
return new SimpleExpression( propertyName, value, ">" );
}
/**
* Apply a "less than" constraint to the named property
* @param propertyName
* @param value
* @return Criterion
*
* @param propertyName The name of the property
* @param value The value to use in comparison
*
* @return The Criterion
*
* @see SimpleExpression
*/
public static SimpleExpression lt(String propertyName, Object value) {
return new SimpleExpression(propertyName, value, "<");
return new SimpleExpression( propertyName, value, "<" );
}
/**
* Apply a "less than or equal" constraint to the named property
* @param propertyName
* @param value
* @return Criterion
*
* @param propertyName The name of the property
* @param value The value to use in comparison
*
* @return The Criterion
*
* @see SimpleExpression
*/
public static SimpleExpression le(String propertyName, Object value) {
return new SimpleExpression(propertyName, value, "<=");
return new SimpleExpression( propertyName, value, "<=" );
}
/**
* Apply a "greater than or equal" constraint to the named property
* @param propertyName
* @param value
* @return Criterion
*
* @param propertyName The name of the property
* @param value The value to use in comparison
*
* @return The Criterion
*
* @see SimpleExpression
*/
public static SimpleExpression ge(String propertyName, Object value) {
return new SimpleExpression(propertyName, value, ">=");
return new SimpleExpression( propertyName, value, ">=" );
}
/**
* Apply a "between" constraint to the named property
* @param propertyName
* @param lo value
* @param hi value
* @return Criterion
*
* @param propertyName The name of the property
* @param lo The low value
* @param hi The high value
*
* @return The Criterion
*
* @see BetweenExpression
*/
public static Criterion between(String propertyName, Object lo, Object hi) {
return new BetweenExpression(propertyName, lo, hi);
return new BetweenExpression( propertyName, lo, hi );
}
/**
* Apply an "in" constraint to the named property
* @param propertyName
* @param values
* @return Criterion
* Apply an "in" constraint to the named property.
*
* @param propertyName The name of the property
* @param values The literal values to use in the IN restriction
*
* @return The Criterion
*
* @see InExpression
*/
public static Criterion in(String propertyName, Object[] values) {
return new InExpression(propertyName, values);
return new InExpression( propertyName, values );
}
/**
* Apply an "in" constraint to the named property
* @param propertyName
* @param values
* @return Criterion
* Apply an "in" constraint to the named property.
*
* @param propertyName The name of the property
* @param values The literal values to use in the IN restriction
*
* @return The Criterion
*
* @see InExpression
*/
public static Criterion in(String propertyName, Collection values) {
return new InExpression( propertyName, values.toArray() );
}
/**
* Apply an "is null" constraint to the named property
*
* @param propertyName The name of the property
*
* @return Criterion
*
* @see NullExpression
*/
public static Criterion isNull(String propertyName) {
return new NullExpression(propertyName);
}
/**
* Apply an "equal" constraint to two properties
*/
public static PropertyExpression eqProperty(String propertyName, String otherPropertyName) {
return new PropertyExpression(propertyName, otherPropertyName, "=");
}
/**
* Apply a "not equal" constraint to two properties
*/
public static PropertyExpression neProperty(String propertyName, String otherPropertyName) {
return new PropertyExpression(propertyName, otherPropertyName, "<>");
}
/**
* Apply a "less than" constraint to two properties
*/
public static PropertyExpression ltProperty(String propertyName, String otherPropertyName) {
return new PropertyExpression(propertyName, otherPropertyName, "<");
}
/**
* Apply a "less than or equal" constraint to two properties
*/
public static PropertyExpression leProperty(String propertyName, String otherPropertyName) {
return new PropertyExpression(propertyName, otherPropertyName, "<=");
}
/**
* Apply a "greater than" constraint to two properties
*/
public static PropertyExpression gtProperty(String propertyName, String otherPropertyName) {
return new PropertyExpression(propertyName, otherPropertyName, ">");
}
/**
* Apply a "greater than or equal" constraint to two properties
*/
public static PropertyExpression geProperty(String propertyName, String otherPropertyName) {
return new PropertyExpression(propertyName, otherPropertyName, ">=");
return new NullExpression( propertyName );
}
/**
* Apply an "is not null" constraint to the named property
* @return Criterion
*
* @param propertyName The property name
*
* @return The Criterion
*
* @see NotNullExpression
*/
public static Criterion isNotNull(String propertyName) {
return new NotNullExpression(propertyName);
return new NotNullExpression( propertyName );
}
/**
* Apply an "equal" constraint to two properties
*
* @param propertyName One property name
* @param otherPropertyName The other property name
*
* @return The Criterion
*
* @see PropertyExpression
*/
public static PropertyExpression eqProperty(String propertyName, String otherPropertyName) {
return new PropertyExpression( propertyName, otherPropertyName, "=" );
}
/**
* Apply a "not equal" constraint to two properties
*
* @param propertyName One property name
* @param otherPropertyName The other property name
*
* @return The Criterion
*
* @see PropertyExpression
*/
public static PropertyExpression neProperty(String propertyName, String otherPropertyName) {
return new PropertyExpression( propertyName, otherPropertyName, "<>" );
}
/**
* Apply a "less than" constraint to two properties
*
* @param propertyName One property name
* @param otherPropertyName The other property name
*
* @return The Criterion
*
* @see PropertyExpression
*/
public static PropertyExpression ltProperty(String propertyName, String otherPropertyName) {
return new PropertyExpression( propertyName, otherPropertyName, "<" );
}
/**
* Apply a "less than or equal" constraint to two properties
*
* @param propertyName One property name
* @param otherPropertyName The other property name
*
* @return The Criterion
*
* @see PropertyExpression
*/
public static PropertyExpression leProperty(String propertyName, String otherPropertyName) {
return new PropertyExpression( propertyName, otherPropertyName, "<=" );
}
/**
* Apply a "greater than" constraint to two properties
*
* @param propertyName One property name
* @param otherPropertyName The other property name
*
* @return The Criterion
*
* @see PropertyExpression
*/
public static PropertyExpression gtProperty(String propertyName, String otherPropertyName) {
return new PropertyExpression( propertyName, otherPropertyName, ">" );
}
/**
* Apply a "greater than or equal" constraint to two properties
*
* @param propertyName One property name
* @param otherPropertyName The other property name
*
* @return The Criterion
*
* @see PropertyExpression
*/
public static PropertyExpression geProperty(String propertyName, String otherPropertyName) {
return new PropertyExpression( propertyName, otherPropertyName, ">=" );
}
/**
* Return the conjuction of two expressions
*
* @param lhs
* @param rhs
* @return Criterion
* @param lhs One expression
* @param rhs The other expression
*
* @return The Criterion
*/
public static LogicalExpression and(Criterion lhs, Criterion rhs) {
return new LogicalExpression(lhs, rhs, "and");
@ -276,24 +410,21 @@ public class Restrictions {
* @return The conjunction
*/
public static Conjunction and(Criterion... predicates) {
Conjunction conjunction = conjunction();
if ( predicates != null ) {
for ( Criterion predicate : predicates ) {
conjunction.add( predicate );
}
}
return conjunction;
return conjunction( predicates );
}
/**
* Return the disjuction of two expressions
*
* @param lhs
* @param rhs
* @return Criterion
* @param lhs One expression
* @param rhs The other expression
*
* @return The Criterion
*/
public static LogicalExpression or(Criterion lhs, Criterion rhs) {
return new LogicalExpression(lhs, rhs, "or");
return new LogicalExpression( lhs, rhs, "or" );
}
/**
* Return the disjuction of multiple expressions
*
@ -302,62 +433,72 @@ public class Restrictions {
* @return The conjunction
*/
public static Disjunction or(Criterion... predicates) {
Disjunction disjunction = disjunction();
if ( predicates != null ) {
for ( Criterion predicate : predicates ) {
disjunction.add( predicate );
}
}
return disjunction;
}
/**
* Return the negation of an expression
*
* @param expression
* @return Criterion
*/
public static Criterion not(Criterion expression) {
return new NotExpression(expression);
}
/**
* Apply a constraint expressed in SQL, with the given JDBC
* parameters. Any occurrences of <tt>{alias}</tt> will be
* replaced by the table alias.
*
* @param sql
* @param values
* @param types
* @return Criterion
*/
public static Criterion sqlRestriction(String sql, Object[] values, Type[] types) {
return new SQLCriterion(sql, values, types);
}
/**
* Apply a constraint expressed in SQL, with the given JDBC
* parameter. Any occurrences of <tt>{alias}</tt> will be replaced
* by the table alias.
*
* @param sql
* @param value
* @param type
* @return Criterion
*/
public static Criterion sqlRestriction(String sql, Object value, Type type) {
return new SQLCriterion(sql, new Object[] { value }, new Type[] { type } );
}
/**
* Apply a constraint expressed in SQL. Any occurrences of <tt>{alias}</tt>
* will be replaced by the table alias.
*
* @param sql
* @return Criterion
*/
public static Criterion sqlRestriction(String sql) {
return new SQLCriterion(sql, ArrayHelper.EMPTY_OBJECT_ARRAY, ArrayHelper.EMPTY_TYPE_ARRAY);
return disjunction( predicates );
}
/**
* Group expressions together in a single conjunction (A and B and C...)
* Return the negation of an expression
*
* @param expression The expression to be negated
*
* @return Criterion
*
* @see NotExpression
*/
public static Criterion not(Criterion expression) {
return new NotExpression( expression );
}
/**
* Create a restriction expressed in SQL with JDBC parameters. Any occurrences of <tt>{alias}</tt> will be
* replaced by the table alias.
*
* @param sql The SQL restriction
* @param values The parameter values
* @param types The parameter types
*
* @return The Criterion
*
* @see SQLCriterion
*/
public static Criterion sqlRestriction(String sql, Object[] values, Type[] types) {
return new SQLCriterion( sql, values, types );
}
/**
* Create a restriction expressed in SQL with one JDBC parameter. Any occurrences of <tt>{alias}</tt> will be
* replaced by the table alias.
*
* @param sql The SQL restriction
* @param value The parameter value
* @param type The parameter type
*
* @return The Criterion
*
* @see SQLCriterion
*/
public static Criterion sqlRestriction(String sql, Object value, Type type) {
return new SQLCriterion( sql, value, type );
}
/**
* Apply a constraint expressed in SQL with no JDBC parameters. Any occurrences of <tt>{alias}</tt> will be
* replaced by the table alias.
*
* @param sql The SQL restriction
*
* @return The Criterion
*
* @see SQLCriterion
*/
public static Criterion sqlRestriction(String sql) {
return new SQLCriterion( sql );
}
/**
* Group expressions together in a single conjunction (A and B and C...).
*
* This form creates an empty conjunction. See {@link Conjunction#add(Criterion)}
*
* @return Conjunction
*/
@ -366,7 +507,20 @@ public class Restrictions {
}
/**
* Group expressions together in a single disjunction (A or B or C...)
* Group expressions together in a single conjunction (A and B and C...).
*
* @param conditions The initial set of conditions to put into the Conjunction
*
* @return Conjunction
*/
public static Conjunction conjunction(Criterion... conditions) {
return new Conjunction( conditions );
}
/**
* Group expressions together in a single disjunction (A or B or C...).
*
* This form creates an empty disjunction. See {@link Disjunction#add(Criterion)}
*
* @return Conjunction
*/
@ -375,89 +529,169 @@ public class Restrictions {
}
/**
* Apply an "equals" constraint to each property in the
* key set of a <tt>Map</tt>
* Group expressions together in a single disjunction (A or B or C...).
*
* @param conditions The initial set of conditions to put into the Disjunction
*
* @return Conjunction
*/
public static Disjunction disjunction(Criterion... conditions) {
return new Disjunction( conditions );
}
/**
* Apply an "equals" constraint to each property in the key set of a <tt>Map</tt>
*
* @param propertyNameValues a map from property names to values
*
* @return Criterion
*
* @see Conjunction
*/
public static Criterion allEq(Map propertyNameValues) {
Conjunction conj = conjunction();
Iterator iter = propertyNameValues.entrySet().iterator();
while ( iter.hasNext() ) {
Map.Entry me = (Map.Entry) iter.next();
conj.add( eq( (String) me.getKey(), me.getValue() ) );
@SuppressWarnings("UnusedDeclaration")
public static Criterion allEq(Map<String,?> propertyNameValues) {
final Conjunction conj = conjunction();
for ( Map.Entry<String,?> entry : propertyNameValues.entrySet() ) {
conj.add( eq( entry.getKey(), entry.getValue() ) );
}
return conj;
}
/**
* Constrain a collection valued property to be empty
*
* @param propertyName The name of the collection property
*
* @return The Criterion
*
* @see EmptyExpression
*/
public static Criterion isEmpty(String propertyName) {
return new EmptyExpression(propertyName);
return new EmptyExpression( propertyName );
}
/**
* Constrain a collection valued property to be non-empty
*
* @param propertyName The name of the collection property
*
* @return The Criterion
*
* @see NotEmptyExpression
*/
public static Criterion isNotEmpty(String propertyName) {
return new NotEmptyExpression(propertyName);
return new NotEmptyExpression( propertyName );
}
/**
* Constrain a collection valued property by size
*
* @param propertyName The name of the collection property
* @param size The size to use in comparison
*
* @return The Criterion
*
* @see SizeExpression
*/
public static Criterion sizeEq(String propertyName, int size) {
return new SizeExpression(propertyName, size, "=");
return new SizeExpression( propertyName, size, "=" );
}
/**
* Constrain a collection valued property by size
*
* @param propertyName The name of the collection property
* @param size The size to use in comparison
*
* @return The Criterion
*
* @see SizeExpression
*/
@SuppressWarnings("UnusedDeclaration")
public static Criterion sizeNe(String propertyName, int size) {
return new SizeExpression(propertyName, size, "<>");
return new SizeExpression( propertyName, size, "<>" );
}
/**
* Constrain a collection valued property by size
*
* @param propertyName The name of the collection property
* @param size The size to use in comparison
*
* @return The Criterion
*
* @see SizeExpression
*/
@SuppressWarnings("UnusedDeclaration")
public static Criterion sizeGt(String propertyName, int size) {
return new SizeExpression(propertyName, size, "<");
return new SizeExpression( propertyName, size, "<" );
}
/**
* Constrain a collection valued property by size
*
* @param propertyName The name of the collection property
* @param size The size to use in comparison
*
* @return The Criterion
*
* @see SizeExpression
*/
@SuppressWarnings("UnusedDeclaration")
public static Criterion sizeLt(String propertyName, int size) {
return new SizeExpression(propertyName, size, ">");
return new SizeExpression( propertyName, size, ">" );
}
/**
* Constrain a collection valued property by size
*
* @param propertyName The name of the collection property
* @param size The size to use in comparison
*
* @return The Criterion
*
* @see SizeExpression
*/
@SuppressWarnings("UnusedDeclaration")
public static Criterion sizeGe(String propertyName, int size) {
return new SizeExpression(propertyName, size, "<=");
return new SizeExpression( propertyName, size, "<=" );
}
/**
* Constrain a collection valued property by size
*
* @param propertyName The name of the collection property
* @param size The size to use in comparison
*
* @return The Criterion
*
* @see SizeExpression
*/
@SuppressWarnings("UnusedDeclaration")
public static Criterion sizeLe(String propertyName, int size) {
return new SizeExpression(propertyName, size, ">=");
return new SizeExpression( propertyName, size, ">=" );
}
/**
* Consider using any of the natural id based loading stuff from session instead, especially in cases
* where the restriction is the full set of natural id values.
*
* @see Session#byNaturalId(Class)
* @see Session#byNaturalId(String)
* @see Session#bySimpleNaturalId(Class)
* @see Session#bySimpleNaturalId(String)
* @return The Criterion
*
* @see NaturalIdentifier
*
* @see org.hibernate.Session#byNaturalId(Class)
* @see org.hibernate.Session#byNaturalId(String)
* @see org.hibernate.Session#bySimpleNaturalId(Class)
* @see org.hibernate.Session#bySimpleNaturalId(String)
*/
public static NaturalIdentifier naturalId() {
return new NaturalIdentifier();
}
protected Restrictions() {
// cannot be instantiated, but needs to be protected so Expression can extend it
}
}

View File

@ -1,7 +1,7 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2010, Red Hat Inc. or third-party contributors as
* Copyright (c) 2010, 2013, 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.
@ -22,11 +22,13 @@
* Boston, MA 02110-1301 USA
*/
package org.hibernate.criterion;
import java.util.List;
import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.dialect.function.SQLFunction;
import org.hibernate.dialect.function.SQLFunctionRegistry;
import org.hibernate.type.Type;
/**
@ -35,30 +37,30 @@ import org.hibernate.type.Type;
* @author Gavin King
*/
public class RowCountProjection extends SimpleProjection {
private static List ARGS = java.util.Collections.singletonList( "*" );
public String toString() {
return "count(*)";
}
private static final List ARGS = java.util.Collections.singletonList( "*" );
@Override
public Type[] getTypes(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException {
return new Type[] {
getFunction( criteriaQuery ).getReturnType( null, criteriaQuery.getFactory() )
};
final Type countFunctionReturnType = getFunction( criteriaQuery ).getReturnType( null, criteriaQuery.getFactory() );
return new Type[] { countFunctionReturnType };
}
@Override
public String toSqlString(Criteria criteria, int position, CriteriaQuery criteriaQuery) throws HibernateException {
return getFunction( criteriaQuery ).render( null, ARGS, criteriaQuery.getFactory() )
+ " as y" + position + '_';
return getFunction( criteriaQuery ).render( null, ARGS, criteriaQuery.getFactory() ) + " as y" + position + '_';
}
protected SQLFunction getFunction(CriteriaQuery criteriaQuery) {
SQLFunction function = criteriaQuery.getFactory()
.getSqlFunctionRegistry()
.findSQLFunction( "count" );
final SQLFunctionRegistry sqlFunctionRegistry = criteriaQuery.getFactory().getSqlFunctionRegistry();
final SQLFunction function = sqlFunctionRegistry.findSQLFunction( "count" );
if ( function == null ) {
throw new HibernateException( "Unable to locate count function mapping" );
}
return function;
}
@Override
public String toString() {
return "count(*)";
}
}

View File

@ -1,10 +1,10 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
* Copyright (c) 2008, 2013, 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 Middleware LLC.
* 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
@ -20,12 +20,10 @@
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*
*/
package org.hibernate.criterion;
import org.hibernate.Criteria;
import org.hibernate.EntityMode;
import org.hibernate.HibernateException;
import org.hibernate.engine.spi.TypedValue;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.type.Type;
@ -35,32 +33,39 @@ import org.hibernate.type.Type;
* alias of the root entity.
*/
public class SQLCriterion implements Criterion {
private final String sql;
private final TypedValue[] typedValues;
public String toSqlString(
Criteria criteria,
CriteriaQuery criteriaQuery)
throws HibernateException {
return StringHelper.replace( sql, "{alias}", criteriaQuery.getSQLAlias( criteria ) );
}
public TypedValue[] getTypedValues(Criteria criteria, CriteriaQuery criteriaQuery)
throws HibernateException {
return typedValues;
}
public String toString() {
return sql;
}
protected SQLCriterion(String sql, Object[] values, Type[] types) {
this.sql = sql;
typedValues = new TypedValue[values.length];
this.typedValues = new TypedValue[values.length];
for ( int i=0; i<typedValues.length; i++ ) {
typedValues[i] = new TypedValue( types[i], values[i], EntityMode.POJO );
typedValues[i] = new TypedValue( types[i], values[i] );
}
}
protected SQLCriterion(String sql, Object value, Type type) {
this.sql = sql;
this.typedValues = new TypedValue[] { new TypedValue( type, value ) };
}
protected SQLCriterion(String sql) {
this.sql = sql;
this.typedValues = new TypedValue[0];
}
@Override
public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery) {
return StringHelper.replace( sql, "{alias}", criteriaQuery.getSQLAlias( criteria ) );
}
@Override
public TypedValue[] getTypedValues(Criteria criteria, CriteriaQuery criteriaQuery) {
return typedValues;
}
@Override
public String toString() {
return sql;
}
}

View File

@ -1,10 +1,10 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
* Copyright (c) 2008, 2013, 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 Middleware LLC.
* 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
@ -20,11 +20,10 @@
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*
*/
package org.hibernate.criterion;
import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.type.Type;
@ -33,7 +32,6 @@ import org.hibernate.type.Type;
* alias of the root entity.
*/
public class SQLProjection implements Projection {
private final String sql;
private final String groupBy;
private final Type[] types;
@ -41,30 +39,8 @@ public class SQLProjection implements Projection {
private String[] columnAliases;
private boolean grouped;
public String toSqlString(
Criteria criteria,
int loc,
CriteriaQuery criteriaQuery)
throws HibernateException {
return StringHelper.replace( sql, "{alias}", criteriaQuery.getSQLAlias(criteria) );
}
public String toGroupSqlString(Criteria criteria, CriteriaQuery criteriaQuery)
throws HibernateException {
return StringHelper.replace( groupBy, "{alias}", criteriaQuery.getSQLAlias( criteria ) );
}
public Type[] getTypes(Criteria crit, CriteriaQuery criteriaQuery)
throws HibernateException {
return types;
}
public String toString() {
return sql;
}
protected SQLProjection(String sql, String[] columnAliases, Type[] types) {
this(sql, null, columnAliases, types);
this( sql, null, columnAliases, types );
}
protected SQLProjection(String sql, String groupBy, String[] columnAliases, Type[] types) {
@ -76,23 +52,48 @@ public class SQLProjection implements Projection {
this.groupBy = groupBy;
}
@Override
public String toSqlString(Criteria criteria, int loc, CriteriaQuery criteriaQuery) {
return StringHelper.replace( sql, "{alias}", criteriaQuery.getSQLAlias( criteria ) );
}
@Override
public String toGroupSqlString(Criteria criteria, CriteriaQuery criteriaQuery) {
return StringHelper.replace( groupBy, "{alias}", criteriaQuery.getSQLAlias( criteria ) );
}
@Override
public Type[] getTypes(Criteria crit, CriteriaQuery criteriaQuery) {
return types;
}
@Override
public String toString() {
return sql;
}
@Override
public String[] getAliases() {
return aliases;
}
@Override
public String[] getColumnAliases(int loc) {
return columnAliases;
}
@Override
public boolean isGrouped() {
return grouped;
}
@Override
public Type[] getTypes(String alias, Criteria crit, CriteriaQuery criteriaQuery) {
return null; //unsupported
return null;
}
@Override
public String[] getColumnAliases(String alias, int loc) {
return null; //unsupported
return null;
}
}

View File

@ -1,7 +1,7 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2008-2012, Red Hat Inc. or third-party contributors as
* Copyright (c) 2008, 2012, 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.
@ -55,55 +55,6 @@ public class SimpleExpression implements Criterion {
this.op = op;
}
public SimpleExpression ignoreCase() {
ignoreCase = true;
return this;
}
public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery)
throws HibernateException {
String[] columns = criteriaQuery.findColumns( propertyName, criteria );
Type type = criteriaQuery.getTypeUsingProjection( criteria, propertyName );
StringBuilder fragment = new StringBuilder();
if ( columns.length > 1 ) {
fragment.append( '(' );
}
SessionFactoryImplementor factory = criteriaQuery.getFactory();
int[] sqlTypes = type.sqlTypes( factory );
for ( int i = 0; i < columns.length; i++ ) {
boolean lower = ignoreCase &&
(sqlTypes[i] == Types.VARCHAR || sqlTypes[i] == Types.CHAR);
if ( lower ) {
fragment.append( factory.getDialect().getLowercaseFunction() )
.append( '(' );
}
fragment.append( columns[i] );
if ( lower ) {
fragment.append( ')' );
}
fragment.append( getOp() ).append( "?" );
if ( i < columns.length - 1 ) {
fragment.append( " and " );
}
}
if ( columns.length > 1 ) {
fragment.append( ')' );
}
return fragment.toString();
}
public TypedValue[] getTypedValues(Criteria criteria, CriteriaQuery criteriaQuery)
throws HibernateException {
Object icvalue = ignoreCase ? value.toString().toLowerCase() : value;
return new TypedValue[] {criteriaQuery.getTypedValue( criteria, propertyName, icvalue )};
}
public String toString() {
return propertyName + getOp() + value;
}
protected final String getOp() {
return op;
}
@ -115,4 +66,58 @@ public class SimpleExpression implements Criterion {
public Object getValue() {
return value;
}
/**
* Make case insensitive. No effect for non-String values
*
* @return {@code this}, for method chaining
*/
public SimpleExpression ignoreCase() {
ignoreCase = true;
return this;
}
@Override
public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException {
final String[] columns = criteriaQuery.findColumns( propertyName, criteria );
final Type type = criteriaQuery.getTypeUsingProjection( criteria, propertyName );
final StringBuilder fragment = new StringBuilder();
if ( columns.length > 1 ) {
fragment.append( '(' );
}
final SessionFactoryImplementor factory = criteriaQuery.getFactory();
final int[] sqlTypes = type.sqlTypes( factory );
for ( int i = 0; i < columns.length; i++ ) {
final boolean lower = ignoreCase && (sqlTypes[i] == Types.VARCHAR || sqlTypes[i] == Types.CHAR);
if ( lower ) {
fragment.append( factory.getDialect().getLowercaseFunction() ).append( '(' );
}
fragment.append( columns[i] );
if ( lower ) {
fragment.append( ')' );
}
fragment.append( getOp() ).append( "?" );
if ( i < columns.length - 1 ) {
fragment.append( " and " );
}
}
if ( columns.length > 1 ) {
fragment.append( ')' );
}
return fragment.toString();
}
@Override
public TypedValue[] getTypedValues(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException {
final Object casedValue = ignoreCase ? value.toString().toLowerCase() : value;
return new TypedValue[] { criteriaQuery.getTypedValue( criteria, propertyName, casedValue ) };
}
@Override
public String toString() {
return propertyName + getOp() + value;
}
}

View File

@ -1,10 +1,10 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
* Copyright (c) 2008, 2013, 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 Middleware LLC.
* 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
@ -20,28 +20,23 @@
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*
*/
package org.hibernate.criterion;
import org.hibernate.Criteria;
import org.hibernate.type.Type;
/**
* A single-column projection that may be aliased
*
* @author Gavin King
*/
public abstract class SimpleProjection implements EnhancedProjection {
private static final int NUM_REUSABLE_ALIASES = 40;
private static final String[] reusableAliases = initializeReusableAliases();
public Projection as(String alias) {
return Projections.alias(this, alias);
}
private static final String[] REUSABLE_ALIASES = initializeReusableAliases();
private static String[] initializeReusableAliases() {
String[] aliases = new String[NUM_REUSABLE_ALIASES];
final String[] aliases = new String[NUM_REUSABLE_ALIASES];
for ( int i = 0; i < NUM_REUSABLE_ALIASES; i++ ) {
aliases[i] = aliasForLocation( i );
}
@ -57,38 +52,62 @@ public abstract class SimpleProjection implements EnhancedProjection {
return aliasForLocation( loc );
}
else {
return reusableAliases[loc];
return REUSABLE_ALIASES[loc];
}
}
/**
* Create an aliased form of this projection
*
* @param alias The alias to apply
*
* @return The aliased projection
*/
public Projection as(String alias) {
return Projections.alias( this, alias );
}
@Override
public String[] getColumnAliases(String alias, int loc) {
return null;
}
@Override
public String[] getColumnAliases(String alias, int loc, Criteria criteria, CriteriaQuery criteriaQuery) {
return getColumnAliases( alias, loc );
}
@Override
public Type[] getTypes(String alias, Criteria criteria, CriteriaQuery criteriaQuery) {
return null;
}
@Override
public String[] getColumnAliases(int loc) {
return new String[] { getAliasForLocation( loc ) };
}
/**
* Count the number of columns this projection uses.
*
* @param criteria The criteria
* @param criteriaQuery The query
*
* @return The number of columns
*/
public int getColumnCount(Criteria criteria, CriteriaQuery criteriaQuery) {
Type types[] = getTypes( criteria, criteriaQuery );
final Type[] types = getTypes( criteria, criteriaQuery );
int count = 0;
for ( int i=0; i<types.length; i++ ) {
count += types[ i ].getColumnSpan( criteriaQuery.getFactory() );
for ( Type type : types ) {
count += type.getColumnSpan( criteriaQuery.getFactory() );
}
return count;
}
@Override
public String[] getColumnAliases(int loc, Criteria criteria, CriteriaQuery criteriaQuery) {
int numColumns = getColumnCount( criteria, criteriaQuery );
String[] aliases = new String[ numColumns ];
final int numColumns = getColumnCount( criteria, criteriaQuery );
final String[] aliases = new String[ numColumns ];
for (int i = 0; i < numColumns; i++) {
aliases[i] = getAliasForLocation( loc );
loc++;
@ -96,14 +115,17 @@ public abstract class SimpleProjection implements EnhancedProjection {
return aliases;
}
@Override
public String[] getAliases() {
return new String[1];
}
@Override
public String toGroupSqlString(Criteria criteria, CriteriaQuery criteriaQuery) {
throw new UnsupportedOperationException("not a grouping projection");
throw new UnsupportedOperationException( "not a grouping projection" );
}
@Override
public boolean isGrouped() {
return false;
}

View File

@ -1,10 +1,10 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
* Copyright (c) 2008, 2013, 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 Middleware LLC.
* 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
@ -20,37 +20,36 @@
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*
*/
package org.hibernate.criterion;
import org.hibernate.Criteria;
import org.hibernate.EntityMode;
import org.hibernate.HibernateException;
import org.hibernate.engine.spi.TypedValue;
/**
* A comparison between a constant value and the the result of a subquery
*
* @author Gavin King
*/
public class SimpleSubqueryExpression extends SubqueryExpression {
private Object value;
protected SimpleSubqueryExpression(Object value, String op, String quantifier, DetachedCriteria dc) {
super(op, quantifier, dc);
super( op, quantifier, dc );
this.value = value;
}
public TypedValue[] getTypedValues(Criteria criteria, CriteriaQuery criteriaQuery)
throws HibernateException {
TypedValue[] superTv = super.getTypedValues(criteria, criteriaQuery);
TypedValue[] result = new TypedValue[superTv.length+1];
System.arraycopy(superTv, 0, result, 1, superTv.length);
result[0] = new TypedValue( getTypes()[0], value, EntityMode.POJO );
@Override
public TypedValue[] getTypedValues(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException {
final TypedValue[] subQueryTypedValues = super.getTypedValues( criteria, criteriaQuery );
final TypedValue[] result = new TypedValue[subQueryTypedValues.length+1];
System.arraycopy( subQueryTypedValues, 0, result, 1, subQueryTypedValues.length );
result[0] = new TypedValue( getTypes()[0], value );
return result;
}
@Override
protected String toLeftSqlString(Criteria criteria, CriteriaQuery criteriaQuery) {
return "?";
}

View File

@ -1,7 +1,7 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2008-2011, Red Hat Inc. or third-party contributors as
* Copyright (c) 2008, 2011, 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.
@ -24,7 +24,6 @@
package org.hibernate.criterion;
import org.hibernate.Criteria;
import org.hibernate.EntityMode;
import org.hibernate.HibernateException;
import org.hibernate.engine.spi.TypedValue;
import org.hibernate.persister.collection.QueryableCollection;
@ -33,10 +32,12 @@ import org.hibernate.sql.ConditionFragment;
import org.hibernate.type.StandardBasicTypes;
/**
* Used to define a restriction on a collection property based on its size.
*
* @author Gavin King
* @author Steve Ebersole
*/
public class SizeExpression implements Criterion {
private final String propertyName;
private final int size;
private final String op;
@ -47,38 +48,35 @@ public class SizeExpression implements Criterion {
this.op = op;
}
@Override
public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException {
final String entityName =criteriaQuery.getEntityName( criteria, propertyName );
final String role = entityName + '.' + criteriaQuery.getPropertyName( propertyName );
final QueryableCollection cp = (QueryableCollection) criteriaQuery.getFactory().getCollectionPersister( role );
final String[] fk = cp.getKeyColumnNames();
final String[] pk = ( (Loadable) cp.getOwnerEntityPersister() ).getIdentifierColumnNames();
final ConditionFragment subQueryRestriction = new ConditionFragment()
.setTableAlias( criteriaQuery.getSQLAlias( criteria, propertyName ) )
.setCondition( pk, fk );
return String.format(
"? %s (select count(*) from %s where %s)",
op,
cp.getTableName(),
subQueryRestriction.toFragmentString()
);
}
@Override
public TypedValue[] getTypedValues(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException {
return new TypedValue[] { new TypedValue( StandardBasicTypes.INTEGER, size ) };
}
@Override
public String toString() {
return propertyName + ".size" + op + size;
}
public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery)
throws HibernateException {
String role = criteriaQuery.getEntityName(criteria, propertyName) +
'.' +
criteriaQuery.getPropertyName(propertyName);
QueryableCollection cp = (QueryableCollection) criteriaQuery.getFactory()
.getCollectionPersister(role);
//String[] fk = StringHelper.qualify( "collection_", cp.getKeyColumnNames() );
String[] fk = cp.getKeyColumnNames();
String[] pk = ( (Loadable) cp.getOwnerEntityPersister() ).getIdentifierColumnNames(); //TODO: handle property-ref
return "? " +
op +
" (select count(*) from " +
cp.getTableName() +
//" collection_ where " +
" where " +
new ConditionFragment()
.setTableAlias( criteriaQuery.getSQLAlias(criteria, propertyName) )
.setCondition(pk, fk)
.toFragmentString() +
")";
}
public TypedValue[] getTypedValues(Criteria criteria, CriteriaQuery criteriaQuery)
throws HibernateException {
return new TypedValue[] {
new TypedValue( StandardBasicTypes.INTEGER, size, EntityMode.POJO )
};
}
}

View File

@ -37,165 +37,612 @@ package org.hibernate.criterion;
@SuppressWarnings( {"UnusedDeclaration"})
public class Subqueries {
/**
* Creates a criterion which checks for the existence of rows in the subquery result
*
* @param dc The detached criteria representing the subquery
*
* @return The Criterion
*
* @see ExistsSubqueryExpression
*/
public static Criterion exists(DetachedCriteria dc) {
return new ExistsSubqueryExpression("exists", dc);
return new ExistsSubqueryExpression( "exists", dc );
}
/**
* Creates a criterion which checks for the non-existence of rows in the subquery result
*
* @param dc The detached criteria representing the subquery
*
* @return The Criterion
*
* @see ExistsSubqueryExpression
*/
public static Criterion notExists(DetachedCriteria dc) {
return new ExistsSubqueryExpression("not exists", dc);
return new ExistsSubqueryExpression( "not exists", dc );
}
/**
* Creates a criterion which checks that the value of a given property equals ALL the values in the
* subquery result.
*
* @param propertyName The name of the property to use in comparison
* @param dc The detached criteria representing the subquery
*
* @return The Criterion
*
* @see PropertySubqueryExpression
*/
public static Criterion propertyEqAll(String propertyName, DetachedCriteria dc) {
return new PropertySubqueryExpression(propertyName, "=", "all", dc);
return new PropertySubqueryExpression( propertyName, "=", "all", dc );
}
/**
* Creates a criterion which checks that the value of a given property is greater-than ALL the values in the
* subquery result.
*
* @param propertyName The name of the property to use in comparison
* @param dc The detached criteria representing the subquery
*
* @return The Criterion
*
* @see PropertySubqueryExpression
*/
public static Criterion propertyGtAll(String propertyName, DetachedCriteria dc) {
return new PropertySubqueryExpression( propertyName, ">", "all", dc );
}
/**
* Creates a criterion which checks that the value of a given property is less-than ALL the values in the
* subquery result.
*
* @param propertyName The name of the property to use in comparison
* @param dc The detached criteria representing the subquery
*
* @return The Criterion
*
* @see PropertySubqueryExpression
*/
public static Criterion propertyLtAll(String propertyName, DetachedCriteria dc) {
return new PropertySubqueryExpression( propertyName, "<", "all", dc );
}
/**
* Creates a criterion which checks that the value of a given property is greater-than-or-equal-to ALL the
* values in the subquery result.
*
* @param propertyName The name of the property to use in comparison
* @param dc The detached criteria representing the subquery
*
* @return The Criterion
*
* @see PropertySubqueryExpression
*/
public static Criterion propertyGeAll(String propertyName, DetachedCriteria dc) {
return new PropertySubqueryExpression( propertyName, ">=", "all", dc );
}
/**
* Creates a criterion which checks that the value of a given property is less-than-or-equal-to ALL the
* values in the subquery result.
*
* @param propertyName The name of the property to use in comparison
* @param dc The detached criteria representing the subquery
*
* @return The Criterion
*
* @see PropertySubqueryExpression
*/
public static Criterion propertyLeAll(String propertyName, DetachedCriteria dc) {
return new PropertySubqueryExpression( propertyName, "<=", "all", dc );
}
/**
* Creates a criterion which checks that the value of a given property is greater-than SOME of the
* values in the subquery result.
*
* @param propertyName The name of the property to use in comparison
* @param dc The detached criteria representing the subquery
*
* @return The Criterion
*
* @see PropertySubqueryExpression
*/
public static Criterion propertyGtSome(String propertyName, DetachedCriteria dc) {
return new PropertySubqueryExpression( propertyName, ">", "some", dc );
}
/**
* Creates a criterion which checks that the value of a given property is less-than SOME of the
* values in the subquery result.
*
* @param propertyName The name of the property to use in comparison
* @param dc The detached criteria representing the subquery
*
* @return The Criterion
*
* @see PropertySubqueryExpression
*/
public static Criterion propertyLtSome(String propertyName, DetachedCriteria dc) {
return new PropertySubqueryExpression( propertyName, "<", "some", dc );
}
/**
* Creates a criterion which checks that the value of a given property is greater-than-or-equal-to SOME of the
* values in the subquery result.
*
* @param propertyName The name of the property to use in comparison
* @param dc The detached criteria representing the subquery
*
* @return The Criterion
*
* @see PropertySubqueryExpression
*/
public static Criterion propertyGeSome(String propertyName, DetachedCriteria dc) {
return new PropertySubqueryExpression( propertyName, ">=", "some", dc );
}
/**
* Creates a criterion which checks that the value of a given property is less-than-or-equal-to SOME of the
* values in the subquery result.
*
* @param propertyName The name of the property to use in comparison
* @param dc The detached criteria representing the subquery
*
* @return The Criterion
*
* @see PropertySubqueryExpression
*/
public static Criterion propertyLeSome(String propertyName, DetachedCriteria dc) {
return new PropertySubqueryExpression( propertyName, "<=", "some", dc );
}
/**
* Creates a criterion which checks that the value of a given property is in the set of values in the
* subquery result.
*
* @param propertyName The name of the property to use in comparison
* @param dc The detached criteria representing the subquery
*
* @return The Criterion
*
* @see PropertySubqueryExpression
*/
public static Criterion propertyIn(String propertyName, DetachedCriteria dc) {
return new PropertySubqueryExpression(propertyName, "in", null, dc);
return new PropertySubqueryExpression( propertyName, "in", null, dc );
}
/**
* Creates a criterion which checks that the value of a given property is not-in the set of values in
* the subquery result.
*
* @param propertyName The name of the property to use in comparison
* @param dc The detached criteria representing the subquery
*
* @return The Criterion
*
* @see PropertySubqueryExpression
*/
public static Criterion propertyNotIn(String propertyName, DetachedCriteria dc) {
return new PropertySubqueryExpression(propertyName, "not in", null, dc);
return new PropertySubqueryExpression( propertyName, "not in", null, dc );
}
/**
* Creates a criterion which checks that the value of a given property as being equal to the set of values in
* the subquery result. The implication is that the subquery returns a single result..
*
* @param propertyName The name of the property to use in comparison
* @param dc The detached criteria representing the subquery
*
* @return The Criterion
*
* @see PropertySubqueryExpression
*/
public static Criterion propertyEq(String propertyName, DetachedCriteria dc) {
return new PropertySubqueryExpression(propertyName, "=", null, dc);
}
public static Criterion propertiesEq(String[] propertyNames, DetachedCriteria dc) {
return new PropertiesSubqueryExpression(propertyNames, "=", dc);
}
public static Criterion propertiesNotEq(String[] propertyNames, DetachedCriteria dc) {
return new PropertiesSubqueryExpression(propertyNames, "<>", dc);
}
public static Criterion propertiesIn(String[] propertyNames, DetachedCriteria dc) {
return new PropertiesSubqueryExpression(propertyNames, "in", dc);
}
public static Criterion propertiesNotIn(String[] propertyNames, DetachedCriteria dc) {
return new PropertiesSubqueryExpression(propertyNames, "not in", dc);
return new PropertySubqueryExpression( propertyName, "=", null, dc );
}
/**
* Creates a criterion which checks that the value of a given property is not equal to the value in the
* subquery result. The assumption is that the subquery returns a single result.
*
* @param propertyName The name of the property to use in comparison
* @param dc The detached criteria representing the subquery
*
* @return The Criterion
*
* @see PropertySubqueryExpression
*/
public static Criterion propertyNe(String propertyName, DetachedCriteria dc) {
return new PropertySubqueryExpression(propertyName, "<>", null, dc);
}
/**
* Creates a criterion which checks that the value of a given property is greater-than the value in the
* subquery result. The assumption is that the subquery returns a single result.
*
* @param propertyName The name of the property to use in comparison
* @param dc The detached criteria representing the subquery
*
* @return The Criterion
*
* @see PropertySubqueryExpression
* @see #propertyGtAll
* @see #propertyGtSome
*/
public static Criterion propertyGt(String propertyName, DetachedCriteria dc) {
return new PropertySubqueryExpression(propertyName, ">", null, dc);
return new PropertySubqueryExpression( propertyName, ">", null, dc );
}
/**
* Creates a criterion which checks that the value of a given property is less-than the value in the
* subquery result. The assumption is that the subquery returns a single result.
*
* @param propertyName The name of the property to use in comparison
* @param dc The detached criteria representing the subquery
*
* @return The Criterion
*
* @see PropertySubqueryExpression
* @see #propertyLtAll
* @see #propertyLtSome
*/
public static Criterion propertyLt(String propertyName, DetachedCriteria dc) {
return new PropertySubqueryExpression(propertyName, "<", null, dc);
return new PropertySubqueryExpression( propertyName, "<", null, dc );
}
/**
* Creates a criterion which checks that the value of a given property is greater-than-or-equal-to the value
* in the subquery result. The assumption is that the subquery returns a single result.
*
* @param propertyName The name of the property to use in comparison
* @param dc The detached criteria representing the subquery
*
* @return The Criterion
*
* @see PropertySubqueryExpression
* @see #propertyGeAll
* @see #propertyGeSome
*/
public static Criterion propertyGe(String propertyName, DetachedCriteria dc) {
return new PropertySubqueryExpression(propertyName, ">=", null, dc);
return new PropertySubqueryExpression( propertyName, ">=", null, dc );
}
/**
* Creates a criterion which checks that the value of a given property is less-than-or-equal-to the value
* in the subquery result. The assumption is that the subquery returns a single result.
*
* @param propertyName The name of the property to use in comparison
* @param dc The detached criteria representing the subquery
*
* @return The Criterion
*
* @see PropertySubqueryExpression
* @see #propertyLeAll
* @see #propertyLeSome
*/
public static Criterion propertyLe(String propertyName, DetachedCriteria dc) {
return new PropertySubqueryExpression(propertyName, "<=", null, dc);
return new PropertySubqueryExpression( propertyName, "<=", null, dc );
}
public static Criterion propertyGtAll(String propertyName, DetachedCriteria dc) {
return new PropertySubqueryExpression(propertyName, ">", "all", dc);
/**
* Creates a criterion which checks that the value of multiple given properties as being equal to the set of
* values in the subquery result. The implication is that the subquery returns a single result. This form is
* however implicitly using tuple comparisons
*
* @param propertyNames The names of the properties to use in comparison
* @param dc The detached criteria representing the subquery
*
* @return The Criterion
*
* @see PropertiesSubqueryExpression
*/
public static Criterion propertiesEq(String[] propertyNames, DetachedCriteria dc) {
return new PropertiesSubqueryExpression( propertyNames, "=", dc );
}
public static Criterion propertyLtAll(String propertyName, DetachedCriteria dc) {
return new PropertySubqueryExpression(propertyName, "<", "all", dc);
/**
* Creates a criterion which checks that the value of multiple given properties as being not-equal to the set of
* values in the subquery result. The assumption is that the subquery returns a single result. This form is
* however implicitly using tuple comparisons
*
* @param propertyNames The names of the properties to use in comparison
* @param dc The detached criteria representing the subquery
*
* @return The Criterion
*
* @see PropertiesSubqueryExpression
*/
public static Criterion propertiesNotEq(String[] propertyNames, DetachedCriteria dc) {
return new PropertiesSubqueryExpression( propertyNames, "<>", dc );
}
public static Criterion propertyGeAll(String propertyName, DetachedCriteria dc) {
return new PropertySubqueryExpression(propertyName, ">=", "all", dc);
/**
* Creates a criterion which checks that the value of multiple given properties as being in to the set of
* values in the subquery result. This form is implicitly using tuple comparisons
*
* @param propertyNames The names of the properties to use in comparison
* @param dc The detached criteria representing the subquery
*
* @return The Criterion
*
* @see PropertiesSubqueryExpression
*/
public static Criterion propertiesIn(String[] propertyNames, DetachedCriteria dc) {
return new PropertiesSubqueryExpression( propertyNames, "in", dc );
}
public static Criterion propertyLeAll(String propertyName, DetachedCriteria dc) {
return new PropertySubqueryExpression(propertyName, "<=", "all", dc);
}
public static Criterion propertyGtSome(String propertyName, DetachedCriteria dc) {
return new PropertySubqueryExpression(propertyName, ">", "some", dc);
}
public static Criterion propertyLtSome(String propertyName, DetachedCriteria dc) {
return new PropertySubqueryExpression(propertyName, "<", "some", dc);
}
public static Criterion propertyGeSome(String propertyName, DetachedCriteria dc) {
return new PropertySubqueryExpression(propertyName, ">=", "some", dc);
}
public static Criterion propertyLeSome(String propertyName, DetachedCriteria dc) {
return new PropertySubqueryExpression(propertyName, "<=", "some", dc);
/**
* Creates a criterion which checks that the value of multiple given properties as being not-in to the set of
* values in the subquery result. This form is implicitly using tuple comparisons
*
* @param propertyNames The names of the properties to use in comparison
* @param dc The detached criteria representing the subquery
*
* @return The Criterion
*
* @see PropertiesSubqueryExpression
*/
public static Criterion propertiesNotIn(String[] propertyNames, DetachedCriteria dc) {
return new PropertiesSubqueryExpression( propertyNames, "not in", dc );
}
/**
* Creates a criterion which checks that the value of a literal equals ALL the values in the
* subquery result.
*
* @param value The literal value to use in comparison
* @param dc The detached criteria representing the subquery
*
* @return The Criterion
*
* @see SimpleSubqueryExpression
*/
public static Criterion eqAll(Object value, DetachedCriteria dc) {
return new SimpleSubqueryExpression(value, "=", "all", dc);
return new SimpleSubqueryExpression( value, "=", "all", dc );
}
/**
* Creates a criterion which checks that the value of a literal is greater-than ALL the values in the
* subquery result.
*
* @param value The literal value to use in comparison
* @param dc The detached criteria representing the subquery
*
* @return The Criterion
*
* @see SimpleSubqueryExpression
*/
public static Criterion gtAll(Object value, DetachedCriteria dc) {
return new SimpleSubqueryExpression( value, ">", "all", dc );
}
/**
* Creates a criterion which checks that the value of a literal is less-than ALL the values in the
* subquery result.
*
* @param value The literal value to use in comparison
* @param dc The detached criteria representing the subquery
*
* @return The Criterion
*
* @see SimpleSubqueryExpression
*/
public static Criterion ltAll(Object value, DetachedCriteria dc) {
return new SimpleSubqueryExpression( value, "<", "all", dc );
}
/**
* Creates a criterion which checks that the value of a literal is greater-than-or-equal-to ALL the values in the
* subquery result.
*
* @param value The literal value to use in comparison
* @param dc The detached criteria representing the subquery
*
* @return The Criterion
*
* @see SimpleSubqueryExpression
*/
public static Criterion geAll(Object value, DetachedCriteria dc) {
return new SimpleSubqueryExpression( value, ">=", "all", dc );
}
/**
* Creates a criterion which checks that the value of a literal is less-than-or-equal-to ALL the values in the
* subquery result.
*
* @param value The literal value to use in comparison
* @param dc The detached criteria representing the subquery
*
* @return The Criterion
*
* @see SimpleSubqueryExpression
*/
public static Criterion leAll(Object value, DetachedCriteria dc) {
return new SimpleSubqueryExpression( value, "<=", "all", dc );
}
/**
* Creates a criterion which checks that the value of a literal is greater-than SOME of the values in the
* subquery result.
*
* @param value The literal value to use in comparison
* @param dc The detached criteria representing the subquery
*
* @return The Criterion
*
* @see SimpleSubqueryExpression
*/
public static Criterion gtSome(Object value, DetachedCriteria dc) {
return new SimpleSubqueryExpression( value, ">", "some", dc );
}
/**
* Creates a criterion which checks that the value of a literal is less-than SOME of the values in the
* subquery result.
*
* @param value The literal value to use in comparison
* @param dc The detached criteria representing the subquery
*
* @return The Criterion
*
* @see SimpleSubqueryExpression
*/
public static Criterion ltSome(Object value, DetachedCriteria dc) {
return new SimpleSubqueryExpression( value, "<", "some", dc );
}
/**
* Creates a criterion which checks that the value of a literal is greater-than-or-equal-to SOME of the values
* in the subquery result.
*
* @param value The literal value to use in comparison
* @param dc The detached criteria representing the subquery
*
* @return The Criterion
*
* @see SimpleSubqueryExpression
*/
public static Criterion geSome(Object value, DetachedCriteria dc) {
return new SimpleSubqueryExpression( value, ">=", "some", dc );
}
/**
* Creates a criterion which checks that the value of a literal is less-than-or-equal-to SOME of the values
* in the subquery result.
*
* @param value The literal value to use in comparison
* @param dc The detached criteria representing the subquery
*
* @return The Criterion
*
* @see SimpleSubqueryExpression
*/
public static Criterion leSome(Object value, DetachedCriteria dc) {
return new SimpleSubqueryExpression( value, "<=", "some", dc );
}
/**
* Creates a criterion which checks that the value of a literal is IN the values in the
* subquery result.
*
* @param value The literal value to use in comparison
* @param dc The detached criteria representing the subquery
*
* @return The Criterion
*
* @see SimpleSubqueryExpression
*/
public static Criterion in(Object value, DetachedCriteria dc) {
return new SimpleSubqueryExpression(value, "in", null, dc);
return new SimpleSubqueryExpression( value, "in", null, dc );
}
/**
* Creates a criterion which checks that the value of a literal is NOT IN the values in the
* subquery result.
*
* @param value The literal value to use in comparison
* @param dc The detached criteria representing the subquery
*
* @return The Criterion
*
* @see SimpleSubqueryExpression
*/
public static Criterion notIn(Object value, DetachedCriteria dc) {
return new SimpleSubqueryExpression(value, "not in", null, dc);
return new SimpleSubqueryExpression( value, "not in", null, dc );
}
/**
* Creates a criterion which checks that the value of a given literal as being equal to the value in
* the subquery result. The implication is that the subquery returns a single result..
*
* @param value The literal value to use in comparison
* @param dc The detached criteria representing the subquery
*
* @return The Criterion
*
* @see SimpleSubqueryExpression
*/
public static Criterion eq(Object value, DetachedCriteria dc) {
return new SimpleSubqueryExpression(value, "=", null, dc);
}
public static Criterion gt(Object value, DetachedCriteria dc) {
return new SimpleSubqueryExpression(value, ">", null, dc);
}
public static Criterion lt(Object value, DetachedCriteria dc) {
return new SimpleSubqueryExpression(value, "<", null, dc);
}
public static Criterion ge(Object value, DetachedCriteria dc) {
return new SimpleSubqueryExpression(value, ">=", null, dc);
}
public static Criterion le(Object value, DetachedCriteria dc) {
return new SimpleSubqueryExpression(value, "<=", null, dc);
return new SimpleSubqueryExpression( value, "=", null, dc );
}
/**
* Creates a criterion which checks that the value of a given literal as being not-equal to the value in
* the subquery result. The implication is that the subquery returns a single result..
*
* @param value The literal value to use in comparison
* @param dc The detached criteria representing the subquery
*
* @return The Criterion
*
* @see SimpleSubqueryExpression
*/
public static Criterion ne(Object value, DetachedCriteria dc) {
return new SimpleSubqueryExpression(value, "<>", null, dc);
}
public static Criterion gtAll(Object value, DetachedCriteria dc) {
return new SimpleSubqueryExpression(value, ">", "all", dc);
/**
* Creates a criterion which checks that the value of a given literal as being greater-than the value in
* the subquery result. The implication is that the subquery returns a single result..
*
* @param value The literal value to use in comparison
* @param dc The detached criteria representing the subquery
*
* @return The Criterion
*
* @see SimpleSubqueryExpression
*/
public static Criterion gt(Object value, DetachedCriteria dc) {
return new SimpleSubqueryExpression( value, ">", null, dc );
}
public static Criterion ltAll(Object value, DetachedCriteria dc) {
return new SimpleSubqueryExpression(value, "<", "all", dc);
/**
* Creates a criterion which checks that the value of a given literal as being less-than the value in
* the subquery result. The implication is that the subquery returns a single result..
*
* @param value The literal value to use in comparison
* @param dc The detached criteria representing the subquery
*
* @return The Criterion
*
* @see SimpleSubqueryExpression
*/
public static Criterion lt(Object value, DetachedCriteria dc) {
return new SimpleSubqueryExpression( value, "<", null, dc );
}
public static Criterion geAll(Object value, DetachedCriteria dc) {
return new SimpleSubqueryExpression(value, ">=", "all", dc);
/**
* Creates a criterion which checks that the value of a given literal as being greater-than-or-equal-to the
* value in the subquery result. The implication is that the subquery returns a single result..
*
* @param value The literal value to use in comparison
* @param dc The detached criteria representing the subquery
*
* @return The Criterion
*
* @see SimpleSubqueryExpression
*/
public static Criterion ge(Object value, DetachedCriteria dc) {
return new SimpleSubqueryExpression( value, ">=", null, dc );
}
public static Criterion leAll(Object value, DetachedCriteria dc) {
return new SimpleSubqueryExpression(value, "<=", "all", dc);
/**
* Creates a criterion which checks that the value of a given literal as being less-than-or-equal-to the
* value in the subquery result. The implication is that the subquery returns a single result..
*
* @param value The literal value to use in comparison
* @param dc The detached criteria representing the subquery
*
* @return The Criterion
*
* @see SimpleSubqueryExpression
*/
public static Criterion le(Object value, DetachedCriteria dc) {
return new SimpleSubqueryExpression( value, "<=", null, dc );
}
public static Criterion gtSome(Object value, DetachedCriteria dc) {
return new SimpleSubqueryExpression(value, ">", "some", dc);
private Subqueries() {
}
public static Criterion ltSome(Object value, DetachedCriteria dc) {
return new SimpleSubqueryExpression(value, "<", "some", dc);
}
public static Criterion geSome(Object value, DetachedCriteria dc) {
return new SimpleSubqueryExpression(value, ">=", "some", dc);
}
public static Criterion leSome(Object value, DetachedCriteria dc) {
return new SimpleSubqueryExpression(value, "<=", "some", dc);
}
}

View File

@ -1,10 +1,10 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
* Copyright (c) 2013, 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 Middleware LLC.
* 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
@ -20,11 +20,10 @@
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*
*/
package org.hibernate.criterion;
import org.hibernate.Criteria;
import org.hibernate.EntityMode;
import org.hibernate.HibernateException;
import org.hibernate.engine.spi.QueryParameters;
import org.hibernate.engine.spi.SessionFactoryImplementor;
@ -37,10 +36,12 @@ import org.hibernate.persister.entity.OuterJoinLoadable;
import org.hibernate.type.Type;
/**
* A criterion that involves a subquery
*
* @author Gavin King
* @author Steve Ebersole
*/
public abstract class SubqueryExpression implements Criterion {
private CriteriaImpl criteriaImpl;
private String quantifier;
private String op;
@ -48,27 +49,36 @@ public abstract class SubqueryExpression implements Criterion {
private Type[] types;
private CriteriaQueryTranslator innerQuery;
protected Type[] getTypes() {
return types;
}
protected SubqueryExpression(String op, String quantifier, DetachedCriteria dc) {
this.criteriaImpl = dc.getCriteriaImpl();
this.quantifier = quantifier;
this.op = op;
}
protected Type[] getTypes() {
return types;
}
protected abstract String toLeftSqlString(Criteria criteria, CriteriaQuery outerQuery);
@Override
public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException {
final StringBuilder buf = new StringBuilder( toLeftSqlString( criteria, criteriaQuery ) );
if ( op != null ) {
buf.append( ' ' ).append( op ).append( ' ' );
}
if ( quantifier != null ) {
buf.append( quantifier ).append( ' ' );
}
final SessionFactoryImplementor factory = criteriaQuery.getFactory();
final OuterJoinLoadable persister =
( OuterJoinLoadable ) factory.getEntityPersister( criteriaImpl.getEntityOrClassName() );
(OuterJoinLoadable) factory.getEntityPersister( criteriaImpl.getEntityOrClassName() );
createAndSetInnerQuery( criteriaQuery, factory );
criteriaImpl.setSession( deriveRootSession( criteria ) );
CriteriaJoinWalker walker = new CriteriaJoinWalker(
final CriteriaJoinWalker walker = new CriteriaJoinWalker(
persister,
innerQuery,
factory,
@ -78,25 +88,15 @@ public abstract class SubqueryExpression implements Criterion {
innerQuery.getRootSQLALias()
);
String sql = walker.getSQLString();
final StringBuilder buf = new StringBuilder( toLeftSqlString(criteria, criteriaQuery) );
if ( op != null ) {
buf.append( ' ' ).append( op ).append( ' ' );
}
if ( quantifier != null ) {
buf.append( quantifier ).append( ' ' );
}
return buf.append( '(' ).append( sql ).append( ')' )
.toString();
return buf.append( '(' ).append( walker.getSQLString() ).append( ')' ).toString();
}
private SessionImplementor deriveRootSession(Criteria criteria) {
if ( criteria instanceof CriteriaImpl ) {
return ( ( CriteriaImpl ) criteria ).getSession();
return ( (CriteriaImpl) criteria ).getSession();
}
else if ( criteria instanceof CriteriaImpl.Subcriteria ) {
return deriveRootSession( ( ( CriteriaImpl.Subcriteria ) criteria ).getParent() );
return deriveRootSession( ( (CriteriaImpl.Subcriteria) criteria ).getParent() );
}
else {
// could happen for custom Criteria impls. Not likely, but...
@ -105,18 +105,18 @@ public abstract class SubqueryExpression implements Criterion {
}
}
public TypedValue[] getTypedValues(Criteria criteria, CriteriaQuery criteriaQuery)
throws HibernateException {
@Override
public TypedValue[] getTypedValues(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException {
//the following two lines were added to ensure that this.params is not null, which
//can happen with two-deep nested subqueries
SessionFactoryImplementor factory = criteriaQuery.getFactory();
createAndSetInnerQuery(criteriaQuery, factory);
final SessionFactoryImplementor factory = criteriaQuery.getFactory();
createAndSetInnerQuery( criteriaQuery, factory );
Type[] ppTypes = params.getPositionalParameterTypes();
Object[] ppValues = params.getPositionalParameterValues();
TypedValue[] tv = new TypedValue[ppTypes.length];
final Type[] ppTypes = params.getPositionalParameterTypes();
final Object[] ppValues = params.getPositionalParameterValues();
final TypedValue[] tv = new TypedValue[ppTypes.length];
for ( int i=0; i<ppTypes.length; i++ ) {
tv[i] = new TypedValue( ppTypes[i], ppValues[i], EntityMode.POJO );
tv[i] = new TypedValue( ppTypes[i], ppValues[i] );
}
return tv;
}
@ -143,7 +143,7 @@ public abstract class SubqueryExpression implements Criterion {
innerQuery = new CriteriaQueryTranslator(
factory,
criteriaImpl,
criteriaImpl.getEntityOrClassName(), //implicit polymorphism not supported (would need a union)
criteriaImpl.getEntityOrClassName(),
alias,
criteriaQuery
);

View File

@ -90,7 +90,7 @@ public final class StringHelper {
}
public static String[] add(String[] x, String sep, String[] y) {
String[] result = new String[x.length];
final String[] result = new String[x.length];
for ( int i = 0; i < x.length; i++ ) {
result[i] = x[i] + sep + y[i];
}

View File

@ -498,18 +498,18 @@ public class CriteriaQueryTranslator implements CriteriaQuery {
}
}
public String[] getIdentifierColumns(Criteria subcriteria) {
public String[] getIdentifierColumns(Criteria criteria) {
String[] idcols =
( ( Loadable ) getPropertyMapping( getEntityName( subcriteria ) ) ).getIdentifierColumnNames();
return StringHelper.qualify( getSQLAlias( subcriteria ), idcols );
( ( Loadable ) getPropertyMapping( getEntityName( criteria ) ) ).getIdentifierColumnNames();
return StringHelper.qualify( getSQLAlias( criteria ), idcols );
}
public Type getIdentifierType(Criteria subcriteria) {
return ( ( Loadable ) getPropertyMapping( getEntityName( subcriteria ) ) ).getIdentifierType();
public Type getIdentifierType(Criteria criteria) {
return ( ( Loadable ) getPropertyMapping( getEntityName( criteria ) ) ).getIdentifierType();
}
public TypedValue getTypedIdentifierValue(Criteria subcriteria, Object value) {
final Loadable loadable = ( Loadable ) getPropertyMapping( getEntityName( subcriteria ) );
public TypedValue getTypedIdentifierValue(Criteria criteria, Object value) {
final Loadable loadable = ( Loadable ) getPropertyMapping( getEntityName( criteria ) );
return new TypedValue(
loadable.getIdentifierType(),
value,
@ -616,19 +616,11 @@ public class CriteriaQueryTranslator implements CriteriaQuery {
else {
throw new QueryException( "Unsupported discriminator type " + type );
}
return new TypedValue(
type,
value,
EntityMode.POJO
);
return new TypedValue( type, value );
}
}
// Otherwise, this is an ordinary value.
return new TypedValue(
getTypeUsingProjection( subcriteria, propertyName ),
value,
EntityMode.POJO
);
return new TypedValue( getTypeUsingProjection( subcriteria, propertyName ), value );
}
private PropertyMapping getPropertyMapping(String entityName)

View File

@ -1,10 +1,10 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
* Copyright (c) 2008, 2013, 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 Middleware LLC.
* 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
@ -20,7 +20,6 @@
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*
*/
package org.hibernate.sql;
@ -32,50 +31,128 @@ import org.hibernate.internal.util.StringHelper;
* @author Gavin King
*/
public abstract class JoinFragment {
public abstract void addJoin(String tableName, String alias, String[] fkColumns, String[] pkColumns, JoinType joinType);
public abstract void addJoin(String tableName, String alias, String[] fkColumns, String[] pkColumns, JoinType joinType, String on);
public abstract void addCrossJoin(String tableName, String alias);
public abstract void addJoins(String fromFragment, String whereFragment);
public abstract String toFromFragmentString();
public abstract String toWhereFragmentString();
// --Commented out by Inspection (12/4/04 9:10 AM): public abstract void addCondition(String alias, String[] columns, String condition);
public abstract void addCondition(String alias, String[] fkColumns, String[] pkColumns);
public abstract boolean addCondition(String condition);
// --Commented out by Inspection (12/4/04 9:10 AM): public abstract void addFromFragmentString(String fromFragmentString);
public abstract JoinFragment copy();
/**
* Specifies an inner join.
*
* @deprecated use {@link JoinType#INNER_JOIN} instead.
*/
@Deprecated
public static final int INNER_JOIN = 0;
public static final int INNER_JOIN = JoinType.INNER_JOIN.getJoinTypeValue();
/**
* Specifies a full join
*
* @deprecated use {@link JoinType#FULL_JOIN} instead.
*/
@Deprecated
public static final int FULL_JOIN = 4;
@SuppressWarnings("UnusedDeclaration")
public static final int FULL_JOIN = JoinType.FULL_JOIN.getJoinTypeValue();
/**
* Specifies a left join.
*
* @deprecated use {@link JoinType#LEFT_OUTER_JOIN} instead.
*/
@Deprecated
public static final int LEFT_OUTER_JOIN = 1;
public static final int LEFT_OUTER_JOIN = JoinType.LEFT_OUTER_JOIN.getJoinTypeValue();
/**
* Specifies a right join.
*
* @deprecated use {@link JoinType#RIGHT_OUTER_JOIN} instead.
*/
@Deprecated
public static final int RIGHT_OUTER_JOIN = 2;
private boolean hasFilterCondition = false;
private boolean hasThetaJoins = false;
@SuppressWarnings("UnusedDeclaration")
public static final int RIGHT_OUTER_JOIN = JoinType.RIGHT_OUTER_JOIN.getJoinTypeValue();
private boolean hasFilterCondition;
private boolean hasThetaJoins;
/**
* Adds a join.
*
* @param tableName The name of the table to be joined
* @param alias The alias to apply to the joined table
* @param fkColumns The names of the columns which reference the joined table
* @param pkColumns The columns in the joined table being referenced
* @param joinType The type of join
*/
public abstract void addJoin(String tableName, String alias, String[] fkColumns, String[] pkColumns, JoinType joinType);
/**
* Adds a join, with an additional ON clause fragment
*
* @param tableName The name of the table to be joined
* @param alias The alias to apply to the joined table
* @param fkColumns The names of the columns which reference the joined table
* @param pkColumns The columns in the joined table being referenced
* @param joinType The type of join
* @param on The additional ON fragment
*/
public abstract void addJoin(String tableName, String alias, String[] fkColumns, String[] pkColumns, JoinType joinType, String on);
/**
* Adds a cross join to the specified table.
*
* @param tableName The name of the table to be joined
* @param alias The alias to apply to the joined table
*/
public abstract void addCrossJoin(String tableName, String alias);
/**
* Free-form form of adding theta-style joins taking the necessary FROM and WHERE clause fragments
*
* @param fromFragment The FROM clause fragment
* @param whereFragment The WHERE clause fragment
*/
public abstract void addJoins(String fromFragment, String whereFragment);
/**
* Render this fragment to its FROM clause portion
*
* @return The FROM clause portion of this fragment
*/
public abstract String toFromFragmentString();
/**
* Render this fragment to its WHERE clause portion
*
* @return The WHERE clause portion of this fragment
*/
public abstract String toWhereFragmentString();
/**
* Adds a condition to the join fragment.
*
* @param alias The alias of the joined table
* @param fkColumns The names of the columns which reference the joined table
* @param pkColumns The columns in the joined table being referenced
*/
public abstract void addCondition(String alias, String[] fkColumns, String[] pkColumns);
/**
* Adds a free-form condition fragment
*
* @param condition The fragment
*
* @return {@code true} if the condition was added
*/
public abstract boolean addCondition(String condition);
/**
* Make a copy.
*
* @return The copy.
*/
public abstract JoinFragment copy();
/**
* Adds another join fragment to this one.
*
* @param ojf The other join fragment
*/
public void addFragment(JoinFragment ojf) {
if ( ojf.hasThetaJoins() ) {
hasThetaJoins = true;
@ -93,7 +170,9 @@ public abstract class JoinFragment {
*/
protected boolean addCondition(StringBuilder buffer, String on) {
if ( StringHelper.isNotEmpty( on ) ) {
if ( !on.startsWith( " and" ) ) buffer.append( " and " );
if ( !on.startsWith( " and" ) ) {
buffer.append( " and " );
}
buffer.append( on );
return true;
}
@ -115,6 +194,11 @@ public abstract class JoinFragment {
this.hasFilterCondition = b;
}
/**
* Determine if the join fragment contained any theta-joins.
*
* @return {@code true} if the fragment contained theta joins
*/
public boolean hasThetaJoins() {
return hasThetaJoins;
}