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 * Defines service registry contracts application are likely to want to utilize for
* configuring Hibernate behavior. * 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; package org.hibernate.boot.registry;

View File

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

View File

@ -57,16 +57,20 @@ import org.hibernate.engine.spi.SessionFactoryImplementor;
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public class ManagedSessionContext extends AbstractCurrentSessionContext { 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) { public ManagedSessionContext(SessionFactoryImplementor factory) {
super( factory ); super( factory );
} }
@Override @Override
public Session currentSession() { public Session currentSession() {
Session current = existingSession( factory() ); final Session current = existingSession( factory() );
if ( current == null ) { if ( current == null ) {
throw new HibernateException( "No session currently bound to execution context" ); 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. * @return The bound session if one, else null.
*/ */
public static Session unbind(SessionFactory factory) { public static Session unbind(SessionFactory factory) {
final Map<SessionFactory,Session> sessionMap = sessionMap();
Session existing = null; Session existing = null;
Map<SessionFactory,Session> sessionMap = sessionMap();
if ( sessionMap != null ) { if ( sessionMap != null ) {
existing = sessionMap.remove( factory ); existing = sessionMap.remove( factory );
doCleanup(); doCleanup();
@ -116,12 +120,12 @@ public class ManagedSessionContext extends AbstractCurrentSessionContext {
} }
private static Session existingSession(SessionFactory factory) { private static Session existingSession(SessionFactory factory) {
Map sessionMap = sessionMap(); final Map sessionMap = sessionMap();
if ( sessionMap == null ) { if ( sessionMap == null ) {
return null; return null;
} }
else { 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) { 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 ) { if ( sessionMap == null && createMap ) {
sessionMap = new HashMap<SessionFactory,Session>(); sessionMap = new HashMap<SessionFactory,Session>();
context.set( sessionMap ); CONTEXT_TL.set( sessionMap );
} }
return sessionMap; return sessionMap;
} }
private static synchronized void doCleanup() { private static synchronized void doCleanup() {
Map<SessionFactory,Session> sessionMap = sessionMap( false ); final Map<SessionFactory,Session> sessionMap = sessionMap( false );
if ( sessionMap != null ) { if ( sessionMap != null ) {
if ( sessionMap.isEmpty() ) { 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.Session;
import org.hibernate.SessionFactory; import org.hibernate.SessionFactory;
import org.hibernate.context.spi.AbstractCurrentSessionContext; import org.hibernate.context.spi.AbstractCurrentSessionContext;
import org.hibernate.context.spi.CurrentSessionContext;
import org.hibernate.engine.jdbc.LobCreationContext; import org.hibernate.engine.jdbc.LobCreationContext;
import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.engine.spi.SessionImplementor;
@ -51,39 +50,37 @@ import org.hibernate.event.spi.EventSource;
import org.hibernate.internal.CoreMessageLogger; import org.hibernate.internal.CoreMessageLogger;
/** /**
* A {@link CurrentSessionContext} impl which scopes the notion of current * 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, * session by the current thread of execution. Unlike the JTA counterpart, threads do not give us a nice
* threads do not give us a nice hook to perform any type of cleanup making * hook to perform any type of cleanup making it questionable for this impl to actually generate Session
* it questionable for this impl to actually generate Session instances. In * instances. In the interest of usability, it was decided to have this default impl actually generate
* the interest of usability, it was decided to have this default impl * a session upon first request and then clean it up after the {@link org.hibernate.Transaction}
* actually generate a session upon first request and then clean it up * associated with that session is committed/rolled-back. In order for ensuring that happens, the
* after the {@link org.hibernate.Transaction} associated with that session * sessions generated here are unusable until after {@link Session#beginTransaction()} has been
* is committed/rolled-back. In order for ensuring that happens, the sessions * called. If <tt>close()</tt> is called on a session managed by this class, it will be automatically
* generated here are unusable until after {@link Session#beginTransaction()} * unbound.
* 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
* <p/> * code to explicitly control opening and closing of these sessions. This, with some from of interception,
* Additionally, the static {@link #bind} and {@link #unbind} methods are * is the preferred approach. It also allows easy framework integration and one possible approach for
* provided to allow application code to explicitly control opening and * implementing long-sessions.
* closing of these sessions. This, with some from of interception, *
* is the preferred approach. It also allows easy framework integration * The {@link #buildOrObtainSession}, {@link #isAutoCloseEnabled}, {@link #isAutoFlushEnabled},
* and one possible approach for implementing long-sessions. * {@link #getConnectionReleaseMode}, and {@link #buildCleanupSynch} methods are all provided to allow easy
* <p/>
* 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). * subclassing (for long-running session scenarios, for example).
* *
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public class ThreadLocalSessionContext extends AbstractCurrentSessionContext { 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[] { private static final Class[] SESSION_PROXY_INTERFACES = new Class[] {
Session.class, Session.class,
SessionImplementor.class, SessionImplementor.class,
EventSource.class, EventSource.class,
TransactionContext.class, TransactionContext.class,
LobCreationContext.class LobCreationContext.class
}; };
@ -91,11 +88,16 @@ public class ThreadLocalSessionContext extends AbstractCurrentSessionContext {
/** /**
* A ThreadLocal maintaining current sessions for the given execution thread. * A ThreadLocal maintaining current sessions for the given execution thread.
* The actual ThreadLocal variable is a java.util.Map to account for * 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. * 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) { public ThreadLocalSessionContext(SessionFactoryImplementor factory) {
super( factory ); super( factory );
} }
@ -122,10 +124,15 @@ public class ThreadLocalSessionContext extends AbstractCurrentSessionContext {
private boolean needsWrapping(Session session) { private boolean needsWrapping(Session session) {
// try to make sure we don't wrap and already wrapped session // try to make sure we don't wrap and already wrapped session
return session != null if ( session != null ) {
&& ! Proxy.isProxyClass( session.getClass() ) if ( Proxy.isProxyClass( session.getClass() ) ) {
|| ( Proxy.getInvocationHandler( session ) != null final InvocationHandler invocationHandler = Proxy.getInvocationHandler( session );
&& ! ( Proxy.getInvocationHandler( session ) instanceof TransactionProtectionWrapper ) ); 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. * support.
* <p/> * <p/>
* This implementation always just opens a new session. * This implementation always just opens a new session.
* *
* @return the built or (re)obtained session. * @return the built or (re)obtained session.
*/ */
@SuppressWarnings("deprecation")
protected Session buildOrObtainSession() { protected Session buildOrObtainSession() {
return baseSessionBuilder() return baseSessionBuilder()
.autoClose( isAutoCloseEnabled() ) .autoClose( isAutoCloseEnabled() )
@ -153,8 +161,8 @@ public class ThreadLocalSessionContext extends AbstractCurrentSessionContext {
.openSession(); .openSession();
} }
protected CleanupSynch buildCleanupSynch() { protected CleanupSync buildCleanupSynch() {
return new CleanupSynch( factory() ); return new CleanupSync( factory() );
} }
/** /**
@ -185,12 +193,12 @@ public class ThreadLocalSessionContext extends AbstractCurrentSessionContext {
} }
protected Session wrap(Session session) { protected Session wrap(Session session) {
TransactionProtectionWrapper wrapper = new TransactionProtectionWrapper( session ); final TransactionProtectionWrapper wrapper = new TransactionProtectionWrapper( session );
Session wrapped = ( Session ) Proxy.newProxyInstance( final Session wrapped = (Session) Proxy.newProxyInstance(
Session.class.getClassLoader(), Session.class.getClassLoader(),
SESSION_PROXY_INTERFACES, SESSION_PROXY_INTERFACES,
wrapper wrapper
); );
// yick! need this for proper serialization/deserialization handling... // yick! need this for proper serialization/deserialization handling...
wrapper.setWrapped( wrapped ); wrapper.setWrapped( wrapped );
return wrapped; return wrapped;
@ -202,13 +210,13 @@ public class ThreadLocalSessionContext extends AbstractCurrentSessionContext {
* @param session The session to bind. * @param session The session to bind.
*/ */
public static void bind(org.hibernate.Session session) { public static void bind(org.hibernate.Session session) {
SessionFactory factory = session.getSessionFactory(); final SessionFactory factory = session.getSessionFactory();
cleanupAnyOrphanedSession( factory ); cleanupAnyOrphanedSession( factory );
doBind( session, factory ); doBind( session, factory );
} }
private static void cleanupAnyOrphanedSession(SessionFactory factory) { private static void cleanupAnyOrphanedSession(SessionFactory factory) {
Session orphan = doUnbind( factory, false ); final Session orphan = doUnbind( factory, false );
if ( orphan != null ) { if ( orphan != null ) {
LOG.alreadySessionBound(); LOG.alreadySessionBound();
try { try {
@ -239,7 +247,7 @@ public class ThreadLocalSessionContext extends AbstractCurrentSessionContext {
} }
private static Session existingSession(SessionFactory factory) { private static Session existingSession(SessionFactory factory) {
Map sessionMap = sessionMap(); final Map sessionMap = sessionMap();
if ( sessionMap == null ) { if ( sessionMap == null ) {
return null; return null;
} }
@ -247,7 +255,7 @@ public class ThreadLocalSessionContext extends AbstractCurrentSessionContext {
} }
protected static Map sessionMap() { protected static Map sessionMap() {
return context.get(); return CONTEXT_TL.get();
} }
@SuppressWarnings({"unchecked"}) @SuppressWarnings({"unchecked"})
@ -255,42 +263,38 @@ public class ThreadLocalSessionContext extends AbstractCurrentSessionContext {
Map sessionMap = sessionMap(); Map sessionMap = sessionMap();
if ( sessionMap == null ) { if ( sessionMap == null ) {
sessionMap = new HashMap(); sessionMap = new HashMap();
context.set( sessionMap ); CONTEXT_TL.set( sessionMap );
} }
sessionMap.put( factory, session ); sessionMap.put( factory, session );
} }
private static Session doUnbind(SessionFactory factory, boolean releaseMapIfEmpty) { private static Session doUnbind(SessionFactory factory, boolean releaseMapIfEmpty) {
Map sessionMap = sessionMap();
Session session = null; Session session = null;
final Map sessionMap = sessionMap();
if ( sessionMap != null ) { if ( sessionMap != null ) {
session = ( Session ) sessionMap.remove( factory ); session = (Session) sessionMap.remove( factory );
if ( releaseMapIfEmpty && sessionMap.isEmpty() ) { if ( releaseMapIfEmpty && sessionMap.isEmpty() ) {
context.set( null ); CONTEXT_TL.set( null );
} }
} }
return session; 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; protected final SessionFactory factory;
public CleanupSynch(SessionFactory factory) { public CleanupSync(SessionFactory factory) {
this.factory = factory; this.factory = factory;
} }
/** @Override
* {@inheritDoc}
*/
public void beforeCompletion() { public void beforeCompletion() {
} }
/** @Override
* {@inheritDoc}
*/
public void afterCompletion(int i) { public void afterCompletion(int i) {
unbind( factory ); unbind( factory );
} }
@ -304,9 +308,7 @@ public class ThreadLocalSessionContext extends AbstractCurrentSessionContext {
this.realSession = realSession; this.realSession = realSession;
} }
/** @Override
* {@inheritDoc}
*/
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
final String methodName = method.getName(); final String methodName = method.getName();
try { try {
@ -315,13 +317,13 @@ public class ThreadLocalSessionContext extends AbstractCurrentSessionContext {
unbind( realSession.getSessionFactory() ); unbind( realSession.getSessionFactory() );
} }
else if ( "toString".equals( methodName ) else if ( "toString".equals( methodName )
|| "equals".equals( methodName ) || "equals".equals( methodName )
|| "hashCode".equals( methodName ) || "hashCode".equals( methodName )
|| "getStatistics".equals( methodName ) || "getStatistics".equals( methodName )
|| "isOpen".equals( methodName ) || "isOpen".equals( methodName )
|| "getListeners".equals( methodName ) || "getListeners".equals( methodName ) ) {
) {
// allow these to go through the the real session no matter what // 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() ) { else if ( !realSession.isOpen() ) {
// essentially, if the real session is closed allow any // 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; // will complain by throwing an appropriate exception;
// NOTE that allowing close() above has the same basic effect, // NOTE that allowing close() above has the same basic effect,
// but we capture that there simply to doAfterTransactionCompletion the unbind... // 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() ) { else if ( !realSession.getTransaction().isActive() ) {
// limit the methods available if no transaction is active // limit the methods available if no transaction is active
@ -339,21 +342,24 @@ public class ThreadLocalSessionContext extends AbstractCurrentSessionContext {
|| "getFactory".equals( methodName ) || "getFactory".equals( methodName )
|| "getSessionFactory".equals( methodName ) || "getSessionFactory".equals( methodName )
|| "getTenantIdentifier".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 ) ) { else if ( "reconnect".equals( methodName ) || "disconnect".equals( methodName ) ) {
// allow these (deprecated) methods to pass through // allow these (deprecated) methods to pass through
LOG.tracef( "Allowing invocation [%s] to proceed to real (non-transacted) session - deprecated methods", methodName );
} }
else { else {
throw new HibernateException( methodName + " is not valid without active transaction" ); 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 ); return method.invoke( realSession, args );
} }
catch ( InvocationTargetException e ) { catch ( InvocationTargetException e ) {
if (e.getTargetException() instanceof RuntimeException) throw (RuntimeException)e.getTargetException(); if (e.getTargetException() instanceof RuntimeException) {
throw e; 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; this.factory = factory;
} }
/**
* Access to the SessionFactory
*
* @return The SessionFactory being serviced by this context
*/
public SessionFactoryImplementor factory() { public SessionFactoryImplementor factory() {
return 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 * 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 * indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are * 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, * 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 * copy, or redistribute it subject to the terms and conditions of the GNU
@ -20,7 +20,6 @@
* Free Software Foundation, Inc. * Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor * 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA * Boston, MA 02110-1301 USA
*
*/ */
package org.hibernate.criterion; package org.hibernate.criterion;
import org.hibernate.Criteria; import org.hibernate.Criteria;
@ -37,7 +36,7 @@ import org.hibernate.type.CollectionType;
import org.hibernate.type.Type; import org.hibernate.type.Type;
/** /**
* Implementation of AbstractEmptinessExpression. * Base expression implementation for (not) emptiness checking of collection properties
* *
* @author Steve Ebersole * @author Steve Ebersole
*/ */
@ -51,43 +50,50 @@ public abstract class AbstractEmptinessExpression implements Criterion {
this.propertyName = propertyName; 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(); protected abstract boolean excludeEmpty();
@Override
public final String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException { public final String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException {
String entityName = criteriaQuery.getEntityName( criteria, propertyName ); final String entityName = criteriaQuery.getEntityName( criteria, propertyName );
String actualPropertyName = criteriaQuery.getPropertyName( propertyName ); final String actualPropertyName = criteriaQuery.getPropertyName( propertyName );
String sqlAlias = criteriaQuery.getSQLAlias( criteria, propertyName ); final String sqlAlias = criteriaQuery.getSQLAlias( criteria, propertyName );
SessionFactoryImplementor factory = criteriaQuery.getFactory(); final SessionFactoryImplementor factory = criteriaQuery.getFactory();
QueryableCollection collectionPersister = getQueryableCollection( entityName, actualPropertyName, factory ); final QueryableCollection collectionPersister = getQueryableCollection( entityName, actualPropertyName, factory );
String[] collectionKeys = collectionPersister.getKeyColumnNames(); final String[] collectionKeys = collectionPersister.getKeyColumnNames();
String[] ownerKeys = ( ( Loadable ) factory.getEntityPersister( entityName ) ).getIdentifierColumnNames(); final String[] ownerKeys = ( (Loadable) factory.getEntityPersister( entityName ) ).getIdentifierColumnNames();
String innerSelect = "(select 1 from " + collectionPersister.getTableName() final String innerSelect = "(select 1 from " + collectionPersister.getTableName() + " where "
+ " where " + new ConditionFragment().setTableAlias( sqlAlias ).setCondition( ownerKeys, collectionKeys ).toFragmentString()
+ new ConditionFragment().setTableAlias( sqlAlias ).setCondition( ownerKeys, collectionKeys ).toFragmentString() + ")";
+ ")";
return excludeEmpty() return excludeEmpty()
? "exists " + innerSelect ? "exists " + innerSelect
: "not exists " + innerSelect; : "not exists " + innerSelect;
} }
protected QueryableCollection getQueryableCollection(String entityName, String propertyName, SessionFactoryImplementor factory) protected QueryableCollection getQueryableCollection(
throws HibernateException { String entityName,
PropertyMapping ownerMapping = ( PropertyMapping ) factory.getEntityPersister( entityName ); String propertyName,
Type type = ownerMapping.toType( propertyName ); SessionFactoryImplementor factory) throws HibernateException {
final PropertyMapping ownerMapping = (PropertyMapping) factory.getEntityPersister( entityName );
final Type type = ownerMapping.toType( propertyName );
if ( !type.isCollectionType() ) { if ( !type.isCollectionType() ) {
throw new MappingException( 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 { try {
return ( QueryableCollection ) factory.getCollectionPersister( role ); return (QueryableCollection) factory.getCollectionPersister( role );
} }
catch ( ClassCastException cce ) { catch ( ClassCastException cce ) {
throw new QueryException( "collection role is not queryable: " + role ); 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) public final TypedValue[] getTypedValues(Criteria criteria, CriteriaQuery criteriaQuery)
throws HibernateException { throws HibernateException {
return NO_VALUES; return NO_VALUES;
} }
@Override
public final String toString() { public final String toString() {
return propertyName + ( excludeEmpty() ? " is not empty" : " is empty" ); return propertyName + ( excludeEmpty() ? " is not empty" : " is empty" );
} }

View File

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

View File

@ -1,10 +1,10 @@
/* /*
* Hibernate, Relational Persistence for Idiomatic Java * 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 * indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are * 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, * 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 * copy, or redistribute it subject to the terms and conditions of the GNU
@ -20,7 +20,6 @@
* Free Software Foundation, Inc. * Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor * 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA * Boston, MA 02110-1301 USA
*
*/ */
package org.hibernate.criterion; package org.hibernate.criterion;
import org.hibernate.Criteria; import org.hibernate.Criteria;
@ -28,71 +27,80 @@ import org.hibernate.HibernateException;
import org.hibernate.type.Type; import org.hibernate.type.Type;
/** /**
* Represents a projection that specifies an alias
*
* @author Gavin King * @author Gavin King
*/ */
public class AliasedProjection implements EnhancedProjection { public class AliasedProjection implements EnhancedProjection {
private final Projection projection; private final Projection projection;
private final String alias; private final String alias;
public String toString() {
return projection.toString() + " as " + alias;
}
protected AliasedProjection(Projection projection, String alias) { protected AliasedProjection(Projection projection, String alias) {
this.projection = projection; this.projection = projection;
this.alias = alias; this.alias = alias;
} }
public String toSqlString(Criteria criteria, int position, CriteriaQuery criteriaQuery) @Override
throws HibernateException { public String toSqlString(Criteria criteria, int position, CriteriaQuery criteriaQuery) throws HibernateException {
return projection.toSqlString(criteria, position, criteriaQuery); return projection.toSqlString( criteria, position, criteriaQuery );
} }
@Override
public String toGroupSqlString(Criteria criteria, CriteriaQuery criteriaQuery) { public String toGroupSqlString(Criteria criteria, CriteriaQuery criteriaQuery) {
return projection.toGroupSqlString(criteria, criteriaQuery); return projection.toGroupSqlString( criteria, criteriaQuery );
} }
public Type[] getTypes(Criteria criteria, CriteriaQuery criteriaQuery) @Override
throws HibernateException { public Type[] getTypes(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException {
return projection.getTypes(criteria, criteriaQuery); return projection.getTypes( criteria, criteriaQuery );
} }
@Override
public String[] getColumnAliases(int loc) { public String[] getColumnAliases(int loc) {
return projection.getColumnAliases(loc); return projection.getColumnAliases( loc );
} }
@Override
public String[] getColumnAliases(int loc, Criteria criteria, CriteriaQuery criteriaQuery) { public String[] getColumnAliases(int loc, Criteria criteria, CriteriaQuery criteriaQuery) {
return projection instanceof EnhancedProjection ? return projection instanceof EnhancedProjection
( ( EnhancedProjection ) projection ).getColumnAliases( loc, criteria, criteriaQuery ) : ? ( (EnhancedProjection) projection ).getColumnAliases( loc, criteria, criteriaQuery )
getColumnAliases( loc ); : getColumnAliases( loc );
} }
public Type[] getTypes(String alias, Criteria criteria, CriteriaQuery criteriaQuery) @Override
throws HibernateException { public Type[] getTypes(String alias, Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException {
return this.alias.equals(alias) ? return this.alias.equals( alias )
getTypes(criteria, criteriaQuery) : ? getTypes( criteria, criteriaQuery )
null; : null;
} }
@Override
public String[] getColumnAliases(String alias, int loc) { public String[] getColumnAliases(String alias, int loc) {
return this.alias.equals(alias) ? return this.alias.equals( alias )
getColumnAliases(loc) : ? getColumnAliases( loc )
null; : null;
} }
@Override
public String[] getColumnAliases(String alias, int loc, Criteria criteria, CriteriaQuery criteriaQuery) { public String[] getColumnAliases(String alias, int loc, Criteria criteria, CriteriaQuery criteriaQuery) {
return this.alias.equals(alias) ? return this.alias.equals( alias )
getColumnAliases( loc, criteria, criteriaQuery ) : ? getColumnAliases( loc, criteria, criteriaQuery )
null; : null;
} }
@Override
public String[] getAliases() { public String[] getAliases() {
return new String[]{ alias }; return new String[] { alias };
} }
@Override
public boolean isGrouped() { public boolean isGrouped() {
return projection.isGrouped(); return projection.isGrouped();
} }
@Override
public String toString() {
return projection.toString() + " as " + alias;
}
} }

View File

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

View File

@ -1,10 +1,10 @@
/* /*
* Hibernate, Relational Persistence for Idiomatic Java * 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 * indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are * 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, * 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 * copy, or redistribute it subject to the terms and conditions of the GNU
@ -20,9 +20,9 @@
* Free Software Foundation, Inc. * Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor * 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA * Boston, MA 02110-1301 USA
*
*/ */
package org.hibernate.criterion; package org.hibernate.criterion;
import org.hibernate.Criteria; import org.hibernate.Criteria;
import org.hibernate.HibernateException; import org.hibernate.HibernateException;
import org.hibernate.engine.spi.TypedValue; import org.hibernate.engine.spi.TypedValue;
@ -30,10 +30,10 @@ import org.hibernate.internal.util.StringHelper;
/** /**
* Constrains a property to between two values * Constrains a property to between two values
*
* @author Gavin King * @author Gavin King
*/ */
public class BetweenExpression implements Criterion { public class BetweenExpression implements Criterion {
private final String propertyName; private final String propertyName;
private final Object lo; private final Object lo;
private final Object hi; private final Object hi;
@ -44,24 +44,22 @@ public class BetweenExpression implements Criterion {
this.hi = hi; this.hi = hi;
} }
public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery) @Override
throws HibernateException { public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException {
return StringHelper.join( final String[] columns = criteriaQuery.findColumns( propertyName, criteria );
" and ", final String[] expressions = StringHelper.suffix( columns, " between ? and ?" );
StringHelper.suffix( criteriaQuery.findColumns(propertyName, criteria), " between ? and ?" ) return StringHelper.join( " and ", expressions );
);
//TODO: get SQL rendering out of this package!
} }
public TypedValue[] getTypedValues(Criteria criteria, CriteriaQuery criteriaQuery) @Override
throws HibernateException { public TypedValue[] getTypedValues(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException {
return new TypedValue[] { return new TypedValue[] {
criteriaQuery.getTypedValue(criteria, propertyName, lo), criteriaQuery.getTypedValue( criteria, propertyName, lo ),
criteriaQuery.getTypedValue(criteria, propertyName, hi) criteriaQuery.getTypedValue( criteria, propertyName, hi )
}; };
} }
@Override
public String toString() { public String toString() {
return propertyName + " between " + lo + " and " + hi; return propertyName + " between " + lo + " and " + hi;
} }

View File

@ -24,10 +24,22 @@
package org.hibernate.criterion; package org.hibernate.criterion;
/** /**
* Defines a conjunction (AND series).
*
* @author Gavin King * @author Gavin King
* @author Steve Ebersole
*
* @see Disjunction
*/ */
public class Conjunction extends Junction { public class Conjunction extends Junction {
/**
* Constructs a Conjunction
*/
public Conjunction() { public Conjunction() {
super( Nature.AND ); 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; import org.hibernate.Criteria;
/** /**
* A count * A count projection
*
* @author Gavin King * @author Gavin King
*/ */
public class CountProjection extends AggregateProjection { public class CountProjection extends AggregateProjection {
private boolean distinct; private boolean distinct;
/**
* Constructs the count projection.
*
* @param prop The property name
*
* @see Projections#count(String)
* @see Projections#countDistinct(String)
*/
protected CountProjection(String prop) { 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() { public String toString() {
if ( distinct ) { if ( distinct ) {
return "distinct " + super.toString(); 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 * 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 * indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are * 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, * 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 * copy, or redistribute it subject to the terms and conditions of the GNU
@ -20,9 +20,9 @@
* Free Software Foundation, Inc. * Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor * 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA * Boston, MA 02110-1301 USA
*
*/ */
package org.hibernate.criterion; package org.hibernate.criterion;
import org.hibernate.Criteria; import org.hibernate.Criteria;
import org.hibernate.HibernateException; import org.hibernate.HibernateException;
import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionFactoryImplementor;
@ -38,93 +38,183 @@ import org.hibernate.type.Type;
* @author Gavin King * @author Gavin King
*/ */
public interface CriteriaQuery { public interface CriteriaQuery {
/**
* Provides access to the SessionFactory
*
* @return The SessionFactory
*/
public SessionFactoryImplementor getFactory(); public SessionFactoryImplementor getFactory();
/** /**
* Get the names of the columns mapped by a property path, * Resolve a property path to the name of the column it maps to. Ignores projection aliases.
* ignoring projection aliases *
* @throws org.hibernate.QueryException if the property maps to more than 1 column * @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) public String getColumn(Criteria criteria, String propertyPath) throws HibernateException;
throws HibernateException;
/** /**
* Get the names of the columns mapped by a property path, * Resolve a property path to the names of the columns it maps to. Ignores projection aliases
* ignoring 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) public String[] getColumns(String propertyPath, Criteria criteria) throws HibernateException;
throws HibernateException;
/** /**
* Get the names of the columns mapped by a property path; if the * Get the names of the columns mapped by a property path; if the property path is not found in criteria, try
* property path is not found in criteria, try the "outer" query. * the "outer" query. Projection aliases are ignored.
* 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) public String[] findColumns(String propertyPath, Criteria criteria) throws HibernateException;
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) public Type getType(Criteria criteria, String propertyPath) throws HibernateException;
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) public String[] getColumnsUsingProjection(Criteria criteria, String propertyPath) throws HibernateException;
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) public Type getTypeUsingProjection(Criteria criteria, String propertyPath) throws HibernateException;
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) public TypedValue getTypedValue(Criteria criteria, String propertyPath, Object value) throws HibernateException;
throws HibernateException;
/** /**
* Get the entity name of an entity * Get the entity name of an entity
*
* @param criteria The criteria
*
* @return The entity name
*/ */
public String getEntityName(Criteria criteria); public String getEntityName(Criteria criteria);
/** /**
* Get the entity name of an entity, taking into account * Get the entity name of an entity, taking into account the qualifier of the property path
* 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); public String getEntityName(Criteria criteria, String propertyPath);
/** /**
* Get the root table alias of an entity * 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 * Get the root table alias of an entity, taking into account
* the qualifier of the property path * 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); public String getSQLAlias(Criteria criteria, String propertyPath);
/** /**
* Get the property name, given a possibly qualified property name * 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); public String getPropertyName(String propertyName);
/** /**
* Get the identifier column names of this entity * 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 * 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(); public String generateSQLAlias();
} }

View File

@ -1,10 +1,10 @@
/* /*
* Hibernate, Relational Persistence for Idiomatic Java * 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 * indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are * 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, * 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 * copy, or redistribute it subject to the terms and conditions of the GNU
@ -20,9 +20,9 @@
* Free Software Foundation, Inc. * Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor * 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA * Boston, MA 02110-1301 USA
*
*/ */
package org.hibernate.criterion; package org.hibernate.criterion;
import org.hibernate.sql.JoinType; import org.hibernate.sql.JoinType;
import org.hibernate.transform.AliasToEntityMapResultTransformer; import org.hibernate.transform.AliasToEntityMapResultTransformer;
import org.hibernate.transform.DistinctRootEntityResultTransformer; import org.hibernate.transform.DistinctRootEntityResultTransformer;
@ -31,6 +31,8 @@ import org.hibernate.transform.ResultTransformer;
import org.hibernate.transform.RootEntityResultTransformer; import org.hibernate.transform.RootEntityResultTransformer;
/** /**
* Commonality between different types of Criteria.
*
* @author Gavin King * @author Gavin King
*/ */
public interface CriteriaSpecification { public interface CriteriaSpecification {
@ -62,24 +64,27 @@ public interface CriteriaSpecification {
/** /**
* Specifies joining to an entity based on an inner join. * 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 @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. * 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 @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. * 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 @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 * 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 * indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are * 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, * 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 * copy, or redistribute it subject to the terms and conditions of the GNU
@ -20,14 +20,13 @@
* Free Software Foundation, Inc. * Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor * 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA * Boston, MA 02110-1301 USA
*
*/ */
package org.hibernate.criterion; package org.hibernate.criterion;
import java.io.Serializable; import java.io.Serializable;
import org.hibernate.Criteria; import org.hibernate.Criteria;
import org.hibernate.FetchMode; import org.hibernate.FetchMode;
import org.hibernate.HibernateException;
import org.hibernate.LockMode; import org.hibernate.LockMode;
import org.hibernate.Session; import org.hibernate.Session;
import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.engine.spi.SessionImplementor;
@ -36,29 +35,36 @@ import org.hibernate.sql.JoinType;
import org.hibernate.transform.ResultTransformer; import org.hibernate.transform.ResultTransformer;
/** /**
* Some applications need to create criteria queries in "detached * Models a detached form of a Criteria (not associated with a Session).
* mode", where the Hibernate session is not available. This class *
* may be instantiated anywhere, and then a <literal>Criteria</literal> * Some applications need to create criteria queries in "detached mode", where the Hibernate Session is
* may be obtained by passing a session to * not available. Applications would create a DetachableCriteria to describe the query, and then later
* <literal>getExecutableCriteria()</literal>. All methods have the * associated it with a Session to obtain the "executable" Criteria:
* same semantics and behavior as the corresponding methods of the * <code>
* <literal>Criteria</literal> interface. * 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 * @see org.hibernate.Criteria
* @author Gavin King
*/ */
public class DetachedCriteria implements CriteriaSpecification, Serializable { public class DetachedCriteria implements CriteriaSpecification, Serializable {
private final CriteriaImpl impl; private final CriteriaImpl impl;
private final Criteria criteria; private final Criteria criteria;
protected DetachedCriteria(String entityName) { protected DetachedCriteria(String entityName) {
impl = new CriteriaImpl(entityName, null); impl = new CriteriaImpl( entityName, null );
criteria = impl; criteria = impl;
} }
protected DetachedCriteria(String entityName, String alias) { protected DetachedCriteria(String entityName, String alias) {
impl = new CriteriaImpl(entityName, alias, null); impl = new CriteriaImpl( entityName, alias, null );
criteria = impl; criteria = impl;
} }
@ -68,154 +74,373 @@ public class DetachedCriteria implements CriteriaSpecification, Serializable {
} }
/** /**
* Get an executable instance of <literal>Criteria</literal>, * Get an executable instance of Criteria to actually run the query.
* to actually run the query. *
* @param session The session to associate the built Criteria with
*
* @return The "executable" Criteria
*/ */
public Criteria getExecutableCriteria(Session session) { public Criteria getExecutableCriteria(Session session) {
impl.setSession( ( SessionImplementor ) session ); impl.setSession( (SessionImplementor) session );
return impl; return impl;
} }
public static DetachedCriteria forEntityName(String entityName) { /**
return new DetachedCriteria(entityName); * Obtain the alias associated with this DetachedCriteria
} *
* @return The alias
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) );
}
public String getAlias() { public String getAlias() {
return criteria.getAlias(); return criteria.getAlias();
} }
public DetachedCriteria setFetchMode(String associationPath, FetchMode mode) /**
throws HibernateException { * Retrieve the CriteriaImpl used internally to hold the DetachedCriteria state
criteria.setFetchMode(associationPath, mode); *
return this; * @return The internally maintained CriteriaImpl
} */
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() + ')';
}
CriteriaImpl getCriteriaImpl() { CriteriaImpl getCriteriaImpl() {
return impl; return impl;
} }
public DetachedCriteria createAlias(String associationPath, String alias, JoinType joinType) throws HibernateException { /**
criteria.createAlias(associationPath, alias, joinType); * Static builder to create a DetachedCriteria for the given entity.
return this; *
} * @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; return this;
} }
public DetachedCriteria createCriteria(String associationPath, JoinType joinType) throws HibernateException { /**
return new DetachedCriteria(impl, criteria.createCriteria(associationPath, joinType)); * Adds an ordering
} *
* @param order The ordering
public DetachedCriteria createCriteria(String associationPath, String alias, JoinType joinType) throws HibernateException { *
return new DetachedCriteria(impl, criteria.createCriteria(associationPath, alias, joinType)); * @return {@code this}, for method chaining
} */
public DetachedCriteria addOrder(Order order) {
public DetachedCriteria createCriteria(String associationPath, String alias, JoinType joinType, Criterion withClause) throws HibernateException { criteria.addOrder( order );
return new DetachedCriteria(impl, criteria.createCriteria(associationPath, alias, joinType, withClause)); 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 use {@link #createAlias(String, String, JoinType)}
*/ */
@Deprecated @Deprecated
public DetachedCriteria createAlias(String associationPath, String alias, int joinType) throws HibernateException { public DetachedCriteria createAlias(String associationPath, String alias, int joinType) {
return createAlias( associationPath, alias, JoinType.parse( 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 use {@link #createAlias(String, String, JoinType, Criterion)}
*/ */
@Deprecated @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 ); 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 use {@link #createCriteria(String, JoinType)}
*/ */
@Deprecated @Deprecated
public DetachedCriteria createCriteria(String associationPath, int joinType) throws HibernateException { public DetachedCriteria createCriteria(String associationPath, int joinType) {
return createCriteria( associationPath, JoinType.parse( 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 use {@link #createCriteria(String, String, JoinType)}
*/ */
@Deprecated @Deprecated
public DetachedCriteria createCriteria(String associationPath, String alias, int joinType) throws HibernateException { public DetachedCriteria createCriteria(String associationPath, String alias, int joinType) {
return createCriteria( associationPath, alias, JoinType.parse( 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 use {@link #createCriteria(String, String, JoinType, Criterion)}
*/ */
@Deprecated @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 ); 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) { public DetachedCriteria setComment(String comment) {
criteria.setComment(comment); criteria.setComment( comment );
return this; return this;
} }
public DetachedCriteria setLockMode(LockMode lockMode) { /**
criteria.setLockMode(lockMode); * Set the lock mode to use.
return this; *
} * @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; package org.hibernate.criterion;
/** /**
* Defines a disjunction (OR series).
*
* @author Gavin King * @author Gavin King
* @author Steve Ebersole
*
* @see Conjunction
*/ */
public class Disjunction extends Junction { public class Disjunction extends Junction {
/**
* Constructs a Disjunction
*/
protected Disjunction() { protected Disjunction() {
super( Nature.OR ); super( Nature.OR );
} }
protected Disjunction(Criterion[] conditions) {
super( Nature.OR, conditions );
}
} }

View File

@ -1,10 +1,10 @@
/* /*
* Hibernate, Relational Persistence for Idiomatic Java * 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 * indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are * 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, * 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 * copy, or redistribute it subject to the terms and conditions of the GNU
@ -20,73 +20,85 @@
* Free Software Foundation, Inc. * Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor * 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA * Boston, MA 02110-1301 USA
*
*/ */
package org.hibernate.criterion; package org.hibernate.criterion;
import org.hibernate.Criteria; import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.type.Type; import org.hibernate.type.Type;
/** /**
* A wrappedProjection that is a wrapper around other projections to apply distinction.
*
* @author Gavin King * @author Gavin King
*/ */
public class Distinct implements EnhancedProjection { public class Distinct implements EnhancedProjection {
private final Projection wrappedProjection;
private final Projection projection; /**
* Constructs a Distinct
public Distinct(Projection proj) { *
this.projection = proj; * @param wrappedProjection The wrapped projection
*/
public Distinct(Projection wrappedProjection) {
this.wrappedProjection = wrappedProjection;
} }
public String toSqlString(Criteria criteria, int position, CriteriaQuery criteriaQuery) @Override
throws HibernateException { public String toSqlString(Criteria criteria, int position, CriteriaQuery criteriaQuery) {
return "distinct " + projection.toSqlString(criteria, position, criteriaQuery); return "distinct " + wrappedProjection.toSqlString( criteria, position, criteriaQuery );
} }
public String toGroupSqlString(Criteria criteria, CriteriaQuery criteriaQuery) @Override
throws HibernateException { public String toGroupSqlString(Criteria criteria, CriteriaQuery criteriaQuery) {
return projection.toGroupSqlString(criteria, criteriaQuery); return wrappedProjection.toGroupSqlString( criteria, criteriaQuery );
} }
public Type[] getTypes(Criteria criteria, CriteriaQuery criteriaQuery) @Override
throws HibernateException { public Type[] getTypes(Criteria criteria, CriteriaQuery criteriaQuery) {
return projection.getTypes(criteria, criteriaQuery); return wrappedProjection.getTypes( criteria, criteriaQuery );
} }
public Type[] getTypes(String alias, Criteria criteria, CriteriaQuery criteriaQuery) @Override
throws HibernateException { public Type[] getTypes(String alias, Criteria criteria, CriteriaQuery criteriaQuery) {
return projection.getTypes(alias, criteria, criteriaQuery); return wrappedProjection.getTypes( alias, criteria, criteriaQuery );
} }
@Override
public String[] getColumnAliases(int loc) { public String[] getColumnAliases(int loc) {
return projection.getColumnAliases(loc); return wrappedProjection.getColumnAliases( loc );
} }
@Override
public String[] getColumnAliases(int loc, Criteria criteria, CriteriaQuery criteriaQuery) { public String[] getColumnAliases(int loc, Criteria criteria, CriteriaQuery criteriaQuery) {
return projection instanceof EnhancedProjection ? return wrappedProjection instanceof EnhancedProjection
( ( EnhancedProjection ) projection ).getColumnAliases( loc, criteria, criteriaQuery ) : ? ( (EnhancedProjection) wrappedProjection).getColumnAliases( loc, criteria, criteriaQuery )
getColumnAliases( loc ); : getColumnAliases( loc );
} }
@Override
public String[] getColumnAliases(String alias, int loc) { 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) { public String[] getColumnAliases(String alias, int loc, Criteria criteria, CriteriaQuery criteriaQuery) {
return projection instanceof EnhancedProjection ? return wrappedProjection instanceof EnhancedProjection
( ( EnhancedProjection ) projection ).getColumnAliases( alias, loc, criteria, criteriaQuery ) : ? ( (EnhancedProjection) wrappedProjection).getColumnAliases( alias, loc, criteria, criteriaQuery )
getColumnAliases( alias, loc ); : getColumnAliases( alias, loc );
} }
@Override
public String[] getAliases() { public String[] getAliases() {
return projection.getAliases(); return wrappedProjection.getAliases();
} }
@Override
public boolean isGrouped() { public boolean isGrouped() {
return projection.isGrouped(); return wrappedProjection.isGrouped();
} }
@Override
public String toString() { public String toString() {
return "distinct " + projection.toString(); return "distinct " + wrappedProjection.toString();
} }
} }

View File

@ -1,10 +1,10 @@
/* /*
* Hibernate, Relational Persistence for Idiomatic Java * 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 * indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are * 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, * 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 * copy, or redistribute it subject to the terms and conditions of the GNU
@ -20,22 +20,28 @@
* Free Software Foundation, Inc. * Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor * 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA * Boston, MA 02110-1301 USA
*
*/ */
package org.hibernate.criterion; package org.hibernate.criterion;
/** /**
* An expression asserting that a collection property is empty
*
* @author Gavin King * @author Gavin King
*/ */
public class EmptyExpression extends AbstractEmptinessExpression implements Criterion { public class EmptyExpression extends AbstractEmptinessExpression implements Criterion {
/**
* Constructs an EmptyExpression
*
* @param propertyName The collection property name
*
* @see Restrictions#isEmpty
*/
protected EmptyExpression(String propertyName) { protected EmptyExpression(String propertyName) {
super( propertyName ); super( propertyName );
} }
@Override
protected boolean excludeEmpty() { protected boolean excludeEmpty() {
return false; return false;
} }
} }

View File

@ -1,10 +1,10 @@
/* /*
* Hibernate, Relational Persistence for Idiomatic Java * 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 * indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are * 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, * 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 * copy, or redistribute it subject to the terms and conditions of the GNU
@ -20,9 +20,9 @@
* Free Software Foundation, Inc. * Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor * 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA * Boston, MA 02110-1301 USA
*
*/ */
package org.hibernate.criterion; package org.hibernate.criterion;
import org.hibernate.Criteria; import org.hibernate.Criteria;
/** /**

View File

@ -22,6 +22,7 @@
* Boston, MA 02110-1301 USA * Boston, MA 02110-1301 USA
*/ */
package org.hibernate.criterion; package org.hibernate.criterion;
import java.io.Serializable; import java.io.Serializable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashSet; import java.util.HashSet;
@ -30,7 +31,6 @@ import java.util.Set;
import org.hibernate.Criteria; import org.hibernate.Criteria;
import org.hibernate.EntityMode; import org.hibernate.EntityMode;
import org.hibernate.HibernateException;
import org.hibernate.engine.spi.TypedValue; import org.hibernate.engine.spi.TypedValue;
import org.hibernate.internal.util.StringHelper; import org.hibernate.internal.util.StringHelper;
import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.entity.EntityPersister;
@ -39,6 +39,7 @@ import org.hibernate.type.Type;
/** /**
* Support for query by example. * Support for query by example.
*
* <pre> * <pre>
* List results = session.createCriteria(Parent.class) * List results = session.createCriteria(Parent.class)
* .add( Example.create(parent).ignoreCase() ) * .add( Example.create(parent).ignoreCase() )
@ -46,68 +47,57 @@ import org.hibernate.type.Type;
* .add( Example.create( parent.getChild() ) ) * .add( Example.create( parent.getChild() ) )
* .list(); * .list();
* </pre> * </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 * @see org.hibernate.Criteria
* @author Gavin King * @author Gavin King
*/ */
public class Example implements Criterion { public class Example implements Criterion {
private final Object exampleEntity;
private final Object entity;
private final Set excludedProperties = new HashSet();
private PropertySelector selector; private PropertySelector selector;
private boolean isLikeEnabled; private boolean isLikeEnabled;
private Character escapeCharacter; private Character escapeCharacter;
private boolean isIgnoreCaseEnabled; private boolean isIgnoreCaseEnabled;
private MatchMode matchMode; private MatchMode matchMode;
private final Set<String> excludedProperties = new HashSet<String>();
/** /**
* A strategy for choosing property values for inclusion in the query * Create a new Example criterion instance, which includes all non-null properties by default
* criteria *
* @param exampleEntity The example bean to use.
*
* @return a new instance of Example
*/ */
public static Example create(Object exampleEntity) {
public static interface PropertySelector extends Serializable { if ( exampleEntity == null ) {
public boolean include(Object propertyValue, String propertyName, Type type); throw new NullPointerException( "null example entity" );
}
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;
} }
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) { public Example setEscapeCharacter(Character escapeCharacter) {
this.escapeCharacter = 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) { public Example setPropertySelector(PropertySelector selector) {
this.selector = 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() { public Example excludeZeroes() {
setPropertySelector(NOT_NULL_OR_ZERO); setPropertySelector( NotNullOrZeroPropertySelector.INSTANCE );
return this; 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() { public Example excludeNone() {
setPropertySelector(ALL); setPropertySelector( AllPropertySelector.INSTANCE );
return this; return this;
} }
/** /**
* Use the "like" operator for all string-valued properties * Exclude a particular property by name.
*/ *
public Example enableLike(MatchMode matchMode) { * @param name The name of the property to exclude
isLikeEnabled = true; *
this.matchMode = matchMode; * @return {@code this}, for method chaining
return this; *
} * @see #setPropertySelector
/**
* 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
*/ */
public Example excludeProperty(String name) { public Example excludeProperty(String name) {
excludedProperties.add(name); excludedProperties.add( name );
return this; return this;
} }
/** @Override
* Create a new instance, which includes all non-null properties public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery) {
* by default final StringBuilder buf = new StringBuilder().append( '(' );
* @param entity final EntityPersister meta = criteriaQuery.getFactory().getEntityPersister(
* @return a new instance of <tt>Example</tt> criteriaQuery.getEntityName( criteria )
*/ );
public static Example create(Object entity) { final String[] propertyNames = meta.getPropertyNames();
if (entity==null) throw new NullPointerException("null example"); final Type[] propertyTypes = meta.getPropertyTypes();
return new Example(entity, NOT_NULL);
}
protected Example(Object entity, PropertySelector selector) { final Object[] propertyValues = meta.getPropertyValues( exampleEntity );
this.entity = entity; for ( int i=0; i<propertyNames.length; i++ ) {
this.selector = selector; final Object propertyValue = propertyValues[i];
} final String propertyName = propertyNames[i];
public String toString() { final boolean isVersionProperty = i == meta.getVersionProperty();
return "example (" + entity + ')'; if ( ! isVersionProperty && isPropertyIncluded( propertyValue, propertyName, propertyTypes[i] ) ) {
}
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) {
if ( propertyTypes[i].isComponentType() ) { if ( propertyTypes[i].isComponentType() ) {
appendComponentCondition( appendComponentCondition(
propertyName, 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) if ( type.isAssociationType() ) {
throws HibernateException { // associations are implicitly excluded
return false;
}
EntityPersister meta = criteriaQuery.getFactory() return selector.include( value, name, type );
.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];
boolean isPropertyIncluded = i!=meta.getVersionProperty() && @Override
isPropertyIncluded(value, name, type); 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() ) { if ( propertyTypes[i].isComponentType() ) {
addComponentTypedValues(name, value, (CompositeType) type, list, criteria, criteriaQuery); addComponentTypedValues( name, value, (CompositeType) type, list, criteria, criteriaQuery );
} }
else { 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) { protected void addPropertyTypedValue(Object value, Type type, List<TypedValue> list) {
EntityPersister meta = criteriaQuery.getFactory() if ( value != null ) {
.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 ) {
if ( value instanceof String ) { if ( value instanceof String ) {
String string = (String) value; String string = (String) value;
if (isIgnoreCaseEnabled) string = string.toLowerCase(); if ( isIgnoreCaseEnabled ) {
if (isLikeEnabled) string = matchMode.toMatchString(string); string = string.toLowerCase();
}
if ( isLikeEnabled ) {
string = matchMode.toMatchString( string );
}
value = 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, String path,
Object component, Object component,
CompositeType type, CompositeType type,
List list, List<TypedValue> list,
Criteria criteria, Criteria criteria,
CriteriaQuery criteriaQuery) CriteriaQuery criteriaQuery) {
throws HibernateException { if ( component != null ) {
final String[] propertyNames = type.getPropertyNames();
if (component!=null) { final Type[] subtypes = type.getSubtypes();
String[] propertyNames = type.getPropertyNames(); final Object[] values = type.getPropertyValues( component, getEntityMode( criteria, criteriaQuery ) );
Type[] subtypes = type.getSubtypes(); for ( int i=0; i<propertyNames.length; i++ ) {
Object[] values = type.getPropertyValues( component, getEntityMode(criteria, criteriaQuery) ); final Object value = values[i];
for (int i=0; i<propertyNames.length; i++) { final Type subtype = subtypes[i];
Object value = values[i]; final String subpath = StringHelper.qualify( path, propertyNames[i] );
Type subtype = subtypes[i]; if ( isPropertyIncluded( value, subpath, subtype ) ) {
String subpath = StringHelper.qualify( path, propertyNames[i] );
if ( isPropertyIncluded(value, subpath, subtype) ) {
if ( subtype.isComponentType() ) { if ( subtype.isComponentType() ) {
addComponentTypedValues(subpath, value, (CompositeType) subtype, list, criteria, criteriaQuery); addComponentTypedValues( subpath, value, (CompositeType) subtype, list, criteria, criteriaQuery );
} }
else { 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( protected void appendPropertyCondition(
String propertyName, String propertyName,
Object propertyValue, Object propertyValue,
Criteria criteria, Criteria criteria,
CriteriaQuery cq, CriteriaQuery cq,
StringBuilder buf) StringBuilder buf) {
throws HibernateException { final Criterion condition;
Criterion crit; if ( propertyValue != null ) {
if ( propertyValue!=null ) { final boolean isString = propertyValue instanceof String;
boolean isString = propertyValue instanceof String;
if ( isLikeEnabled && isString ) { if ( isLikeEnabled && isString ) {
crit = new LikeExpression( condition = new LikeExpression(
propertyName, propertyName,
( String ) propertyValue, (String) propertyValue,
matchMode, matchMode,
escapeCharacter, escapeCharacter,
isIgnoreCaseEnabled isIgnoreCaseEnabled
); );
} }
else { else {
crit = new SimpleExpression( propertyName, propertyValue, "=", isIgnoreCaseEnabled && isString ); condition = new SimpleExpression( propertyName, propertyValue, "=", isIgnoreCaseEnabled && isString );
} }
} }
else { 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( protected void appendComponentCondition(
String path, String path,
Object component, Object component,
CompositeType type, CompositeType type,
Criteria criteria, Criteria criteria,
CriteriaQuery criteriaQuery, CriteriaQuery criteriaQuery,
StringBuilder buf) StringBuilder buf) {
throws HibernateException { if ( component != null ) {
final String[] propertyNames = type.getPropertyNames();
if (component!=null) { final Object[] values = type.getPropertyValues( component, getEntityMode( criteria, criteriaQuery ) );
String[] propertyNames = type.getPropertyNames(); final Type[] subtypes = type.getSubtypes();
Object[] values = type.getPropertyValues( component, getEntityMode(criteria, criteriaQuery) ); for ( int i=0; i<propertyNames.length; i++ ) {
Type[] subtypes = type.getSubtypes(); final String subPath = StringHelper.qualify( path, propertyNames[i] );
for (int i=0; i<propertyNames.length; i++) { final Object value = values[i];
String subpath = StringHelper.qualify( path, propertyNames[i] ); if ( isPropertyIncluded( value, subPath, subtypes[i] ) ) {
Object value = values[i]; final Type subtype = subtypes[i];
if ( isPropertyIncluded( value, subpath, subtypes[i] ) ) {
Type subtype = subtypes[i];
if ( subtype.isComponentType() ) { if ( subtype.isComponentType() ) {
appendComponentCondition( appendComponentCondition(
subpath, subPath,
value, value,
(CompositeType) subtype, (CompositeType) subtype,
criteria, criteria,
criteriaQuery, criteriaQuery,
buf buf
); );
} }
else { else {
appendPropertyCondition( appendPropertyCondition(
subpath, subPath,
value, value,
criteria, criteria,
criteriaQuery, criteriaQuery,
buf 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 * 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 * indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are * 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, * 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 * copy, or redistribute it subject to the terms and conditions of the GNU
@ -20,21 +20,32 @@
* Free Software Foundation, Inc. * Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor * 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA * Boston, MA 02110-1301 USA
*
*/ */
package org.hibernate.criterion; package org.hibernate.criterion;
import org.hibernate.Criteria; import org.hibernate.Criteria;
/** /**
* Expression that checks the existence of rows in a sub-query
*
* @author Gavin King * @author Gavin King
*/ */
public class ExistsSubqueryExpression extends SubqueryExpression { 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) { protected String toLeftSqlString(Criteria criteria, CriteriaQuery outerQuery) {
return ""; return "";
} }
protected ExistsSubqueryExpression(String quantifier, DetachedCriteria dc) {
super(null, quantifier, dc);
}
} }

View File

@ -1,10 +1,10 @@
/* /*
* Hibernate, Relational Persistence for Idiomatic Java * 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 * indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are * 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, * 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 * copy, or redistribute it subject to the terms and conditions of the GNU
@ -20,66 +20,72 @@
* Free Software Foundation, Inc. * Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor * 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA * Boston, MA 02110-1301 USA
*
*/ */
package org.hibernate.criterion; package org.hibernate.criterion;
import org.hibernate.internal.util.collections.ArrayHelper;
import org.hibernate.type.Type; import org.hibernate.type.Type;
/** /**
* @deprecated Use <tt>Restrictions</tt>. * Factory for Criterion objects. Deprecated!
* @see Restrictions *
* @author Gavin King * @author Gavin King
*
* @see Restrictions
*
* @deprecated Use {@link Restrictions} instead
*/ */
@Deprecated @Deprecated
public final class Expression extends Restrictions { 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() { private Expression() {
//cannot be instantiated //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 * 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 * indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are * 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, * 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 * copy, or redistribute it subject to the terms and conditions of the GNU
@ -20,46 +20,49 @@
* Free Software Foundation, Inc. * Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor * 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA * Boston, MA 02110-1301 USA
*
*/ */
package org.hibernate.criterion; package org.hibernate.criterion;
import org.hibernate.Criteria; import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.engine.spi.TypedValue; import org.hibernate.engine.spi.TypedValue;
import org.hibernate.internal.util.StringHelper; import org.hibernate.internal.util.StringHelper;
/** /**
* An identifier constraint * An identifier constraint
*
* @author Gavin King * @author Gavin King
*/ */
public class IdentifierEqExpression implements Criterion { public class IdentifierEqExpression implements Criterion {
private final Object value; private final Object value;
/**
* Constructs an IdentifierEqExpression
*
* @param value The identifier value
*
* @see Restrictions#idEq
*/
protected IdentifierEqExpression(Object value) { protected IdentifierEqExpression(Object value) {
this.value = value; this.value = value;
} }
public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery) @Override
throws HibernateException { 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) {
String result = StringHelper.join( result = '(' + result + ')';
" and ", }
StringHelper.suffix( columns, " = ?" )
);
if (columns.length>1) result = '(' + result + ')';
return result; return result;
//TODO: get SQL rendering out of this package!
} }
public TypedValue[] getTypedValues(Criteria criteria, CriteriaQuery criteriaQuery) @Override
throws HibernateException { public TypedValue[] getTypedValues(Criteria criteria, CriteriaQuery criteriaQuery) {
return new TypedValue[] { criteriaQuery.getTypedIdentifierValue(criteria, value) }; return new TypedValue[] { criteriaQuery.getTypedIdentifierValue( criteria, value ) };
} }
@Override
public String toString() { public String toString() {
return "id = " + value; return "id = " + value;
} }

View File

@ -1,10 +1,10 @@
/* /*
* Hibernate, Relational Persistence for Idiomatic Java * 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 * indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are * 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, * 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 * copy, or redistribute it subject to the terms and conditions of the GNU
@ -20,66 +20,77 @@
* Free Software Foundation, Inc. * Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor * 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA * Boston, MA 02110-1301 USA
*
*/ */
package org.hibernate.criterion; package org.hibernate.criterion;
import org.hibernate.Criteria; import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.internal.util.StringHelper; import org.hibernate.internal.util.StringHelper;
import org.hibernate.type.Type; import org.hibernate.type.Type;
/** /**
* A property value, or grouped property value * A property value, or grouped property value
*
* @author Gavin King * @author Gavin King
*/ */
public class IdentifierProjection extends SimpleProjection { public class IdentifierProjection extends SimpleProjection {
private boolean grouped; 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; this.grouped = grouped;
} }
protected IdentifierProjection() { @Override
this(false); public Type[] getTypes(Criteria criteria, CriteriaQuery criteriaQuery) {
return new Type[] { criteriaQuery.getIdentifierType( criteria ) };
} }
public String toString() { @Override
return "id"; public String toSqlString(Criteria criteria, int position, CriteriaQuery criteriaQuery) {
} final StringBuilder buf = new StringBuilder();
final String[] cols = criteriaQuery.getIdentifierColumns( criteria );
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);
for ( int i=0; i<cols.length; i++ ) { for ( int i=0; i<cols.length; i++ ) {
buf.append( cols[i] ) buf.append( cols[i] )
.append(" as y") .append( " as y" )
.append(position + i) .append( position + i )
.append('_'); .append( '_' );
if (i < cols.length -1) if ( i < cols.length -1 ) {
buf.append(", "); buf.append( ", " );
}
} }
return buf.toString(); return buf.toString();
} }
@Override
public boolean isGrouped() { public boolean isGrouped() {
return grouped; return grouped;
} }
public String toGroupSqlString(Criteria criteria, CriteriaQuery criteriaQuery) @Override
throws HibernateException { public String toGroupSqlString(Criteria criteria, CriteriaQuery criteriaQuery) {
if (!grouped) { if ( !grouped ) {
return super.toGroupSqlString(criteria, criteriaQuery); return super.toGroupSqlString( criteria, criteriaQuery );
} }
else { 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; import org.hibernate.engine.spi.TypedValue;
/** /**
* A case-insensitive "like" * A case-insensitive "like".
* *
* @author Gavin King * @author Gavin King
*
* @deprecated Prefer {@link LikeExpression} which now has case-insensitivity capability.
*/ */
@Deprecated @Deprecated
@SuppressWarnings({"deprecation", "UnusedDeclaration"})
public class IlikeExpression implements Criterion { public class IlikeExpression implements Criterion {
private final String propertyName; private final String propertyName;
private final Object value; private final Object value;
@ -51,10 +53,10 @@ public class IlikeExpression implements Criterion {
this( propertyName, matchMode.toMatchString( value ) ); this( propertyName, matchMode.toMatchString( value ) );
} }
public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery) @Override
throws HibernateException { public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery) {
Dialect dialect = criteriaQuery.getFactory().getDialect(); final Dialect dialect = criteriaQuery.getFactory().getDialect();
String[] columns = criteriaQuery.findColumns( propertyName, criteria ); final String[] columns = criteriaQuery.findColumns( propertyName, criteria );
if ( columns.length != 1 ) { if ( columns.length != 1 ) {
throw new HibernateException( "ilike may only be used with single-column properties" ); throw new HibernateException( "ilike may only be used with single-column properties" );
} }
@ -64,12 +66,10 @@ public class IlikeExpression implements Criterion {
else { else {
return dialect.getLowercaseFunction() + '(' + columns[0] + ") like ?"; return dialect.getLowercaseFunction() + '(' + columns[0] + ") like ?";
} }
//TODO: get SQL rendering out of this package!
} }
public TypedValue[] getTypedValues(Criteria criteria, CriteriaQuery criteriaQuery) @Override
throws HibernateException { public TypedValue[] getTypedValues(Criteria criteria, CriteriaQuery criteriaQuery) {
return new TypedValue[] { return new TypedValue[] {
criteriaQuery.getTypedValue( criteriaQuery.getTypedValue(
criteria, criteria,
@ -79,6 +79,7 @@ public class IlikeExpression implements Criterion {
}; };
} }
@Override
public String toString() { public String toString() {
return propertyName + " ilike " + value; return propertyName + " ilike " + value;
} }

View File

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

View File

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

View File

@ -1,10 +1,10 @@
/* /*
* Hibernate, Relational Persistence for Idiomatic Java * 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 * indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are * 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, * 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 * copy, or redistribute it subject to the terms and conditions of the GNU
@ -20,9 +20,9 @@
* Free Software Foundation, Inc. * Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor * 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA * Boston, MA 02110-1301 USA
*
*/ */
package org.hibernate.criterion; package org.hibernate.criterion;
import org.hibernate.Criteria; import org.hibernate.Criteria;
import org.hibernate.HibernateException; import org.hibernate.HibernateException;
import org.hibernate.dialect.Dialect; import org.hibernate.dialect.Dialect;
@ -51,16 +51,12 @@ public class LikeExpression implements Criterion {
this.ignoreCase = ignoreCase; this.ignoreCase = ignoreCase;
} }
protected LikeExpression( protected LikeExpression(String propertyName, String value) {
String propertyName,
String value) {
this( propertyName, value, null, false ); this( propertyName, value, null, false );
} }
protected LikeExpression( @SuppressWarnings("UnusedDeclaration")
String propertyName, protected LikeExpression(String propertyName, String value, MatchMode matchMode) {
String value,
MatchMode matchMode) {
this( propertyName, matchMode.toMatchString( value ) ); this( propertyName, matchMode.toMatchString( value ) );
} }
@ -73,16 +69,16 @@ public class LikeExpression implements Criterion {
this( propertyName, matchMode.toMatchString( value ), escapeChar, ignoreCase ); this( propertyName, matchMode.toMatchString( value ), escapeChar, ignoreCase );
} }
public String toSqlString( @Override
Criteria criteria, public String toSqlString(Criteria criteria,CriteriaQuery criteriaQuery) {
CriteriaQuery criteriaQuery) throws HibernateException { final Dialect dialect = criteriaQuery.getFactory().getDialect();
Dialect dialect = criteriaQuery.getFactory().getDialect(); final String[] columns = criteriaQuery.findColumns( propertyName, criteria );
String[] columns = criteriaQuery.findColumns(propertyName, criteria);
if ( columns.length != 1 ) { if ( columns.length != 1 ) {
throw new HibernateException( "Like may only be used with single-column properties" ); 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 ( ignoreCase ) {
if ( dialect.supportsCaseInsensitiveLike() ) { if ( dialect.supportsCaseInsensitiveLike() ) {
return column +" " + dialect.getCaseInsensitiveLike() + " ?" + escape; return column +" " + dialect.getCaseInsensitiveLike() + " ?" + escape;
@ -96,11 +92,10 @@ public class LikeExpression implements Criterion {
} }
} }
public TypedValue[] getTypedValues( @Override
Criteria criteria, public TypedValue[] getTypedValues(Criteria criteria, CriteriaQuery criteriaQuery) {
CriteriaQuery criteriaQuery) throws HibernateException { final String matchValue = ignoreCase ? value.toString().toLowerCase() : value.toString();
return new TypedValue[] {
criteriaQuery.getTypedValue( criteria, propertyName, 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 * 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 * indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are * 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, * 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 * copy, or redistribute it subject to the terms and conditions of the GNU
@ -20,19 +20,18 @@
* Free Software Foundation, Inc. * Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor * 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA * Boston, MA 02110-1301 USA
*
*/ */
package org.hibernate.criterion; package org.hibernate.criterion;
import org.hibernate.Criteria; import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.engine.spi.TypedValue; import org.hibernate.engine.spi.TypedValue;
/** /**
* Superclass of binary logical expressions * Superclass of binary logical expressions
*
* @author Gavin King * @author Gavin King
*/ */
public class LogicalExpression implements Criterion { public class LogicalExpression implements Criterion {
private final Criterion lhs; private final Criterion lhs;
private final Criterion rhs; private final Criterion rhs;
private final String op; private final String op;
@ -43,33 +42,33 @@ public class LogicalExpression implements Criterion {
this.op = op; this.op = op;
} }
public TypedValue[] getTypedValues(Criteria criteria, CriteriaQuery criteriaQuery) @Override
throws HibernateException { 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); final TypedValue[] result = new TypedValue[ lhsTypedValues.length + rhsTypedValues.length ];
TypedValue[] rhstv = rhs.getTypedValues(criteria, criteriaQuery); System.arraycopy( lhsTypedValues, 0, result, 0, lhsTypedValues.length );
TypedValue[] result = new TypedValue[ lhstv.length + rhstv.length ]; System.arraycopy( rhsTypedValues, 0, result, lhsTypedValues.length, rhsTypedValues.length );
System.arraycopy(lhstv, 0, result, 0, lhstv.length);
System.arraycopy(rhstv, 0, result, lhstv.length, rhstv.length);
return result; return result;
} }
public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery) @Override
throws HibernateException { public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery) {
return '('
return '(' + + lhs.toSqlString( criteria, criteriaQuery )
lhs.toSqlString(criteria, criteriaQuery) + + ' '
' ' + + getOp()
getOp() + + ' '
' ' + + rhs.toSqlString( criteria, criteriaQuery )
rhs.toSqlString(criteria, criteriaQuery) + + ')';
')';
} }
public String getOp() { public String getOp() {
return op; return op;
} }
@Override
public String toString() { public String toString() {
return lhs.toString() + ' ' + getOp() + ' ' + rhs.toString(); return lhs.toString() + ' ' + getOp() + ' ' + rhs.toString();
} }

View File

@ -1,10 +1,10 @@
/* /*
* Hibernate, Relational Persistence for Idiomatic Java * 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 * indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are * 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, * 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 * copy, or redistribute it subject to the terms and conditions of the GNU
@ -20,7 +20,6 @@
* Free Software Foundation, Inc. * Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor * 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA * Boston, MA 02110-1301 USA
*
*/ */
package org.hibernate.criterion; package org.hibernate.criterion;
@ -36,6 +35,7 @@ public enum MatchMode {
* Match the entire string to the pattern * Match the entire string to the pattern
*/ */
EXACT { EXACT {
@Override
public String toMatchString(String pattern) { public String toMatchString(String pattern) {
return pattern; return pattern;
} }
@ -45,6 +45,7 @@ public enum MatchMode {
* Match the start of the string to the pattern * Match the start of the string to the pattern
*/ */
START { START {
@Override
public String toMatchString(String pattern) { public String toMatchString(String pattern) {
return pattern + '%'; return pattern + '%';
} }
@ -54,6 +55,7 @@ public enum MatchMode {
* Match the end of the string to the pattern * Match the end of the string to the pattern
*/ */
END { END {
@Override
public String toMatchString(String pattern) { public String toMatchString(String pattern) {
return '%' + pattern; return '%' + pattern;
} }
@ -63,13 +65,18 @@ public enum MatchMode {
* Match the pattern anywhere in the string * Match the pattern anywhere in the string
*/ */
ANYWHERE { ANYWHERE {
@Override
public String toMatchString(String pattern) { public String toMatchString(String pattern) {
return '%' + 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); public abstract String toMatchString(String pattern);

View File

@ -28,27 +28,37 @@ import java.util.concurrent.ConcurrentHashMap;
import org.hibernate.Criteria; import org.hibernate.Criteria;
import org.hibernate.HibernateException; import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.engine.spi.TypedValue; import org.hibernate.engine.spi.TypedValue;
/** /**
* An expression pertaining to an entity's defined natural identifier
*
* @author Gavin King * @author Gavin King
* @see Session#byNaturalId(Class) *
* @see Session#byNaturalId(String) * @see org.hibernate.Session#byNaturalId(Class)
* @see Session#bySimpleNaturalId(Class) * @see org.hibernate.Session#byNaturalId(String)
* @see Session#bySimpleNaturalId(String) * @see org.hibernate.Session#bySimpleNaturalId(Class)
* @see org.hibernate.Session#bySimpleNaturalId(String)
*/ */
public class NaturalIdentifier implements Criterion { public class NaturalIdentifier implements Criterion {
private final Conjunction conjunction = new Conjunction(); private final Conjunction conjunction = new Conjunction();
@Override
public TypedValue[] getTypedValues(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException { public TypedValue[] getTypedValues(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException {
return conjunction.getTypedValues( criteria, criteriaQuery ); return conjunction.getTypedValues( criteria, criteriaQuery );
} }
@Override
public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException { public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException {
return conjunction.toSqlString( criteria, criteriaQuery ); 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() { public Map<String, Object> getNaturalIdValues() {
final Map<String, Object> naturalIdValueMap = new ConcurrentHashMap<String, Object>(); final Map<String, Object> naturalIdValueMap = new ConcurrentHashMap<String, Object>();
for ( Criterion condition : conjunction.conditions() ) { for ( Criterion condition : conjunction.conditions() ) {
@ -65,6 +75,14 @@ public class NaturalIdentifier implements Criterion {
return naturalIdValueMap; 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) { public NaturalIdentifier set(String property, Object value) {
conjunction.add( Restrictions.eq( property, value ) ); conjunction.add( Restrictions.eq( property, value ) );
return this; return this;

View File

@ -1,10 +1,10 @@
/* /*
* Hibernate, Relational Persistence for Idiomatic Java * 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 * indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are * 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, * 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 * copy, or redistribute it subject to the terms and conditions of the GNU
@ -20,20 +20,27 @@
* Free Software Foundation, Inc. * Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor * 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA * Boston, MA 02110-1301 USA
*
*/ */
package org.hibernate.criterion; package org.hibernate.criterion;
/** /**
* An expression asserting that a collection property is empty
*
* @author Gavin King * @author Gavin King
*/ */
public class NotEmptyExpression extends AbstractEmptinessExpression implements Criterion { public class NotEmptyExpression extends AbstractEmptinessExpression implements Criterion {
/**
* Constructs an EmptyExpression
*
* @param propertyName The collection property name
*
* @see Restrictions#isNotEmpty
*/
protected NotEmptyExpression(String propertyName) { protected NotEmptyExpression(String propertyName) {
super( propertyName ); super( propertyName );
} }
@Override
protected boolean excludeEmpty() { protected boolean excludeEmpty() {
return true; return true;
} }

View File

@ -28,29 +28,37 @@ import org.hibernate.HibernateException;
import org.hibernate.engine.spi.TypedValue; 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 Gavin King
* @author Brett Meyer
*/ */
public class NotExpression implements Criterion { public class NotExpression implements Criterion {
private Criterion criterion; private Criterion criterion;
/**
* Constructs a NotExpression
*
* @param criterion The expression to wrap and negate
*
* @see Restrictions#not
*/
protected NotExpression(Criterion criterion) { protected NotExpression(Criterion criterion) {
this.criterion = criterion; this.criterion = criterion;
} }
@Override
public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException { public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException {
return criteriaQuery.getFactory().getDialect().getNotExpression( return criteriaQuery.getFactory().getDialect().getNotExpression(
criterion.toSqlString( criteria, criteriaQuery ) ); criterion.toSqlString( criteria, criteriaQuery )
);
} }
public TypedValue[] getTypedValues( @Override
Criteria criteria, CriteriaQuery criteriaQuery) public TypedValue[] getTypedValues(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException {
throws HibernateException { return criterion.getTypedValues( criteria, criteriaQuery );
return criterion.getTypedValues(criteria, criteriaQuery);
} }
@Override
public String toString() { public String toString() {
return "not " + criterion.toString(); return "not " + criterion.toString();
} }

View File

@ -1,10 +1,10 @@
/* /*
* Hibernate, Relational Persistence for Idiomatic Java * 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 * indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are * 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, * 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 * copy, or redistribute it subject to the terms and conditions of the GNU
@ -20,9 +20,9 @@
* Free Software Foundation, Inc. * Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor * 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA * Boston, MA 02110-1301 USA
*
*/ */
package org.hibernate.criterion; package org.hibernate.criterion;
import org.hibernate.Criteria; import org.hibernate.Criteria;
import org.hibernate.HibernateException; import org.hibernate.HibernateException;
import org.hibernate.engine.spi.TypedValue; import org.hibernate.engine.spi.TypedValue;
@ -30,36 +30,37 @@ import org.hibernate.internal.util.StringHelper;
/** /**
* Constrains a property to be non-null * Constrains a property to be non-null
*
* @author Gavin King * @author Gavin King
*/ */
public class NotNullExpression implements Criterion { public class NotNullExpression implements Criterion {
private static final TypedValue[] NO_VALUES = new TypedValue[0];
private final String propertyName; private final String propertyName;
private static final TypedValue[] NO_VALUES = new TypedValue[0];
protected NotNullExpression(String propertyName) { protected NotNullExpression(String propertyName) {
this.propertyName = propertyName; this.propertyName = propertyName;
} }
public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery) @Override
throws HibernateException { public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException {
String[] columns = criteriaQuery.findColumns(propertyName, criteria); final String[] columns = criteriaQuery.findColumns( propertyName, criteria );
String result = StringHelper.join( String result = StringHelper.join(
" or ", " or ",
StringHelper.suffix( columns, " is not null" ) StringHelper.suffix( columns, " is not null" )
); );
if (columns.length>1) result = '(' + result + ')'; if ( columns.length > 1 ) {
result = '(' + result + ')';
}
return result; return result;
//TODO: get SQL rendering out of this package!
} }
public TypedValue[] getTypedValues(Criteria criteria, CriteriaQuery criteriaQuery) @Override
throws HibernateException { public TypedValue[] getTypedValues(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException {
return NO_VALUES; return NO_VALUES;
} }
@Override
public String toString() { public String toString() {
return propertyName + " is not null"; return propertyName + " is not null";
} }

View File

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

View File

@ -1,10 +1,10 @@
/* /*
* Hibernate, Relational Persistence for Idiomatic Java * 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 * indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are * 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, * 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 * copy, or redistribute it subject to the terms and conditions of the GNU
@ -20,24 +20,22 @@
* Free Software Foundation, Inc. * Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor * 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA * Boston, MA 02110-1301 USA
*
*/ */
package org.hibernate.criterion; package org.hibernate.criterion;
import java.io.Serializable; import java.io.Serializable;
import java.sql.Types; import java.sql.Types;
import org.hibernate.Criteria; import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.NullPrecedence; import org.hibernate.NullPrecedence;
import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.type.Type; 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 Gavin King
* @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com) * @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com)
* @author Brett Meyer
*/ */
public class Order implements Serializable { public class Order implements Serializable {
private boolean ascending; private boolean ascending;
@ -45,22 +43,33 @@ public class Order implements Serializable {
private String propertyName; private String propertyName;
private NullPrecedence nullPrecedence; private NullPrecedence nullPrecedence;
public String toString() { /**
return propertyName + ' ' + ( ascending ? "asc" : "desc" ) + ( nullPrecedence != null ? ' ' + nullPrecedence.name().toLowerCase() : "" ); * Ascending order
} *
* @param propertyName The property to order on
public Order ignoreCase() { *
ignoreCase = true; * @return The build Order instance
return this; */
} public static Order asc(String propertyName) {
return new Order( propertyName, true );
public Order nulls(NullPrecedence nullPrecedence) {
this.nullPrecedence = nullPrecedence;
return this;
} }
/** /**
* 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) { protected Order(String propertyName, boolean ascending) {
this.propertyName = propertyName; 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) public Order ignoreCase() {
throws HibernateException { ignoreCase = true;
String[] columns = criteriaQuery.getColumnsUsingProjection(criteria, propertyName); return this;
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;
}
if (lower) { /**
expression.append( factory.getDialect().getLowercaseFunction() ).append('('); * Defines precedence for nulls.
} *
expression.append( columns[i] ); * @param nullPrecedence The null precedence to use
if (lower) expression.append(')'); *
fragment.append( * @return {@code this}, for method chaining
factory.getDialect() */
.renderOrderByElement( public Order nulls(NullPrecedence nullPrecedence) {
expression.toString(), this.nullPrecedence = nullPrecedence;
null, return this;
ascending ? "asc" : "desc",
nullPrecedence != null ? nullPrecedence : factory.getSettings().getDefaultNullPrecedence()
)
);
if ( i<columns.length-1 ) fragment.append(", ");
}
return fragment.toString();
} }
public String getPropertyName() { public String getPropertyName() {
return propertyName; return propertyName;
} }
@SuppressWarnings("UnusedDeclaration")
public boolean isAscending() { public boolean isAscending() {
return ascending; return ascending;
} }
@SuppressWarnings("UnusedDeclaration")
public boolean isIgnoreCase() { public boolean isIgnoreCase() {
return ignoreCase; 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 * @param criteria The criteria
* @return Order * @param criteriaQuery The overall query
*
* @return The ORDER BY fragment for this ordering
*/ */
public static Order desc(String propertyName) { public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery) {
return new Order(propertyName, false); 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 * 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 * indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are * 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, * 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 * copy, or redistribute it subject to the terms and conditions of the GNU
@ -20,9 +20,9 @@
* Free Software Foundation, Inc. * Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor * 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA * Boston, MA 02110-1301 USA
*
*/ */
package org.hibernate.criterion; package org.hibernate.criterion;
import java.io.Serializable; import java.io.Serializable;
import org.hibernate.Criteria; import org.hibernate.Criteria;
@ -36,6 +36,7 @@ import org.hibernate.type.Type;
* *
* @author Gavin King * @author Gavin King
* @author Steve Ebersole * @author Steve Ebersole
*
* @see Projections * @see Projections
* @see Criteria * @see Criteria
*/ */

View File

@ -1,10 +1,10 @@
/* /*
* Hibernate, Relational Persistence for Idiomatic Java * 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 * indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are * 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, * 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 * copy, or redistribute it subject to the terms and conditions of the GNU
@ -20,159 +20,223 @@
* Free Software Foundation, Inc. * Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor * 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA * Boston, MA 02110-1301 USA
*
*/ */
package org.hibernate.criterion; package org.hibernate.criterion;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.List; import java.util.List;
import org.hibernate.Criteria; import org.hibernate.Criteria;
import org.hibernate.HibernateException; import org.hibernate.HibernateException;
import org.hibernate.internal.util.collections.ArrayHelper;
import org.hibernate.type.Type; import org.hibernate.type.Type;
/** /**
* A projection that wraps other projections to allow selecting multiple values.
*
* @author Gavin King * @author Gavin King
*/ */
public class ProjectionList implements EnhancedProjection { public class ProjectionList implements EnhancedProjection {
private List<Projection> elements = new ArrayList<Projection>();
private List elements = new ArrayList(); /**
* Constructs a ProjectionList
protected 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() { public ProjectionList create() {
return new ProjectionList(); 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; 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) { public ProjectionList add(Projection projection, String alias) {
return add( Projections.alias( projection, alias ) ); return add( Projections.alias( projection, alias ) );
} }
public Type[] getTypes(Criteria criteria, CriteriaQuery criteriaQuery) @Override
throws HibernateException { public boolean isGrouped() {
List types = new ArrayList( getLength() ); for ( Projection projection : elements ) {
for ( int i=0; i<getLength(); i++ ) { if ( projection.isGrouped() ) {
Type[] elemTypes = getProjection(i).getTypes(criteria, criteriaQuery); return true;
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(", ");
} }
} }
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(); return buf.toString();
} }
public String[] getColumnAliases(int loc) { @Override
List result = new ArrayList( getLength() ); public String toGroupSqlString(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException {
for ( int i=0; i<getLength(); i++ ) { final StringBuilder buf = new StringBuilder();
String[] colAliases = getProjection(i).getColumnAliases(loc); String separator = "";
ArrayHelper.addAll(result, colAliases); for ( Projection projection : elements ) {
loc+=colAliases.length; 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) { @Override
List result = new ArrayList( getLength() ); public String[] getColumnAliases(final int loc) {
for ( int i=0; i<getLength(); i++ ) { int position = loc;
String[] colAliases = getColumnAliases( loc, criteria, criteriaQuery, getProjection( i ) ); final List<String> result = new ArrayList<String>( getLength() );
ArrayHelper.addAll(result, colAliases); for ( Projection projection : elements ) {
loc+=colAliases.length; 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) { @Override
for ( int i=0; i<getLength(); i++ ) { public String[] getColumnAliases(final int loc, Criteria criteria, CriteriaQuery criteriaQuery) {
String[] result = getProjection(i).getColumnAliases(alias, loc); int position = loc;
if (result!=null) return result; final List<String> result = new ArrayList<String>( getLength() );
loc += getProjection(i).getColumnAliases(loc).length; 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; return null;
} }
@Override
public String[] getColumnAliases(String alias, int loc, Criteria criteria, CriteriaQuery criteriaQuery) { public String[] getColumnAliases(String alias, int loc, Criteria criteria, CriteriaQuery criteriaQuery) {
for ( int i=0; i<getLength(); i++ ) { int position = loc;
String[] result = getColumnAliases( alias, loc, criteria, criteriaQuery, getProjection(i) ); for ( Projection projection : elements ) {
if (result!=null) return result; final String[] aliases = getColumnAliases( alias, position, criteria, criteriaQuery, projection );
loc += getColumnAliases( loc, criteria, criteriaQuery, getProjection( i ) ).length; if ( aliases != null ) {
return aliases;
}
position += getColumnAliases( position, criteria, criteriaQuery, projection ).length;
} }
return null; return null;
} }
private static String[] getColumnAliases(int loc, Criteria criteria, CriteriaQuery criteriaQuery, Projection projection) { private static String[] getColumnAliases(int loc, Criteria criteria, CriteriaQuery criteriaQuery, Projection projection) {
return projection instanceof EnhancedProjection ? return projection instanceof EnhancedProjection
( ( EnhancedProjection ) projection ).getColumnAliases( loc, criteria, criteriaQuery ) : ? ( (EnhancedProjection) projection ).getColumnAliases( loc, criteria, criteriaQuery )
projection.getColumnAliases( loc ); : projection.getColumnAliases( loc );
} }
private static String[] getColumnAliases(String alias, int loc, Criteria criteria, CriteriaQuery criteriaQuery, Projection projection) { private static String[] getColumnAliases(String alias, int loc, Criteria criteria, CriteriaQuery criteriaQuery, Projection projection) {
return projection instanceof EnhancedProjection ? return projection instanceof EnhancedProjection
( ( EnhancedProjection ) projection ).getColumnAliases( alias, loc, criteria, criteriaQuery ) : ? ( (EnhancedProjection) projection ).getColumnAliases( alias, loc, criteria, criteriaQuery )
projection.getColumnAliases( alias, loc ); : projection.getColumnAliases( alias, loc );
} }
@Override
public Type[] getTypes(String alias, Criteria criteria, CriteriaQuery criteriaQuery) { public Type[] getTypes(String alias, Criteria criteria, CriteriaQuery criteriaQuery) {
for ( int i=0; i<getLength(); i++ ) { for ( Projection projection : elements ) {
Type[] result = getProjection(i).getTypes(alias, criteria, criteriaQuery); final Type[] types = projection.getTypes( alias, criteria, criteriaQuery );
if (result!=null) return result; if ( types != null ) {
return types;
}
} }
return null; return null;
} }
@Override
public String[] getAliases() { public String[] getAliases() {
List result = new ArrayList( getLength() ); final List<String> result = new ArrayList<String>( getLength() );
for ( int i=0; i<getLength(); i++ ) { for ( Projection projection : elements ) {
String[] aliases = getProjection(i).getAliases(); final String[] aliases = projection.getAliases();
ArrayHelper.addAll( result, aliases ); 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) { public Projection getProjection(int i) {
return (Projection) elements.get(i); return elements.get( i );
} }
public int getLength() { public int getLength() {
return elements.size(); return elements.size();
} }
@Override
public String toString() { public String toString() {
return elements.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 * 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 * indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are * 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, * 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 * copy, or redistribute it subject to the terms and conditions of the GNU
@ -20,38 +20,81 @@
* Free Software Foundation, Inc. * Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor * 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA * Boston, MA 02110-1301 USA
*
*/ */
package org.hibernate.criterion; package org.hibernate.criterion;
import org.hibernate.type.Type; import org.hibernate.type.Type;
/** /**
* The <tt>criterion</tt> package may be used by applications as a framework for building * 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 * 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/> * simply use the built-in projection types via the static factory methods of this class.
* <br/> *
* The factory methods that take an alias allow the projected value to be referred to by * The factory methods that take an alias allow the projected value to be referred to by
* criterion and order instances. * criterion and order instances.
* *
* @see org.hibernate.Criteria * See also the {@link Restrictions} factory methods for generating {@link Criterion} instances
* @see Restrictions factory methods for <tt>Criterion</tt> instances *
* @author Gavin King * @author Gavin King
* @author Steve Ebersole
*
* @see org.hibernate.Criteria
*/ */
public final class Projections { 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) { public static PropertyProjection property(String propertyName) {
return new Distinct(proj); 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() { public static ProjectionList projectionList() {
return new ProjectionList(); return new ProjectionList();
@ -59,92 +102,141 @@ public final class Projections {
/** /**
* The query row count, ie. <tt>count(*)</tt> * The query row count, ie. <tt>count(*)</tt>
*
* @return The projection representing the row count
*
* @see RowCountProjection
*/ */
public static Projection rowCount() { public static Projection rowCount() {
return new RowCountProjection(); 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) { 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) { 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) { 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) { 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) { 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) { public static AggregateProjection sum(String propertyName) {
return new AggregateProjection("sum", 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();
} }
/** /**
* Assign an alias to a projection, by wrapping it * 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) { 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; package org.hibernate.criterion;
import org.hibernate.Criteria; 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. * 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) * @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com)
*/ */
public class PropertiesSubqueryExpression extends SubqueryExpression { public class PropertiesSubqueryExpression extends SubqueryExpression {
@ -17,7 +41,7 @@ public class PropertiesSubqueryExpression extends SubqueryExpression {
@Override @Override
protected String toLeftSqlString(Criteria criteria, CriteriaQuery outerQuery) { protected String toLeftSqlString(Criteria criteria, CriteriaQuery outerQuery) {
StringBuilder left = new StringBuilder( "(" ); final StringBuilder left = new StringBuilder( "(" );
final String[] sqlColumnNames = new String[propertyNames.length]; final String[] sqlColumnNames = new String[propertyNames.length];
for ( int i = 0; i < sqlColumnNames.length; ++i ) { for ( int i = 0; i < sqlColumnNames.length; ++i ) {
sqlColumnNames[i] = outerQuery.getColumn( criteria, propertyNames[i] ); sqlColumnNames[i] = outerQuery.getColumn( criteria, propertyNames[i] );

View File

@ -1,10 +1,10 @@
/* /*
* Hibernate, Relational Persistence for Idiomatic Java * 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 * indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are * 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, * 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 * copy, or redistribute it subject to the terms and conditions of the GNU
@ -20,244 +20,737 @@
* Free Software Foundation, Inc. * Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor * 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA * Boston, MA 02110-1301 USA
*
*/ */
package org.hibernate.criterion; package org.hibernate.criterion;
import java.util.Collection; import java.util.Collection;
/** /**
* A factory for property-specific criterion and projection instances * A factory for property-specific criterion and projection instances
*
* @author Gavin King * @author Gavin King
* @author Steve Ebersole
*/ */
public class Property extends PropertyProjection { 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) { 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) { 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) { 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) { 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) { 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) { 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) { 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) { 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) { 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) { 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) { 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) { 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) { 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) { 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) { public PropertyExpression eqProperty(Property other) {
return Restrictions.eqProperty( getPropertyName(), other.getPropertyName() ); return Restrictions.eqProperty( getPropertyName(), other.getPropertyName() );
} }
public PropertyExpression neProperty(Property other) { /**
return Restrictions.neProperty( getPropertyName(), other.getPropertyName() ); * Creates an equality restriction between 2 properties
} *
* @param other The other property to compare against
public PropertyExpression leProperty(Property other) { *
return Restrictions.leProperty( getPropertyName(), other.getPropertyName() ); * @return The restriction
} *
* @see Restrictions#eqProperty(String, String)
public PropertyExpression geProperty(Property other) { */
return Restrictions.geProperty( getPropertyName(), other.getPropertyName() ); @SuppressWarnings("UnusedDeclaration")
}
public PropertyExpression ltProperty(Property other) {
return Restrictions.ltProperty( getPropertyName(), other.getPropertyName() );
}
public PropertyExpression gtProperty(Property other) {
return Restrictions.gtProperty( getPropertyName(), other.getPropertyName() );
}
public PropertyExpression eqProperty(String other) { public PropertyExpression eqProperty(String other) {
return Restrictions.eqProperty( getPropertyName(), 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) { public PropertyExpression neProperty(String other) {
return Restrictions.neProperty( getPropertyName(), 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) { public PropertyExpression leProperty(String other) {
return Restrictions.leProperty( getPropertyName(), 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) { public PropertyExpression geProperty(String other) {
return Restrictions.geProperty( getPropertyName(), 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) { public PropertyExpression ltProperty(String other) {
return Restrictions.ltProperty( getPropertyName(), 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) { public PropertyExpression gtProperty(String other) {
return Restrictions.gtProperty( getPropertyName(), other ); return Restrictions.gtProperty( getPropertyName(), other );
} }
/**
* Creates a NULL restriction
*
* @return The restriction
*
* @see Restrictions#isNull(String)
*/
public Criterion isNull() { public Criterion isNull() {
return Restrictions.isNull(getPropertyName()); 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);
} }
/** /**
* 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) { public Property getProperty(String propertyName) {
return forName( getPropertyName() + '.' + 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) { public Criterion eq(DetachedCriteria subselect) {
return Subqueries.propertyEq( getPropertyName(), 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) { public Criterion ne(DetachedCriteria subselect) {
return Subqueries.propertyNe( getPropertyName(), 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) { public Criterion lt(DetachedCriteria subselect) {
return Subqueries.propertyLt( getPropertyName(), 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) { public Criterion le(DetachedCriteria subselect) {
return Subqueries.propertyLe( getPropertyName(), 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) { public Criterion gt(DetachedCriteria subselect) {
return Subqueries.propertyGt( getPropertyName(), 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) { public Criterion ge(DetachedCriteria subselect) {
return Subqueries.propertyGe( getPropertyName(), 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) { public Criterion notIn(DetachedCriteria subselect) {
return Subqueries.propertyNotIn( getPropertyName(), 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) { public Criterion in(DetachedCriteria subselect) {
return Subqueries.propertyIn( getPropertyName(), 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) { public Criterion eqAll(DetachedCriteria subselect) {
return Subqueries.propertyEqAll( getPropertyName(), 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) { public Criterion gtAll(DetachedCriteria subselect) {
return Subqueries.propertyGtAll( getPropertyName(), 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) { public Criterion ltAll(DetachedCriteria subselect) {
return Subqueries.propertyLtAll( getPropertyName(), 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) { public Criterion leAll(DetachedCriteria subselect) {
return Subqueries.propertyLeAll( getPropertyName(), 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) { public Criterion geAll(DetachedCriteria subselect) {
return Subqueries.propertyGeAll( getPropertyName(), 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) { public Criterion gtSome(DetachedCriteria subselect) {
return Subqueries.propertyGtSome( getPropertyName(), 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) { public Criterion ltSome(DetachedCriteria subselect) {
return Subqueries.propertyLtSome( getPropertyName(), 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) { public Criterion leSome(DetachedCriteria subselect) {
return Subqueries.propertyLeSome( getPropertyName(), 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) { public Criterion geSome(DetachedCriteria subselect) {
return Subqueries.propertyGeSome( getPropertyName(), subselect ); return Subqueries.propertyGeSome( getPropertyName(), subselect );
} }

View File

@ -1,10 +1,10 @@
/* /*
* Hibernate, Relational Persistence for Idiomatic Java * 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 * indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are * 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, * 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 * copy, or redistribute it subject to the terms and conditions of the GNU
@ -20,9 +20,9 @@
* Free Software Foundation, Inc. * Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor * 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA * Boston, MA 02110-1301 USA
*
*/ */
package org.hibernate.criterion; package org.hibernate.criterion;
import org.hibernate.Criteria; import org.hibernate.Criteria;
import org.hibernate.HibernateException; import org.hibernate.HibernateException;
import org.hibernate.engine.spi.TypedValue; 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) * superclass for comparisons between two properties (with SQL binary operators)
*
* @author Gavin King * @author Gavin King
*/ */
public class PropertyExpression implements Criterion { public class PropertyExpression implements Criterion {
private static final TypedValue[] NO_TYPED_VALUES = new TypedValue[0];
private final String propertyName; private final String propertyName;
private final String otherPropertyName; private final String otherPropertyName;
private final String op; private final String op;
private static final TypedValue[] NO_TYPED_VALUES = new TypedValue[0];
protected PropertyExpression(String propertyName, String otherPropertyName, String op) { protected PropertyExpression(String propertyName, String otherPropertyName, String op) {
this.propertyName = propertyName; this.propertyName = propertyName;
this.otherPropertyName = otherPropertyName; this.otherPropertyName = otherPropertyName;
this.op = op; 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() { public String getOp() {
return op; 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 * A property value, or grouped property value
*
* @author Gavin King * @author Gavin King
* @author Steve Ebersole
*/ */
public class PropertyProjection extends SimpleProjection { public class PropertyProjection extends SimpleProjection {
private String propertyName; private String propertyName;
private boolean grouped; private boolean grouped;
@ -46,46 +47,49 @@ public class PropertyProjection extends SimpleProjection {
this(prop, false); this(prop, false);
} }
public String getPropertyName() { @Override
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();
}
public boolean isGrouped() { public boolean isGrouped() {
return grouped; return grouped;
} }
public String toGroupSqlString(Criteria criteria, CriteriaQuery criteriaQuery) public String getPropertyName() {
throws HibernateException { return propertyName;
if (!grouped) { }
return super.toGroupSqlString(criteria, criteriaQuery);
@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 { else {
return StringHelper.join( ", ", criteriaQuery.getColumns( propertyName, criteria ) ); 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 * 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 * indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are * 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, * 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 * copy, or redistribute it subject to the terms and conditions of the GNU
@ -20,26 +20,28 @@
* Free Software Foundation, Inc. * Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor * 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA * Boston, MA 02110-1301 USA
*
*/ */
package org.hibernate.criterion; package org.hibernate.criterion;
import org.hibernate.Criteria; import org.hibernate.Criteria;
/** /**
* A comparison between a property value in the outer query and the * A comparison between a property value in the outer query and the result of a subquery
* result of a subquery *
* @author Gavin King * @author Gavin King
* @author Steve Ebersole
*/ */
public class PropertySubqueryExpression extends SubqueryExpression { public class PropertySubqueryExpression extends SubqueryExpression {
private String propertyName; private String propertyName;
protected PropertySubqueryExpression(String propertyName, String op, String quantifier, DetachedCriteria dc) { protected PropertySubqueryExpression(String propertyName, String op, String quantifier, DetachedCriteria dc) {
super(op, quantifier, dc); super( op, quantifier, dc );
this.propertyName = propertyName; this.propertyName = propertyName;
} }
@Override
protected String toLeftSqlString(Criteria criteria, CriteriaQuery criteriaQuery) { 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 * 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 * indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are * 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, * 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 * copy, or redistribute it subject to the terms and conditions of the GNU
@ -20,16 +20,12 @@
* Free Software Foundation, Inc. * Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor * 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA * Boston, MA 02110-1301 USA
*
*/ */
package org.hibernate.criterion; package org.hibernate.criterion;
import java.util.Collection; import java.util.Collection;
import java.util.Iterator;
import java.util.Map; import java.util.Map;
import org.hibernate.Session;
import org.hibernate.internal.util.collections.ArrayHelper;
import org.hibernate.type.Type; 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 * 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. * simply use the built-in criterion types via the static factory methods of this class.
* *
* @see org.hibernate.Criteria * See also the {@link Projections} factory methods for generating {@link Projection} instances
* @see Projections factory methods for <tt>Projection</tt> instances *
* @author Gavin King * @author Gavin King
* @author Steve Ebersole
*
* @see org.hibernate.Criteria
*/ */
public class Restrictions { public class Restrictions {
Restrictions() {
//cannot be instantiated
}
/** /**
* Apply an "equal" constraint to the identifier property * Apply an "equal" constraint to the identifier property
* @param value *
* @param value The value to use in comparison
*
* @return Criterion * @return Criterion
*
* @see IdentifierEqExpression
*/ */
public static Criterion idEq(Object value) { public static Criterion idEq(Object value) {
return new IdentifierEqExpression(value); return new IdentifierEqExpression( value );
} }
/** /**
* Apply an "equal" constraint to the named property * 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 * @return SimpleExpression
*
* @see SimpleExpression
*/ */
public static SimpleExpression eq(String propertyName, Object value) { public static SimpleExpression eq(String propertyName, Object value) {
return new SimpleExpression(propertyName, 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 " );
} }
/** /**
* A case-insensitive "like", similar to Postgres <tt>ilike</tt> * Apply an "equal" constraint to the named property. If the value
* operator * is null, instead apply "is null".
* *
* @param propertyName * @param propertyName The name of the property
* @param value * @param value The value to use in comparison
* @return Criterion *
* @return The Criterion
*
* @see #eq
* @see #isNull
*/ */
public static Criterion ilike(String propertyName, String value, MatchMode matchMode) { public static Criterion eqOrIsNull(String propertyName, Object value) {
return new LikeExpression(propertyName, value, matchMode, null, true); return value == null
? isNull( propertyName )
: eq( propertyName, value );
} }
/** /**
* A case-insensitive "like", similar to Postgres <tt>ilike</tt> * Apply a "not equal" constraint to the named property
* operator
* *
* @param propertyName * @param propertyName The name of the property
* @param value * @param value The value to use in comparison
* @return Criterion *
* @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) { public static Criterion ilike(String propertyName, Object value) {
if ( value == null ) { if ( value == null ) {
@ -144,126 +165,239 @@ public class Restrictions {
return ilike( propertyName, value.toString(), MatchMode.EXACT ); 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 * Apply a "greater than" constraint to the named property
* @param propertyName *
* @param value * @param propertyName The name of the property
* @return Criterion * @param value The value to use in comparison
*
* @return The Criterion
*
* @see SimpleExpression
*/ */
public static SimpleExpression gt(String propertyName, Object value) { 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 * Apply a "less than" constraint to the named property
* @param propertyName *
* @param value * @param propertyName The name of the property
* @return Criterion * @param value The value to use in comparison
*
* @return The Criterion
*
* @see SimpleExpression
*/ */
public static SimpleExpression lt(String propertyName, Object value) { 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 * Apply a "less than or equal" constraint to the named property
* @param propertyName *
* @param value * @param propertyName The name of the property
* @return Criterion * @param value The value to use in comparison
*
* @return The Criterion
*
* @see SimpleExpression
*/ */
public static SimpleExpression le(String propertyName, Object value) { 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 * Apply a "greater than or equal" constraint to the named property
* @param propertyName *
* @param value * @param propertyName The name of the property
* @return Criterion * @param value The value to use in comparison
*
* @return The Criterion
*
* @see SimpleExpression
*/ */
public static SimpleExpression ge(String propertyName, Object value) { 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 * Apply a "between" constraint to the named property
* @param propertyName *
* @param lo value * @param propertyName The name of the property
* @param hi value * @param lo The low value
* @return Criterion * @param hi The high value
*
* @return The Criterion
*
* @see BetweenExpression
*/ */
public static Criterion between(String propertyName, Object lo, Object hi) { 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 * Apply an "in" constraint to the named property.
* @param propertyName *
* @param values * @param propertyName The name of the property
* @return Criterion * @param values The literal values to use in the IN restriction
*
* @return The Criterion
*
* @see InExpression
*/ */
public static Criterion in(String propertyName, Object[] values) { 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 * Apply an "in" constraint to the named property.
* @param propertyName *
* @param values * @param propertyName The name of the property
* @return Criterion * @param values The literal values to use in the IN restriction
*
* @return The Criterion
*
* @see InExpression
*/ */
public static Criterion in(String propertyName, Collection values) { public static Criterion in(String propertyName, Collection values) {
return new InExpression( propertyName, values.toArray() ); return new InExpression( propertyName, values.toArray() );
} }
/** /**
* Apply an "is null" constraint to the named property * Apply an "is null" constraint to the named property
*
* @param propertyName The name of the property
*
* @return Criterion * @return Criterion
*
* @see NullExpression
*/ */
public static Criterion isNull(String propertyName) { public static Criterion isNull(String propertyName) {
return new NullExpression(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, ">=");
} }
/** /**
* Apply an "is not null" constraint to the named property * 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) { 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 * Return the conjuction of two expressions
* *
* @param lhs * @param lhs One expression
* @param rhs * @param rhs The other expression
* @return Criterion *
* @return The Criterion
*/ */
public static LogicalExpression and(Criterion lhs, Criterion rhs) { public static LogicalExpression and(Criterion lhs, Criterion rhs) {
return new LogicalExpression(lhs, rhs, "and"); return new LogicalExpression(lhs, rhs, "and");
@ -276,24 +410,21 @@ public class Restrictions {
* @return The conjunction * @return The conjunction
*/ */
public static Conjunction and(Criterion... predicates) { public static Conjunction and(Criterion... predicates) {
Conjunction conjunction = conjunction(); return conjunction( predicates );
if ( predicates != null ) {
for ( Criterion predicate : predicates ) {
conjunction.add( predicate );
}
}
return conjunction;
} }
/** /**
* Return the disjuction of two expressions * Return the disjuction of two expressions
* *
* @param lhs * @param lhs One expression
* @param rhs * @param rhs The other expression
* @return Criterion *
* @return The Criterion
*/ */
public static LogicalExpression or(Criterion lhs, Criterion rhs) { 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 * Return the disjuction of multiple expressions
* *
@ -302,62 +433,72 @@ public class Restrictions {
* @return The conjunction * @return The conjunction
*/ */
public static Disjunction or(Criterion... predicates) { public static Disjunction or(Criterion... predicates) {
Disjunction disjunction = disjunction(); return disjunction( predicates );
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);
} }
/** /**
* 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 * @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 * @return Conjunction
*/ */
@ -375,89 +529,169 @@ public class Restrictions {
} }
/** /**
* Apply an "equals" constraint to each property in the * Group expressions together in a single disjunction (A or B or C...).
* key set of a <tt>Map</tt> *
* @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 * @param propertyNameValues a map from property names to values
*
* @return Criterion * @return Criterion
*
* @see Conjunction
*/ */
public static Criterion allEq(Map propertyNameValues) { @SuppressWarnings("UnusedDeclaration")
Conjunction conj = conjunction(); public static Criterion allEq(Map<String,?> propertyNameValues) {
Iterator iter = propertyNameValues.entrySet().iterator(); final Conjunction conj = conjunction();
while ( iter.hasNext() ) {
Map.Entry me = (Map.Entry) iter.next(); for ( Map.Entry<String,?> entry : propertyNameValues.entrySet() ) {
conj.add( eq( (String) me.getKey(), me.getValue() ) ); conj.add( eq( entry.getKey(), entry.getValue() ) );
} }
return conj; return conj;
} }
/** /**
* Constrain a collection valued property to be empty * 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) { public static Criterion isEmpty(String propertyName) {
return new EmptyExpression(propertyName); return new EmptyExpression( propertyName );
} }
/** /**
* Constrain a collection valued property to be non-empty * 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) { public static Criterion isNotEmpty(String propertyName) {
return new NotEmptyExpression(propertyName); return new NotEmptyExpression( propertyName );
} }
/** /**
* Constrain a collection valued property by 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
*/ */
public static Criterion sizeEq(String propertyName, int size) { 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 * 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) { 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 * 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) { 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 * 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) { 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 * 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) { 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 * 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) { 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 * 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. * where the restriction is the full set of natural id values.
* *
* @see Session#byNaturalId(Class) * @return The Criterion
* @see Session#byNaturalId(String) *
* @see Session#bySimpleNaturalId(Class) * @see NaturalIdentifier
* @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 static NaturalIdentifier naturalId() { public static NaturalIdentifier naturalId() {
return new NaturalIdentifier(); 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 * 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 * indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are * statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Inc. * distributed under license by Red Hat Inc.
@ -22,11 +22,13 @@
* Boston, MA 02110-1301 USA * Boston, MA 02110-1301 USA
*/ */
package org.hibernate.criterion; package org.hibernate.criterion;
import java.util.List; import java.util.List;
import org.hibernate.Criteria; import org.hibernate.Criteria;
import org.hibernate.HibernateException; import org.hibernate.HibernateException;
import org.hibernate.dialect.function.SQLFunction; import org.hibernate.dialect.function.SQLFunction;
import org.hibernate.dialect.function.SQLFunctionRegistry;
import org.hibernate.type.Type; import org.hibernate.type.Type;
/** /**
@ -35,30 +37,30 @@ import org.hibernate.type.Type;
* @author Gavin King * @author Gavin King
*/ */
public class RowCountProjection extends SimpleProjection { public class RowCountProjection extends SimpleProjection {
private static List ARGS = java.util.Collections.singletonList( "*" ); private static final List ARGS = java.util.Collections.singletonList( "*" );
public String toString() {
return "count(*)";
}
@Override
public Type[] getTypes(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException { public Type[] getTypes(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException {
return new Type[] { final Type countFunctionReturnType = getFunction( criteriaQuery ).getReturnType( null, criteriaQuery.getFactory() );
getFunction( criteriaQuery ).getReturnType( null, criteriaQuery.getFactory() ) return new Type[] { countFunctionReturnType };
};
} }
@Override
public String toSqlString(Criteria criteria, int position, CriteriaQuery criteriaQuery) throws HibernateException { public String toSqlString(Criteria criteria, int position, CriteriaQuery criteriaQuery) throws HibernateException {
return getFunction( criteriaQuery ).render( null, ARGS, criteriaQuery.getFactory() ) return getFunction( criteriaQuery ).render( null, ARGS, criteriaQuery.getFactory() ) + " as y" + position + '_';
+ " as y" + position + '_';
} }
protected SQLFunction getFunction(CriteriaQuery criteriaQuery) { protected SQLFunction getFunction(CriteriaQuery criteriaQuery) {
SQLFunction function = criteriaQuery.getFactory() final SQLFunctionRegistry sqlFunctionRegistry = criteriaQuery.getFactory().getSqlFunctionRegistry();
.getSqlFunctionRegistry() final SQLFunction function = sqlFunctionRegistry.findSQLFunction( "count" );
.findSQLFunction( "count" );
if ( function == null ) { if ( function == null ) {
throw new HibernateException( "Unable to locate count function mapping" ); throw new HibernateException( "Unable to locate count function mapping" );
} }
return function; return function;
} }
@Override
public String toString() {
return "count(*)";
}
} }

View File

@ -1,10 +1,10 @@
/* /*
* Hibernate, Relational Persistence for Idiomatic Java * 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 * indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are * 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, * 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 * copy, or redistribute it subject to the terms and conditions of the GNU
@ -20,12 +20,10 @@
* Free Software Foundation, Inc. * Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor * 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA * Boston, MA 02110-1301 USA
*
*/ */
package org.hibernate.criterion; package org.hibernate.criterion;
import org.hibernate.Criteria; import org.hibernate.Criteria;
import org.hibernate.EntityMode;
import org.hibernate.HibernateException;
import org.hibernate.engine.spi.TypedValue; import org.hibernate.engine.spi.TypedValue;
import org.hibernate.internal.util.StringHelper; import org.hibernate.internal.util.StringHelper;
import org.hibernate.type.Type; import org.hibernate.type.Type;
@ -35,32 +33,39 @@ import org.hibernate.type.Type;
* alias of the root entity. * alias of the root entity.
*/ */
public class SQLCriterion implements Criterion { public class SQLCriterion implements Criterion {
private final String sql; private final String sql;
private final TypedValue[] typedValues; 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) { protected SQLCriterion(String sql, Object[] values, Type[] types) {
this.sql = sql; this.sql = sql;
typedValues = new TypedValue[values.length]; this.typedValues = new TypedValue[values.length];
for ( int i=0; i<typedValues.length; i++ ) { 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 * 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 * indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are * 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, * 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 * copy, or redistribute it subject to the terms and conditions of the GNU
@ -20,11 +20,10 @@
* Free Software Foundation, Inc. * Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor * 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA * Boston, MA 02110-1301 USA
*
*/ */
package org.hibernate.criterion; package org.hibernate.criterion;
import org.hibernate.Criteria; import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.internal.util.StringHelper; import org.hibernate.internal.util.StringHelper;
import org.hibernate.type.Type; import org.hibernate.type.Type;
@ -33,7 +32,6 @@ import org.hibernate.type.Type;
* alias of the root entity. * alias of the root entity.
*/ */
public class SQLProjection implements Projection { public class SQLProjection implements Projection {
private final String sql; private final String sql;
private final String groupBy; private final String groupBy;
private final Type[] types; private final Type[] types;
@ -41,30 +39,8 @@ public class SQLProjection implements Projection {
private String[] columnAliases; private String[] columnAliases;
private boolean grouped; 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) { 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) { protected SQLProjection(String sql, String groupBy, String[] columnAliases, Type[] types) {
@ -76,23 +52,48 @@ public class SQLProjection implements Projection {
this.groupBy = groupBy; 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() { public String[] getAliases() {
return aliases; return aliases;
} }
@Override
public String[] getColumnAliases(int loc) { public String[] getColumnAliases(int loc) {
return columnAliases; return columnAliases;
} }
@Override
public boolean isGrouped() { public boolean isGrouped() {
return grouped; return grouped;
} }
@Override
public Type[] getTypes(String alias, Criteria crit, CriteriaQuery criteriaQuery) { public Type[] getTypes(String alias, Criteria crit, CriteriaQuery criteriaQuery) {
return null; //unsupported return null;
} }
@Override
public String[] getColumnAliases(String alias, int loc) { public String[] getColumnAliases(String alias, int loc) {
return null; //unsupported return null;
} }
} }

View File

@ -1,7 +1,7 @@
/* /*
* Hibernate, Relational Persistence for Idiomatic Java * 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 * indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are * statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Inc. * distributed under license by Red Hat Inc.
@ -55,55 +55,6 @@ public class SimpleExpression implements Criterion {
this.op = op; 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() { protected final String getOp() {
return op; return op;
} }
@ -115,4 +66,58 @@ public class SimpleExpression implements Criterion {
public Object getValue() { public Object getValue() {
return value; 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 * 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 * indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are * 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, * 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 * copy, or redistribute it subject to the terms and conditions of the GNU
@ -20,28 +20,23 @@
* Free Software Foundation, Inc. * Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor * 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA * Boston, MA 02110-1301 USA
*
*/ */
package org.hibernate.criterion; package org.hibernate.criterion;
import org.hibernate.Criteria; import org.hibernate.Criteria;
import org.hibernate.type.Type; import org.hibernate.type.Type;
/** /**
* A single-column projection that may be aliased * A single-column projection that may be aliased
*
* @author Gavin King * @author Gavin King
*/ */
public abstract class SimpleProjection implements EnhancedProjection { public abstract class SimpleProjection implements EnhancedProjection {
private static final int NUM_REUSABLE_ALIASES = 40; private static final int NUM_REUSABLE_ALIASES = 40;
private static final String[] reusableAliases = initializeReusableAliases(); private static final String[] REUSABLE_ALIASES = initializeReusableAliases();
public Projection as(String alias) {
return Projections.alias(this, alias);
}
private static String[] 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++ ) { for ( int i = 0; i < NUM_REUSABLE_ALIASES; i++ ) {
aliases[i] = aliasForLocation( i ); aliases[i] = aliasForLocation( i );
} }
@ -57,38 +52,62 @@ public abstract class SimpleProjection implements EnhancedProjection {
return aliasForLocation( loc ); return aliasForLocation( loc );
} }
else { 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) { public String[] getColumnAliases(String alias, int loc) {
return null; return null;
} }
@Override
public String[] getColumnAliases(String alias, int loc, Criteria criteria, CriteriaQuery criteriaQuery) { public String[] getColumnAliases(String alias, int loc, Criteria criteria, CriteriaQuery criteriaQuery) {
return getColumnAliases( alias, loc ); return getColumnAliases( alias, loc );
} }
@Override
public Type[] getTypes(String alias, Criteria criteria, CriteriaQuery criteriaQuery) { public Type[] getTypes(String alias, Criteria criteria, CriteriaQuery criteriaQuery) {
return null; return null;
} }
@Override
public String[] getColumnAliases(int loc) { public String[] getColumnAliases(int loc) {
return new String[] { getAliasForLocation( 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) { public int getColumnCount(Criteria criteria, CriteriaQuery criteriaQuery) {
Type types[] = getTypes( criteria, criteriaQuery ); final Type[] types = getTypes( criteria, criteriaQuery );
int count = 0; int count = 0;
for ( int i=0; i<types.length; i++ ) { for ( Type type : types ) {
count += types[ i ].getColumnSpan( criteriaQuery.getFactory() ); count += type.getColumnSpan( criteriaQuery.getFactory() );
} }
return count; return count;
} }
@Override
public String[] getColumnAliases(int loc, Criteria criteria, CriteriaQuery criteriaQuery) { public String[] getColumnAliases(int loc, Criteria criteria, CriteriaQuery criteriaQuery) {
int numColumns = getColumnCount( criteria, criteriaQuery ); final int numColumns = getColumnCount( criteria, criteriaQuery );
String[] aliases = new String[ numColumns ]; final String[] aliases = new String[ numColumns ];
for (int i = 0; i < numColumns; i++) { for (int i = 0; i < numColumns; i++) {
aliases[i] = getAliasForLocation( loc ); aliases[i] = getAliasForLocation( loc );
loc++; loc++;
@ -96,14 +115,17 @@ public abstract class SimpleProjection implements EnhancedProjection {
return aliases; return aliases;
} }
@Override
public String[] getAliases() { public String[] getAliases() {
return new String[1]; return new String[1];
} }
@Override
public String toGroupSqlString(Criteria criteria, CriteriaQuery criteriaQuery) { 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() { public boolean isGrouped() {
return false; return false;
} }

View File

@ -1,10 +1,10 @@
/* /*
* Hibernate, Relational Persistence for Idiomatic Java * 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 * indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are * 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, * 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 * copy, or redistribute it subject to the terms and conditions of the GNU
@ -20,37 +20,36 @@
* Free Software Foundation, Inc. * Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor * 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA * Boston, MA 02110-1301 USA
*
*/ */
package org.hibernate.criterion; package org.hibernate.criterion;
import org.hibernate.Criteria; import org.hibernate.Criteria;
import org.hibernate.EntityMode;
import org.hibernate.HibernateException; import org.hibernate.HibernateException;
import org.hibernate.engine.spi.TypedValue; import org.hibernate.engine.spi.TypedValue;
/** /**
* A comparison between a constant value and the the result of a subquery * A comparison between a constant value and the the result of a subquery
*
* @author Gavin King * @author Gavin King
*/ */
public class SimpleSubqueryExpression extends SubqueryExpression { public class SimpleSubqueryExpression extends SubqueryExpression {
private Object value; private Object value;
protected SimpleSubqueryExpression(Object value, String op, String quantifier, DetachedCriteria dc) { protected SimpleSubqueryExpression(Object value, String op, String quantifier, DetachedCriteria dc) {
super(op, quantifier, dc); super( op, quantifier, dc );
this.value = value; this.value = value;
} }
@Override
public TypedValue[] getTypedValues(Criteria criteria, CriteriaQuery criteriaQuery) public TypedValue[] getTypedValues(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException {
throws HibernateException { final TypedValue[] subQueryTypedValues = super.getTypedValues( criteria, criteriaQuery );
TypedValue[] superTv = super.getTypedValues(criteria, criteriaQuery); final TypedValue[] result = new TypedValue[subQueryTypedValues.length+1];
TypedValue[] result = new TypedValue[superTv.length+1]; System.arraycopy( subQueryTypedValues, 0, result, 1, subQueryTypedValues.length );
System.arraycopy(superTv, 0, result, 1, superTv.length); result[0] = new TypedValue( getTypes()[0], value );
result[0] = new TypedValue( getTypes()[0], value, EntityMode.POJO );
return result; return result;
} }
@Override
protected String toLeftSqlString(Criteria criteria, CriteriaQuery criteriaQuery) { protected String toLeftSqlString(Criteria criteria, CriteriaQuery criteriaQuery) {
return "?"; return "?";
} }

View File

@ -1,7 +1,7 @@
/* /*
* Hibernate, Relational Persistence for Idiomatic Java * 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 * indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are * statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Inc. * distributed under license by Red Hat Inc.
@ -24,7 +24,6 @@
package org.hibernate.criterion; package org.hibernate.criterion;
import org.hibernate.Criteria; import org.hibernate.Criteria;
import org.hibernate.EntityMode;
import org.hibernate.HibernateException; import org.hibernate.HibernateException;
import org.hibernate.engine.spi.TypedValue; import org.hibernate.engine.spi.TypedValue;
import org.hibernate.persister.collection.QueryableCollection; import org.hibernate.persister.collection.QueryableCollection;
@ -33,10 +32,12 @@ import org.hibernate.sql.ConditionFragment;
import org.hibernate.type.StandardBasicTypes; import org.hibernate.type.StandardBasicTypes;
/** /**
* Used to define a restriction on a collection property based on its size.
*
* @author Gavin King * @author Gavin King
* @author Steve Ebersole
*/ */
public class SizeExpression implements Criterion { public class SizeExpression implements Criterion {
private final String propertyName; private final String propertyName;
private final int size; private final int size;
private final String op; private final String op;
@ -47,38 +48,35 @@ public class SizeExpression implements Criterion {
this.op = op; 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() { public String toString() {
return propertyName + ".size" + op + size; 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"}) @SuppressWarnings( {"UnusedDeclaration"})
public class Subqueries { 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) { 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) { 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) { 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) { 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) { 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) { public static Criterion propertyEq(String propertyName, DetachedCriteria dc) {
return new PropertySubqueryExpression(propertyName, "=", null, 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);
} }
/**
* 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) { public static Criterion propertyNe(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 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) { 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) { 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) { 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) { 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); * 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
*
public static Criterion propertyGtSome(String propertyName, DetachedCriteria dc) { * @param propertyNames The names of the properties to use in comparison
return new PropertySubqueryExpression(propertyName, ">", "some", dc); * @param dc The detached criteria representing the subquery
} *
* @return The Criterion
public static Criterion propertyLtSome(String propertyName, DetachedCriteria dc) { *
return new PropertySubqueryExpression(propertyName, "<", "some", dc); * @see PropertiesSubqueryExpression
} */
public static Criterion propertiesNotIn(String[] propertyNames, DetachedCriteria dc) {
public static Criterion propertyGeSome(String propertyName, DetachedCriteria dc) { return new PropertiesSubqueryExpression( propertyNames, "not in", 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 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) { 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) { 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) { 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) { public static Criterion eq(Object value, DetachedCriteria dc) {
return new SimpleSubqueryExpression(value, "=", null, 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);
} }
/**
* 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) { public static Criterion ne(Object value, DetachedCriteria dc) {
return new SimpleSubqueryExpression(value, "<>", null, 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) { private Subqueries() {
return new SimpleSubqueryExpression(value, ">", "some", dc);
} }
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 * 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 * indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are * 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, * 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 * copy, or redistribute it subject to the terms and conditions of the GNU
@ -20,11 +20,10 @@
* Free Software Foundation, Inc. * Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor * 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA * Boston, MA 02110-1301 USA
*
*/ */
package org.hibernate.criterion; package org.hibernate.criterion;
import org.hibernate.Criteria; import org.hibernate.Criteria;
import org.hibernate.EntityMode;
import org.hibernate.HibernateException; import org.hibernate.HibernateException;
import org.hibernate.engine.spi.QueryParameters; import org.hibernate.engine.spi.QueryParameters;
import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionFactoryImplementor;
@ -37,10 +36,12 @@ import org.hibernate.persister.entity.OuterJoinLoadable;
import org.hibernate.type.Type; import org.hibernate.type.Type;
/** /**
* A criterion that involves a subquery
*
* @author Gavin King * @author Gavin King
* @author Steve Ebersole
*/ */
public abstract class SubqueryExpression implements Criterion { public abstract class SubqueryExpression implements Criterion {
private CriteriaImpl criteriaImpl; private CriteriaImpl criteriaImpl;
private String quantifier; private String quantifier;
private String op; private String op;
@ -48,27 +49,36 @@ public abstract class SubqueryExpression implements Criterion {
private Type[] types; private Type[] types;
private CriteriaQueryTranslator innerQuery; private CriteriaQueryTranslator innerQuery;
protected Type[] getTypes() {
return types;
}
protected SubqueryExpression(String op, String quantifier, DetachedCriteria dc) { protected SubqueryExpression(String op, String quantifier, DetachedCriteria dc) {
this.criteriaImpl = dc.getCriteriaImpl(); this.criteriaImpl = dc.getCriteriaImpl();
this.quantifier = quantifier; this.quantifier = quantifier;
this.op = op; this.op = op;
} }
protected Type[] getTypes() {
return types;
}
protected abstract String toLeftSqlString(Criteria criteria, CriteriaQuery outerQuery); protected abstract String toLeftSqlString(Criteria criteria, CriteriaQuery outerQuery);
@Override
public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException { 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 SessionFactoryImplementor factory = criteriaQuery.getFactory();
final OuterJoinLoadable persister = final OuterJoinLoadable persister =
( OuterJoinLoadable ) factory.getEntityPersister( criteriaImpl.getEntityOrClassName() ); (OuterJoinLoadable) factory.getEntityPersister( criteriaImpl.getEntityOrClassName() );
createAndSetInnerQuery( criteriaQuery, factory ); createAndSetInnerQuery( criteriaQuery, factory );
criteriaImpl.setSession( deriveRootSession( criteria ) ); criteriaImpl.setSession( deriveRootSession( criteria ) );
CriteriaJoinWalker walker = new CriteriaJoinWalker( final CriteriaJoinWalker walker = new CriteriaJoinWalker(
persister, persister,
innerQuery, innerQuery,
factory, factory,
@ -78,25 +88,15 @@ public abstract class SubqueryExpression implements Criterion {
innerQuery.getRootSQLALias() innerQuery.getRootSQLALias()
); );
String sql = walker.getSQLString(); return buf.append( '(' ).append( walker.getSQLString() ).append( ')' ).toString();
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();
} }
private SessionImplementor deriveRootSession(Criteria criteria) { private SessionImplementor deriveRootSession(Criteria criteria) {
if ( criteria instanceof CriteriaImpl ) { if ( criteria instanceof CriteriaImpl ) {
return ( ( CriteriaImpl ) criteria ).getSession(); return ( (CriteriaImpl) criteria ).getSession();
} }
else if ( criteria instanceof CriteriaImpl.Subcriteria ) { else if ( criteria instanceof CriteriaImpl.Subcriteria ) {
return deriveRootSession( ( ( CriteriaImpl.Subcriteria ) criteria ).getParent() ); return deriveRootSession( ( (CriteriaImpl.Subcriteria) criteria ).getParent() );
} }
else { else {
// could happen for custom Criteria impls. Not likely, but... // 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) @Override
throws HibernateException { public TypedValue[] getTypedValues(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException {
//the following two lines were added to ensure that this.params is not null, which //the following two lines were added to ensure that this.params is not null, which
//can happen with two-deep nested subqueries //can happen with two-deep nested subqueries
SessionFactoryImplementor factory = criteriaQuery.getFactory(); final SessionFactoryImplementor factory = criteriaQuery.getFactory();
createAndSetInnerQuery(criteriaQuery, factory); createAndSetInnerQuery( criteriaQuery, factory );
Type[] ppTypes = params.getPositionalParameterTypes(); final Type[] ppTypes = params.getPositionalParameterTypes();
Object[] ppValues = params.getPositionalParameterValues(); final Object[] ppValues = params.getPositionalParameterValues();
TypedValue[] tv = new TypedValue[ppTypes.length]; final TypedValue[] tv = new TypedValue[ppTypes.length];
for ( int i=0; i<ppTypes.length; i++ ) { 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; return tv;
} }
@ -143,7 +143,7 @@ public abstract class SubqueryExpression implements Criterion {
innerQuery = new CriteriaQueryTranslator( innerQuery = new CriteriaQueryTranslator(
factory, factory,
criteriaImpl, criteriaImpl,
criteriaImpl.getEntityOrClassName(), //implicit polymorphism not supported (would need a union) criteriaImpl.getEntityOrClassName(),
alias, alias,
criteriaQuery criteriaQuery
); );

View File

@ -90,7 +90,7 @@ public final class StringHelper {
} }
public static String[] add(String[] x, String sep, String[] y) { 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++ ) { for ( int i = 0; i < x.length; i++ ) {
result[i] = x[i] + sep + y[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 = String[] idcols =
( ( Loadable ) getPropertyMapping( getEntityName( subcriteria ) ) ).getIdentifierColumnNames(); ( ( Loadable ) getPropertyMapping( getEntityName( criteria ) ) ).getIdentifierColumnNames();
return StringHelper.qualify( getSQLAlias( subcriteria ), idcols ); return StringHelper.qualify( getSQLAlias( criteria ), idcols );
} }
public Type getIdentifierType(Criteria subcriteria) { public Type getIdentifierType(Criteria criteria) {
return ( ( Loadable ) getPropertyMapping( getEntityName( subcriteria ) ) ).getIdentifierType(); return ( ( Loadable ) getPropertyMapping( getEntityName( criteria ) ) ).getIdentifierType();
} }
public TypedValue getTypedIdentifierValue(Criteria subcriteria, Object value) { public TypedValue getTypedIdentifierValue(Criteria criteria, Object value) {
final Loadable loadable = ( Loadable ) getPropertyMapping( getEntityName( subcriteria ) ); final Loadable loadable = ( Loadable ) getPropertyMapping( getEntityName( criteria ) );
return new TypedValue( return new TypedValue(
loadable.getIdentifierType(), loadable.getIdentifierType(),
value, value,
@ -616,19 +616,11 @@ public class CriteriaQueryTranslator implements CriteriaQuery {
else { else {
throw new QueryException( "Unsupported discriminator type " + type ); throw new QueryException( "Unsupported discriminator type " + type );
} }
return new TypedValue( return new TypedValue( type, value );
type,
value,
EntityMode.POJO
);
} }
} }
// Otherwise, this is an ordinary value. // Otherwise, this is an ordinary value.
return new TypedValue( return new TypedValue( getTypeUsingProjection( subcriteria, propertyName ), value );
getTypeUsingProjection( subcriteria, propertyName ),
value,
EntityMode.POJO
);
} }
private PropertyMapping getPropertyMapping(String entityName) private PropertyMapping getPropertyMapping(String entityName)

View File

@ -1,10 +1,10 @@
/* /*
* Hibernate, Relational Persistence for Idiomatic Java * 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 * indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are * 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, * 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 * copy, or redistribute it subject to the terms and conditions of the GNU
@ -20,7 +20,6 @@
* Free Software Foundation, Inc. * Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor * 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA * Boston, MA 02110-1301 USA
*
*/ */
package org.hibernate.sql; package org.hibernate.sql;
@ -32,50 +31,128 @@ import org.hibernate.internal.util.StringHelper;
* @author Gavin King * @author Gavin King
*/ */
public abstract class JoinFragment { 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 use {@link JoinType#INNER_JOIN} instead.
*/ */
@Deprecated @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 use {@link JoinType#FULL_JOIN} instead.
*/ */
@Deprecated @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 use {@link JoinType#LEFT_OUTER_JOIN} instead.
*/ */
@Deprecated @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 use {@link JoinType#RIGHT_OUTER_JOIN} instead.
*/ */
@Deprecated @Deprecated
public static final int RIGHT_OUTER_JOIN = 2; @SuppressWarnings("UnusedDeclaration")
private boolean hasFilterCondition = false; public static final int RIGHT_OUTER_JOIN = JoinType.RIGHT_OUTER_JOIN.getJoinTypeValue();
private boolean hasThetaJoins = false;
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) { public void addFragment(JoinFragment ojf) {
if ( ojf.hasThetaJoins() ) { if ( ojf.hasThetaJoins() ) {
hasThetaJoins = true; hasThetaJoins = true;
@ -93,7 +170,9 @@ public abstract class JoinFragment {
*/ */
protected boolean addCondition(StringBuilder buffer, String on) { protected boolean addCondition(StringBuilder buffer, String on) {
if ( StringHelper.isNotEmpty( on ) ) { if ( StringHelper.isNotEmpty( on ) ) {
if ( !on.startsWith( " and" ) ) buffer.append( " and " ); if ( !on.startsWith( " and" ) ) {
buffer.append( " and " );
}
buffer.append( on ); buffer.append( on );
return true; return true;
} }
@ -115,6 +194,11 @@ public abstract class JoinFragment {
this.hasFilterCondition = b; this.hasFilterCondition = b;
} }
/**
* Determine if the join fragment contained any theta-joins.
*
* @return {@code true} if the fragment contained theta joins
*/
public boolean hasThetaJoins() { public boolean hasThetaJoins() {
return hasThetaJoins; return hasThetaJoins;
} }