merge master
This commit is contained in:
commit
b9249e548a
|
@ -8,18 +8,20 @@ contributing to a minimum, there are a few guidelines we ask that you mind.
|
|||
If you are just getting started with Git, GitHub and/or contributing to Hibernate via
|
||||
GitHub there are a few pre-requisite steps.
|
||||
|
||||
* Make sure you have signed a [Contributor License Aggrement](https://cla.jboss.org) (CLA) for the Hibernate project
|
||||
* Make sure you have a [Hibernate Jira account](https://hibernate.onjira.com)
|
||||
* Make sure you have a [GitHub account](https://github.com/signup/free)
|
||||
* [Fork](http://help.github.com/fork-a-repo) the Hibernate repository. As discussed in
|
||||
the linked page, this also includes:
|
||||
* [Set](https://help.github.com/articles/set-up-git) up your local git install
|
||||
* Clone your fork
|
||||
|
||||
* See the wiki pages for setting up your IDE, whether you use [IntelliJ IDEA](https://community.jboss.org/wiki/ContributingToHibernateUsingIntelliJ)
|
||||
or [Eclipse](https://community.jboss.org/wiki/ContributingToHibernateUsingEclipse).
|
||||
|
||||
## Create the working (topic) branch
|
||||
Create a "topic" branch on which you will work. The convention is to name the branch
|
||||
using the JIRA issue key. If there is not already a Jira issue covering the work you
|
||||
want to do, create one. Assuming you will be working from the master branch and working
|
||||
Create a [topic branch](http://git-scm.com/book/en/Git-Branching-Branching-Workflows#Topic-Branches) on which you
|
||||
will work. The convention is to name the branch using the JIRA issue key. If there is not already a Jira issue
|
||||
covering the work you want to do, create one. Assuming you will be working from the master branch and working
|
||||
on the Jira HHH-123 : `git checkout -b HHH-123 master`
|
||||
|
||||
|
||||
|
@ -39,7 +41,7 @@ appreciated btw), please use rebasing rather than merging. Merging creates
|
|||
"merge commits" that really muck up the project timeline._
|
||||
|
||||
## Submit
|
||||
* Sign the [Contributor License Agreement](https://cla.jboss.org/index.seam).
|
||||
* Push your changes to a topic branch in your fork of the repository.
|
||||
* If you have not already, sign the [Contributor License Agreement](https://cla.jboss.org).
|
||||
* Push your changes to the topic branch in your fork of the repository.
|
||||
* Initiate a [pull request](http://help.github.com/send-pull-requests/)
|
||||
* Update the Jira issue, adding a comment inclusing a link to the created pull request
|
||||
|
|
18
build.gradle
18
build.gradle
|
@ -348,14 +348,30 @@ subprojects { subProject ->
|
|||
ignoreFailures = true
|
||||
}
|
||||
// exclude generated sources
|
||||
checkstyleMain.exclude '**/generated-src/**'
|
||||
// unfortunately this nice easy approach does not seem to work : http://forums.gradle.org/gradle/topics/specify_excludes_to_checkstyle_task
|
||||
//checkstyleMain.exclude '**/generated-src/**'
|
||||
checkstyleMain.exclude '**/org/hibernate/hql/internal/antlr/**'
|
||||
checkstyleMain.exclude '**/org/hibernate/hql/internal/antlr/*'
|
||||
checkstyleMain.exclude '**/org/hibernate/sql/ordering/antlr/*'
|
||||
checkstyleMain.exclude '**/*_$logger*'
|
||||
checkstyleMain.exclude '**/org/hibernate/internal/jaxb/**'
|
||||
// because cfg package is a mess mainly from annotation stuff
|
||||
checkstyleMain.exclude '**/org/hibernate/cfg/**'
|
||||
checkstyleMain.exclude '**/org/hibernate/cfg/*'
|
||||
|
||||
findbugs {
|
||||
sourceSets = [ subProject.sourceSets.main, subProject.sourceSets.test ]
|
||||
ignoreFailures = true
|
||||
}
|
||||
// exclude generated sources
|
||||
// unfortunately this nice easy approach does not seem to work : http://forums.gradle.org/gradle/topics/specify_excludes_to_checkstyle_task
|
||||
//findbugsMain.exclude '**/generated-src/**'
|
||||
findbugsMain.exclude '**/org/hibernate/hql/internal/antlr/**'
|
||||
findbugsMain.exclude '**/org/hibernate/hql/internal/antlr/*'
|
||||
findbugsMain.exclude '**/org/hibernate/sql/ordering/antlr/*'
|
||||
findbugsMain.exclude '**/*_$logger*'
|
||||
findbugsMain.exclude '**/org/hibernate/internal/jaxb/**'
|
||||
|
||||
|
||||
buildDashboard.dependsOn check
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
|
|
@ -129,7 +129,10 @@ public class Jdk {
|
|||
|
||||
try {
|
||||
final File javaCommand = getJavaExecutable();
|
||||
Process javaProcess = Runtime.getRuntime().exec( javaCommand.getAbsolutePath() + " -version" );
|
||||
|
||||
// Fix build for e.g. windows when path to java command contains spaces
|
||||
// Using the array for Runtime.exec will make sure that arguments with spaces get quoted
|
||||
Process javaProcess = Runtime.getRuntime().exec( new String[]{javaCommand.getAbsolutePath(), "-version"} );
|
||||
|
||||
try {
|
||||
version = extractVersion( new BufferedReader( new InputStreamReader( javaProcess.getErrorStream() ) ) );
|
||||
|
|
|
@ -5,6 +5,68 @@ match the actual issue resolution (i.e. a bug might not be a bug). Please
|
|||
refer to the particular case on JIRA using the issue tracking number to learn
|
||||
more about each case.
|
||||
|
||||
Changes in version 4.3.0.Beta2 (2013.05.02)
|
||||
------------------------------------------------------------------------------------------------------------------------
|
||||
https://hibernate.atlassian.net/browse/HHH/fixforversion/13052
|
||||
|
||||
** Sub-task
|
||||
* [HHH-7617] - Gradle eclipse task missing src paths and test source generation
|
||||
* [HHH-7943] - C3P0, Proxool, ehcache, and infinispan services for OSGi
|
||||
* [HHH-7944] - Envers OSGi support
|
||||
* [HHH-7993] - Support jar scanning in OSGi
|
||||
* [HHH-7995] - Auto-discovery of Hibernate extension points in OSGi
|
||||
* [HHH-8141] - Upgrade to Gradle 1.5
|
||||
* [HHH-8142] - Create a 'compile' task that performs all copmpilations
|
||||
* [HHH-8143] - Create a 'generateSources' task that performs all generation tasks
|
||||
* [HHH-8145] - Add MaxPermSize to test configuration
|
||||
* [HHH-8146] - Update to use maven-publishing plugin
|
||||
* [HHH-8147] - Update to use distribution plugin for createing release bundles
|
||||
* [HHH-8151] - Consolidate defining "java language level" in one place
|
||||
* [HHH-8152] - General cleanup
|
||||
* [HHH-8156] - Apply new Gradle plugins
|
||||
* [HHH-8160] - Integrate with Aries JPA 2.1 branch
|
||||
|
||||
** Bug
|
||||
* [HHH-5845] - Lazy Loading of audited entites with revision type 'delete'
|
||||
* [HHH-7357] - Incorrect exception translation when using Oracle
|
||||
* [HHH-7478] - ConcurrentModificationException when adding a BeforeTransactionCompletionProcess from with a PostInsertEventListener for an @Audited entity
|
||||
* [HHH-7880] - SessionFactory.openStatelessSession() does not respect tenant identifier from CurrentTenantIdentifierResolver
|
||||
* [HHH-7974] - Session.getTenantIdentifier() not callable without active transaction
|
||||
* [HHH-8049] - Initialization error with <dynamic-component> mapping
|
||||
* [HHH-8084] - LobMergeTest fails on oracle
|
||||
* [HHH-8103] - Oracle LOB ordering not working with SequenceIdentityGenerator
|
||||
* [HHH-8137] - Javadoc generation is currently not playing nicely with Java7 javadoc changes
|
||||
* [HHH-8171] - Auditing of collections of embeddables only supporting single element changes
|
||||
* [HHH-8173] - AvailableSettings constants for javax.persistence.schema-generation contain space
|
||||
* [HHH-8178] - Natural IDs generating one UniqueKey per Column
|
||||
* [HHH-8182] - Correct intermittent UpgradeLockTest failures
|
||||
* [HHH-8189] - Audit records are not rolled back when transaction is rolled back
|
||||
* [HHH-8207] - Locale conversion is broken
|
||||
* [HHH-8215] - Windows Build with Eclipse does not work
|
||||
|
||||
** Deprecation
|
||||
* [HHH-8170] - Deprecate Hibernate @ForeignKey in favor of JPA 2.1 introduced @ForeignKey annotation
|
||||
|
||||
** Improvement
|
||||
* [HHH-7605] - Provide details "An entity copy was already assigned to a different entity."
|
||||
* [HHH-7908] - Logging level checking.
|
||||
* [HHH-8138] - Log SQLException in DatabaseTarget with cause of schema export CREATE statement failure
|
||||
* [HHH-8159] - Apply fixups indicated by analysis tools
|
||||
* [HHH-8162] - Make unique constraint handling on schema update configurable
|
||||
* [HHH-8167] - Adding @NotNull to a @ManyToOne association with @JoinColumnsOrFormulas leads to ClassCastException
|
||||
* [HHH-8180] - Improve performance of logging level checks
|
||||
* [HHH-8183] - Also support synonyms for schema validation
|
||||
|
||||
** New Feature
|
||||
* [HHH-8157] - Adding DBAllocator labels for new DBs
|
||||
* [HHH-8163] - Deprecate @IndexColumn and add @ListIndexBase
|
||||
|
||||
** Task
|
||||
* [HHH-8164] - Deprecate @Sort in favor of @SortNatural and @SortComparator
|
||||
* [HHH-8175] - Add support for Postgresql 9.2, Postgres Plus 9.2 and IBM DB2 10.1
|
||||
* [HHH-8186] - Type in docs? Caching section nonstrict != nontrict
|
||||
* [HHH-8212] - Add CLA ref to CONTRIBUTING.md
|
||||
|
||||
|
||||
Changes in version 4.3.0.Beta1 (2012.07.12)
|
||||
------------------------------------------------------------------------------------------------------------------------
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.service.jdbc.connections.internal;
|
||||
package org.hibernate.c3p0.internal;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
|
@ -31,6 +31,7 @@ import java.util.Properties;
|
|||
import javax.sql.DataSource;
|
||||
|
||||
import com.mchange.v2.c3p0.DataSources;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
|
@ -56,22 +57,25 @@ import org.hibernate.service.spi.Stoppable;
|
|||
public class C3P0ConnectionProvider
|
||||
implements ConnectionProvider, Configurable, Stoppable, ServiceRegistryAwareService {
|
||||
|
||||
private static final C3P0MessageLogger LOG = Logger.getMessageLogger(C3P0MessageLogger.class, C3P0ConnectionProvider.class.getName());
|
||||
private static final C3P0MessageLogger LOG = Logger.getMessageLogger(
|
||||
C3P0MessageLogger.class,
|
||||
C3P0ConnectionProvider.class.getName()
|
||||
);
|
||||
|
||||
//swaldman 2006-08-28: define c3p0-style configuration parameters for properties with
|
||||
// hibernate-specific overrides to detect and warn about conflicting
|
||||
// declarations
|
||||
private final static String C3P0_STYLE_MIN_POOL_SIZE = "c3p0.minPoolSize";
|
||||
private final static String C3P0_STYLE_MAX_POOL_SIZE = "c3p0.maxPoolSize";
|
||||
private final static String C3P0_STYLE_MAX_IDLE_TIME = "c3p0.maxIdleTime";
|
||||
private final static String C3P0_STYLE_MAX_STATEMENTS = "c3p0.maxStatements";
|
||||
private final static String C3P0_STYLE_ACQUIRE_INCREMENT = "c3p0.acquireIncrement";
|
||||
private final static String C3P0_STYLE_IDLE_CONNECTION_TEST_PERIOD = "c3p0.idleConnectionTestPeriod";
|
||||
private static final String C3P0_STYLE_MIN_POOL_SIZE = "c3p0.minPoolSize";
|
||||
private static final String C3P0_STYLE_MAX_POOL_SIZE = "c3p0.maxPoolSize";
|
||||
private static final String C3P0_STYLE_MAX_IDLE_TIME = "c3p0.maxIdleTime";
|
||||
private static final String C3P0_STYLE_MAX_STATEMENTS = "c3p0.maxStatements";
|
||||
private static final String C3P0_STYLE_ACQUIRE_INCREMENT = "c3p0.acquireIncrement";
|
||||
private static final String C3P0_STYLE_IDLE_CONNECTION_TEST_PERIOD = "c3p0.idleConnectionTestPeriod";
|
||||
|
||||
//swaldman 2006-08-28: define c3p0-style configuration parameters for initialPoolSize, which
|
||||
// hibernate sensibly lets default to minPoolSize, but we'll let users
|
||||
// override it with the c3p0-style property if they want.
|
||||
private final static String C3P0_STYLE_INITIAL_POOL_SIZE = "c3p0.initialPoolSize";
|
||||
private static final String C3P0_STYLE_INITIAL_POOL_SIZE = "c3p0.initialPoolSize";
|
||||
|
||||
private DataSource ds;
|
||||
private Integer isolation;
|
||||
|
@ -105,7 +109,7 @@ public class C3P0ConnectionProvider
|
|||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings( {"unchecked"})
|
||||
@SuppressWarnings({"unchecked"})
|
||||
public <T> T unwrap(Class<T> unwrapType) {
|
||||
if ( ConnectionProvider.class.equals( unwrapType ) ||
|
||||
C3P0ConnectionProvider.class.isAssignableFrom( unwrapType ) ) {
|
||||
|
@ -120,46 +124,46 @@ public class C3P0ConnectionProvider
|
|||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings( {"unchecked"})
|
||||
@SuppressWarnings({"unchecked"})
|
||||
public void configure(Map props) {
|
||||
String jdbcDriverClass = (String) props.get( Environment.DRIVER );
|
||||
String jdbcUrl = (String) props.get( Environment.URL );
|
||||
Properties connectionProps = ConnectionProviderInitiator.getConnectionProperties( props );
|
||||
final String jdbcDriverClass = (String) props.get( Environment.DRIVER );
|
||||
final String jdbcUrl = (String) props.get( Environment.URL );
|
||||
final Properties connectionProps = ConnectionProviderInitiator.getConnectionProperties( props );
|
||||
|
||||
LOG.c3p0UsingDriver(jdbcDriverClass, jdbcUrl);
|
||||
LOG.connectionProperties(ConfigurationHelper.maskOut(connectionProps, "password"));
|
||||
LOG.c3p0UsingDriver( jdbcDriverClass, jdbcUrl );
|
||||
LOG.connectionProperties( ConfigurationHelper.maskOut( connectionProps, "password" ) );
|
||||
|
||||
autocommit = ConfigurationHelper.getBoolean( Environment.AUTOCOMMIT, props );
|
||||
LOG.autoCommitMode( autocommit );
|
||||
|
||||
if (jdbcDriverClass == null) {
|
||||
LOG.jdbcDriverNotSpecified(Environment.DRIVER);
|
||||
if ( jdbcDriverClass == null ) {
|
||||
LOG.jdbcDriverNotSpecified( Environment.DRIVER );
|
||||
}
|
||||
else {
|
||||
try {
|
||||
serviceRegistry.getService( ClassLoaderService.class ).classForName( jdbcDriverClass );
|
||||
}
|
||||
catch ( ClassLoadingException e ) {
|
||||
throw new ClassLoadingException( LOG.jdbcDriverNotFound(jdbcDriverClass), e );
|
||||
catch (ClassLoadingException e) {
|
||||
throw new ClassLoadingException( LOG.jdbcDriverNotFound( jdbcDriverClass ), e );
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
//swaldman 2004-02-07: modify to allow null values to signify fall through to c3p0 PoolConfig defaults
|
||||
Integer minPoolSize = ConfigurationHelper.getInteger( Environment.C3P0_MIN_SIZE, props );
|
||||
Integer maxPoolSize = ConfigurationHelper.getInteger( Environment.C3P0_MAX_SIZE, props );
|
||||
Integer maxIdleTime = ConfigurationHelper.getInteger( Environment.C3P0_TIMEOUT, props );
|
||||
Integer maxStatements = ConfigurationHelper.getInteger( Environment.C3P0_MAX_STATEMENTS, props );
|
||||
Integer acquireIncrement = ConfigurationHelper.getInteger( Environment.C3P0_ACQUIRE_INCREMENT, props );
|
||||
Integer idleTestPeriod = ConfigurationHelper.getInteger( Environment.C3P0_IDLE_TEST_PERIOD, props );
|
||||
final Integer minPoolSize = ConfigurationHelper.getInteger( Environment.C3P0_MIN_SIZE, props );
|
||||
final Integer maxPoolSize = ConfigurationHelper.getInteger( Environment.C3P0_MAX_SIZE, props );
|
||||
final Integer maxIdleTime = ConfigurationHelper.getInteger( Environment.C3P0_TIMEOUT, props );
|
||||
final Integer maxStatements = ConfigurationHelper.getInteger( Environment.C3P0_MAX_STATEMENTS, props );
|
||||
final Integer acquireIncrement = ConfigurationHelper.getInteger( Environment.C3P0_ACQUIRE_INCREMENT, props );
|
||||
final Integer idleTestPeriod = ConfigurationHelper.getInteger( Environment.C3P0_IDLE_TEST_PERIOD, props );
|
||||
|
||||
Properties c3props = new Properties();
|
||||
final Properties c3props = new Properties();
|
||||
|
||||
// turn hibernate.c3p0.* into c3p0.*, so c3p0
|
||||
// gets a chance to see all hibernate.c3p0.*
|
||||
for ( Object o : props.keySet() ) {
|
||||
if ( ! String.class.isInstance( o ) ) {
|
||||
if ( !String.class.isInstance( o ) ) {
|
||||
continue;
|
||||
}
|
||||
final String key = (String) o;
|
||||
|
@ -182,63 +186,62 @@ public class C3P0ConnectionProvider
|
|||
Environment.C3P0_ACQUIRE_INCREMENT, C3P0_STYLE_ACQUIRE_INCREMENT, props, c3props, acquireIncrement
|
||||
);
|
||||
setOverwriteProperty(
|
||||
Environment.C3P0_IDLE_TEST_PERIOD, C3P0_STYLE_IDLE_CONNECTION_TEST_PERIOD, props, c3props, idleTestPeriod
|
||||
Environment.C3P0_IDLE_TEST_PERIOD,
|
||||
C3P0_STYLE_IDLE_CONNECTION_TEST_PERIOD,
|
||||
props,
|
||||
c3props,
|
||||
idleTestPeriod
|
||||
);
|
||||
|
||||
// revert to traditional hibernate behavior of setting initialPoolSize to minPoolSize
|
||||
// unless otherwise specified with a c3p0.*-style parameter.
|
||||
Integer initialPoolSize = ConfigurationHelper.getInteger( C3P0_STYLE_INITIAL_POOL_SIZE, props );
|
||||
final Integer initialPoolSize = ConfigurationHelper.getInteger( C3P0_STYLE_INITIAL_POOL_SIZE, props );
|
||||
if ( initialPoolSize == null && minPoolSize != null ) {
|
||||
c3props.put( C3P0_STYLE_INITIAL_POOL_SIZE, String.valueOf( minPoolSize ).trim() );
|
||||
}
|
||||
|
||||
/*DataSource unpooled = DataSources.unpooledDataSource(
|
||||
jdbcUrl, props.getProperty(Environment.USER), props.getProperty(Environment.PASS)
|
||||
);*/
|
||||
DataSource unpooled = DataSources.unpooledDataSource( jdbcUrl, connectionProps );
|
||||
final DataSource unpooled = DataSources.unpooledDataSource( jdbcUrl, connectionProps );
|
||||
|
||||
Map allProps = new HashMap();
|
||||
final Map allProps = new HashMap();
|
||||
allProps.putAll( props );
|
||||
allProps.putAll( c3props );
|
||||
|
||||
ds = DataSources.pooledDataSource( unpooled, allProps );
|
||||
}
|
||||
catch ( Exception e ) {
|
||||
LOG.error(LOG.unableToInstantiateC3p0ConnectionPool(), e);
|
||||
throw new HibernateException(LOG.unableToInstantiateC3p0ConnectionPool(), e);
|
||||
catch (Exception e) {
|
||||
LOG.error( LOG.unableToInstantiateC3p0ConnectionPool(), e );
|
||||
throw new HibernateException( LOG.unableToInstantiateC3p0ConnectionPool(), e );
|
||||
}
|
||||
|
||||
String i = (String) props.get( Environment.ISOLATION );
|
||||
if (i == null) isolation = null;
|
||||
final String i = (String) props.get( Environment.ISOLATION );
|
||||
if ( i == null ) {
|
||||
isolation = null;
|
||||
}
|
||||
else {
|
||||
isolation = Integer.valueOf( i );
|
||||
LOG.jdbcIsolationLevel(Environment.isolationLevelToString(isolation));
|
||||
LOG.jdbcIsolationLevel( Environment.isolationLevelToString( isolation ) );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void close() {
|
||||
try {
|
||||
DataSources.destroy( ds );
|
||||
}
|
||||
catch ( SQLException sqle ) {
|
||||
LOG.unableToDestroyC3p0ConnectionPool(sqle);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsAggressiveRelease() {
|
||||
return false;
|
||||
}
|
||||
|
||||
private void setOverwriteProperty(String hibernateStyleKey, String c3p0StyleKey, Map hibp, Properties c3p, Integer value) {
|
||||
private void setOverwriteProperty(
|
||||
String hibernateStyleKey,
|
||||
String c3p0StyleKey,
|
||||
Map hibp,
|
||||
Properties c3p,
|
||||
Integer value) {
|
||||
if ( value != null ) {
|
||||
String peeledC3p0Key = c3p0StyleKey.substring(5);
|
||||
final String peeledC3p0Key = c3p0StyleKey.substring( 5 );
|
||||
c3p.put( peeledC3p0Key, String.valueOf( value ).trim() );
|
||||
if ( hibp.containsKey( c3p0StyleKey ) ) {
|
||||
warnPropertyConflict( hibernateStyleKey, c3p0StyleKey );
|
||||
}
|
||||
String longC3p0StyleKey = "hibernate." + c3p0StyleKey;
|
||||
final String longC3p0StyleKey = "hibernate." + c3p0StyleKey;
|
||||
if ( hibp.containsKey( longC3p0StyleKey ) ) {
|
||||
warnPropertyConflict( hibernateStyleKey, longC3p0StyleKey );
|
||||
}
|
||||
|
@ -246,12 +249,27 @@ public class C3P0ConnectionProvider
|
|||
}
|
||||
|
||||
private void warnPropertyConflict(String hibernateStyle, String c3p0Style) {
|
||||
LOG.bothHibernateAndC3p0StylesSet(hibernateStyle, c3p0Style, hibernateStyle, c3p0Style);
|
||||
LOG.bothHibernateAndC3p0StylesSet( hibernateStyle, c3p0Style );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop() {
|
||||
close();
|
||||
try {
|
||||
DataSources.destroy( ds );
|
||||
}
|
||||
catch (SQLException sqle) {
|
||||
LOG.unableToDestroyC3p0ConnectionPool( sqle );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the provider.
|
||||
*
|
||||
* @deprecated Use {@link #stop} instead
|
||||
*/
|
||||
@Deprecated
|
||||
public void close() {
|
||||
stop();
|
||||
}
|
||||
|
||||
@Override
|
|
@ -0,0 +1,94 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2007-2011, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* 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.c3p0.internal;
|
||||
|
||||
import java.sql.SQLException;
|
||||
|
||||
import org.jboss.logging.Cause;
|
||||
import org.jboss.logging.LogMessage;
|
||||
import org.jboss.logging.Message;
|
||||
import org.jboss.logging.MessageLogger;
|
||||
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
|
||||
import static org.jboss.logging.Logger.Level.INFO;
|
||||
import static org.jboss.logging.Logger.Level.WARN;
|
||||
|
||||
/**
|
||||
* The jboss-logging {@link MessageLogger} for the hibernate-c3p0 module. It reserves message ids ranging from
|
||||
* 10001 to 15000 inclusively.
|
||||
* <p/>
|
||||
* New messages must be added after the last message defined to ensure message codes are unique.
|
||||
*/
|
||||
@MessageLogger(projectCode = "HHH")
|
||||
public interface C3P0MessageLogger extends CoreMessageLogger {
|
||||
|
||||
/**
|
||||
* Log a message (WARN) about conflicting {@code hibernate.c3p0.XYZ} and {@code c3p0.XYZ} settings
|
||||
*
|
||||
* @param hibernateStyle The {@code hibernate.c3p0} prefixed setting
|
||||
* @param c3p0Style The {@code c3p0.} prefixed setting
|
||||
*/
|
||||
@LogMessage(level = WARN)
|
||||
@Message(value = "Both hibernate-style property '%1$s' and c3p0-style property '%2$s' have been set in Hibernate "
|
||||
+ "properties. Hibernate-style property '%1$s' will be used and c3p0-style property '%2$s' will be ignored!", id = 10001)
|
||||
void bothHibernateAndC3p0StylesSet(String hibernateStyle,String c3p0Style);
|
||||
|
||||
/**
|
||||
* Log a message (INFO) about which Driver class is being used.
|
||||
*
|
||||
* @param jdbcDriverClass The JDBC Driver class
|
||||
* @param jdbcUrl The JDBC URL
|
||||
*/
|
||||
@LogMessage(level = INFO)
|
||||
@Message(value = "C3P0 using driver: %s at URL: %s", id = 10002)
|
||||
void c3p0UsingDriver(String jdbcDriverClass, String jdbcUrl);
|
||||
|
||||
/**
|
||||
* Build a message about not being able to find the JDBC driver class
|
||||
*
|
||||
* @param jdbcDriverClass The JDBC driver class we could not find
|
||||
*
|
||||
* @return The message
|
||||
*/
|
||||
@Message(value = "JDBC Driver class not found: %s", id = 10003)
|
||||
String jdbcDriverNotFound(String jdbcDriverClass);
|
||||
|
||||
/**
|
||||
* Log a message (WARN) about not being able to stop the underlying c3p0 pool.
|
||||
*
|
||||
* @param e The exception when we tried to stop pool
|
||||
*/
|
||||
@LogMessage(level = WARN)
|
||||
@Message(value = "Could not destroy C3P0 connection pool", id = 10004)
|
||||
void unableToDestroyC3p0ConnectionPool(@Cause SQLException e);
|
||||
|
||||
/**
|
||||
* Build a message about not being able to start the underlying c3p0 pool.
|
||||
*
|
||||
* @return The message
|
||||
*/
|
||||
@Message(value = "Could not instantiate C3P0 connection pool", id = 10005)
|
||||
String unableToInstantiateC3p0ConnectionPool();
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2012, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* 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.c3p0.internal;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.boot.registry.selector.SimpleStrategyRegistrationImpl;
|
||||
import org.hibernate.boot.registry.selector.StrategyRegistration;
|
||||
import org.hibernate.boot.registry.selector.StrategyRegistrationProvider;
|
||||
import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider;
|
||||
|
||||
/**
|
||||
* Provides the {@link C3P0ConnectionProvider} to the
|
||||
* {@link org.hibernate.boot.registry.selector.spi.StrategySelector} service.
|
||||
*
|
||||
* @author Brett Meyer
|
||||
*/
|
||||
public class StrategyRegistrationProviderImpl implements StrategyRegistrationProvider {
|
||||
private static final List<StrategyRegistration> REGISTRATIONS = Collections.singletonList(
|
||||
(StrategyRegistration) new SimpleStrategyRegistrationImpl<ConnectionProvider>(
|
||||
ConnectionProvider.class,
|
||||
C3P0ConnectionProvider.class,
|
||||
"c3p0",
|
||||
C3P0ConnectionProvider.class.getSimpleName(),
|
||||
// legacy
|
||||
"org.hibernate.connection.C3P0ConnectionProvider",
|
||||
// legacy
|
||||
"org.hibernate.service.jdbc.connections.internal.C3P0ConnectionProvider"
|
||||
)
|
||||
);
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Iterable<StrategyRegistration> getStrategyRegistrations() {
|
||||
return REGISTRATIONS;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
/**
|
||||
* Implementation of ConnectionProvider using the c3p0 Connection pool.
|
||||
*/
|
||||
package org.hibernate.c3p0.internal;
|
|
@ -1,69 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2007-2011, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* 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.service.jdbc.connections.internal;
|
||||
|
||||
import java.sql.SQLException;
|
||||
|
||||
import org.jboss.logging.Cause;
|
||||
import org.jboss.logging.LogMessage;
|
||||
import org.jboss.logging.Message;
|
||||
import org.jboss.logging.MessageLogger;
|
||||
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
|
||||
import static org.jboss.logging.Logger.Level.INFO;
|
||||
import static org.jboss.logging.Logger.Level.WARN;
|
||||
|
||||
/**
|
||||
* The jboss-logging {@link MessageLogger} for the hibernate-c3p0 module. It reserves message ids ranging from
|
||||
* 10001 to 15000 inclusively.
|
||||
* <p/>
|
||||
* New messages must be added after the last message defined to ensure message codes are unique.
|
||||
*/
|
||||
@MessageLogger( projectCode = "HHH" )
|
||||
public interface C3P0MessageLogger extends CoreMessageLogger {
|
||||
|
||||
@LogMessage( level = WARN )
|
||||
@Message( value = "Both hibernate-style property '%s' and c3p0-style property '%s' have been set in hibernate.properties. "
|
||||
+ "Hibernate-style property '%s' will be used and c3p0-style property '%s' will be ignored!", id = 10001 )
|
||||
void bothHibernateAndC3p0StylesSet( String hibernateStyle,
|
||||
String c3p0Style,
|
||||
String hibernateStyle2,
|
||||
String c3p0Style2 );
|
||||
|
||||
@LogMessage( level = INFO )
|
||||
@Message( value = "C3P0 using driver: %s at URL: %s", id = 10002 )
|
||||
void c3p0UsingDriver( String jdbcDriverClass,
|
||||
String jdbcUrl );
|
||||
|
||||
@Message( value = "JDBC Driver class not found: %s", id = 10003 )
|
||||
String jdbcDriverNotFound( String jdbcDriverClass );
|
||||
|
||||
@LogMessage( level = WARN )
|
||||
@Message( value = "Could not destroy C3P0 connection pool", id = 10004 )
|
||||
void unableToDestroyC3p0ConnectionPool( @Cause SQLException e );
|
||||
|
||||
@Message( value = "Could not instantiate C3P0 connection pool", id = 10005 )
|
||||
String unableToInstantiateC3p0ConnectionPool();
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
org.hibernate.c3p0.internal.StrategyRegistrationProviderImpl
|
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<blueprint default-activation="eager"
|
||||
xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
|
||||
<bean id="strategyRegistrationProvider" class="org.hibernate.c3p0.internal.StrategyRegistrationProviderImpl"/>
|
||||
<service ref="strategyRegistrationProvider" interface="org.hibernate.boot.registry.selector.StrategyRegistrationProvider"/>
|
||||
|
||||
</blueprint>
|
|
@ -30,8 +30,8 @@ import javax.management.ObjectName;
|
|||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.hibernate.c3p0.internal.C3P0ConnectionProvider;
|
||||
import org.hibernate.engine.jdbc.spi.JdbcServices;
|
||||
import org.hibernate.service.jdbc.connections.internal.C3P0ConnectionProvider;
|
||||
import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider;
|
||||
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
||||
|
||||
|
|
|
@ -23,15 +23,11 @@
|
|||
*/
|
||||
package org.hibernate;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
/**
|
||||
* A problem occurred translating a Hibernate query to SQL due to invalid query syntax, etc.
|
||||
*/
|
||||
public class QueryException extends HibernateException {
|
||||
private static final Logger log = Logger.getLogger( QueryException.class );
|
||||
|
||||
private String queryString;
|
||||
private final String queryString;
|
||||
|
||||
/**
|
||||
* Constructs a QueryException using the specified exception message.
|
||||
|
@ -39,7 +35,7 @@ public class QueryException extends HibernateException {
|
|||
* @param message A message explaining the exception condition
|
||||
*/
|
||||
public QueryException(String message) {
|
||||
super( message );
|
||||
this( message, null, null );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -48,8 +44,8 @@ public class QueryException extends HibernateException {
|
|||
* @param message A message explaining the exception condition
|
||||
* @param cause The underlying cause
|
||||
*/
|
||||
public QueryException(String message, Throwable cause) {
|
||||
super( message, cause );
|
||||
public QueryException(String message, Exception cause) {
|
||||
this( message, null, cause );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -59,7 +55,18 @@ public class QueryException extends HibernateException {
|
|||
* @param queryString The query being evaluated when the exception occurred
|
||||
*/
|
||||
public QueryException(String message, String queryString) {
|
||||
super( message );
|
||||
this( message, queryString, null );
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a QueryException using the specified exception message and query-string.
|
||||
*
|
||||
* @param message A message explaining the exception condition
|
||||
* @param queryString The query being evaluated when the exception occurred
|
||||
* @param cause The underlying cause
|
||||
*/
|
||||
public QueryException(String message, String queryString, Exception cause) {
|
||||
super( message, cause );
|
||||
this.queryString = queryString;
|
||||
}
|
||||
|
||||
|
@ -69,7 +76,7 @@ public class QueryException extends HibernateException {
|
|||
* @param cause The underlying cause
|
||||
*/
|
||||
public QueryException(Exception cause) {
|
||||
super( cause );
|
||||
this( "A query exception occurred", null, cause );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -81,30 +88,52 @@ public class QueryException extends HibernateException {
|
|||
return queryString;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the query string. Even an option since often the part of the code generating the exception does not
|
||||
* have access to the query overall.
|
||||
*
|
||||
* @param queryString The query string.
|
||||
*/
|
||||
public void setQueryString(String queryString) {
|
||||
if ( this.queryString != null ) {
|
||||
log.debugf(
|
||||
"queryString overriding non-null previous value [%s] : %s",
|
||||
this.queryString,
|
||||
queryString
|
||||
);
|
||||
}
|
||||
this.queryString = queryString;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage() {
|
||||
String msg = super.getMessage();
|
||||
if ( queryString!=null ) {
|
||||
String msg = getOriginalMessage();
|
||||
if ( queryString != null ) {
|
||||
msg += " [" + queryString + ']';
|
||||
}
|
||||
return msg;
|
||||
}
|
||||
|
||||
protected final String getOriginalMessage() {
|
||||
return super.getMessage();
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps this exception with another, of same kind, with the specified queryString. If this exception already
|
||||
* has a queryString defined, the same exception ({@code this}) is returned. Otherwise the protected
|
||||
* {@link #generateQueryException(String)} is called, to allow subclasses to properly create the correct
|
||||
* subclass for return.
|
||||
*
|
||||
* @param queryString The query string that led to the QueryException
|
||||
*
|
||||
* @return {@code this}, if {@code this} has {@code null} for {@link #getQueryString()}; otherwise a new
|
||||
* QueryException (or subclass) is returned.
|
||||
*/
|
||||
public final QueryException wrapWithQueryString(String queryString) {
|
||||
if ( this.getQueryString() != null ) {
|
||||
return this;
|
||||
}
|
||||
|
||||
return generateQueryException( queryString );
|
||||
}
|
||||
|
||||
/**
|
||||
* Called from {@link #wrapWithQueryString(String)} when we really need to generate a new QueryException
|
||||
* (or subclass).
|
||||
* <p/>
|
||||
* NOTE : implementors should take care to use {@link #getOriginalMessage()} for the message, not
|
||||
* {@link #getMessage()}
|
||||
*
|
||||
* @param queryString The query string
|
||||
*
|
||||
* @return The generated QueryException (or subclass)
|
||||
*
|
||||
* @see #getOriginalMessage()
|
||||
*/
|
||||
protected QueryException generateQueryException(String queryString) {
|
||||
return new QueryException( getOriginalMessage(), queryString, this );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,4 +37,20 @@ public class QueryParameterException extends QueryException {
|
|||
public QueryParameterException(String message) {
|
||||
super( message );
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a QueryParameterException
|
||||
*
|
||||
* @param message The message explaining the exception condition
|
||||
* @param queryString The query that led to the exception
|
||||
* @param cause The underlying cause
|
||||
*/
|
||||
public QueryParameterException(String message, String queryString, Exception cause) {
|
||||
super( message, queryString, cause );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected QueryException generateQueryException(String queryString) {
|
||||
return new QueryParameterException( super.getOriginalMessage(), queryString, this );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -217,7 +217,7 @@ public class BulkOperationCleanupAction implements Executable, Serializable {
|
|||
// nothing to do
|
||||
}
|
||||
|
||||
private static class EntityCleanup {
|
||||
private static class EntityCleanup implements Serializable {
|
||||
private final EntityRegionAccessStrategy cacheAccess;
|
||||
private final SoftLock cacheLock;
|
||||
|
||||
|
@ -232,7 +232,7 @@ public class BulkOperationCleanupAction implements Executable, Serializable {
|
|||
}
|
||||
}
|
||||
|
||||
private static class CollectionCleanup {
|
||||
private static class CollectionCleanup implements Serializable {
|
||||
private final CollectionRegionAccessStrategy cacheAccess;
|
||||
private final SoftLock cacheLock;
|
||||
|
||||
|
@ -247,7 +247,7 @@ public class BulkOperationCleanupAction implements Executable, Serializable {
|
|||
}
|
||||
}
|
||||
|
||||
private class NaturalIdCleanup {
|
||||
private static class NaturalIdCleanup implements Serializable {
|
||||
private final NaturalIdRegionAccessStrategy naturalIdCacheAccessStrategy;
|
||||
private final SoftLock cacheLock;
|
||||
|
||||
|
|
|
@ -48,7 +48,6 @@ import org.hibernate.persister.entity.EntityPersister;
|
|||
* @see EntityIdentityInsertAction
|
||||
*/
|
||||
public final class EntityInsertAction extends AbstractEntityInsertAction {
|
||||
|
||||
private Object version;
|
||||
private Object cacheEntry;
|
||||
|
||||
|
@ -130,7 +129,7 @@ public final class EntityInsertAction extends AbstractEntityInsertAction {
|
|||
version,
|
||||
session
|
||||
);
|
||||
cacheEntry = persister.getCacheEntryStructure().structure(ce);
|
||||
cacheEntry = persister.getCacheEntryStructure().structure( ce );
|
||||
final CacheKey ck = session.generateCacheKey( id, persister.getIdentifierType(), persister.getRootEntityName() );
|
||||
final boolean put = persister.getCacheAccessStrategy().insert( ck, cacheEntry, version );
|
||||
|
||||
|
|
|
@ -32,8 +32,8 @@ import java.util.Set;
|
|||
import org.hibernate.boot.registry.classloading.internal.ClassLoaderServiceImpl;
|
||||
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
|
||||
import org.hibernate.boot.registry.internal.BootstrapServiceRegistryImpl;
|
||||
import org.hibernate.boot.registry.selector.Availability;
|
||||
import org.hibernate.boot.registry.selector.AvailabilityAnnouncer;
|
||||
import org.hibernate.boot.registry.selector.StrategyRegistration;
|
||||
import org.hibernate.boot.registry.selector.StrategyRegistrationProvider;
|
||||
import org.hibernate.boot.registry.selector.internal.StrategySelectorBuilder;
|
||||
import org.hibernate.integrator.internal.IntegratorServiceImpl;
|
||||
import org.hibernate.integrator.spi.Integrator;
|
||||
|
@ -169,23 +169,23 @@ public class BootstrapServiceRegistryBuilder {
|
|||
*/
|
||||
@SuppressWarnings( {"UnusedDeclaration"})
|
||||
public <T> BootstrapServiceRegistryBuilder withStrategySelector(Class<T> strategy, String name, Class<? extends T> implementation) {
|
||||
this.strategySelectorBuilder.addExplicitAvailability( strategy, implementation, name );
|
||||
this.strategySelectorBuilder.addExplicitStrategyRegistration( strategy, implementation, name );
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies one or more strategy selectors announced as available by the passed announcer.
|
||||
*
|
||||
* @param availabilityAnnouncer An announcer for one or more available selectors
|
||||
* @param strategyRegistrationProvider An provider for one or more available selectors
|
||||
*
|
||||
* @return {@code this}, for method chaining
|
||||
*
|
||||
* @see org.hibernate.boot.registry.selector.spi.StrategySelector#registerStrategyImplementor(Class, String, Class)
|
||||
*/
|
||||
@SuppressWarnings( {"UnusedDeclaration"})
|
||||
public BootstrapServiceRegistryBuilder withStrategySelectors(AvailabilityAnnouncer availabilityAnnouncer) {
|
||||
for ( Availability availability : availabilityAnnouncer.getAvailabilities() ) {
|
||||
this.strategySelectorBuilder.addExplicitAvailability( availability );
|
||||
public BootstrapServiceRegistryBuilder withStrategySelectors(StrategyRegistrationProvider strategyRegistrationProvider) {
|
||||
for ( StrategyRegistration strategyRegistration : strategyRegistrationProvider.getStrategyRegistrations() ) {
|
||||
this.strategySelectorBuilder.addExplicitStrategyRegistration( strategyRegistration );
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
|
|
@ -2,6 +2,18 @@
|
|||
* Defines service registry contracts application are likely to want to utilize for
|
||||
* configuring Hibernate behavior.
|
||||
*
|
||||
* {@link BootstrapServiceRegistry} is the
|
||||
* Service registries are designed to be hierarchical. This works in 2 fashions. First registries can "hide" or
|
||||
* "override" services from parent registries. It also allows granular building of registries as services
|
||||
* become available.
|
||||
*
|
||||
* {@link BootstrapServiceRegistry} is the base service registry, intended to be built via
|
||||
* {@link BootstrapServiceRegistryBuilder} if you need customization. For non-customized
|
||||
* {@link BootstrapServiceRegistry} usage, the {@link BootstrapServiceRegistryBuilder} and
|
||||
* {@link BootstrapServiceRegistry} can be bypassed altogether.
|
||||
*
|
||||
* Usually the next level in a standard registry set up is the {@link StandardServiceRegistry}, intended to be built
|
||||
* by the {@link StandardServiceRegistryBuilder} if you need customization. The builder optionally takes the
|
||||
* {@link BootstrapServiceRegistry} to use as a base; if none is provided a default one is generated assuming sensible
|
||||
* defaults in Java SE and EE environments, particularly in respect to Class loading.
|
||||
*/
|
||||
package org.hibernate.boot.registry;
|
||||
|
|
|
@ -26,25 +26,25 @@ package org.hibernate.boot.registry.selector;
|
|||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* A simple implementation of Availability.
|
||||
* A simple implementation of StrategyRegistration.
|
||||
*
|
||||
* @param <T> The strategy type.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class SimpleAvailabilityImpl<T> implements Availability<T> {
|
||||
public class SimpleStrategyRegistrationImpl<T> implements StrategyRegistration<T> {
|
||||
private final Class<T> strategyRole;
|
||||
private final Class<? extends T> strategyImplementation;
|
||||
private final Iterable<String> selectorNames;
|
||||
|
||||
/**
|
||||
* Constructs a SimpleAvailabilityImpl.
|
||||
* Constructs a SimpleStrategyRegistrationImpl.
|
||||
*
|
||||
* @param strategyRole The strategy contract
|
||||
* @param strategyImplementation The strategy implementation class
|
||||
* @param selectorNames The selection/registration names for this implementation
|
||||
*/
|
||||
public SimpleAvailabilityImpl(
|
||||
public SimpleStrategyRegistrationImpl(
|
||||
Class<T> strategyRole,
|
||||
Class<? extends T> strategyImplementation,
|
||||
Iterable<String> selectorNames) {
|
||||
|
@ -54,13 +54,13 @@ public class SimpleAvailabilityImpl<T> implements Availability<T> {
|
|||
}
|
||||
|
||||
/**
|
||||
* Constructs a SimpleAvailabilityImpl.
|
||||
* Constructs a SimpleStrategyRegistrationImpl.
|
||||
*
|
||||
* @param strategyRole The strategy contract
|
||||
* @param strategyImplementation The strategy implementation class
|
||||
* @param selectorNames The selection/registration names for this implementation
|
||||
*/
|
||||
public SimpleAvailabilityImpl(
|
||||
public SimpleStrategyRegistrationImpl(
|
||||
Class<T> strategyRole,
|
||||
Class<? extends T> strategyImplementation,
|
||||
String... selectorNames) {
|
|
@ -24,16 +24,14 @@
|
|||
package org.hibernate.boot.registry.selector;
|
||||
|
||||
/**
|
||||
* Describes the availability of a named strategy implementation. A strategy + selector name should resolve
|
||||
* Describes the registration of a named strategy implementation. A strategy + selector name should resolve
|
||||
* to a single implementation.
|
||||
*
|
||||
* todo : better name?
|
||||
*
|
||||
* @param <T> The type of the strategy described by this implementation availability.
|
||||
* @param <T> The type of the strategy described by this implementation registration.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface Availability<T> {
|
||||
public interface StrategyRegistration<T> {
|
||||
/**
|
||||
* The strategy role. Best practice says this should be an interface.
|
||||
*
|
||||
|
@ -42,7 +40,7 @@ public interface Availability<T> {
|
|||
public Class<T> getStrategyRole();
|
||||
|
||||
/**
|
||||
* Any registered names for this strategy availability.
|
||||
* Any registered names for this strategy registration.
|
||||
*
|
||||
* @return The registered selection names.
|
||||
*/
|
|
@ -24,18 +24,16 @@
|
|||
package org.hibernate.boot.registry.selector;
|
||||
|
||||
/**
|
||||
* Responsible for announcing the availability of strategy selector(s). Can be registered directly with the
|
||||
* Responsible for providing the registrations of strategy selector(s). Can be registered directly with the
|
||||
* {@link org.hibernate.boot.registry.BootstrapServiceRegistry} or located via discovery.
|
||||
*
|
||||
* todo : better name?
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface AvailabilityAnnouncer {
|
||||
public interface StrategyRegistrationProvider {
|
||||
/**
|
||||
* Get all availabilities announced by this announcer.
|
||||
* Get all StrategyRegistrations announced by this provider.
|
||||
*
|
||||
* @return All announced availabilities
|
||||
* @return All StrategyRegistrations
|
||||
*/
|
||||
public Iterable<Availability> getAvailabilities();
|
||||
public Iterable<StrategyRegistration> getStrategyRegistrations();
|
||||
}
|
|
@ -29,9 +29,9 @@ import java.util.List;
|
|||
import org.jboss.logging.Logger;
|
||||
|
||||
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
|
||||
import org.hibernate.boot.registry.selector.Availability;
|
||||
import org.hibernate.boot.registry.selector.AvailabilityAnnouncer;
|
||||
import org.hibernate.boot.registry.selector.SimpleAvailabilityImpl;
|
||||
import org.hibernate.boot.registry.selector.StrategyRegistration;
|
||||
import org.hibernate.boot.registry.selector.StrategyRegistrationProvider;
|
||||
import org.hibernate.boot.registry.selector.SimpleStrategyRegistrationImpl;
|
||||
import org.hibernate.boot.registry.selector.spi.StrategySelectionException;
|
||||
import org.hibernate.boot.registry.selector.spi.StrategySelector;
|
||||
import org.hibernate.dialect.CUBRIDDialect;
|
||||
|
@ -106,10 +106,10 @@ import org.hibernate.hql.spi.TemporaryTableBulkIdStrategy;
|
|||
public class StrategySelectorBuilder {
|
||||
private static final Logger log = Logger.getLogger( StrategySelectorBuilder.class );
|
||||
|
||||
private final List<Availability> explicitAvailabilities = new ArrayList<Availability>();
|
||||
private final List<StrategyRegistration> explicitStrategyRegistrations = new ArrayList<StrategyRegistration>();
|
||||
|
||||
/**
|
||||
* Adds an explicit (as opposed to discovered) strategy availability.
|
||||
* Adds an explicit (as opposed to discovered) strategy registration.
|
||||
*
|
||||
* @param strategy The strategy
|
||||
* @param implementation The strategy implementation
|
||||
|
@ -118,31 +118,31 @@ public class StrategySelectorBuilder {
|
|||
* compatible.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> void addExplicitAvailability(Class<T> strategy, Class<? extends T> implementation, String name) {
|
||||
addExplicitAvailability( new SimpleAvailabilityImpl<T>( strategy, implementation, name ) );
|
||||
public <T> void addExplicitStrategyRegistration(Class<T> strategy, Class<? extends T> implementation, String name) {
|
||||
addExplicitStrategyRegistration( new SimpleStrategyRegistrationImpl<T>( strategy, implementation, name ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an explicit (as opposed to discovered) strategy availability.
|
||||
* Adds an explicit (as opposed to discovered) strategy registration.
|
||||
*
|
||||
* @param availability The strategy implementation availability.
|
||||
* @param strategyRegistration The strategy implementation registration.
|
||||
* @param <T> The type of the strategy. Used to make sure that the strategy and implementation are type
|
||||
* compatible.
|
||||
*/
|
||||
public <T> void addExplicitAvailability(Availability<T> availability) {
|
||||
if ( !availability.getStrategyRole().isInterface() ) {
|
||||
public <T> void addExplicitStrategyRegistration(StrategyRegistration<T> strategyRegistration) {
|
||||
if ( !strategyRegistration.getStrategyRole().isInterface() ) {
|
||||
// not good form...
|
||||
log.debug( "Registering non-interface strategy : " + availability.getStrategyRole().getName() );
|
||||
log.debug( "Registering non-interface strategy : " + strategyRegistration.getStrategyRole().getName() );
|
||||
}
|
||||
|
||||
if ( ! availability.getStrategyRole().isAssignableFrom( availability.getStrategyImplementation() ) ) {
|
||||
if ( ! strategyRegistration.getStrategyRole().isAssignableFrom( strategyRegistration.getStrategyImplementation() ) ) {
|
||||
throw new StrategySelectionException(
|
||||
"Implementation class [" + availability.getStrategyImplementation().getName()
|
||||
"Implementation class [" + strategyRegistration.getStrategyImplementation().getName()
|
||||
+ "] does not implement strategy interface ["
|
||||
+ availability.getStrategyRole().getName() + "]"
|
||||
+ strategyRegistration.getStrategyRole().getName() + "]"
|
||||
);
|
||||
}
|
||||
explicitAvailabilities.add( availability );
|
||||
explicitStrategyRegistrations.add( strategyRegistration );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -163,27 +163,27 @@ public class StrategySelectorBuilder {
|
|||
addMultiTableBulkIdStrategies( strategySelector );
|
||||
|
||||
// apply auto-discovered registrations
|
||||
for ( AvailabilityAnnouncer announcer : classLoaderService.loadJavaServices( AvailabilityAnnouncer.class ) ) {
|
||||
for ( Availability discoveredAvailability : announcer.getAvailabilities() ) {
|
||||
applyFromAvailability( strategySelector, discoveredAvailability );
|
||||
for ( StrategyRegistrationProvider provider : classLoaderService.loadJavaServices( StrategyRegistrationProvider.class ) ) {
|
||||
for ( StrategyRegistration discoveredStrategyRegistration : provider.getStrategyRegistrations() ) {
|
||||
applyFromStrategyRegistration( strategySelector, discoveredStrategyRegistration );
|
||||
}
|
||||
}
|
||||
|
||||
// apply customizations
|
||||
for ( Availability explicitAvailability : explicitAvailabilities ) {
|
||||
applyFromAvailability( strategySelector, explicitAvailability );
|
||||
for ( StrategyRegistration explicitStrategyRegistration : explicitStrategyRegistrations ) {
|
||||
applyFromStrategyRegistration( strategySelector, explicitStrategyRegistration );
|
||||
}
|
||||
|
||||
return strategySelector;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T> void applyFromAvailability(StrategySelectorImpl strategySelector, Availability<T> availability) {
|
||||
for ( String name : availability.getSelectorNames() ) {
|
||||
private <T> void applyFromStrategyRegistration(StrategySelectorImpl strategySelector, StrategyRegistration<T> strategyRegistration) {
|
||||
for ( String name : strategyRegistration.getSelectorNames() ) {
|
||||
strategySelector.registerStrategyImplementor(
|
||||
availability.getStrategyRole(),
|
||||
strategyRegistration.getStrategyRole(),
|
||||
name,
|
||||
availability.getStrategyImplementation()
|
||||
strategyRegistration.getStrategyImplementation()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -63,7 +63,7 @@ public class TransformingClassLoader extends ClassLoader {
|
|||
try {
|
||||
final CtClass cc = classPool.get( name );
|
||||
// todo : modify the class definition if not already transformed...
|
||||
byte[] b = cc.toBytecode();
|
||||
final byte[] b = cc.toBytecode();
|
||||
return defineClass( name, b, 0, b.length );
|
||||
}
|
||||
catch (NotFoundException e) {
|
||||
|
|
|
@ -30,10 +30,11 @@ import org.hibernate.mapping.Collection;
|
|||
import org.hibernate.mapping.PersistentClass;
|
||||
import org.hibernate.metamodel.spi.binding.EntityBinding;
|
||||
import org.hibernate.metamodel.spi.binding.PluralAttributeBinding;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.type.VersionType;
|
||||
|
||||
/**
|
||||
* Standard CacheDataDescription implementation.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class CacheDataDescriptionImpl implements CacheDataDescription {
|
||||
|
@ -41,48 +42,87 @@ public class CacheDataDescriptionImpl implements CacheDataDescription {
|
|||
private final boolean versioned;
|
||||
private final Comparator versionComparator;
|
||||
|
||||
/**
|
||||
* Constructs a CacheDataDescriptionImpl instance. Generally speaking, code should use one of the
|
||||
* overloaded {@link #decode} methods rather than direct instantiation.
|
||||
*
|
||||
* @param mutable Is the described data mutable?
|
||||
* @param versioned Is the described data versioned?
|
||||
* @param versionComparator The described data's version value comparator (if versioned).
|
||||
*/
|
||||
public CacheDataDescriptionImpl(boolean mutable, boolean versioned, Comparator versionComparator) {
|
||||
this.mutable = mutable;
|
||||
this.versioned = versioned;
|
||||
this.versionComparator = versionComparator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMutable() {
|
||||
return mutable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isVersioned() {
|
||||
return versioned;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Comparator getVersionComparator() {
|
||||
return versionComparator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a CacheDataDescriptionImpl from the mapping model of an entity class.
|
||||
*
|
||||
* @param model The mapping model.
|
||||
*
|
||||
* @return The constructed CacheDataDescriptionImpl
|
||||
*/
|
||||
public static CacheDataDescriptionImpl decode(PersistentClass model) {
|
||||
return new CacheDataDescriptionImpl(
|
||||
model.isMutable(),
|
||||
model.isVersioned(),
|
||||
model.isVersioned() ? ( ( VersionType ) model.getVersion().getType() ).getComparator() : null
|
||||
model.isVersioned()
|
||||
? ( (VersionType) model.getVersion().getType() ).getComparator()
|
||||
: null
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a CacheDataDescriptionImpl from the mapping model of an entity class (using the new metamodel code).
|
||||
*
|
||||
* @param model The mapping model.
|
||||
*
|
||||
* @return The constructed CacheDataDescriptionImpl
|
||||
*/
|
||||
public static CacheDataDescriptionImpl decode(EntityBinding model) {
|
||||
return new CacheDataDescriptionImpl(
|
||||
model.isMutable(),
|
||||
model.isVersioned(),
|
||||
getVersionComparator( model )
|
||||
);
|
||||
return new CacheDataDescriptionImpl( model.isMutable(), model.isVersioned(), getVersionComparator( model ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a CacheDataDescriptionImpl from the mapping model of a collection
|
||||
*
|
||||
* @param model The mapping model.
|
||||
*
|
||||
* @return The constructed CacheDataDescriptionImpl
|
||||
*/
|
||||
public static CacheDataDescriptionImpl decode(Collection model) {
|
||||
return new CacheDataDescriptionImpl(
|
||||
model.isMutable(),
|
||||
model.getOwner().isVersioned(),
|
||||
model.getOwner().isVersioned() ? ( ( VersionType ) model.getOwner().getVersion().getType() ).getComparator() : null
|
||||
model.getOwner().isVersioned()
|
||||
? ( (VersionType) model.getOwner().getVersion().getType() ).getComparator()
|
||||
: null
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a CacheDataDescriptionImpl from the mapping model of a collection (using the new metamodel code).
|
||||
*
|
||||
* @param model The mapping model.
|
||||
*
|
||||
* @return The constructed CacheDataDescriptionImpl
|
||||
*/
|
||||
public static CacheDataDescriptionImpl decode(PluralAttributeBinding model) {
|
||||
return new CacheDataDescriptionImpl(
|
||||
model.isMutable(),
|
||||
|
@ -91,18 +131,9 @@ public class CacheDataDescriptionImpl implements CacheDataDescription {
|
|||
);
|
||||
}
|
||||
|
||||
public static CacheDataDescriptionImpl decode(EntityPersister persister) {
|
||||
return new CacheDataDescriptionImpl(
|
||||
!persister.getEntityMetamodel().hasImmutableNaturalId(),
|
||||
false,
|
||||
null
|
||||
);
|
||||
}
|
||||
|
||||
private static Comparator getVersionComparator(EntityBinding model ) {
|
||||
Comparator versionComparator = null;
|
||||
if ( model.isVersioned() ) {
|
||||
versionComparator = (
|
||||
return (
|
||||
( VersionType ) model.getHierarchyDetails()
|
||||
.getEntityVersion()
|
||||
.getVersioningAttributeBinding()
|
||||
|
@ -110,6 +141,7 @@ public class CacheDataDescriptionImpl implements CacheDataDescription {
|
|||
.getResolvedTypeMapping()
|
||||
).getComparator();
|
||||
}
|
||||
return versionComparator;
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,7 +42,16 @@ import org.hibernate.cache.spi.access.AccessType;
|
|||
* @author Steve Ebersole
|
||||
*/
|
||||
public class NoCachingRegionFactory extends AbstractRegionFactory {
|
||||
public static NoCachingRegionFactory INSTANCE = new NoCachingRegionFactory();
|
||||
/**
|
||||
* Singleton access
|
||||
*/
|
||||
public static final NoCachingRegionFactory INSTANCE = new NoCachingRegionFactory();
|
||||
|
||||
/**
|
||||
* Constructs a NoCachingRegionFactory. Although access should generally use {@link #INSTANCE}
|
||||
*/
|
||||
public NoCachingRegionFactory() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start() {
|
||||
|
@ -51,37 +60,45 @@ public class NoCachingRegionFactory extends AbstractRegionFactory {
|
|||
@Override
|
||||
public void stop() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMinimalPutsEnabledByDefault() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AccessType getDefaultAccessType() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long nextTimestamp() {
|
||||
return System.currentTimeMillis() / 100;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityRegion buildEntityRegion(String regionName, Properties properties, CacheDataDescription metadata)
|
||||
throws CacheException {
|
||||
throw new NoCacheRegionFactoryAvailableException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public NaturalIdRegion buildNaturalIdRegion(String regionName, Properties properties, CacheDataDescription metadata)
|
||||
throws CacheException {
|
||||
throw new NoCacheRegionFactoryAvailableException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CollectionRegion buildCollectionRegion(String regionName, Properties properties, CacheDataDescription metadata)
|
||||
throws CacheException {
|
||||
throw new NoCacheRegionFactoryAvailableException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryResultsRegion buildQueryResultsRegion(String regionName, Properties properties) throws CacheException {
|
||||
throw new NoCacheRegionFactoryAvailableException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TimestampsRegion buildTimestampsRegion(String regionName, Properties properties) throws CacheException {
|
||||
throw new NoCacheRegionFactoryAvailableException();
|
||||
|
|
|
@ -28,32 +28,30 @@ import org.jboss.logging.Logger;
|
|||
import org.hibernate.boot.registry.selector.spi.StrategySelector;
|
||||
import org.hibernate.cache.spi.RegionFactory;
|
||||
import org.hibernate.cfg.AvailableSettings;
|
||||
import org.hibernate.cfg.Configuration;
|
||||
import org.hibernate.engine.config.spi.ConfigurationService;
|
||||
import org.hibernate.engine.config.spi.StandardConverters;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
import org.hibernate.metamodel.spi.MetadataImplementor;
|
||||
import org.hibernate.service.spi.ServiceRegistryImplementor;
|
||||
import org.hibernate.service.spi.SessionFactoryServiceInitiator;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.boot.registry.StandardServiceInitiator;
|
||||
import org.hibernate.internal.util.config.ConfigurationHelper;
|
||||
|
||||
/**
|
||||
* Initiator for the {@link RegionFactory} service.
|
||||
*
|
||||
* @author Hardy Ferentschik
|
||||
* @author Brett Meyer
|
||||
*/
|
||||
public class RegionFactoryInitiator implements SessionFactoryServiceInitiator<RegionFactory> {
|
||||
public static final RegionFactoryInitiator INSTANCE = new RegionFactoryInitiator();
|
||||
private static final String DEFAULT_IMPL = NoCachingRegionFactory.class.getName();
|
||||
private static final CoreMessageLogger LOG = Logger.getMessageLogger(
|
||||
CoreMessageLogger.class,
|
||||
RegionFactoryInitiator.class.getName()
|
||||
);
|
||||
public class RegionFactoryInitiator implements StandardServiceInitiator<RegionFactory> {
|
||||
|
||||
private static final CoreMessageLogger LOG = Logger.getMessageLogger( CoreMessageLogger.class,
|
||||
RegionFactoryInitiator.class.getName() );
|
||||
|
||||
/**
|
||||
* Property name to use to configure the full qualified class name for the {@code RegionFactory}
|
||||
* Singleton access
|
||||
*/
|
||||
public static final String IMPL_NAME = AvailableSettings.CACHE_REGION_FACTORY;
|
||||
public static final RegionFactoryInitiator INSTANCE = new RegionFactoryInitiator();
|
||||
|
||||
@Override
|
||||
public Class<RegionFactory> getServiceInitiated() {
|
||||
|
@ -61,50 +59,58 @@ public class RegionFactoryInitiator implements SessionFactoryServiceInitiator<Re
|
|||
}
|
||||
|
||||
@Override
|
||||
public RegionFactory initiateService(SessionFactoryImplementor sessionFactory, Configuration configuration, ServiceRegistryImplementor registry) {
|
||||
return initiateService(sessionFactory, registry);
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
public RegionFactory initiateService(Map configurationValues, ServiceRegistryImplementor registry) {
|
||||
Properties p = new Properties();
|
||||
if (configurationValues != null) {
|
||||
p.putAll( configurationValues );
|
||||
}
|
||||
|
||||
@Override
|
||||
public RegionFactory initiateService(SessionFactoryImplementor sessionFactory, MetadataImplementor metadata, ServiceRegistryImplementor registry) {
|
||||
return initiateService(sessionFactory, registry);
|
||||
boolean useSecondLevelCache = ConfigurationHelper.getBoolean( AvailableSettings.USE_SECOND_LEVEL_CACHE,
|
||||
configurationValues, true );
|
||||
boolean useQueryCache = ConfigurationHelper.getBoolean( AvailableSettings.USE_QUERY_CACHE, configurationValues );
|
||||
|
||||
RegionFactory regionFactory = NoCachingRegionFactory.INSTANCE;
|
||||
|
||||
// The cache provider is needed when we either have second-level cache enabled
|
||||
// or query cache enabled. Note that useSecondLevelCache is enabled by default
|
||||
final Object setting = configurationValues.get( AvailableSettings.CACHE_REGION_FACTORY ) ;
|
||||
// ConfigurationHelper.get( AvailableSettings.CACHE_REGION_FACTORY,
|
||||
// configurationValues, null );
|
||||
if ( ( useSecondLevelCache || useQueryCache ) && setting != null ) {
|
||||
try {
|
||||
regionFactory = registry.getService( StrategySelector.class )
|
||||
.resolveStrategy( RegionFactory.class, setting );
|
||||
// try {
|
||||
// regionFactory = regionFactoryClass.getConstructor( Properties.class ).newInstance( p );
|
||||
// }
|
||||
// catch ( NoSuchMethodException e ) {
|
||||
// // no constructor accepting Properties found, try no arg constructor
|
||||
// LOG.debugf(
|
||||
// "%s did not provide constructor accepting java.util.Properties; attempting no-arg constructor.",
|
||||
// regionFactoryClass.getSimpleName() );
|
||||
// regionFactory = regionFactoryClass.getConstructor().newInstance();
|
||||
// }
|
||||
}
|
||||
catch ( Exception e ) {
|
||||
throw new HibernateException( "could not instantiate RegionFactory [" + setting + "]", e );
|
||||
}
|
||||
}
|
||||
|
||||
private RegionFactory initiateService(SessionFactoryImplementor sessionFactory, ServiceRegistryImplementor registry){
|
||||
boolean isCacheEnabled = isCacheEnabled( registry );
|
||||
if ( !isCacheEnabled ) {
|
||||
LOG.debugf(
|
||||
"Second level cache has been disabled, so using % as cache region factory",
|
||||
NoCachingRegionFactory.class.getName()
|
||||
);
|
||||
return NoCachingRegionFactory.INSTANCE;
|
||||
LOG.debugf( "Cache region factory : %s", regionFactory.getClass().getName() );
|
||||
|
||||
return regionFactory;
|
||||
}
|
||||
|
||||
final Object setting = registry.getService( ConfigurationService.class ).getSettings().get( IMPL_NAME );
|
||||
return registry.getService( StrategySelector.class ).resolveDefaultableStrategy(
|
||||
RegionFactory.class,
|
||||
setting,
|
||||
NoCachingRegionFactory.INSTANCE
|
||||
);
|
||||
}
|
||||
|
||||
private static boolean isCacheEnabled(ServiceRegistryImplementor serviceRegistry) {
|
||||
final ConfigurationService configurationService = serviceRegistry.getService( ConfigurationService.class );
|
||||
final boolean useSecondLevelCache = configurationService.getSetting(
|
||||
AvailableSettings.USE_SECOND_LEVEL_CACHE,
|
||||
StandardConverters.BOOLEAN,
|
||||
true
|
||||
);
|
||||
final boolean useQueryCache = configurationService.getSetting(
|
||||
AvailableSettings.USE_QUERY_CACHE,
|
||||
StandardConverters.BOOLEAN,
|
||||
false
|
||||
);
|
||||
return useSecondLevelCache || useQueryCache;
|
||||
}
|
||||
|
||||
// todo this shouldn't be public (nor really static):
|
||||
// hack for org.hibernate.cfg.SettingsFactory.createRegionFactory()
|
||||
/**
|
||||
* Map legacy names unto the new corollary.
|
||||
*
|
||||
* TODO: temporary hack for org.hibernate.cfg.SettingsFactory.createRegionFactory()
|
||||
*
|
||||
* @param name The (possibly legacy) factory name
|
||||
*
|
||||
* @return The factory name to use.
|
||||
*/
|
||||
public static String mapLegacyNames(final String name) {
|
||||
if ( "org.hibernate.cache.EhCacheRegionFactory".equals( name ) ) {
|
||||
return "org.hibernate.cache.ehcache.EhCacheRegionFactory";
|
||||
|
|
|
@ -51,14 +51,13 @@ import org.hibernate.type.TypeHelper;
|
|||
/**
|
||||
* The standard implementation of the Hibernate QueryCache interface. This
|
||||
* implementation is very good at recognizing stale query results and
|
||||
* and re-running queries when it detects this condition, recaching the new
|
||||
* and re-running queries when it detects this condition, re-caching the new
|
||||
* results.
|
||||
*
|
||||
* @author Gavin King
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class StandardQueryCache implements QueryCache {
|
||||
|
||||
private static final CoreMessageLogger LOG = Logger.getMessageLogger(
|
||||
CoreMessageLogger.class,
|
||||
StandardQueryCache.class.getName()
|
||||
|
@ -69,31 +68,58 @@ public class StandardQueryCache implements QueryCache {
|
|||
|
||||
private QueryResultsRegion cacheRegion;
|
||||
private UpdateTimestampsCache updateTimestampsCache;
|
||||
|
||||
/**
|
||||
* Constructs a StandardQueryCache instance
|
||||
*
|
||||
* @param sessionFactoryImplementor The SessionFactory.
|
||||
* @param updateTimestampsCache The update-timestamps cache to use.
|
||||
* @param regionName The base query cache region name
|
||||
*/
|
||||
public StandardQueryCache(SessionFactoryImplementor sessionFactoryImplementor, UpdateTimestampsCache updateTimestampsCache, String regionName) {
|
||||
if ( regionName == null ) {
|
||||
regionName = StandardQueryCache.class.getName();
|
||||
String regionNameToUse = regionName;
|
||||
if ( regionNameToUse == null ) {
|
||||
regionNameToUse = StandardQueryCache.class.getName();
|
||||
}
|
||||
String prefix = sessionFactoryImplementor.getServiceRegistry()
|
||||
.getService( ConfigurationService.class )
|
||||
.getSetting(
|
||||
AvailableSettings.CACHE_REGION_PREFIX, StandardConverters.STRING, null
|
||||
);
|
||||
|
||||
if ( prefix != null ) {
|
||||
regionName = prefix + '.' + regionName;
|
||||
regionNameToUse = prefix + '.' + regionNameToUse;
|
||||
}
|
||||
LOG.startingQueryCache( regionName );
|
||||
LOG.startingQueryCache( regionNameToUse );
|
||||
|
||||
this.cacheRegion = sessionFactoryImplementor.getServiceRegistry()
|
||||
.getService( RegionFactory.class )
|
||||
.buildQueryResultsRegion( regionName, sessionFactoryImplementor.getProperties() );
|
||||
.buildQueryResultsRegion( regionNameToUse, sessionFactoryImplementor.getProperties() );
|
||||
this.updateTimestampsCache = updateTimestampsCache;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public QueryResultsRegion getRegion() {
|
||||
return cacheRegion;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
try {
|
||||
cacheRegion.destroy();
|
||||
}
|
||||
catch ( Exception e ) {
|
||||
LOG.unableToDestroyQueryCache( cacheRegion.getName(), e.getMessage() );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() throws CacheException {
|
||||
cacheRegion.evictAll();
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
public boolean put(
|
||||
final QueryKey key,
|
||||
final Type[] returnTypes,
|
||||
|
@ -103,20 +129,21 @@ public class StandardQueryCache implements QueryCache {
|
|||
if ( isNaturalKeyLookup && result.isEmpty() ) {
|
||||
return false;
|
||||
}
|
||||
long ts = cacheRegion.nextTimestamp();
|
||||
final long ts = cacheRegion.nextTimestamp();
|
||||
|
||||
if ( DEBUGGING ) LOG.debugf( "Caching query results in region: %s; timestamp=%s", cacheRegion.getName(), ts );
|
||||
if ( DEBUGGING ) {
|
||||
LOG.debugf( "Caching query results in region: %s; timestamp=%s", cacheRegion.getName(), ts );
|
||||
}
|
||||
|
||||
List cacheable = new ArrayList( result.size() + 1 );
|
||||
final List cacheable = new ArrayList( result.size() + 1 );
|
||||
logCachedResultDetails( key, null, returnTypes, cacheable );
|
||||
cacheable.add( ts );
|
||||
final boolean singleResult = returnTypes.length == 1;
|
||||
|
||||
final boolean isSingleResult = returnTypes.length == 1;
|
||||
for ( Object aResult : result ) {
|
||||
Serializable cacheItem = singleResult ? returnTypes[0].disassemble(
|
||||
aResult,
|
||||
session,
|
||||
null
|
||||
) : TypeHelper.disassemble( (Object[]) aResult, returnTypes, null, session, null );
|
||||
final Serializable cacheItem = isSingleResult
|
||||
? returnTypes[0].disassemble( aResult, session, null )
|
||||
: TypeHelper.disassemble( (Object[]) aResult, returnTypes, null, session, null );
|
||||
cacheable.add( cacheItem );
|
||||
logCachedResultRowDetails( returnTypes, aResult );
|
||||
}
|
||||
|
@ -125,6 +152,7 @@ public class StandardQueryCache implements QueryCache {
|
|||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
public List get(
|
||||
final QueryKey key,
|
||||
|
@ -132,23 +160,31 @@ public class StandardQueryCache implements QueryCache {
|
|||
final boolean isNaturalKeyLookup,
|
||||
final Set spaces,
|
||||
final SessionImplementor session) throws HibernateException {
|
||||
if ( DEBUGGING ) LOG.debugf( "Checking cached query results in region: %s", cacheRegion.getName() );
|
||||
if ( DEBUGGING ) {
|
||||
LOG.debugf( "Checking cached query results in region: %s", cacheRegion.getName() );
|
||||
}
|
||||
|
||||
List cacheable = (List) cacheRegion.get( key );
|
||||
final List cacheable = (List) cacheRegion.get( key );
|
||||
logCachedResultDetails( key, spaces, returnTypes, cacheable );
|
||||
|
||||
if ( cacheable == null ) {
|
||||
if ( DEBUGGING ) LOG.debug( "Query results were not found in cache" );
|
||||
if ( DEBUGGING ) {
|
||||
LOG.debug( "Query results were not found in cache" );
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
Long timestamp = (Long) cacheable.get( 0 );
|
||||
final Long timestamp = (Long) cacheable.get( 0 );
|
||||
if ( !isNaturalKeyLookup && !isUpToDate( spaces, timestamp ) ) {
|
||||
if ( DEBUGGING ) LOG.debug( "Cached query results were not up-to-date" );
|
||||
if ( DEBUGGING ) {
|
||||
LOG.debug( "Cached query results were not up-to-date" );
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
if ( DEBUGGING ) LOG.debug( "Returning cached query results" );
|
||||
if ( DEBUGGING ) {
|
||||
LOG.debug( "Returning cached query results" );
|
||||
}
|
||||
final boolean singleResult = returnTypes.length == 1;
|
||||
for ( int i = 1; i < cacheable.size(); i++ ) {
|
||||
if ( singleResult ) {
|
||||
|
@ -158,7 +194,8 @@ public class StandardQueryCache implements QueryCache {
|
|||
TypeHelper.beforeAssemble( (Serializable[]) cacheable.get( i ), returnTypes, session );
|
||||
}
|
||||
}
|
||||
List result = new ArrayList( cacheable.size() - 1 );
|
||||
|
||||
final List result = new ArrayList( cacheable.size() - 1 );
|
||||
for ( int i = 1; i < cacheable.size(); i++ ) {
|
||||
try {
|
||||
if ( singleResult ) {
|
||||
|
@ -172,17 +209,19 @@ public class StandardQueryCache implements QueryCache {
|
|||
logCachedResultRowDetails( returnTypes, result.get( i - 1 ) );
|
||||
}
|
||||
catch ( RuntimeException ex ) {
|
||||
if ( isNaturalKeyLookup &&
|
||||
( UnresolvableObjectException.class.isInstance( ex ) ||
|
||||
EntityNotFoundException.class.isInstance( ex ) ) ) {
|
||||
//TODO: not really completely correct, since
|
||||
// the uoe could occur while resolving
|
||||
// associations, leaving the PC in an
|
||||
// inconsistent state
|
||||
if ( DEBUGGING ) LOG.debug( "Unable to reassemble cached result set" );
|
||||
if ( isNaturalKeyLookup ) {
|
||||
// potentially perform special handling for natural-id look ups.
|
||||
if ( UnresolvableObjectException.class.isInstance( ex )
|
||||
|| EntityNotFoundException.class.isInstance( ex ) ) {
|
||||
if ( DEBUGGING ) {
|
||||
LOG.debug( "Unable to reassemble cached natural-id query result" );
|
||||
}
|
||||
cacheRegion.evict( key );
|
||||
|
||||
// EARLY EXIT !!!!!
|
||||
return null;
|
||||
}
|
||||
}
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
@ -190,23 +229,12 @@ public class StandardQueryCache implements QueryCache {
|
|||
}
|
||||
|
||||
protected boolean isUpToDate(final Set spaces, final Long timestamp) {
|
||||
if ( DEBUGGING ) LOG.debugf( "Checking query spaces are up-to-date: %s", spaces );
|
||||
if ( DEBUGGING ) {
|
||||
LOG.debugf( "Checking query spaces are up-to-date: %s", spaces );
|
||||
}
|
||||
return updateTimestampsCache.isUpToDate( spaces, timestamp );
|
||||
}
|
||||
|
||||
public void destroy() {
|
||||
try {
|
||||
cacheRegion.destroy();
|
||||
}
|
||||
catch ( Exception e ) {
|
||||
LOG.unableToDestroyQueryCache( cacheRegion.getName(), e.getMessage() );
|
||||
}
|
||||
}
|
||||
|
||||
public QueryResultsRegion getRegion() {
|
||||
return cacheRegion;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "StandardQueryCache(" + cacheRegion.getName() + ')';
|
||||
|
@ -226,12 +254,13 @@ public class StandardQueryCache implements QueryCache {
|
|||
);
|
||||
}
|
||||
else {
|
||||
StringBuilder returnTypeInfo = new StringBuilder();
|
||||
for ( int i = 0; i < returnTypes.length; i++ ) {
|
||||
final StringBuilder returnTypeInfo = new StringBuilder();
|
||||
for ( Type returnType : returnTypes ) {
|
||||
returnTypeInfo.append( "typename=" )
|
||||
.append( returnTypes[i].getName() )
|
||||
.append( returnType.getName() )
|
||||
.append( " class=" )
|
||||
.append( returnTypes[i].getReturnedClass().getName() ).append( ' ' );
|
||||
.append( returnType.getReturnedClass().getName() )
|
||||
.append( ' ' );
|
||||
}
|
||||
LOG.trace( "unexpected returnTypes is " + returnTypeInfo.toString() + "! result" );
|
||||
}
|
||||
|
@ -252,7 +281,10 @@ public class StandardQueryCache implements QueryCache {
|
|||
return;
|
||||
}
|
||||
if ( tuple == null ) {
|
||||
LOG.trace( " tuple is null; returnTypes is " + returnTypes == null ? "null" : "Type[" + returnTypes.length + "]" );
|
||||
LOG.tracef(
|
||||
"tuple is null; returnTypes is %s",
|
||||
returnTypes == null ? "null" : "Type[" + returnTypes.length + "]"
|
||||
);
|
||||
if ( returnTypes != null && returnTypes.length > 1 ) {
|
||||
LOG.trace(
|
||||
"Unexpected result tuple! tuple is null; should be Object["
|
||||
|
@ -267,8 +299,12 @@ public class StandardQueryCache implements QueryCache {
|
|||
+ ( returnTypes == null ? "null" : "empty" )
|
||||
);
|
||||
}
|
||||
LOG.trace( " tuple is Object[" + tuple.length + "]; returnTypes is Type[" + returnTypes.length + "]" );
|
||||
if ( tuple.length != returnTypes.length ) {
|
||||
LOG.tracef(
|
||||
"tuple is Object[%s]; returnTypes is %s",
|
||||
tuple.length,
|
||||
returnTypes == null ? "null" : "Type[" + returnTypes.length + "]"
|
||||
);
|
||||
if ( returnTypes != null && tuple.length != returnTypes.length ) {
|
||||
LOG.trace(
|
||||
"Unexpected tuple length! transformer= expected="
|
||||
+ returnTypes.length + " got=" + tuple.length
|
||||
|
@ -276,7 +312,8 @@ public class StandardQueryCache implements QueryCache {
|
|||
}
|
||||
else {
|
||||
for ( int j = 0; j < tuple.length; j++ ) {
|
||||
if ( tuple[j] != null && !returnTypes[j].getReturnedClass().isInstance( tuple[j] ) ) {
|
||||
if ( tuple[j] != null && returnTypes != null
|
||||
&& ! returnTypes[j].getReturnedClass().isInstance( tuple[j] ) ) {
|
||||
LOG.trace(
|
||||
"Unexpected tuple value type! transformer= expected="
|
||||
+ returnTypes[j].getReturnedClass().getName()
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/**
|
||||
* Internal implementations and support for second-level caching.
|
||||
*/
|
||||
package org.hibernate.cache.internal;
|
|
@ -29,7 +29,6 @@ import java.util.Set;
|
|||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.cache.CacheException;
|
||||
import org.hibernate.cfg.Settings;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
|
|
|
@ -150,6 +150,7 @@ import org.hibernate.cfg.annotations.PropertyBinder;
|
|||
import org.hibernate.cfg.annotations.QueryBinder;
|
||||
import org.hibernate.cfg.annotations.SimpleValueBinder;
|
||||
import org.hibernate.cfg.annotations.TableBinder;
|
||||
import org.hibernate.engine.OptimisticLockStyle;
|
||||
import org.hibernate.engine.internal.Versioning;
|
||||
import org.hibernate.engine.spi.FilterDefinition;
|
||||
import org.hibernate.id.MultipleHiLoPerTableGenerator;
|
||||
|
@ -1561,7 +1562,7 @@ public final class AnnotationBinder {
|
|||
|
||||
SimpleValue simpleValue = ( SimpleValue ) prop.getValue();
|
||||
simpleValue.setNullValue( "undefined" );
|
||||
rootClass.setOptimisticLockMode( Versioning.OPTIMISTIC_LOCK_VERSION );
|
||||
rootClass.setOptimisticLockStyle( OptimisticLockStyle.VERSION );
|
||||
if ( traceEnabled ) {
|
||||
LOG.tracev( "Version name: {0}, unsavedValue: {1}", rootClass.getVersion().getName(),
|
||||
( (SimpleValue) rootClass.getVersion().getValue() ).getNullValue() );
|
||||
|
|
|
@ -23,8 +23,6 @@
|
|||
*/
|
||||
package org.hibernate.cfg;
|
||||
|
||||
import org.hibernate.tool.hbm2ddl.DatabaseMetadata;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
|
@ -697,4 +695,22 @@ public interface AvailableSettings {
|
|||
* Oracle), this is disabled by default.
|
||||
*/
|
||||
public static final String ENABLE_SYNONYMS = "hibernate.synonyms";
|
||||
|
||||
/**
|
||||
* Unique columns and unique keys both use unique constraints in most dialects.
|
||||
* SchemaUpdate needs to create these constraints, but DB's
|
||||
* support for finding existing constraints is extremely inconsistent. Further,
|
||||
* non-explicitly-named unique constraints use randomly generated characters.
|
||||
*
|
||||
* Therefore, select from these strategies.
|
||||
* {@link org.hibernate.tool.hbm2ddl.UniqueConstraintSchemaUpdateStrategy#DROP_RECREATE_QUIETLY} (DEFAULT):
|
||||
* Attempt to drop, then (re-)create each unique constraint.
|
||||
* Ignore any exceptions thrown.
|
||||
* {@link org.hibernate.tool.hbm2ddl.UniqueConstraintSchemaUpdateStrategy#RECREATE_QUIETLY}:
|
||||
* attempt to (re-)create unique constraints,
|
||||
* ignoring exceptions thrown if the constraint already existed
|
||||
* {@link org.hibernate.tool.hbm2ddl.UniqueConstraintSchemaUpdateStrategy#SKIP}:
|
||||
* do not attempt to create unique constraints on a schema update
|
||||
*/
|
||||
public static final String UNIQUE_CONSTRAINT_SCHEMA_UPDATE_STRATEGY = "hibernate.schema_update.unique_constraint_strategy";
|
||||
}
|
||||
|
|
|
@ -82,6 +82,7 @@ import org.hibernate.annotations.common.reflection.ReflectionManager;
|
|||
import org.hibernate.annotations.common.reflection.XClass;
|
||||
import org.hibernate.annotations.common.reflection.java.JavaReflectionManager;
|
||||
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
|
||||
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
|
||||
import org.hibernate.boot.registry.internal.StandardServiceRegistryImpl;
|
||||
import org.hibernate.cfg.annotations.reflection.JPAMetadataProvider;
|
||||
import org.hibernate.context.spi.CurrentTenantIdentifierResolver;
|
||||
|
@ -89,6 +90,7 @@ import org.hibernate.dialect.Dialect;
|
|||
import org.hibernate.dialect.MySQLDialect;
|
||||
import org.hibernate.dialect.function.SQLFunction;
|
||||
import org.hibernate.engine.ResultSetMappingDefinition;
|
||||
import org.hibernate.engine.jdbc.spi.JdbcServices;
|
||||
import org.hibernate.engine.spi.FilterDefinition;
|
||||
import org.hibernate.engine.spi.Mapping;
|
||||
import org.hibernate.engine.spi.NamedQueryDefinition;
|
||||
|
@ -136,13 +138,17 @@ import org.hibernate.mapping.SimpleValue;
|
|||
import org.hibernate.mapping.Table;
|
||||
import org.hibernate.mapping.TypeDef;
|
||||
import org.hibernate.mapping.UniqueKey;
|
||||
import org.hibernate.metamodel.spi.TypeContributions;
|
||||
import org.hibernate.metamodel.spi.TypeContributor;
|
||||
import org.hibernate.proxy.EntityNotFoundDelegate;
|
||||
import org.hibernate.secure.spi.GrantedPermission;
|
||||
import org.hibernate.secure.spi.JaccPermissionDeclarations;
|
||||
import org.hibernate.service.ServiceRegistry;
|
||||
import org.hibernate.tool.hbm2ddl.DatabaseMetadata;
|
||||
import org.hibernate.tool.hbm2ddl.IndexMetadata;
|
||||
import org.hibernate.tool.hbm2ddl.SchemaUpdateScript;
|
||||
import org.hibernate.tool.hbm2ddl.TableMetadata;
|
||||
import org.hibernate.tool.hbm2ddl.UniqueConstraintSchemaUpdateStrategy;
|
||||
import org.hibernate.tuple.entity.EntityTuplizerFactory;
|
||||
import org.hibernate.type.BasicType;
|
||||
import org.hibernate.type.SerializationException;
|
||||
|
@ -221,7 +227,9 @@ public class Configuration implements Serializable {
|
|||
protected Map<ExtendsQueueEntry, ?> extendsQueue;
|
||||
|
||||
protected Map<String, SQLFunction> sqlFunctions;
|
||||
|
||||
private TypeResolver typeResolver = new TypeResolver();
|
||||
private List<TypeContributor> typeContributorRegistrations = new ArrayList<TypeContributor>();
|
||||
|
||||
private EntityTuplizerFactory entityTuplizerFactory;
|
||||
// private ComponentTuplizerFactory componentTuplizerFactory; todo : HHH-3517 and HHH-1907
|
||||
|
@ -1117,57 +1125,64 @@ public class Configuration implements Serializable {
|
|||
*
|
||||
* @throws HibernateException Generally indicates a problem calling {@link #buildMappings()}
|
||||
*
|
||||
* @see org.hibernate.tool.hbm2ddl.SchemaExport
|
||||
* @see org.hibernate.tool.hbm2ddl.SchemaUpdate
|
||||
*
|
||||
* @deprecated Use {@link #generateSchemaUpdateScriptList(Dialect, DatabaseMetadata)} instead
|
||||
*/
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
@Deprecated
|
||||
public String[] generateSchemaUpdateScript(Dialect dialect, DatabaseMetadata databaseMetadata)
|
||||
throws HibernateException {
|
||||
List<SchemaUpdateScript> scripts = generateSchemaUpdateScriptList( dialect, databaseMetadata );
|
||||
return SchemaUpdateScript.toStringArray( scripts );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param dialect The dialect for which to generate the creation script
|
||||
* @param databaseMetadata The database catalog information for the database to be updated; needed to work out what
|
||||
* should be created/altered
|
||||
*
|
||||
* @return The sequence of DDL commands to apply the schema objects
|
||||
*
|
||||
* @throws HibernateException Generally indicates a problem calling {@link #buildMappings()}
|
||||
*
|
||||
* @see org.hibernate.tool.hbm2ddl.SchemaUpdate
|
||||
*/
|
||||
public List<SchemaUpdateScript> generateSchemaUpdateScriptList(Dialect dialect, DatabaseMetadata databaseMetadata)
|
||||
throws HibernateException {
|
||||
secondPassCompile();
|
||||
|
||||
String defaultCatalog = properties.getProperty( Environment.DEFAULT_CATALOG );
|
||||
String defaultSchema = properties.getProperty( Environment.DEFAULT_SCHEMA );
|
||||
UniqueConstraintSchemaUpdateStrategy constraintMethod = UniqueConstraintSchemaUpdateStrategy.interpret( properties
|
||||
.get( Environment.UNIQUE_CONSTRAINT_SCHEMA_UPDATE_STRATEGY ) );
|
||||
|
||||
ArrayList<String> script = new ArrayList<String>( 50 );
|
||||
List<SchemaUpdateScript> scripts = new ArrayList<SchemaUpdateScript>();
|
||||
|
||||
Iterator iter = getTableMappings();
|
||||
while ( iter.hasNext() ) {
|
||||
Table table = (Table) iter.next();
|
||||
String tableSchema = ( table.getSchema() == null ) ? defaultSchema : table.getSchema() ;
|
||||
String tableSchema = ( table.getSchema() == null ) ? defaultSchema : table.getSchema();
|
||||
String tableCatalog = ( table.getCatalog() == null ) ? defaultCatalog : table.getCatalog();
|
||||
if ( table.isPhysicalTable() ) {
|
||||
|
||||
TableMetadata tableInfo = databaseMetadata.getTableMetadata(
|
||||
table.getName(),
|
||||
tableSchema,
|
||||
tableCatalog,
|
||||
table.isQuoted()
|
||||
);
|
||||
TableMetadata tableInfo = databaseMetadata.getTableMetadata( table.getName(), tableSchema,
|
||||
tableCatalog, table.isQuoted() );
|
||||
if ( tableInfo == null ) {
|
||||
script.add(
|
||||
table.sqlCreateString(
|
||||
dialect,
|
||||
mapping,
|
||||
tableCatalog,
|
||||
tableSchema
|
||||
)
|
||||
);
|
||||
scripts.add( new SchemaUpdateScript( table.sqlCreateString( dialect, mapping, tableCatalog,
|
||||
tableSchema ), false ) );
|
||||
}
|
||||
else {
|
||||
Iterator<String> subiter = table.sqlAlterStrings(
|
||||
dialect,
|
||||
mapping,
|
||||
tableInfo,
|
||||
tableCatalog,
|
||||
tableSchema
|
||||
);
|
||||
Iterator<String> subiter = table.sqlAlterStrings( dialect, mapping, tableInfo, tableCatalog,
|
||||
tableSchema );
|
||||
while ( subiter.hasNext() ) {
|
||||
script.add( subiter.next() );
|
||||
scripts.add( new SchemaUpdateScript( subiter.next(), false ) );
|
||||
}
|
||||
}
|
||||
|
||||
Iterator<String> comments = table.sqlCommentStrings( dialect, defaultCatalog, defaultSchema );
|
||||
while ( comments.hasNext() ) {
|
||||
script.add( comments.next() );
|
||||
scripts.add( new SchemaUpdateScript( comments.next(), false ) );
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1176,17 +1191,14 @@ public class Configuration implements Serializable {
|
|||
iter = getTableMappings();
|
||||
while ( iter.hasNext() ) {
|
||||
Table table = (Table) iter.next();
|
||||
String tableSchema = ( table.getSchema() == null ) ? defaultSchema : table.getSchema() ;
|
||||
String tableSchema = ( table.getSchema() == null ) ? defaultSchema : table.getSchema();
|
||||
String tableCatalog = ( table.getCatalog() == null ) ? defaultCatalog : table.getCatalog();
|
||||
if ( table.isPhysicalTable() ) {
|
||||
|
||||
TableMetadata tableInfo = databaseMetadata.getTableMetadata(
|
||||
table.getName(),
|
||||
tableSchema,
|
||||
tableCatalog,
|
||||
table.isQuoted()
|
||||
);
|
||||
TableMetadata tableInfo = databaseMetadata.getTableMetadata( table.getName(), tableSchema,
|
||||
tableCatalog, table.isQuoted() );
|
||||
|
||||
if (! constraintMethod.equals( UniqueConstraintSchemaUpdateStrategy.SKIP )) {
|
||||
Iterator uniqueIter = table.getUniqueKeyIterator();
|
||||
while ( uniqueIter.hasNext() ) {
|
||||
final UniqueKey uniqueKey = (UniqueKey) uniqueIter.next();
|
||||
|
@ -1199,9 +1211,14 @@ public class Configuration implements Serializable {
|
|||
continue;
|
||||
}
|
||||
}
|
||||
String constraintString = uniqueKey.sqlCreateString( dialect,
|
||||
mapping, tableCatalog, tableSchema );
|
||||
if (constraintString != null) script.add( constraintString );
|
||||
String constraintString = uniqueKey.sqlCreateString( dialect, mapping, tableCatalog, tableSchema );
|
||||
if ( constraintString != null && !constraintString.isEmpty() )
|
||||
if ( constraintMethod.equals( UniqueConstraintSchemaUpdateStrategy.DROP_RECREATE_QUIETLY ) ) {
|
||||
String constraintDropString = uniqueKey.sqlDropString( dialect, tableCatalog, tableCatalog );
|
||||
scripts.add( new SchemaUpdateScript( constraintDropString, true) );
|
||||
}
|
||||
scripts.add( new SchemaUpdateScript( constraintString, true) );
|
||||
}
|
||||
}
|
||||
|
||||
if ( dialect.hasAlterTable() ) {
|
||||
|
@ -1209,22 +1226,12 @@ public class Configuration implements Serializable {
|
|||
while ( subIter.hasNext() ) {
|
||||
ForeignKey fk = (ForeignKey) subIter.next();
|
||||
if ( fk.isPhysicalConstraint() ) {
|
||||
boolean create = tableInfo == null || (
|
||||
tableInfo.getForeignKeyMetadata( fk ) == null && (
|
||||
//Icky workaround for MySQL bug:
|
||||
!( dialect instanceof MySQLDialect ) ||
|
||||
tableInfo.getIndexMetadata( fk.getName() ) == null
|
||||
)
|
||||
);
|
||||
boolean create = tableInfo == null || ( tableInfo.getForeignKeyMetadata( fk ) == null && (
|
||||
// Icky workaround for MySQL bug:
|
||||
!( dialect instanceof MySQLDialect ) || tableInfo.getIndexMetadata( fk.getName() ) == null ) );
|
||||
if ( create ) {
|
||||
script.add(
|
||||
fk.sqlCreateString(
|
||||
dialect,
|
||||
mapping,
|
||||
tableCatalog,
|
||||
tableSchema
|
||||
)
|
||||
);
|
||||
scripts.add( new SchemaUpdateScript( fk.sqlCreateString( dialect, mapping,
|
||||
tableCatalog, tableSchema ), false ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1240,14 +1247,8 @@ public class Configuration implements Serializable {
|
|||
continue;
|
||||
}
|
||||
}
|
||||
script.add(
|
||||
index.sqlCreateString(
|
||||
dialect,
|
||||
mapping,
|
||||
tableCatalog,
|
||||
tableSchema
|
||||
)
|
||||
);
|
||||
scripts.add( new SchemaUpdateScript( index.sqlCreateString( dialect, mapping, tableCatalog,
|
||||
tableSchema ), false ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1258,11 +1259,11 @@ public class Configuration implements Serializable {
|
|||
Object key = generator.generatorKey();
|
||||
if ( !databaseMetadata.isSequence( key ) && !databaseMetadata.isTable( key ) ) {
|
||||
String[] lines = generator.sqlCreateStrings( dialect );
|
||||
script.addAll( Arrays.asList( lines ) );
|
||||
scripts.addAll( SchemaUpdateScript.fromStringArray( lines, false ) );
|
||||
}
|
||||
}
|
||||
|
||||
return ArrayHelper.toStringArray( script );
|
||||
return scripts;
|
||||
}
|
||||
|
||||
public void validateSchema(Dialect dialect, DatabaseMetadata databaseMetadata)throws HibernateException {
|
||||
|
@ -1788,6 +1789,7 @@ public class Configuration implements Serializable {
|
|||
public SessionFactory buildSessionFactory(ServiceRegistry serviceRegistry) throws HibernateException {
|
||||
LOG.debugf( "Preparing to build session factory with filters : %s", filterDefinitions );
|
||||
|
||||
buildTypeRegistrations( serviceRegistry );
|
||||
secondPassCompile();
|
||||
if ( !metadataSourceQueue.isEmpty() ) {
|
||||
LOG.incompleteMappingMetadataCacheProcessing();
|
||||
|
@ -1810,6 +1812,39 @@ public class Configuration implements Serializable {
|
|||
);
|
||||
}
|
||||
|
||||
private void buildTypeRegistrations(ServiceRegistry serviceRegistry) {
|
||||
final TypeContributions typeContributions = new TypeContributions() {
|
||||
@Override
|
||||
public void contributeType(BasicType type) {
|
||||
typeResolver.registerTypeOverride( type );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void contributeType(UserType type, String[] keys) {
|
||||
typeResolver.registerTypeOverride( type, keys );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void contributeType(CompositeUserType type, String[] keys) {
|
||||
typeResolver.registerTypeOverride( type, keys );
|
||||
}
|
||||
};
|
||||
|
||||
// add Dialect contributed types
|
||||
final Dialect dialect = serviceRegistry.getService( JdbcServices.class ).getDialect();
|
||||
dialect.contributeTypes( typeContributions, serviceRegistry );
|
||||
|
||||
// add TypeContributor contributed types.
|
||||
ClassLoaderService classLoaderService = serviceRegistry.getService( ClassLoaderService.class );
|
||||
for ( TypeContributor contributor : classLoaderService.loadJavaServices( TypeContributor.class ) ) {
|
||||
contributor.contribute( typeContributions, serviceRegistry );
|
||||
}
|
||||
// from app registrations
|
||||
for ( TypeContributor contributor : typeContributorRegistrations ) {
|
||||
contributor.contribute( typeContributions, serviceRegistry );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a {@link SessionFactory} using the properties and mappings in this configuration. The
|
||||
* {@link SessionFactory} will be immutable, so changes made to {@code this} {@link Configuration} after
|
||||
|
@ -2515,6 +2550,10 @@ public class Configuration implements Serializable {
|
|||
getTypeResolver().registerTypeOverride( type, keys );
|
||||
}
|
||||
|
||||
public void registerTypeContributor(TypeContributor typeContributor) {
|
||||
typeContributorRegistrations.add( typeContributor );
|
||||
}
|
||||
|
||||
public SessionFactoryObserver getSessionFactoryObserver() {
|
||||
return sessionFactoryObserver;
|
||||
}
|
||||
|
|
|
@ -40,7 +40,7 @@ import org.hibernate.EntityMode;
|
|||
import org.hibernate.FetchMode;
|
||||
import org.hibernate.FlushMode;
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.engine.internal.Versioning;
|
||||
import org.hibernate.engine.OptimisticLockStyle;
|
||||
import org.hibernate.engine.spi.ExecuteUpdateResultCheckStyle;
|
||||
import org.hibernate.engine.spi.FilterDefinition;
|
||||
import org.hibernate.engine.spi.NamedQueryDefinition;
|
||||
|
@ -687,7 +687,7 @@ public final class HbmBinder {
|
|||
|
||||
// OPTIMISTIC LOCK MODE
|
||||
Attribute olNode = node.attribute( "optimistic-lock" );
|
||||
entity.setOptimisticLockMode( getOptimisticLockMode( olNode ) );
|
||||
entity.setOptimisticLockStyle( getOptimisticLockStyle( olNode ) );
|
||||
|
||||
entity.setMetaAttributes( getMetas( node, inheritedMetas ) );
|
||||
|
||||
|
@ -2896,21 +2896,23 @@ public final class HbmBinder {
|
|||
}
|
||||
}
|
||||
|
||||
private static int getOptimisticLockMode(Attribute olAtt) throws MappingException {
|
||||
private static OptimisticLockStyle getOptimisticLockStyle(Attribute olAtt) throws MappingException {
|
||||
if ( olAtt == null ) {
|
||||
return OptimisticLockStyle.VERSION;
|
||||
}
|
||||
|
||||
if ( olAtt == null ) return Versioning.OPTIMISTIC_LOCK_VERSION;
|
||||
String olMode = olAtt.getValue();
|
||||
final String olMode = olAtt.getValue();
|
||||
if ( olMode == null || "version".equals( olMode ) ) {
|
||||
return Versioning.OPTIMISTIC_LOCK_VERSION;
|
||||
return OptimisticLockStyle.VERSION;
|
||||
}
|
||||
else if ( "dirty".equals( olMode ) ) {
|
||||
return Versioning.OPTIMISTIC_LOCK_DIRTY;
|
||||
return OptimisticLockStyle.DIRTY;
|
||||
}
|
||||
else if ( "all".equals( olMode ) ) {
|
||||
return Versioning.OPTIMISTIC_LOCK_ALL;
|
||||
return OptimisticLockStyle.ALL;
|
||||
}
|
||||
else if ( "none".equals( olMode ) ) {
|
||||
return Versioning.OPTIMISTIC_LOCK_NONE;
|
||||
return OptimisticLockStyle.NONE;
|
||||
}
|
||||
else {
|
||||
throw new MappingException( "Unsupported optimistic-lock style: " + olMode );
|
||||
|
@ -2932,7 +2934,7 @@ public final class HbmBinder {
|
|||
boolean inheritable = Boolean
|
||||
.valueOf( metaNode.attributeValue( "inherit" ) )
|
||||
.booleanValue();
|
||||
if ( onlyInheritable & !inheritable ) {
|
||||
if ( onlyInheritable && !inheritable ) {
|
||||
continue;
|
||||
}
|
||||
String name = metaNode.attributeValue( "attribute" );
|
||||
|
|
|
@ -1139,7 +1139,11 @@ public abstract class CollectionBinder {
|
|||
XProperty property,
|
||||
PropertyHolder parentPropertyHolder,
|
||||
Mappings mappings) throws MappingException {
|
||||
PersistentClass collectionEntity = (PersistentClass) persistentClasses.get( collType.getName() );
|
||||
if ( property == null ) {
|
||||
throw new IllegalArgumentException( "null was passed for argument property" );
|
||||
}
|
||||
|
||||
final PersistentClass collectionEntity = (PersistentClass) persistentClasses.get( collType.getName() );
|
||||
final String hqlOrderBy = extractHqlOrderBy( jpaOrderBy );
|
||||
|
||||
boolean isCollectionOfEntities = collectionEntity != null;
|
||||
|
@ -1269,9 +1273,11 @@ public abstract class CollectionBinder {
|
|||
buildOrderByClauseFromHql( hqlOrderBy, collectionEntity, collValue.getRole() )
|
||||
);
|
||||
}
|
||||
ForeignKey fk = property != null ? property.getAnnotation( ForeignKey.class ) : null;
|
||||
final ForeignKey fk = property.getAnnotation( ForeignKey.class );
|
||||
String fkName = fk != null ? fk.inverseName() : "";
|
||||
if ( !BinderHelper.isEmptyAnnotationValue( fkName ) ) element.setForeignKeyName( fkName );
|
||||
if ( !BinderHelper.isEmptyAnnotationValue( fkName ) ) {
|
||||
element.setForeignKeyName( fkName );
|
||||
}
|
||||
}
|
||||
else if ( anyAnn != null ) {
|
||||
//@ManyToAny
|
||||
|
|
|
@ -82,6 +82,7 @@ import org.hibernate.cfg.ObjectNameNormalizer;
|
|||
import org.hibernate.cfg.ObjectNameSource;
|
||||
import org.hibernate.cfg.PropertyHolder;
|
||||
import org.hibernate.cfg.UniqueConstraintHolder;
|
||||
import org.hibernate.engine.OptimisticLockStyle;
|
||||
import org.hibernate.engine.internal.Versioning;
|
||||
import org.hibernate.engine.spi.ExecuteUpdateResultCheckStyle;
|
||||
import org.hibernate.engine.spi.FilterDefinition;
|
||||
|
@ -270,7 +271,7 @@ public class EntityBinder {
|
|||
LOG.immutableAnnotationOnNonRoot(annotatedClass.getName());
|
||||
}
|
||||
}
|
||||
persistentClass.setOptimisticLockMode( getVersioning( optimisticLockType ) );
|
||||
persistentClass.setOptimisticLockStyle( getVersioning( optimisticLockType ) );
|
||||
persistentClass.setSelectBeforeUpdate( selectBeforeUpdate );
|
||||
|
||||
//set persister if needed
|
||||
|
@ -404,16 +405,16 @@ public class EntityBinder {
|
|||
}
|
||||
}
|
||||
|
||||
int getVersioning(OptimisticLockType type) {
|
||||
OptimisticLockStyle getVersioning(OptimisticLockType type) {
|
||||
switch ( type ) {
|
||||
case VERSION:
|
||||
return Versioning.OPTIMISTIC_LOCK_VERSION;
|
||||
return OptimisticLockStyle.VERSION;
|
||||
case NONE:
|
||||
return Versioning.OPTIMISTIC_LOCK_NONE;
|
||||
return OptimisticLockStyle.NONE;
|
||||
case DIRTY:
|
||||
return Versioning.OPTIMISTIC_LOCK_DIRTY;
|
||||
return OptimisticLockStyle.DIRTY;
|
||||
case ALL:
|
||||
return Versioning.OPTIMISTIC_LOCK_ALL;
|
||||
return OptimisticLockStyle.ALL;
|
||||
default:
|
||||
throw new AssertionFailure( "optimistic locking not supported: " + type );
|
||||
}
|
||||
|
|
|
@ -75,7 +75,7 @@ public interface Lifecycle {
|
|||
* Called when an entity is saved.
|
||||
* @param s the session
|
||||
* @return true to veto save
|
||||
* @throws CallbackException
|
||||
* @throws CallbackException Indicates a problem happened during callback
|
||||
*/
|
||||
public boolean onSave(Session s) throws CallbackException;
|
||||
|
||||
|
@ -85,7 +85,7 @@ public interface Lifecycle {
|
|||
* state is persisted during a flush.
|
||||
* @param s the session
|
||||
* @return true to veto update
|
||||
* @throws CallbackException
|
||||
* @throws CallbackException Indicates a problem happened during callback
|
||||
*/
|
||||
public boolean onUpdate(Session s) throws CallbackException;
|
||||
|
||||
|
@ -93,7 +93,7 @@ public interface Lifecycle {
|
|||
* Called when an entity is deleted.
|
||||
* @param s the session
|
||||
* @return true to veto delete
|
||||
* @throws CallbackException
|
||||
* @throws CallbackException Indicates a problem happened during callback
|
||||
*/
|
||||
public boolean onDelete(Session s) throws CallbackException;
|
||||
|
||||
|
@ -108,9 +108,3 @@ public interface Lifecycle {
|
|||
*/
|
||||
public void onLoad(Session s, Serializable id);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -80,41 +80,57 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
|
|||
private Serializable storedSnapshot;
|
||||
|
||||
private String sessionFactoryUuid;
|
||||
private boolean specjLazyLoad = false;
|
||||
private boolean specjLazyLoad;
|
||||
|
||||
/**
|
||||
* Not called by Hibernate, but used by non-JDK serialization,
|
||||
* eg. SOAP libraries.
|
||||
*/
|
||||
public AbstractPersistentCollection() {
|
||||
}
|
||||
|
||||
protected AbstractPersistentCollection(SessionImplementor session) {
|
||||
this.session = session;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String getRole() {
|
||||
return role;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Serializable getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean isUnreferenced() {
|
||||
return role == null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean isDirty() {
|
||||
return dirty;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void clearDirty() {
|
||||
dirty = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void dirty() {
|
||||
dirty = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Serializable getStoredSnapshot() {
|
||||
return storedSnapshot;
|
||||
}
|
||||
|
||||
//Careful: these methods do not initialize the collection.
|
||||
|
||||
/**
|
||||
* Is the initialized collection empty?
|
||||
*/
|
||||
@Override
|
||||
public abstract boolean empty();
|
||||
|
||||
/**
|
||||
|
@ -134,14 +150,14 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
|
|||
return true;
|
||||
}
|
||||
else {
|
||||
boolean isExtraLazy = withTemporarySessionIfNeeded(
|
||||
final boolean isExtraLazy = withTemporarySessionIfNeeded(
|
||||
new LazyInitializationWork<Boolean>() {
|
||||
@Override
|
||||
public Boolean doWork() {
|
||||
CollectionEntry entry = session.getPersistenceContext().getCollectionEntry( AbstractPersistentCollection.this );
|
||||
final CollectionEntry entry = session.getPersistenceContext().getCollectionEntry( AbstractPersistentCollection.this );
|
||||
|
||||
if ( entry != null ) {
|
||||
CollectionPersister persister = entry.getLoadedPersister();
|
||||
final CollectionPersister persister = entry.getLoadedPersister();
|
||||
if ( persister.isExtraLazy() ) {
|
||||
if ( hasQueuedOperations() ) {
|
||||
session.flush();
|
||||
|
@ -168,7 +184,17 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
|
|||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* TBH not sure why this is public
|
||||
*
|
||||
* @param <T> The java type of the return for this LazyInitializationWork
|
||||
*/
|
||||
public static interface LazyInitializationWork<T> {
|
||||
/**
|
||||
* Do the represented work and return the result.
|
||||
*
|
||||
* @return The result
|
||||
*/
|
||||
public T doWork();
|
||||
}
|
||||
|
||||
|
@ -221,7 +247,7 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
|
|||
// be created even if a current session and transaction are
|
||||
// open (ex: session.clear() was used). We must prevent
|
||||
// multiple transactions.
|
||||
( ( Session) session ).beginTransaction();
|
||||
( (Session) session ).beginTransaction();
|
||||
}
|
||||
|
||||
session.getPersistenceContext().addUninitializedDetachedCollection(
|
||||
|
@ -238,7 +264,7 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
|
|||
// make sure the just opened temp session gets closed!
|
||||
try {
|
||||
if ( !isJTA ) {
|
||||
( ( Session) session ).getTransaction().commit();
|
||||
( (Session) session ).getTransaction().commit();
|
||||
}
|
||||
( (Session) session ).close();
|
||||
}
|
||||
|
@ -255,19 +281,19 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
|
|||
throwLazyInitializationException( "SessionFactory UUID not known to create temporary Session for loading" );
|
||||
}
|
||||
|
||||
SessionFactoryImplementor sf = (SessionFactoryImplementor)
|
||||
final SessionFactoryImplementor sf = (SessionFactoryImplementor)
|
||||
SessionFactoryRegistry.INSTANCE.getSessionFactory( sessionFactoryUuid );
|
||||
return (SessionImplementor) sf.openSession();
|
||||
}
|
||||
|
||||
protected Boolean readIndexExistence(final Object index) {
|
||||
if ( !initialized ) {
|
||||
Boolean extraLazyExistenceCheck = withTemporarySessionIfNeeded(
|
||||
final Boolean extraLazyExistenceCheck = withTemporarySessionIfNeeded(
|
||||
new LazyInitializationWork<Boolean>() {
|
||||
@Override
|
||||
public Boolean doWork() {
|
||||
CollectionEntry entry = session.getPersistenceContext().getCollectionEntry( AbstractPersistentCollection.this );
|
||||
CollectionPersister persister = entry.getLoadedPersister();
|
||||
final CollectionEntry entry = session.getPersistenceContext().getCollectionEntry( AbstractPersistentCollection.this );
|
||||
final CollectionPersister persister = entry.getLoadedPersister();
|
||||
if ( persister.isExtraLazy() ) {
|
||||
if ( hasQueuedOperations() ) {
|
||||
session.flush();
|
||||
|
@ -290,12 +316,12 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
|
|||
|
||||
protected Boolean readElementExistence(final Object element) {
|
||||
if ( !initialized ) {
|
||||
Boolean extraLazyExistenceCheck = withTemporarySessionIfNeeded(
|
||||
final Boolean extraLazyExistenceCheck = withTemporarySessionIfNeeded(
|
||||
new LazyInitializationWork<Boolean>() {
|
||||
@Override
|
||||
public Boolean doWork() {
|
||||
CollectionEntry entry = session.getPersistenceContext().getCollectionEntry( AbstractPersistentCollection.this );
|
||||
CollectionPersister persister = entry.getLoadedPersister();
|
||||
final CollectionEntry entry = session.getPersistenceContext().getCollectionEntry( AbstractPersistentCollection.this );
|
||||
final CollectionPersister persister = entry.getLoadedPersister();
|
||||
if ( persister.isExtraLazy() ) {
|
||||
if ( hasQueuedOperations() ) {
|
||||
session.flush();
|
||||
|
@ -326,8 +352,8 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
|
|||
|
||||
@Override
|
||||
public Object doWork() {
|
||||
CollectionEntry entry = session.getPersistenceContext().getCollectionEntry( AbstractPersistentCollection.this );
|
||||
CollectionPersister persister = entry.getLoadedPersister();
|
||||
final CollectionEntry entry = session.getPersistenceContext().getCollectionEntry( AbstractPersistentCollection.this );
|
||||
final CollectionPersister persister = entry.getLoadedPersister();
|
||||
isExtraLazy = persister.isExtraLazy();
|
||||
if ( isExtraLazy ) {
|
||||
if ( hasQueuedOperations() ) {
|
||||
|
@ -342,7 +368,7 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
|
|||
}
|
||||
}
|
||||
|
||||
ExtraLazyElementByIndexReader reader = new ExtraLazyElementByIndexReader();
|
||||
final ExtraLazyElementByIndexReader reader = new ExtraLazyElementByIndexReader();
|
||||
//noinspection unchecked
|
||||
withTemporarySessionIfNeeded( reader );
|
||||
if ( reader.isExtraLazy ) {
|
||||
|
@ -358,9 +384,9 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
|
|||
}
|
||||
|
||||
private boolean isConnectedToSession() {
|
||||
return session != null &&
|
||||
session.isOpen() &&
|
||||
session.getPersistenceContext().containsCollection( this );
|
||||
return session != null
|
||||
&& session.isOpen()
|
||||
&& session.getPersistenceContext().containsCollection( this );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -377,9 +403,9 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
|
|||
*/
|
||||
@SuppressWarnings({"JavaDoc"})
|
||||
protected boolean isOperationQueueEnabled() {
|
||||
return !initialized &&
|
||||
isConnectedToSession() &&
|
||||
isInverseCollection();
|
||||
return !initialized
|
||||
&& isConnectedToSession()
|
||||
&& isInverseCollection();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -389,9 +415,9 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
|
|||
*/
|
||||
@SuppressWarnings({"JavaDoc"})
|
||||
protected boolean isPutQueueEnabled() {
|
||||
return !initialized &&
|
||||
isConnectedToSession() &&
|
||||
isInverseOneToManyOrNoOrphanDelete();
|
||||
return !initialized
|
||||
&& isConnectedToSession()
|
||||
&& isInverseOneToManyOrNoOrphanDelete();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -401,9 +427,9 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
|
|||
*/
|
||||
@SuppressWarnings({"JavaDoc"})
|
||||
protected boolean isClearQueueEnabled() {
|
||||
return !initialized &&
|
||||
isConnectedToSession() &&
|
||||
isInverseCollectionNoOrphanDelete();
|
||||
return !initialized
|
||||
&& isConnectedToSession()
|
||||
&& isInverseCollectionNoOrphanDelete();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -411,7 +437,7 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
|
|||
*/
|
||||
@SuppressWarnings({"JavaDoc"})
|
||||
private boolean isInverseCollection() {
|
||||
CollectionEntry ce = session.getPersistenceContext().getCollectionEntry( this );
|
||||
final CollectionEntry ce = session.getPersistenceContext().getCollectionEntry( this );
|
||||
return ce != null && ce.getLoadedPersister().isInverse();
|
||||
}
|
||||
|
||||
|
@ -421,8 +447,9 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
|
|||
*/
|
||||
@SuppressWarnings({"JavaDoc"})
|
||||
private boolean isInverseCollectionNoOrphanDelete() {
|
||||
CollectionEntry ce = session.getPersistenceContext().getCollectionEntry( this );
|
||||
return ce != null &&
|
||||
final CollectionEntry ce = session.getPersistenceContext().getCollectionEntry( this );
|
||||
return ce != null
|
||||
&&
|
||||
ce.getLoadedPersister().isInverse() &&
|
||||
!ce.getLoadedPersister().hasOrphanDelete();
|
||||
}
|
||||
|
@ -433,11 +460,10 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
|
|||
*/
|
||||
@SuppressWarnings({"JavaDoc"})
|
||||
private boolean isInverseOneToManyOrNoOrphanDelete() {
|
||||
CollectionEntry ce = session.getPersistenceContext().getCollectionEntry( this );
|
||||
return ce != null && ce.getLoadedPersister().isInverse() && (
|
||||
ce.getLoadedPersister().isOneToMany() ||
|
||||
!ce.getLoadedPersister().hasOrphanDelete()
|
||||
);
|
||||
final CollectionEntry ce = session.getPersistenceContext().getCollectionEntry( this );
|
||||
return ce != null
|
||||
&& ce.getLoadedPersister().isInverse()
|
||||
&& ( ce.getLoadedPersister().isOneToMany() || !ce.getLoadedPersister().hasOrphanDelete() );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -449,7 +475,8 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
|
|||
operationQueue = new ArrayList<DelayedOperation>( 10 );
|
||||
}
|
||||
operationQueue.add( operation );
|
||||
dirty = true; //needed so that we remove this collection from the second-level cache
|
||||
//needed so that we remove this collection from the second-level cache
|
||||
dirty = true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -462,59 +489,38 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* After flushing, re-init snapshot state.
|
||||
*/
|
||||
@Override
|
||||
public void setSnapshot(Serializable key, String role, Serializable snapshot) {
|
||||
this.key = key;
|
||||
this.role = role;
|
||||
this.storedSnapshot = snapshot;
|
||||
}
|
||||
|
||||
/**
|
||||
* After flushing, clear any "queued" additions, since the
|
||||
* database state is now synchronized with the memory state.
|
||||
*/
|
||||
@Override
|
||||
public void postAction() {
|
||||
operationQueue = null;
|
||||
cachedSize = -1;
|
||||
clearDirty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Not called by Hibernate, but used by non-JDK serialization,
|
||||
* eg. SOAP libraries.
|
||||
*/
|
||||
public AbstractPersistentCollection() {
|
||||
}
|
||||
|
||||
protected AbstractPersistentCollection(SessionImplementor session) {
|
||||
this.session = session;
|
||||
}
|
||||
|
||||
/**
|
||||
* return the user-visible collection (or array) instance
|
||||
*/
|
||||
@Override
|
||||
public Object getValue() {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called just before reading any rows from the JDBC result set
|
||||
*/
|
||||
@Override
|
||||
public void beginRead() {
|
||||
// override on some subclasses
|
||||
initializing = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called after reading all rows from the JDBC result set
|
||||
*/
|
||||
@Override
|
||||
public boolean endRead() {
|
||||
//override on some subclasses
|
||||
return afterInitialize();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean afterInitialize() {
|
||||
setInitialized();
|
||||
//do this bit after setting initialized to true or it will recurse
|
||||
|
@ -579,19 +585,12 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
|
|||
this.directlyAccessible = directlyAccessible;
|
||||
}
|
||||
|
||||
/**
|
||||
* Could the application possibly have a direct reference to
|
||||
* the underlying collection implementation?
|
||||
*/
|
||||
@Override
|
||||
public boolean isDirectlyAccessible() {
|
||||
return directlyAccessible;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disassociate this collection from the given session.
|
||||
*
|
||||
* @return true if this was currently associated with the given session
|
||||
*/
|
||||
@Override
|
||||
public final boolean unsetSession(SessionImplementor currentSession) {
|
||||
prepareForPossibleSpecialSpecjInitialization();
|
||||
if ( currentSession == this.session ) {
|
||||
|
@ -619,21 +618,14 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* Associate the collection with the given session.
|
||||
*
|
||||
* @return false if the collection was already associated with the session
|
||||
*
|
||||
* @throws HibernateException if the collection was already associated
|
||||
* with another open session
|
||||
*/
|
||||
@Override
|
||||
public final boolean setCurrentSession(SessionImplementor session) throws HibernateException {
|
||||
if ( session == this.session ) {
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
if ( isConnectedToSession() ) {
|
||||
CollectionEntry ce = session.getPersistenceContext().getCollectionEntry( this );
|
||||
final CollectionEntry ce = session.getPersistenceContext().getCollectionEntry( this );
|
||||
if ( ce == null ) {
|
||||
throw new HibernateException(
|
||||
"Illegal attempt to associate a collection with two open sessions"
|
||||
|
@ -656,17 +648,12 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Do we need to completely recreate this collection when it changes?
|
||||
*/
|
||||
@Override
|
||||
public boolean needsRecreate(CollectionPersister persister) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* To be called internally by the session, forcing
|
||||
* immediate initialization.
|
||||
*/
|
||||
@Override
|
||||
public final void forceInitialization() throws HibernateException {
|
||||
if ( !initialized ) {
|
||||
if ( initializing ) {
|
||||
|
@ -691,40 +678,38 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
|
|||
return session.getPersistenceContext().getSnapshot( this );
|
||||
}
|
||||
|
||||
/**
|
||||
* Is this instance initialized?
|
||||
*/
|
||||
@Override
|
||||
public final boolean wasInitialized() {
|
||||
return initialized;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRowUpdatePossible() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Does this instance have any "queued" additions?
|
||||
*/
|
||||
@Override
|
||||
public final boolean hasQueuedOperations() {
|
||||
return operationQueue != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterate the "queued" additions
|
||||
*/
|
||||
@Override
|
||||
public final Iterator queuedAdditionIterator() {
|
||||
if ( hasQueuedOperations() ) {
|
||||
return new Iterator() {
|
||||
int i = 0;
|
||||
private int index;
|
||||
|
||||
@Override
|
||||
public Object next() {
|
||||
return operationQueue.get( i++ ).getAddedInstance();
|
||||
return operationQueue.get( index++ ).getAddedInstance();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return i < operationQueue.size();
|
||||
return index < operationQueue.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
@ -735,14 +720,12 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterate the "queued" additions
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings({"unchecked"})
|
||||
public final Collection getQueuedOrphans(String entityName) {
|
||||
if ( hasQueuedOperations() ) {
|
||||
Collection additions = new ArrayList( operationQueue.size() );
|
||||
Collection removals = new ArrayList( operationQueue.size() );
|
||||
final Collection additions = new ArrayList( operationQueue.size() );
|
||||
final Collection removals = new ArrayList( operationQueue.size() );
|
||||
for ( DelayedOperation operation : operationQueue ) {
|
||||
additions.add( operation.getAddedInstance() );
|
||||
removals.add( operation.getOrphan() );
|
||||
|
@ -754,28 +737,22 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called before inserting rows, to ensure that any surrogate keys
|
||||
* are fully generated
|
||||
*/
|
||||
@Override
|
||||
public void preInsert(CollectionPersister persister) throws HibernateException {
|
||||
}
|
||||
|
||||
/**
|
||||
* Called after inserting a row, to fetch the natively generated id
|
||||
*/
|
||||
@Override
|
||||
public void afterRowInsert(CollectionPersister persister, Object entry, int i) throws HibernateException {
|
||||
}
|
||||
|
||||
/**
|
||||
* get all "orphaned" elements
|
||||
*/
|
||||
@Override
|
||||
public abstract Collection getOrphans(Serializable snapshot, String entityName) throws HibernateException;
|
||||
|
||||
/**
|
||||
* Get the current session
|
||||
* Get the session currently associated with this collection.
|
||||
*
|
||||
* @return The session
|
||||
*/
|
||||
@SuppressWarnings({"JavaDoc"})
|
||||
public final SessionImplementor getSession() {
|
||||
return session;
|
||||
}
|
||||
|
@ -787,19 +764,21 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
|
|||
this.itr = itr;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return itr.hasNext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object next() {
|
||||
return itr.next();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
write();
|
||||
itr.remove();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected final class ListIteratorProxy implements ListIterator {
|
||||
|
@ -809,47 +788,55 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
|
|||
this.itr = itr;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({"unchecked"})
|
||||
public void add(Object o) {
|
||||
write();
|
||||
itr.add( o );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return itr.hasNext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPrevious() {
|
||||
return itr.hasPrevious();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object next() {
|
||||
return itr.next();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int nextIndex() {
|
||||
return itr.nextIndex();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object previous() {
|
||||
return itr.previous();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int previousIndex() {
|
||||
return itr.previousIndex();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
write();
|
||||
itr.remove();
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({"unchecked"})
|
||||
public void set(Object o) {
|
||||
write();
|
||||
itr.set( o );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected class SetProxy implements java.util.Set {
|
||||
|
@ -859,67 +846,82 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
|
|||
this.set = set;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({"unchecked"})
|
||||
public boolean add(Object o) {
|
||||
write();
|
||||
return set.add( o );
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({"unchecked"})
|
||||
public boolean addAll(Collection c) {
|
||||
write();
|
||||
return set.addAll( c );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
write();
|
||||
set.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(Object o) {
|
||||
return set.contains( o );
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public boolean containsAll(Collection c) {
|
||||
return set.containsAll( c );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return set.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator iterator() {
|
||||
return new IteratorProxy( set.iterator() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean remove(Object o) {
|
||||
write();
|
||||
return set.remove( o );
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public boolean removeAll(Collection c) {
|
||||
write();
|
||||
return set.removeAll( c );
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public boolean retainAll(Collection c) {
|
||||
write();
|
||||
return set.retainAll( c );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return set.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object[] toArray() {
|
||||
return set.toArray();
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({"unchecked"})
|
||||
public Object[] toArray(Object[] array) {
|
||||
return set.toArray( array );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected final class ListProxy implements java.util.List {
|
||||
|
@ -969,6 +971,7 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
|
|||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public boolean containsAll(Collection c) {
|
||||
return list.containsAll( c );
|
||||
}
|
||||
|
@ -1021,12 +1024,14 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
|
|||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public boolean removeAll(Collection c) {
|
||||
write();
|
||||
return list.removeAll( c );
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public boolean retainAll(Collection c) {
|
||||
write();
|
||||
return list.retainAll( c );
|
||||
|
@ -1087,29 +1092,31 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
|
|||
|
||||
// short-circuit(s)
|
||||
if ( currentElements.size() == 0 ) {
|
||||
return oldElements; // no new elements, the old list contains only Orphans
|
||||
// no new elements, the old list contains only Orphans
|
||||
return oldElements;
|
||||
}
|
||||
if ( oldElements.size() == 0 ) {
|
||||
return oldElements; // no old elements, so no Orphans neither
|
||||
// no old elements, so no Orphans neither
|
||||
return oldElements;
|
||||
}
|
||||
|
||||
final EntityPersister entityPersister = session.getFactory().getEntityPersister( entityName );
|
||||
final Type idType = entityPersister.getIdentifierType();
|
||||
|
||||
// create the collection holding the Orphans
|
||||
Collection res = new ArrayList();
|
||||
final Collection res = new ArrayList();
|
||||
|
||||
// collect EntityIdentifier(s) of the *current* elements - add them into a HashSet for fast access
|
||||
java.util.Set currentIds = new HashSet();
|
||||
java.util.Set currentSaving = new IdentitySet();
|
||||
final java.util.Set currentIds = new HashSet();
|
||||
final java.util.Set currentSaving = new IdentitySet();
|
||||
for ( Object current : currentElements ) {
|
||||
if ( current != null && ForeignKeys.isNotTransient( entityName, current, null, session ) ) {
|
||||
EntityEntry ee = session.getPersistenceContext().getEntry( current );
|
||||
final EntityEntry ee = session.getPersistenceContext().getEntry( current );
|
||||
if ( ee != null && ee.getStatus() == Status.SAVING ) {
|
||||
currentSaving.add( current );
|
||||
}
|
||||
else {
|
||||
Serializable currentId = ForeignKeys.getEntityIdentifierIfNotUnsaved(
|
||||
final Serializable currentId = ForeignKeys.getEntityIdentifierIfNotUnsaved(
|
||||
entityName,
|
||||
current,
|
||||
session
|
||||
|
@ -1122,7 +1129,7 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
|
|||
// iterate over the *old* list
|
||||
for ( Object old : oldElements ) {
|
||||
if ( !currentSaving.contains( old ) ) {
|
||||
Serializable oldId = ForeignKeys.getEntityIdentifierIfNotUnsaved( entityName, old, session );
|
||||
final Serializable oldId = ForeignKeys.getEntityIdentifierIfNotUnsaved( entityName, old, session );
|
||||
if ( !currentIds.contains( new TypedValue( idType, oldId ) ) ) {
|
||||
res.add( old );
|
||||
}
|
||||
|
@ -1132,20 +1139,28 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
|
|||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes entity entries that have an equal identifier with the incoming entity instance
|
||||
*
|
||||
* @param list The list containing the entity instances
|
||||
* @param entityInstance The entity instance to match elements.
|
||||
* @param entityName The entity name
|
||||
* @param session The session
|
||||
*/
|
||||
public static void identityRemove(
|
||||
Collection list,
|
||||
Object object,
|
||||
Object entityInstance,
|
||||
String entityName,
|
||||
SessionImplementor session) throws HibernateException {
|
||||
SessionImplementor session) {
|
||||
|
||||
if ( object != null && ForeignKeys.isNotTransient( entityName, object, null, session ) ) {
|
||||
if ( entityInstance != null && ForeignKeys.isNotTransient( entityName, entityInstance, null, session ) ) {
|
||||
final EntityPersister entityPersister = session.getFactory().getEntityPersister( entityName );
|
||||
Type idType = entityPersister.getIdentifierType();
|
||||
final Type idType = entityPersister.getIdentifierType();
|
||||
|
||||
Serializable idOfCurrent = ForeignKeys.getEntityIdentifierIfNotUnsaved( entityName, object, session );
|
||||
Iterator itr = list.iterator();
|
||||
final Serializable idOfCurrent = ForeignKeys.getEntityIdentifierIfNotUnsaved( entityName, entityInstance, session );
|
||||
final Iterator itr = list.iterator();
|
||||
while ( itr.hasNext() ) {
|
||||
Serializable idOfOld = ForeignKeys.getEntityIdentifierIfNotUnsaved( entityName, itr.next(), session );
|
||||
final Serializable idOfOld = ForeignKeys.getEntityIdentifierIfNotUnsaved( entityName, itr.next(), session );
|
||||
if ( idType.isEqual( idOfCurrent, idOfOld, session.getFactory() ) ) {
|
||||
itr.remove();
|
||||
break;
|
||||
|
@ -1155,14 +1170,17 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getIdentifier(Object entry, int i) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getOwner() {
|
||||
return owner;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOwner(Object owner) {
|
||||
this.owner = owner;
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@ import java.sql.ResultSet;
|
|||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
@ -48,27 +49,52 @@ import org.hibernate.type.Type;
|
|||
* @author Gavin King
|
||||
*/
|
||||
public class PersistentArrayHolder extends AbstractPersistentCollection {
|
||||
protected Object array;
|
||||
private static final CoreMessageLogger LOG = Logger.getMessageLogger(
|
||||
CoreMessageLogger.class,
|
||||
PersistentArrayHolder.class.getName()
|
||||
);
|
||||
|
||||
private static final CoreMessageLogger LOG = Logger.getMessageLogger(CoreMessageLogger.class, PersistentArrayHolder.class.getName());
|
||||
protected Object array;
|
||||
|
||||
//just to help out during the load (ugly, i know)
|
||||
private transient Class elementClass;
|
||||
private transient java.util.List tempList;
|
||||
|
||||
/**
|
||||
* Constructs a PersistentCollection instance for holding an array.
|
||||
*
|
||||
* @param session The session
|
||||
* @param array The array (the persistent "collection").
|
||||
*/
|
||||
public PersistentArrayHolder(SessionImplementor session, Object array) {
|
||||
super(session);
|
||||
super( session );
|
||||
this.array = array;
|
||||
setInitialized();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a PersistentCollection instance for holding an array.
|
||||
*
|
||||
* @param session The session
|
||||
* @param persister The persister for the array
|
||||
*/
|
||||
public PersistentArrayHolder(SessionImplementor session, CollectionPersister persister) {
|
||||
super( session );
|
||||
elementClass = persister.getElementClass();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public Serializable getSnapshot(CollectionPersister persister) throws HibernateException {
|
||||
int length = /*(array==null) ? tempList.size() :*/ Array.getLength(array);
|
||||
Serializable result = (Serializable) Array.newInstance( persister.getElementClass(), length );
|
||||
// final int length = (array==null) ? tempList.size() : Array.getLength( array );
|
||||
final int length = Array.getLength( array );
|
||||
final Serializable result = (Serializable) Array.newInstance( persister.getElementClass(), length );
|
||||
for ( int i=0; i<length; i++ ) {
|
||||
Object elt = /*(array==null) ? tempList.get(i) :*/ Array.get(array, i);
|
||||
// final Object elt = (array==null) ? tempList.get( i ) : Array.get( array, i );
|
||||
final Object elt = Array.get( array, i );
|
||||
try {
|
||||
Array.set( result, i, persister.getElementType().deepCopy(elt, persister.getFactory()) );
|
||||
Array.set( result, i, persister.getElementType().deepCopy( elt, persister.getFactory() ) );
|
||||
}
|
||||
catch (IllegalArgumentException iae) {
|
||||
LOG.invalidArrayElementType( iae.getMessage() );
|
||||
|
@ -78,70 +104,84 @@ public class PersistentArrayHolder extends AbstractPersistentCollection {
|
|||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSnapshotEmpty(Serializable snapshot) {
|
||||
return Array.getLength( snapshot ) == 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection getOrphans(Serializable snapshot, String entityName) throws HibernateException {
|
||||
Object[] sn = (Object[]) snapshot;
|
||||
Object[] arr = (Object[]) array;
|
||||
ArrayList result = new ArrayList();
|
||||
for (int i=0; i<sn.length; i++) result.add( sn[i] );
|
||||
for (int i=0; i<sn.length; i++) identityRemove( result, arr[i], entityName, getSession() );
|
||||
final Object[] sn = (Object[]) snapshot;
|
||||
final Object[] arr = (Object[]) array;
|
||||
final ArrayList result = new ArrayList();
|
||||
Collections.addAll( result, sn );
|
||||
for ( int i=0; i<sn.length; i++ ) {
|
||||
identityRemove( result, arr[i], entityName, getSession() );
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public PersistentArrayHolder(SessionImplementor session, CollectionPersister persister) throws HibernateException {
|
||||
super(session);
|
||||
elementClass = persister.getElementClass();
|
||||
}
|
||||
|
||||
@SuppressWarnings("UnusedDeclaration")
|
||||
public Object getArray() {
|
||||
return array;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isWrapper(Object collection) {
|
||||
return array==collection;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equalsSnapshot(CollectionPersister persister) throws HibernateException {
|
||||
Type elementType = persister.getElementType();
|
||||
Serializable snapshot = getSnapshot();
|
||||
int xlen = Array.getLength(snapshot);
|
||||
if ( xlen!= Array.getLength(array) ) return false;
|
||||
final Type elementType = persister.getElementType();
|
||||
final Serializable snapshot = getSnapshot();
|
||||
final int xlen = Array.getLength( snapshot );
|
||||
if ( xlen!= Array.getLength( array ) ) {
|
||||
return false;
|
||||
}
|
||||
for ( int i=0; i<xlen; i++) {
|
||||
if ( elementType.isDirty( Array.get(snapshot, i), Array.get(array, i), getSession() ) ) return false;
|
||||
if ( elementType.isDirty( Array.get( snapshot, i ), Array.get( array, i ), getSession() ) ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an iterator over the array elements
|
||||
*
|
||||
* @return The iterator
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public Iterator elements() {
|
||||
//if (array==null) return tempList.iterator();
|
||||
int length = Array.getLength(array);
|
||||
java.util.List list = new ArrayList(length);
|
||||
for (int i=0; i<length; i++) {
|
||||
list.add( Array.get(array, i) );
|
||||
final int length = Array.getLength( array );
|
||||
final java.util.List list = new ArrayList( length );
|
||||
for ( int i=0; i<length; i++ ) {
|
||||
list.add( Array.get( array, i ) );
|
||||
}
|
||||
return list.iterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean empty() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Object readFrom(ResultSet rs, CollectionPersister persister, CollectionAliases descriptor, Object owner)
|
||||
throws HibernateException, SQLException {
|
||||
|
||||
Object element = persister.readElement( rs, owner, descriptor.getSuffixedElementAliases(), getSession() );
|
||||
int index = (Integer) persister.readIndex( rs, descriptor.getSuffixedIndexAliases(), getSession() );
|
||||
final Object element = persister.readElement( rs, owner, descriptor.getSuffixedElementAliases(), getSession() );
|
||||
final int index = (Integer) persister.readIndex( rs, descriptor.getSuffixedIndexAliases(), getSession() );
|
||||
for ( int i = tempList.size(); i<=index; i++) {
|
||||
tempList.add(i, null);
|
||||
tempList.add( i, null );
|
||||
}
|
||||
tempList.set(index, element);
|
||||
tempList.set( index, element );
|
||||
return element;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Iterator entries(CollectionPersister persister) {
|
||||
return elements();
|
||||
}
|
||||
|
@ -151,17 +191,19 @@ public class PersistentArrayHolder extends AbstractPersistentCollection {
|
|||
super.beginRead();
|
||||
tempList = new ArrayList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean endRead() {
|
||||
setInitialized();
|
||||
array = Array.newInstance( elementClass, tempList.size() );
|
||||
for ( int i=0; i<tempList.size(); i++) {
|
||||
Array.set(array, i, tempList.get(i) );
|
||||
for ( int i=0; i<tempList.size(); i++ ) {
|
||||
Array.set( array, i, tempList.get( i ) );
|
||||
}
|
||||
tempList=null;
|
||||
tempList = null;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beforeInitialize(CollectionPersister persister, int anticipatedSize) {
|
||||
//if (tempList==null) throw new UnsupportedOperationException("Can't lazily initialize arrays");
|
||||
}
|
||||
|
@ -171,10 +213,10 @@ public class PersistentArrayHolder extends AbstractPersistentCollection {
|
|||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initializeFromCache(CollectionPersister persister, Serializable disassembled, Object owner)
|
||||
throws HibernateException {
|
||||
Serializable[] cached = (Serializable[]) disassembled;
|
||||
|
||||
final Serializable[] cached = (Serializable[]) disassembled;
|
||||
array = Array.newInstance( persister.getElementClass(), cached.length );
|
||||
|
||||
for ( int i=0; i<cached.length; i++ ) {
|
||||
|
@ -182,21 +224,15 @@ public class PersistentArrayHolder extends AbstractPersistentCollection {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Serializable disassemble(CollectionPersister persister) throws HibernateException {
|
||||
int length = Array.getLength(array);
|
||||
Serializable[] result = new Serializable[length];
|
||||
final int length = Array.getLength( array );
|
||||
final Serializable[] result = new Serializable[length];
|
||||
for ( int i=0; i<length; i++ ) {
|
||||
result[i] = persister.getElementType().disassemble( Array.get(array,i), getSession(), null );
|
||||
result[i] = persister.getElementType().disassemble( Array.get( array,i ), getSession(), null );
|
||||
}
|
||||
|
||||
/*int length = tempList.size();
|
||||
Serializable[] result = new Serializable[length];
|
||||
for ( int i=0; i<length; i++ ) {
|
||||
result[i] = persister.getElementType().disassemble( tempList.get(i), session );
|
||||
}*/
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -204,52 +240,63 @@ public class PersistentArrayHolder extends AbstractPersistentCollection {
|
|||
return array;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator getDeletes(CollectionPersister persister, boolean indexIsFormula) throws HibernateException {
|
||||
java.util.List<Integer> deletes = new ArrayList<Integer>();
|
||||
Serializable sn = getSnapshot();
|
||||
int snSize = Array.getLength(sn);
|
||||
int arraySize = Array.getLength(array);
|
||||
final java.util.List<Integer> deletes = new ArrayList<Integer>();
|
||||
final Serializable sn = getSnapshot();
|
||||
final int snSize = Array.getLength( sn );
|
||||
final int arraySize = Array.getLength( array );
|
||||
int end;
|
||||
if ( snSize > arraySize ) {
|
||||
for ( int i=arraySize; i<snSize; i++ ) deletes.add( i );
|
||||
for ( int i=arraySize; i<snSize; i++ ) {
|
||||
deletes.add( i );
|
||||
}
|
||||
end = arraySize;
|
||||
}
|
||||
else {
|
||||
end = snSize;
|
||||
}
|
||||
for ( int i=0; i<end; i++ ) {
|
||||
if ( Array.get(array, i)==null && Array.get(sn, i)!=null ) deletes.add( i );
|
||||
if ( Array.get( array, i ) == null && Array.get( sn, i ) != null ) {
|
||||
deletes.add( i );
|
||||
}
|
||||
}
|
||||
return deletes.iterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean needsInserting(Object entry, int i, Type elemType) throws HibernateException {
|
||||
Serializable sn = getSnapshot();
|
||||
return Array.get(array, i)!=null && ( i >= Array.getLength(sn) || Array.get(sn, i)==null );
|
||||
final Serializable sn = getSnapshot();
|
||||
return Array.get( array, i ) != null && ( i >= Array.getLength( sn ) || Array.get( sn, i ) == null );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean needsUpdating(Object entry, int i, Type elemType) throws HibernateException {
|
||||
Serializable sn = getSnapshot();
|
||||
return i<Array.getLength(sn) &&
|
||||
Array.get(sn, i)!=null &&
|
||||
Array.get(array, i)!=null &&
|
||||
elemType.isDirty( Array.get(array, i), Array.get(sn, i), getSession() );
|
||||
final Serializable sn = getSnapshot();
|
||||
return i < Array.getLength( sn )
|
||||
&& Array.get( sn, i ) != null
|
||||
&& Array.get( array, i ) != null
|
||||
&& elemType.isDirty( Array.get( array, i ), Array.get( sn, i ), getSession() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getIndex(Object entry, int i, CollectionPersister persister) {
|
||||
return i;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getElement(Object entry) {
|
||||
return entry;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getSnapshotElement(Object entry, int i) {
|
||||
Serializable sn = getSnapshot();
|
||||
return Array.get(sn, i);
|
||||
final Serializable sn = getSnapshot();
|
||||
return Array.get( sn, i );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean entryExists(Object entry, int i) {
|
||||
return entry!=null;
|
||||
return entry != null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,59 +50,86 @@ public class PersistentBag extends AbstractPersistentCollection implements List
|
|||
|
||||
protected List bag;
|
||||
|
||||
public PersistentBag(SessionImplementor session) {
|
||||
super(session);
|
||||
/**
|
||||
* Constructs a PersistentBag. Needed for SOAP libraries, etc
|
||||
*/
|
||||
@SuppressWarnings("UnusedDeclaration")
|
||||
public PersistentBag() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a PersistentBag
|
||||
*
|
||||
* @param session The session
|
||||
*/
|
||||
public PersistentBag(SessionImplementor session) {
|
||||
super( session );
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a PersistentBag
|
||||
*
|
||||
* @param session The session
|
||||
* @param coll The base elements.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public PersistentBag(SessionImplementor session, Collection coll) {
|
||||
super(session);
|
||||
if (coll instanceof List) {
|
||||
super( session );
|
||||
if ( coll instanceof List ) {
|
||||
bag = (List) coll;
|
||||
}
|
||||
else {
|
||||
bag = new ArrayList();
|
||||
Iterator iter = coll.iterator();
|
||||
while ( iter.hasNext() ) {
|
||||
bag.add( iter.next() );
|
||||
for ( Object element : coll ) {
|
||||
bag.add( element );
|
||||
}
|
||||
}
|
||||
setInitialized();
|
||||
setDirectlyAccessible(true);
|
||||
setDirectlyAccessible( true );
|
||||
}
|
||||
|
||||
public PersistentBag() {} //needed for SOAP libraries, etc
|
||||
|
||||
@Override
|
||||
public boolean isWrapper(Object collection) {
|
||||
return bag==collection;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean empty() {
|
||||
return bag.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator entries(CollectionPersister persister) {
|
||||
return bag.iterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Object readFrom(ResultSet rs, CollectionPersister persister, CollectionAliases descriptor, Object owner)
|
||||
throws HibernateException, SQLException {
|
||||
// note that if we load this collection from a cartesian product
|
||||
// the multiplicity would be broken ... so use an idbag instead
|
||||
Object element = persister.readElement( rs, owner, descriptor.getSuffixedElementAliases(), getSession() ) ;
|
||||
if (element!=null) bag.add(element);
|
||||
final Object element = persister.readElement( rs, owner, descriptor.getSuffixedElementAliases(), getSession() ) ;
|
||||
if ( element != null ) {
|
||||
bag.add( element );
|
||||
}
|
||||
return element;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beforeInitialize(CollectionPersister persister, int anticipatedSize) {
|
||||
this.bag = ( List ) persister.getCollectionType().instantiate( anticipatedSize );
|
||||
this.bag = (List) persister.getCollectionType().instantiate( anticipatedSize );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equalsSnapshot(CollectionPersister persister) throws HibernateException {
|
||||
Type elementType = persister.getElementType();
|
||||
List sn = (List) getSnapshot();
|
||||
if ( sn.size()!=bag.size() ) return false;
|
||||
final Type elementType = persister.getElementType();
|
||||
final List sn = (List) getSnapshot();
|
||||
if ( sn.size() != bag.size() ) {
|
||||
return false;
|
||||
}
|
||||
for ( Object elt : bag ) {
|
||||
final boolean unequal = countOccurrences( elt, bag, elementType )
|
||||
!= countOccurrences( elt, sn, elementType );
|
||||
final boolean unequal = countOccurrences( elt, bag, elementType ) != countOccurrences( elt, sn, elementType );
|
||||
if ( unequal ) {
|
||||
return false;
|
||||
}
|
||||
|
@ -110,60 +137,67 @@ public class PersistentBag extends AbstractPersistentCollection implements List
|
|||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSnapshotEmpty(Serializable snapshot) {
|
||||
return ( (Collection) snapshot ).isEmpty();
|
||||
}
|
||||
|
||||
private int countOccurrences(Object element, List list, Type elementType)
|
||||
throws HibernateException {
|
||||
Iterator iter = list.iterator();
|
||||
int result=0;
|
||||
final Iterator iter = list.iterator();
|
||||
int result = 0;
|
||||
while ( iter.hasNext() ) {
|
||||
if ( elementType.isSame( element, iter.next() ) ) result++;
|
||||
if ( elementType.isSame( element, iter.next() ) ) {
|
||||
result++;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Serializable getSnapshot(CollectionPersister persister)
|
||||
throws HibernateException {
|
||||
ArrayList clonedList = new ArrayList( bag.size() );
|
||||
Iterator iter = bag.iterator();
|
||||
while ( iter.hasNext() ) {
|
||||
clonedList.add( persister.getElementType().deepCopy( iter.next(), persister.getFactory() ) );
|
||||
final ArrayList clonedList = new ArrayList( bag.size() );
|
||||
for ( Object item : bag ) {
|
||||
clonedList.add( persister.getElementType().deepCopy( item, persister.getFactory() ) );
|
||||
}
|
||||
return clonedList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection getOrphans(Serializable snapshot, String entityName) throws HibernateException {
|
||||
List sn = (List) snapshot;
|
||||
final List sn = (List) snapshot;
|
||||
return getOrphans( sn, bag, entityName, getSession() );
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Serializable disassemble(CollectionPersister persister)
|
||||
throws HibernateException {
|
||||
|
||||
int length = bag.size();
|
||||
Serializable[] result = new Serializable[length];
|
||||
final int length = bag.size();
|
||||
final Serializable[] result = new Serializable[length];
|
||||
for ( int i=0; i<length; i++ ) {
|
||||
result[i] = persister.getElementType().disassemble( bag.get(i), getSession(), null );
|
||||
result[i] = persister.getElementType().disassemble( bag.get( i ), getSession(), null );
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public void initializeFromCache(CollectionPersister persister, Serializable disassembled, Object owner)
|
||||
throws HibernateException {
|
||||
Serializable[] array = (Serializable[]) disassembled;
|
||||
int size = array.length;
|
||||
final Serializable[] array = (Serializable[]) disassembled;
|
||||
final int size = array.length;
|
||||
beforeInitialize( persister, size );
|
||||
for ( int i = 0; i < size; i++ ) {
|
||||
Object element = persister.getElementType().assemble( array[i], getSession(), owner );
|
||||
if ( element!=null ) {
|
||||
for ( Serializable item : array ) {
|
||||
final Object element = persister.getElementType().assemble( item, getSession(), owner );
|
||||
if ( element != null ) {
|
||||
bag.add( element );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean needsRecreate(CollectionPersister persister) {
|
||||
return !persister.isOneToMany();
|
||||
}
|
||||
|
@ -177,18 +211,19 @@ public class PersistentBag extends AbstractPersistentCollection implements List
|
|||
// Anyway, here we implement <set> semantics for a
|
||||
// <one-to-many> <bag>!
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Iterator getDeletes(CollectionPersister persister, boolean indexIsFormula) throws HibernateException {
|
||||
//if ( !persister.isOneToMany() ) throw new AssertionFailure("Not implemented for Bags");
|
||||
Type elementType = persister.getElementType();
|
||||
ArrayList deletes = new ArrayList();
|
||||
List sn = (List) getSnapshot();
|
||||
Iterator olditer = sn.iterator();
|
||||
final Type elementType = persister.getElementType();
|
||||
final ArrayList deletes = new ArrayList();
|
||||
final List sn = (List) getSnapshot();
|
||||
final Iterator olditer = sn.iterator();
|
||||
int i=0;
|
||||
while ( olditer.hasNext() ) {
|
||||
Object old = olditer.next();
|
||||
Iterator newiter = bag.iterator();
|
||||
final Object old = olditer.next();
|
||||
final Iterator newiter = bag.iterator();
|
||||
boolean found = false;
|
||||
if ( bag.size()>i && elementType.isSame( old, bag.get(i++) ) ) {
|
||||
if ( bag.size()>i && elementType.isSame( old, bag.get( i++ ) ) ) {
|
||||
//a shortcut if its location didn't change!
|
||||
found = true;
|
||||
}
|
||||
|
@ -202,104 +237,91 @@ public class PersistentBag extends AbstractPersistentCollection implements List
|
|||
}
|
||||
}
|
||||
}
|
||||
if (!found) deletes.add(old);
|
||||
if ( !found ) {
|
||||
deletes.add( old );
|
||||
}
|
||||
}
|
||||
return deletes.iterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean needsInserting(Object entry, int i, Type elemType) throws HibernateException {
|
||||
//if ( !persister.isOneToMany() ) throw new AssertionFailure("Not implemented for Bags");
|
||||
List sn = (List) getSnapshot();
|
||||
if ( sn.size()>i && elemType.isSame( sn.get(i), entry ) ) {
|
||||
final List sn = (List) getSnapshot();
|
||||
if ( sn.size() > i && elemType.isSame( sn.get( i ), entry ) ) {
|
||||
//a shortcut if its location didn't change!
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
//search for it
|
||||
//note that this code is incorrect for other than one-to-many
|
||||
Iterator olditer = sn.iterator();
|
||||
while ( olditer.hasNext() ) {
|
||||
Object old = olditer.next();
|
||||
if ( elemType.isSame( old, entry ) ) return false;
|
||||
for ( Object old : sn ) {
|
||||
if ( elemType.isSame( old, entry ) ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRowUpdatePossible() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean needsUpdating(Object entry, int i, Type elemType) {
|
||||
//if ( !persister.isOneToMany() ) throw new AssertionFailure("Not implemented for Bags");
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.util.Collection#size()
|
||||
*/
|
||||
@Override
|
||||
public int size() {
|
||||
return readSize() ? getCachedSize() : bag.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.util.Collection#isEmpty()
|
||||
*/
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return readSize() ? getCachedSize()==0 : bag.isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.util.Collection#contains(Object)
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("UnnecessaryUnboxing")
|
||||
public boolean contains(Object object) {
|
||||
Boolean exists = readElementExistence(object);
|
||||
return exists==null ?
|
||||
bag.contains(object) :
|
||||
exists.booleanValue();
|
||||
final Boolean exists = readElementExistence( object );
|
||||
return exists == null ? bag.contains( object ) : exists.booleanValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.util.Collection#iterator()
|
||||
*/
|
||||
@Override
|
||||
public Iterator iterator() {
|
||||
read();
|
||||
return new IteratorProxy( bag.iterator() );
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.util.Collection#toArray()
|
||||
*/
|
||||
@Override
|
||||
public Object[] toArray() {
|
||||
read();
|
||||
return bag.toArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.util.Collection#toArray(Object[])
|
||||
*/
|
||||
@Override
|
||||
public Object[] toArray(Object[] a) {
|
||||
read();
|
||||
return bag.toArray(a);
|
||||
return bag.toArray( a );
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.util.Collection#add(Object)
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public boolean add(Object object) {
|
||||
if ( !isOperationQueueEnabled() ) {
|
||||
write();
|
||||
return bag.add(object);
|
||||
return bag.add( object );
|
||||
}
|
||||
else {
|
||||
queueOperation( new SimpleAdd(object) );
|
||||
queueOperation( new SimpleAdd( object ) );
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.util.Collection#remove(Object)
|
||||
*/
|
||||
@Override
|
||||
public boolean remove(Object o) {
|
||||
initialize( true );
|
||||
if ( bag.remove( o ) ) {
|
||||
|
@ -311,35 +333,33 @@ public class PersistentBag extends AbstractPersistentCollection implements List
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.util.Collection#containsAll(Collection)
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public boolean containsAll(Collection c) {
|
||||
read();
|
||||
return bag.containsAll(c);
|
||||
return bag.containsAll( c );
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.util.Collection#addAll(Collection)
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public boolean addAll(Collection values) {
|
||||
if ( values.size()==0 ) return false;
|
||||
if ( values.size()==0 ) {
|
||||
return false;
|
||||
}
|
||||
if ( !isOperationQueueEnabled() ) {
|
||||
write();
|
||||
return bag.addAll(values);
|
||||
return bag.addAll( values );
|
||||
}
|
||||
else {
|
||||
Iterator iter = values.iterator();
|
||||
while ( iter.hasNext() ) {
|
||||
queueOperation( new SimpleAdd( iter.next() ) );
|
||||
for ( Object value : values ) {
|
||||
queueOperation( new SimpleAdd( value ) );
|
||||
}
|
||||
return values.size()>0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.util.Collection#removeAll(Collection)
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public boolean removeAll(Collection c) {
|
||||
if ( c.size()>0 ) {
|
||||
initialize( true );
|
||||
|
@ -356,9 +376,8 @@ public class PersistentBag extends AbstractPersistentCollection implements List
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.util.Collection#retainAll(Collection)
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public boolean retainAll(Collection c) {
|
||||
initialize( true );
|
||||
if ( bag.retainAll( c ) ) {
|
||||
|
@ -370,9 +389,8 @@ public class PersistentBag extends AbstractPersistentCollection implements List
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.util.Collection#clear()
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public void clear() {
|
||||
if ( isClearQueueEnabled() ) {
|
||||
queueOperation( new Clear() );
|
||||
|
@ -386,160 +404,161 @@ public class PersistentBag extends AbstractPersistentCollection implements List
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getIndex(Object entry, int i, CollectionPersister persister) {
|
||||
throw new UnsupportedOperationException("Bags don't have indexes");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getElement(Object entry) {
|
||||
return entry;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getSnapshotElement(Object entry, int i) {
|
||||
List sn = (List) getSnapshot();
|
||||
return sn.get(i);
|
||||
final List sn = (List) getSnapshot();
|
||||
return sn.get( i );
|
||||
}
|
||||
|
||||
/**
|
||||
* Count how many times the given object occurs in the elements
|
||||
*
|
||||
* @param o The object to check
|
||||
*
|
||||
* @return The number of occurences.
|
||||
*/
|
||||
@SuppressWarnings("UnusedDeclaration")
|
||||
public int occurrences(Object o) {
|
||||
read();
|
||||
Iterator iter = bag.iterator();
|
||||
int result=0;
|
||||
while ( iter.hasNext() ) {
|
||||
if ( o.equals( iter.next() ) ) result++;
|
||||
final Iterator itr = bag.iterator();
|
||||
int result = 0;
|
||||
while ( itr.hasNext() ) {
|
||||
if ( o.equals( itr.next() ) ) {
|
||||
result++;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// List OPERATIONS:
|
||||
|
||||
/**
|
||||
* @see java.util.List#add(int, Object)
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public void add(int i, Object o) {
|
||||
write();
|
||||
bag.add(i, o);
|
||||
bag.add( i, o );
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.util.List#addAll(int, Collection)
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public boolean addAll(int i, Collection c) {
|
||||
if ( c.size()>0 ) {
|
||||
if ( c.size() > 0 ) {
|
||||
write();
|
||||
return bag.addAll(i, c);
|
||||
return bag.addAll( i, c );
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.util.List#get(int)
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Object get(int i) {
|
||||
read();
|
||||
return bag.get(i);
|
||||
return bag.get( i );
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.util.List#indexOf(Object)
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public int indexOf(Object o) {
|
||||
read();
|
||||
return bag.indexOf(o);
|
||||
return bag.indexOf( o );
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.util.List#lastIndexOf(Object)
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public int lastIndexOf(Object o) {
|
||||
read();
|
||||
return bag.lastIndexOf(o);
|
||||
return bag.lastIndexOf( o );
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.util.List#listIterator()
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public ListIterator listIterator() {
|
||||
read();
|
||||
return new ListIteratorProxy( bag.listIterator() );
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.util.List#listIterator(int)
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public ListIterator listIterator(int i) {
|
||||
read();
|
||||
return new ListIteratorProxy( bag.listIterator(i) );
|
||||
return new ListIteratorProxy( bag.listIterator( i ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.util.List#remove(int)
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Object remove(int i) {
|
||||
write();
|
||||
return bag.remove(i);
|
||||
return bag.remove( i );
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.util.List#set(int, Object)
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Object set(int i, Object o) {
|
||||
write();
|
||||
return bag.set(i, o);
|
||||
return bag.set( i, o );
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.util.List#subList(int, int)
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public List subList(int start, int end) {
|
||||
read();
|
||||
return new ListProxy( bag.subList(start, end) );
|
||||
return new ListProxy( bag.subList( start, end ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean entryExists(Object entry, int i) {
|
||||
return entry!=null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
read();
|
||||
return bag.toString();
|
||||
}
|
||||
|
||||
/*public boolean equals(Object other) {
|
||||
read();
|
||||
return bag.equals(other);
|
||||
}
|
||||
|
||||
public int hashCode(Object other) {
|
||||
read();
|
||||
return bag.hashCode();
|
||||
}*/
|
||||
|
||||
public boolean entryExists(Object entry, int i) {
|
||||
return entry!=null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Bag does not respect the collection API and do an
|
||||
* JVM instance comparison to do the equals.
|
||||
* The semantic is broken not to have to initialize a
|
||||
* collection for a simple equals() operation.
|
||||
* @see java.lang.Object#equals(java.lang.Object)
|
||||
*
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
return super.equals(obj);
|
||||
return super.equals( obj );
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.lang.Object#hashCode()
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return super.hashCode();
|
||||
}
|
||||
|
||||
final class Clear implements DelayedOperation {
|
||||
@Override
|
||||
public void operate() {
|
||||
bag.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getAddedInstance() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getOrphan() {
|
||||
throw new UnsupportedOperationException("queued clear cannot be used with orphan delete");
|
||||
}
|
||||
|
@ -551,12 +570,19 @@ public class PersistentBag extends AbstractPersistentCollection implements List
|
|||
public SimpleAdd(Object value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public void operate() {
|
||||
bag.add(value);
|
||||
bag.add( value );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getAddedInstance() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getOrphan() {
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -53,37 +53,53 @@ import org.hibernate.type.Type;
|
|||
* @author Gavin King
|
||||
*/
|
||||
public class PersistentIdentifierBag extends AbstractPersistentCollection implements List {
|
||||
protected List<Object> values;
|
||||
protected Map<Integer, Object> identifiers;
|
||||
|
||||
protected List values; //element
|
||||
protected Map identifiers; //index -> id
|
||||
|
||||
public PersistentIdentifierBag(SessionImplementor session) {
|
||||
super(session);
|
||||
/**
|
||||
* Constructs a PersistentIdentifierBag. This form needed for SOAP libraries, etc
|
||||
*/
|
||||
@SuppressWarnings("UnusedDeclaration")
|
||||
public PersistentIdentifierBag() {
|
||||
}
|
||||
|
||||
public PersistentIdentifierBag() {} //needed for SOAP libraries, etc
|
||||
/**
|
||||
* Constructs a PersistentIdentifierBag.
|
||||
*
|
||||
* @param session The session
|
||||
*/
|
||||
public PersistentIdentifierBag(SessionImplementor session) {
|
||||
super( session );
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a PersistentIdentifierBag.
|
||||
*
|
||||
* @param session The session
|
||||
* @param coll The base elements
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public PersistentIdentifierBag(SessionImplementor session, Collection coll) {
|
||||
super(session);
|
||||
super( session );
|
||||
if (coll instanceof List) {
|
||||
values = (List) coll;
|
||||
values = (List<Object>) coll;
|
||||
}
|
||||
else {
|
||||
values = new ArrayList();
|
||||
Iterator iter = coll.iterator();
|
||||
while ( iter.hasNext() ) {
|
||||
values.add( iter.next() );
|
||||
values = new ArrayList<Object>();
|
||||
for ( Object element : coll ) {
|
||||
values.add( element );
|
||||
}
|
||||
}
|
||||
setInitialized();
|
||||
setDirectlyAccessible(true);
|
||||
identifiers = new HashMap();
|
||||
setDirectlyAccessible( true );
|
||||
identifiers = new HashMap<Integer, Object>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initializeFromCache(CollectionPersister persister, Serializable disassembled, Object owner)
|
||||
throws HibernateException {
|
||||
Serializable[] array = (Serializable[]) disassembled;
|
||||
int size = array.length;
|
||||
final Serializable[] array = (Serializable[]) disassembled;
|
||||
final int size = array.length;
|
||||
beforeInitialize( persister, size );
|
||||
for ( int i = 0; i < size; i+=2 ) {
|
||||
identifiers.put(
|
||||
|
@ -94,20 +110,24 @@ public class PersistentIdentifierBag extends AbstractPersistentCollection implem
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getIdentifier(Object entry, int i) {
|
||||
return identifiers.get( i );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isWrapper(Object collection) {
|
||||
return values==collection;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean add(Object o) {
|
||||
write();
|
||||
values.add(o);
|
||||
values.add( o );
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
initialize( true );
|
||||
if ( ! values.isEmpty() || ! identifiers.isEmpty() ) {
|
||||
|
@ -117,31 +137,36 @@ public class PersistentIdentifierBag extends AbstractPersistentCollection implem
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(Object o) {
|
||||
read();
|
||||
return values.contains(o);
|
||||
return values.contains( o );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsAll(Collection c) {
|
||||
read();
|
||||
return values.containsAll(c);
|
||||
return values.containsAll( c );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return readSize() ? getCachedSize()==0 : values.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator iterator() {
|
||||
read();
|
||||
return new IteratorProxy( values.iterator() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean remove(Object o) {
|
||||
initialize( true );
|
||||
int index = values.indexOf(o);
|
||||
if (index>=0) {
|
||||
beforeRemove(index);
|
||||
values.remove(index);
|
||||
final int index = values.indexOf( o );
|
||||
if ( index >= 0 ) {
|
||||
beforeRemove( index );
|
||||
values.remove( index );
|
||||
dirty();
|
||||
return true;
|
||||
}
|
||||
|
@ -150,12 +175,14 @@ public class PersistentIdentifierBag extends AbstractPersistentCollection implem
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeAll(Collection c) {
|
||||
if ( c.size() > 0 ) {
|
||||
boolean result = false;
|
||||
Iterator iter = c.iterator();
|
||||
while ( iter.hasNext() ) {
|
||||
if ( remove( iter.next() ) ) result=true;
|
||||
for ( Object element : c ) {
|
||||
if ( remove( element ) ) {
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -164,6 +191,7 @@ public class PersistentIdentifierBag extends AbstractPersistentCollection implem
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean retainAll(Collection c) {
|
||||
initialize( true );
|
||||
if ( values.retainAll( c ) ) {
|
||||
|
@ -175,168 +203,210 @@ public class PersistentIdentifierBag extends AbstractPersistentCollection implem
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return readSize() ? getCachedSize() : values.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object[] toArray() {
|
||||
read();
|
||||
return values.toArray();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object[] toArray(Object[] a) {
|
||||
read();
|
||||
return values.toArray(a);
|
||||
return values.toArray( a );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beforeInitialize(CollectionPersister persister, int anticipatedSize) {
|
||||
identifiers = anticipatedSize <= 0 ? new HashMap() : new HashMap( anticipatedSize + 1 + (int)( anticipatedSize * .75f ), .75f );
|
||||
values = anticipatedSize <= 0 ? new ArrayList() : new ArrayList( anticipatedSize );
|
||||
identifiers = anticipatedSize <= 0
|
||||
? new HashMap<Integer, Object>()
|
||||
: new HashMap<Integer, Object>( anticipatedSize + 1 + (int)( anticipatedSize * .75f ), .75f );
|
||||
values = anticipatedSize <= 0
|
||||
? new ArrayList<Object>()
|
||||
: new ArrayList<Object>( anticipatedSize );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Serializable disassemble(CollectionPersister persister)
|
||||
throws HibernateException {
|
||||
Serializable[] result = new Serializable[ values.size() * 2 ];
|
||||
int i=0;
|
||||
for (int j=0; j< values.size(); j++) {
|
||||
Object value = values.get(j);
|
||||
final Serializable[] result = new Serializable[ values.size() * 2 ];
|
||||
int i = 0;
|
||||
for ( int j=0; j< values.size(); j++ ) {
|
||||
final Object value = values.get( j );
|
||||
result[i++] = persister.getIdentifierType().disassemble( identifiers.get( j ), getSession(), null );
|
||||
result[i++] = persister.getElementType().disassemble( value, getSession(), null );
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean empty() {
|
||||
return values.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator entries(CollectionPersister persister) {
|
||||
return values.iterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean entryExists(Object entry, int i) {
|
||||
return entry!=null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equalsSnapshot(CollectionPersister persister) throws HibernateException {
|
||||
Type elementType = persister.getElementType();
|
||||
Map snap = (Map) getSnapshot();
|
||||
if ( snap.size()!= values.size() ) return false;
|
||||
final Type elementType = persister.getElementType();
|
||||
final Map snap = (Map) getSnapshot();
|
||||
if ( snap.size()!= values.size() ) {
|
||||
return false;
|
||||
}
|
||||
for ( int i=0; i<values.size(); i++ ) {
|
||||
Object value = values.get(i);
|
||||
Object id = identifiers.get( i );
|
||||
if (id==null) return false;
|
||||
Object old = snap.get(id);
|
||||
if ( elementType.isDirty( old, value, getSession() ) ) return false;
|
||||
final Object value = values.get( i );
|
||||
final Object id = identifiers.get( i );
|
||||
if ( id == null ) {
|
||||
return false;
|
||||
}
|
||||
final Object old = snap.get( id );
|
||||
if ( elementType.isDirty( old, value, getSession() ) ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSnapshotEmpty(Serializable snapshot) {
|
||||
return ( (Map) snapshot ).isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Iterator getDeletes(CollectionPersister persister, boolean indexIsFormula) throws HibernateException {
|
||||
Map snap = (Map) getSnapshot();
|
||||
List deletes = new ArrayList( snap.keySet() );
|
||||
final Map snap = (Map) getSnapshot();
|
||||
final List deletes = new ArrayList( snap.keySet() );
|
||||
for ( int i=0; i<values.size(); i++ ) {
|
||||
if ( values.get(i)!=null ) deletes.remove( identifiers.get( i ) );
|
||||
if ( values.get( i ) != null ) {
|
||||
deletes.remove( identifiers.get( i ) );
|
||||
}
|
||||
}
|
||||
return deletes.iterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getIndex(Object entry, int i, CollectionPersister persister) {
|
||||
throw new UnsupportedOperationException("Bags don't have indexes");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getElement(Object entry) {
|
||||
return entry;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getSnapshotElement(Object entry, int i) {
|
||||
Map snap = (Map) getSnapshot();
|
||||
Object id = identifiers.get( i );
|
||||
return snap.get(id);
|
||||
final Map snap = (Map) getSnapshot();
|
||||
final Object id = identifiers.get( i );
|
||||
return snap.get( id );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean needsInserting(Object entry, int i, Type elemType)
|
||||
throws HibernateException {
|
||||
|
||||
Map snap = (Map) getSnapshot();
|
||||
Object id = identifiers.get( i );
|
||||
return entry!=null && ( id==null || snap.get(id)==null );
|
||||
final Map snap = (Map) getSnapshot();
|
||||
final Object id = identifiers.get( i );
|
||||
return entry != null
|
||||
&& ( id==null || snap.get( id )==null );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean needsUpdating(Object entry, int i, Type elemType) throws HibernateException {
|
||||
|
||||
if (entry==null) return false;
|
||||
Map snap = (Map) getSnapshot();
|
||||
Object id = identifiers.get( i );
|
||||
if (id==null) return false;
|
||||
Object old = snap.get(id);
|
||||
return old!=null && elemType.isDirty( old, entry, getSession() );
|
||||
if ( entry == null ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final Map snap = (Map) getSnapshot();
|
||||
final Object id = identifiers.get( i );
|
||||
if ( id == null ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final Object old = snap.get( id );
|
||||
return old != null && elemType.isDirty( old, entry, getSession() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object readFrom(
|
||||
ResultSet rs,
|
||||
CollectionPersister persister,
|
||||
CollectionAliases descriptor,
|
||||
Object owner)
|
||||
throws HibernateException, SQLException {
|
||||
|
||||
Object element = persister.readElement( rs, owner, descriptor.getSuffixedElementAliases(), getSession() );
|
||||
Object old = identifiers.put(
|
||||
Object owner) throws HibernateException, SQLException {
|
||||
final Object element = persister.readElement( rs, owner, descriptor.getSuffixedElementAliases(), getSession() );
|
||||
final Object old = identifiers.put(
|
||||
values.size(),
|
||||
persister.readIdentifier( rs, descriptor.getSuffixedIdentifierAlias(), getSession() )
|
||||
);
|
||||
if ( old==null ) values.add(element); //maintain correct duplication if loaded in a cartesian product
|
||||
|
||||
if ( old == null ) {
|
||||
//maintain correct duplication if loaded in a cartesian product
|
||||
values.add( element );
|
||||
}
|
||||
return element;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Serializable getSnapshot(CollectionPersister persister) throws HibernateException {
|
||||
HashMap map = new HashMap( values.size() );
|
||||
Iterator iter = values.iterator();
|
||||
final HashMap map = new HashMap( values.size() );
|
||||
final Iterator iter = values.iterator();
|
||||
int i=0;
|
||||
while ( iter.hasNext() ) {
|
||||
Object value = iter.next();
|
||||
final Object value = iter.next();
|
||||
map.put(
|
||||
identifiers.get( i++ ),
|
||||
persister.getElementType().deepCopy(value, persister.getFactory())
|
||||
persister.getElementType().deepCopy( value, persister.getFactory() )
|
||||
);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection getOrphans(Serializable snapshot, String entityName) throws HibernateException {
|
||||
Map sn = (Map) snapshot;
|
||||
final Map sn = (Map) snapshot;
|
||||
return getOrphans( sn.values(), values, entityName, getSession() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preInsert(CollectionPersister persister) throws HibernateException {
|
||||
Iterator iter = values.iterator();
|
||||
int i=0;
|
||||
while ( iter.hasNext() ) {
|
||||
Object entry = iter.next();
|
||||
Integer loc = i++;
|
||||
if ( !identifiers.containsKey(loc) ) { //TODO: native ids
|
||||
Serializable id = persister.getIdentifierGenerator().generate( getSession(), entry );
|
||||
identifiers.put(loc, id);
|
||||
final Iterator itr = values.iterator();
|
||||
int i = 0;
|
||||
while ( itr.hasNext() ) {
|
||||
final Object entry = itr.next();
|
||||
final Integer loc = i++;
|
||||
if ( !identifiers.containsKey( loc ) ) {
|
||||
//TODO: native ids
|
||||
final Serializable id = persister.getIdentifierGenerator().generate( getSession(), entry );
|
||||
identifiers.put( loc, id );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add(int index, Object element) {
|
||||
write();
|
||||
beforeAdd(index);
|
||||
values.add(index, element);
|
||||
beforeAdd( index );
|
||||
values.add( index, element );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addAll(int index, Collection c) {
|
||||
if ( c.size() > 0 ) {
|
||||
Iterator iter = c.iterator();
|
||||
while ( iter.hasNext() ) {
|
||||
add( index++, iter.next() );
|
||||
for ( Object element : c ) {
|
||||
add( index++, element );
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -345,37 +415,42 @@ public class PersistentIdentifierBag extends AbstractPersistentCollection implem
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object get(int index) {
|
||||
read();
|
||||
return values.get(index);
|
||||
return values.get( index );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int indexOf(Object o) {
|
||||
read();
|
||||
return values.indexOf(o);
|
||||
return values.indexOf( o );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int lastIndexOf(Object o) {
|
||||
read();
|
||||
return values.lastIndexOf(o);
|
||||
return values.lastIndexOf( o );
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListIterator listIterator() {
|
||||
read();
|
||||
return new ListIteratorProxy( values.listIterator() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListIterator listIterator(int index) {
|
||||
read();
|
||||
return new ListIteratorProxy( values.listIterator(index) );
|
||||
return new ListIteratorProxy( values.listIterator( index ) );
|
||||
}
|
||||
|
||||
private void beforeRemove(int index) {
|
||||
Object removedId = identifiers.get( index );
|
||||
int last = values.size()-1;
|
||||
final Object removedId = identifiers.get( index );
|
||||
final int last = values.size()-1;
|
||||
for ( int i=index; i<last; i++ ) {
|
||||
Object id = identifiers.get( i+1 );
|
||||
if ( id==null ) {
|
||||
final Object id = identifiers.get( i+1 );
|
||||
if ( id == null ) {
|
||||
identifiers.remove( i );
|
||||
}
|
||||
else {
|
||||
|
@ -392,37 +467,41 @@ public class PersistentIdentifierBag extends AbstractPersistentCollection implem
|
|||
identifiers.remove( index );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object remove(int index) {
|
||||
write();
|
||||
beforeRemove(index);
|
||||
return values.remove(index);
|
||||
beforeRemove( index );
|
||||
return values.remove( index );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object set(int index, Object element) {
|
||||
write();
|
||||
return values.set(index, element);
|
||||
return values.set( index, element );
|
||||
}
|
||||
|
||||
@Override
|
||||
public List subList(int fromIndex, int toIndex) {
|
||||
read();
|
||||
return new ListProxy( values.subList(fromIndex, toIndex) );
|
||||
return new ListProxy( values.subList( fromIndex, toIndex ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addAll(Collection c) {
|
||||
if ( c.size()> 0 ) {
|
||||
write();
|
||||
return values.addAll(c);
|
||||
return values.addAll( c );
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterRowInsert(
|
||||
CollectionPersister persister,
|
||||
Object entry,
|
||||
int i)
|
||||
throws HibernateException {
|
||||
int i) throws HibernateException {
|
||||
//TODO: if we are using identity columns, fetch the identifier
|
||||
}
|
||||
|
||||
|
|
|
@ -48,12 +48,40 @@ import org.hibernate.type.Type;
|
|||
public class PersistentList extends AbstractPersistentCollection implements List {
|
||||
protected List list;
|
||||
|
||||
/**
|
||||
* Constructs a PersistentList. This form needed for SOAP libraries, etc
|
||||
*/
|
||||
public PersistentList() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a PersistentList.
|
||||
*
|
||||
* @param session The session
|
||||
*/
|
||||
public PersistentList(SessionImplementor session) {
|
||||
super( session );
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a PersistentList.
|
||||
*
|
||||
* @param session The session
|
||||
* @param list The raw list
|
||||
*/
|
||||
public PersistentList(SessionImplementor session, List list) {
|
||||
super( session );
|
||||
this.list = list;
|
||||
setInitialized();
|
||||
setDirectlyAccessible( true );
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings( {"unchecked"})
|
||||
public Serializable getSnapshot(CollectionPersister persister) throws HibernateException {
|
||||
ArrayList clonedList = new ArrayList( list.size() );
|
||||
final ArrayList clonedList = new ArrayList( list.size() );
|
||||
for ( Object element : list ) {
|
||||
Object deepCopy = persister.getElementType().deepCopy( element, persister.getFactory() );
|
||||
final Object deepCopy = persister.getElementType().deepCopy( element, persister.getFactory() );
|
||||
clonedList.add( deepCopy );
|
||||
}
|
||||
return clonedList;
|
||||
|
@ -61,19 +89,23 @@ public class PersistentList extends AbstractPersistentCollection implements List
|
|||
|
||||
@Override
|
||||
public Collection getOrphans(Serializable snapshot, String entityName) throws HibernateException {
|
||||
List sn = (List) snapshot;
|
||||
final List sn = (List) snapshot;
|
||||
return getOrphans( sn, list, entityName, getSession() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equalsSnapshot(CollectionPersister persister) throws HibernateException {
|
||||
Type elementType = persister.getElementType();
|
||||
List sn = (List) getSnapshot();
|
||||
if ( sn.size()!=this.list.size() ) return false;
|
||||
Iterator iter = list.iterator();
|
||||
Iterator sniter = sn.iterator();
|
||||
while ( iter.hasNext() ) {
|
||||
if ( elementType.isDirty( iter.next(), sniter.next(), getSession() ) ) return false;
|
||||
final Type elementType = persister.getElementType();
|
||||
final List sn = (List) getSnapshot();
|
||||
if ( sn.size()!=this.list.size() ) {
|
||||
return false;
|
||||
}
|
||||
final Iterator itr = list.iterator();
|
||||
final Iterator snapshotItr = sn.iterator();
|
||||
while ( itr.hasNext() ) {
|
||||
if ( elementType.isDirty( itr.next(), snapshotItr.next(), getSession() ) ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -83,94 +115,70 @@ public class PersistentList extends AbstractPersistentCollection implements List
|
|||
return ( (Collection) snapshot ).isEmpty();
|
||||
}
|
||||
|
||||
public PersistentList(SessionImplementor session) {
|
||||
super(session);
|
||||
}
|
||||
|
||||
public PersistentList(SessionImplementor session, List list) {
|
||||
super(session);
|
||||
this.list = list;
|
||||
setInitialized();
|
||||
setDirectlyAccessible(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beforeInitialize(CollectionPersister persister, int anticipatedSize) {
|
||||
this.list = ( List ) persister.getCollectionType().instantiate( anticipatedSize );
|
||||
this.list = (List) persister.getCollectionType().instantiate( anticipatedSize );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isWrapper(Object collection) {
|
||||
return list==collection;
|
||||
}
|
||||
|
||||
public PersistentList() {} //needed for SOAP libraries, etc
|
||||
|
||||
/**
|
||||
* @see java.util.List#size()
|
||||
*/
|
||||
@Override
|
||||
public int size() {
|
||||
return readSize() ? getCachedSize() : list.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.util.List#isEmpty()
|
||||
*/
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return readSize() ? getCachedSize()==0 : list.isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.util.List#contains(Object)
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("UnnecessaryUnboxing")
|
||||
public boolean contains(Object object) {
|
||||
Boolean exists = readElementExistence(object);
|
||||
return exists==null ?
|
||||
list.contains(object) :
|
||||
exists.booleanValue();
|
||||
final Boolean exists = readElementExistence( object );
|
||||
return exists == null
|
||||
? list.contains( object )
|
||||
: exists.booleanValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.util.List#iterator()
|
||||
*/
|
||||
@Override
|
||||
public Iterator iterator() {
|
||||
read();
|
||||
return new IteratorProxy( list.iterator() );
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.util.List#toArray()
|
||||
*/
|
||||
@Override
|
||||
public Object[] toArray() {
|
||||
read();
|
||||
return list.toArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.util.List#toArray(Object[])
|
||||
*/
|
||||
@Override
|
||||
public Object[] toArray(Object[] array) {
|
||||
read();
|
||||
return list.toArray(array);
|
||||
return list.toArray( array );
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.util.List#add(Object)
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public boolean add(Object object) {
|
||||
if ( !isOperationQueueEnabled() ) {
|
||||
write();
|
||||
return list.add(object);
|
||||
return list.add( object );
|
||||
}
|
||||
else {
|
||||
queueOperation( new SimpleAdd(object) );
|
||||
queueOperation( new SimpleAdd( object ) );
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.util.List#remove(Object)
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("UnnecessaryUnboxing")
|
||||
public boolean remove(Object value) {
|
||||
Boolean exists = isPutQueueEnabled() ? readElementExistence(value) : null;
|
||||
final Boolean exists = isPutQueueEnabled() ? readElementExistence( value ) : null;
|
||||
if ( exists == null ) {
|
||||
initialize( true );
|
||||
if ( list.remove( value ) ) {
|
||||
|
@ -182,7 +190,7 @@ public class PersistentList extends AbstractPersistentCollection implements List
|
|||
}
|
||||
}
|
||||
else if ( exists.booleanValue() ) {
|
||||
queueOperation( new SimpleRemove(value) );
|
||||
queueOperation( new SimpleRemove( value ) );
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
|
@ -190,50 +198,45 @@ public class PersistentList extends AbstractPersistentCollection implements List
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.util.List#containsAll(Collection)
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public boolean containsAll(Collection coll) {
|
||||
read();
|
||||
return list.containsAll(coll);
|
||||
return list.containsAll( coll );
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.util.List#addAll(Collection)
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public boolean addAll(Collection values) {
|
||||
if ( values.size()==0 ) {
|
||||
return false;
|
||||
}
|
||||
if ( !isOperationQueueEnabled() ) {
|
||||
write();
|
||||
return list.addAll(values);
|
||||
return list.addAll( values );
|
||||
}
|
||||
else {
|
||||
Iterator iter = values.iterator();
|
||||
while ( iter.hasNext() ) {
|
||||
queueOperation( new SimpleAdd( iter.next() ) );
|
||||
for ( Object value : values ) {
|
||||
queueOperation( new SimpleAdd( value ) );
|
||||
}
|
||||
return values.size()>0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.util.List#addAll(int, Collection)
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public boolean addAll(int index, Collection coll) {
|
||||
if ( coll.size()>0 ) {
|
||||
write();
|
||||
return list.addAll(index, coll);
|
||||
return list.addAll( index, coll );
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.util.List#removeAll(Collection)
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public boolean removeAll(Collection coll) {
|
||||
if ( coll.size()>0 ) {
|
||||
initialize( true );
|
||||
|
@ -250,9 +253,8 @@ public class PersistentList extends AbstractPersistentCollection implements List
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.util.List#retainAll(Collection)
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public boolean retainAll(Collection coll) {
|
||||
initialize( true );
|
||||
if ( list.retainAll( coll ) ) {
|
||||
|
@ -264,9 +266,8 @@ public class PersistentList extends AbstractPersistentCollection implements List
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.util.List#clear()
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public void clear() {
|
||||
if ( isClearQueueEnabled() ) {
|
||||
queueOperation( new Clear() );
|
||||
|
@ -280,166 +281,167 @@ public class PersistentList extends AbstractPersistentCollection implements List
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.util.List#get(int)
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Object get(int index) {
|
||||
if (index<0) {
|
||||
throw new ArrayIndexOutOfBoundsException("negative index");
|
||||
if ( index < 0 ) {
|
||||
throw new ArrayIndexOutOfBoundsException( "negative index" );
|
||||
}
|
||||
Object result = readElementByIndex( index );
|
||||
return result==UNKNOWN ? list.get(index) : result;
|
||||
final Object result = readElementByIndex( index );
|
||||
return result == UNKNOWN ? list.get( index ) : result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.util.List#set(int, Object)
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Object set(int index, Object value) {
|
||||
if (index<0) {
|
||||
throw new ArrayIndexOutOfBoundsException("negative index");
|
||||
}
|
||||
Object old = isPutQueueEnabled() ? readElementByIndex( index ) : UNKNOWN;
|
||||
|
||||
final Object old = isPutQueueEnabled() ? readElementByIndex( index ) : UNKNOWN;
|
||||
|
||||
if ( old==UNKNOWN ) {
|
||||
write();
|
||||
return list.set(index, value);
|
||||
return list.set( index, value );
|
||||
}
|
||||
else {
|
||||
queueOperation( new Set(index, value, old) );
|
||||
queueOperation( new Set( index, value, old ) );
|
||||
return old;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.util.List#add(int, Object)
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Object remove(int index) {
|
||||
if ( index < 0 ) {
|
||||
throw new ArrayIndexOutOfBoundsException( "negative index" );
|
||||
}
|
||||
final Object old = isPutQueueEnabled() ? readElementByIndex( index ) : UNKNOWN;
|
||||
if ( old == UNKNOWN ) {
|
||||
write();
|
||||
return list.remove( index );
|
||||
}
|
||||
else {
|
||||
queueOperation( new Remove( index, old ) );
|
||||
return old;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public void add(int index, Object value) {
|
||||
if (index<0) {
|
||||
throw new ArrayIndexOutOfBoundsException("negative index");
|
||||
if ( index < 0 ) {
|
||||
throw new ArrayIndexOutOfBoundsException( "negative index" );
|
||||
}
|
||||
if ( !isOperationQueueEnabled() ) {
|
||||
write();
|
||||
list.add(index, value);
|
||||
list.add( index, value );
|
||||
}
|
||||
else {
|
||||
queueOperation( new Add(index, value) );
|
||||
queueOperation( new Add( index, value ) );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.util.List#remove(int)
|
||||
*/
|
||||
public Object remove(int index) {
|
||||
if (index<0) {
|
||||
throw new ArrayIndexOutOfBoundsException("negative index");
|
||||
}
|
||||
Object old = isPutQueueEnabled() ?
|
||||
readElementByIndex( index ) : UNKNOWN;
|
||||
if ( old==UNKNOWN ) {
|
||||
write();
|
||||
return list.remove(index);
|
||||
}
|
||||
else {
|
||||
queueOperation( new Remove(index, old) );
|
||||
return old;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.util.List#indexOf(Object)
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public int indexOf(Object value) {
|
||||
read();
|
||||
return list.indexOf(value);
|
||||
return list.indexOf( value );
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.util.List#lastIndexOf(Object)
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public int lastIndexOf(Object value) {
|
||||
read();
|
||||
return list.lastIndexOf(value);
|
||||
return list.lastIndexOf( value );
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.util.List#listIterator()
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public ListIterator listIterator() {
|
||||
read();
|
||||
return new ListIteratorProxy( list.listIterator() );
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.util.List#listIterator(int)
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public ListIterator listIterator(int index) {
|
||||
read();
|
||||
return new ListIteratorProxy( list.listIterator(index) );
|
||||
return new ListIteratorProxy( list.listIterator( index ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.util.List#subList(int, int)
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public java.util.List subList(int from, int to) {
|
||||
read();
|
||||
return new ListProxy( list.subList(from, to) );
|
||||
return new ListProxy( list.subList( from, to ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean empty() {
|
||||
return list.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
read();
|
||||
return list.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Object readFrom(ResultSet rs, CollectionPersister persister, CollectionAliases descriptor, Object owner)
|
||||
throws HibernateException, SQLException {
|
||||
Object element = persister.readElement( rs, owner, descriptor.getSuffixedElementAliases(), getSession() ) ;
|
||||
int index = (Integer) persister.readIndex( rs, descriptor.getSuffixedIndexAliases(), getSession() );
|
||||
final Object element = persister.readElement( rs, owner, descriptor.getSuffixedElementAliases(), getSession() ) ;
|
||||
final int index = (Integer) persister.readIndex( rs, descriptor.getSuffixedIndexAliases(), getSession() );
|
||||
|
||||
//pad with nulls from the current last element up to the new index
|
||||
for ( int i = list.size(); i<=index; i++) {
|
||||
list.add(i, null);
|
||||
list.add( i, null );
|
||||
}
|
||||
|
||||
list.set(index, element);
|
||||
list.set( index, element );
|
||||
return element;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Iterator entries(CollectionPersister persister) {
|
||||
return list.iterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public void initializeFromCache(CollectionPersister persister, Serializable disassembled, Object owner)
|
||||
throws HibernateException {
|
||||
Serializable[] array = ( Serializable[] ) disassembled;
|
||||
int size = array.length;
|
||||
final Serializable[] array = (Serializable[]) disassembled;
|
||||
final int size = array.length;
|
||||
beforeInitialize( persister, size );
|
||||
for ( int i = 0; i < size; i++ ) {
|
||||
list.add( persister.getElementType().assemble( array[i], getSession(), owner ) );
|
||||
for ( Serializable arrayElement : array ) {
|
||||
list.add( persister.getElementType().assemble( arrayElement, getSession(), owner ) );
|
||||
}
|
||||
}
|
||||
|
||||
public Serializable disassemble(CollectionPersister persister)
|
||||
throws HibernateException {
|
||||
|
||||
int length = list.size();
|
||||
Serializable[] result = new Serializable[length];
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Serializable disassemble(CollectionPersister persister) throws HibernateException {
|
||||
final int length = list.size();
|
||||
final Serializable[] result = new Serializable[length];
|
||||
for ( int i=0; i<length; i++ ) {
|
||||
result[i] = persister.getElementType().disassemble( list.get(i), getSession(), null );
|
||||
result[i] = persister.getElementType().disassemble( list.get( i ), getSession(), null );
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Iterator getDeletes(CollectionPersister persister, boolean indexIsFormula) throws HibernateException {
|
||||
List deletes = new ArrayList();
|
||||
List sn = (List) getSnapshot();
|
||||
final List deletes = new ArrayList();
|
||||
final List sn = (List) getSnapshot();
|
||||
int end;
|
||||
if ( sn.size() > list.size() ) {
|
||||
for ( int i=list.size(); i<sn.size(); i++ ) {
|
||||
deletes.add( indexIsFormula ? sn.get(i) : i );
|
||||
deletes.add( indexIsFormula ? sn.get( i ) : i );
|
||||
}
|
||||
end = list.size();
|
||||
}
|
||||
|
@ -447,60 +449,78 @@ public class PersistentList extends AbstractPersistentCollection implements List
|
|||
end = sn.size();
|
||||
}
|
||||
for ( int i=0; i<end; i++ ) {
|
||||
if ( list.get(i)==null && sn.get(i)!=null ) {
|
||||
deletes.add( indexIsFormula ? sn.get(i) : i );
|
||||
final Object item = list.get( i );
|
||||
final Object snapshotItem = sn.get( i );
|
||||
if ( item == null && snapshotItem != null ) {
|
||||
deletes.add( indexIsFormula ? snapshotItem : i );
|
||||
}
|
||||
}
|
||||
return deletes.iterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean needsInserting(Object entry, int i, Type elemType) throws HibernateException {
|
||||
final List sn = (List) getSnapshot();
|
||||
return list.get(i)!=null && ( i >= sn.size() || sn.get(i)==null );
|
||||
return list.get( i ) != null && ( i >= sn.size() || sn.get( i ) == null );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean needsUpdating(Object entry, int i, Type elemType) throws HibernateException {
|
||||
final List sn = (List) getSnapshot();
|
||||
return i<sn.size() && sn.get(i)!=null && list.get(i)!=null &&
|
||||
elemType.isDirty( list.get(i), sn.get(i), getSession() );
|
||||
return i < sn.size()
|
||||
&& sn.get( i ) != null
|
||||
&& list.get( i ) != null
|
||||
&& elemType.isDirty( list.get( i ), sn.get( i ), getSession() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getIndex(Object entry, int i, CollectionPersister persister) {
|
||||
return i;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getElement(Object entry) {
|
||||
return entry;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getSnapshotElement(Object entry, int i) {
|
||||
final List sn = (List) getSnapshot();
|
||||
return sn.get(i);
|
||||
return sn.get( i );
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("EqualsWhichDoesntCheckParameterClass")
|
||||
public boolean equals(Object other) {
|
||||
read();
|
||||
return list.equals(other);
|
||||
return list.equals( other );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
read();
|
||||
return list.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean entryExists(Object entry, int i) {
|
||||
return entry!=null;
|
||||
}
|
||||
|
||||
final class Clear implements DelayedOperation {
|
||||
@Override
|
||||
public void operate() {
|
||||
list.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getAddedInstance() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getOrphan() {
|
||||
throw new UnsupportedOperationException("queued clear cannot be used with orphan delete");
|
||||
throw new UnsupportedOperationException( "queued clear cannot be used with orphan delete" );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -510,12 +530,19 @@ public class PersistentList extends AbstractPersistentCollection implements List
|
|||
public SimpleAdd(Object value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public void operate() {
|
||||
list.add(value);
|
||||
list.add( value );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getAddedInstance() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getOrphan() {
|
||||
return null;
|
||||
}
|
||||
|
@ -529,12 +556,19 @@ public class PersistentList extends AbstractPersistentCollection implements List
|
|||
this.index = index;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public void operate() {
|
||||
list.add(index, value);
|
||||
list.add( index, value );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getAddedInstance() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getOrphan() {
|
||||
return null;
|
||||
}
|
||||
|
@ -550,12 +584,19 @@ public class PersistentList extends AbstractPersistentCollection implements List
|
|||
this.value = value;
|
||||
this.old = old;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public void operate() {
|
||||
list.set(index, value);
|
||||
list.set( index, value );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getAddedInstance() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getOrphan() {
|
||||
return old;
|
||||
}
|
||||
|
@ -569,12 +610,19 @@ public class PersistentList extends AbstractPersistentCollection implements List
|
|||
this.index = index;
|
||||
this.old = old;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public void operate() {
|
||||
list.remove(index);
|
||||
list.remove( index );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getAddedInstance() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getOrphan() {
|
||||
return old;
|
||||
}
|
||||
|
@ -586,12 +634,19 @@ public class PersistentList extends AbstractPersistentCollection implements List
|
|||
public SimpleRemove(Object value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public void operate() {
|
||||
list.remove(value);
|
||||
list.remove( value );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getAddedInstance() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getOrphan() {
|
||||
return value;
|
||||
}
|
||||
|
|
|
@ -68,7 +68,7 @@ public class PersistentMap extends AbstractPersistentCollection implements Map {
|
|||
* @param session The session to which this map will belong.
|
||||
*/
|
||||
public PersistentMap(SessionImplementor session) {
|
||||
super(session);
|
||||
super( session );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -79,106 +79,108 @@ public class PersistentMap extends AbstractPersistentCollection implements Map {
|
|||
* @param map The underlying map data.
|
||||
*/
|
||||
public PersistentMap(SessionImplementor session, Map map) {
|
||||
super(session);
|
||||
super( session );
|
||||
this.map = map;
|
||||
setInitialized();
|
||||
setDirectlyAccessible(true);
|
||||
setDirectlyAccessible( true );
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings( {"unchecked"})
|
||||
public Serializable getSnapshot(CollectionPersister persister) throws HibernateException {
|
||||
HashMap clonedMap = new HashMap( map.size() );
|
||||
final HashMap clonedMap = new HashMap( map.size() );
|
||||
for ( Object o : map.entrySet() ) {
|
||||
Entry e = (Entry) o;
|
||||
final Entry e = (Entry) o;
|
||||
final Object copy = persister.getElementType().deepCopy( e.getValue(), persister.getFactory() );
|
||||
clonedMap.put( e.getKey(), copy );
|
||||
}
|
||||
return clonedMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection getOrphans(Serializable snapshot, String entityName) throws HibernateException {
|
||||
Map sn = (Map) snapshot;
|
||||
final Map sn = (Map) snapshot;
|
||||
return getOrphans( sn.values(), map.values(), entityName, getSession() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equalsSnapshot(CollectionPersister persister) throws HibernateException {
|
||||
Type elementType = persister.getElementType();
|
||||
Map xmap = (Map) getSnapshot();
|
||||
if ( xmap.size()!=this.map.size() ) return false;
|
||||
Iterator iter = map.entrySet().iterator();
|
||||
while ( iter.hasNext() ) {
|
||||
Map.Entry entry = (Map.Entry) iter.next();
|
||||
if ( elementType.isDirty( entry.getValue(), xmap.get( entry.getKey() ), getSession() ) ) return false;
|
||||
final Type elementType = persister.getElementType();
|
||||
final Map snapshotMap = (Map) getSnapshot();
|
||||
if ( snapshotMap.size() != this.map.size() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for ( Object o : map.entrySet() ) {
|
||||
final Entry entry = (Entry) o;
|
||||
if ( elementType.isDirty( entry.getValue(), snapshotMap.get( entry.getKey() ), getSession() ) ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSnapshotEmpty(Serializable snapshot) {
|
||||
return ( (Map) snapshot ).isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isWrapper(Object collection) {
|
||||
return map==collection;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beforeInitialize(CollectionPersister persister, int anticipatedSize) {
|
||||
this.map = ( Map ) persister.getCollectionType().instantiate( anticipatedSize );
|
||||
this.map = (Map) persister.getCollectionType().instantiate( anticipatedSize );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @see java.util.Map#size()
|
||||
*/
|
||||
@Override
|
||||
public int size() {
|
||||
return readSize() ? getCachedSize() : map.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.util.Map#isEmpty()
|
||||
*/
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return readSize() ? getCachedSize()==0 : map.isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.util.Map#containsKey(Object)
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("UnnecessaryUnboxing")
|
||||
public boolean containsKey(Object key) {
|
||||
Boolean exists = readIndexExistence(key);
|
||||
return exists==null ? map.containsKey(key) : exists.booleanValue();
|
||||
final Boolean exists = readIndexExistence( key );
|
||||
return exists == null ? map.containsKey( key ) : exists.booleanValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.util.Map#containsValue(Object)
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("UnnecessaryUnboxing")
|
||||
public boolean containsValue(Object value) {
|
||||
Boolean exists = readElementExistence(value);
|
||||
return exists==null ?
|
||||
map.containsValue(value) :
|
||||
exists.booleanValue();
|
||||
final Boolean exists = readElementExistence( value );
|
||||
return exists == null
|
||||
? map.containsValue( value )
|
||||
: exists.booleanValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.util.Map#get(Object)
|
||||
*/
|
||||
@Override
|
||||
public Object get(Object key) {
|
||||
Object result = readElementByIndex(key);
|
||||
return result==UNKNOWN ? map.get(key) : result;
|
||||
final Object result = readElementByIndex( key );
|
||||
return result == UNKNOWN
|
||||
? map.get( key )
|
||||
: result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.util.Map#put(Object, Object)
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Object put(Object key, Object value) {
|
||||
if ( isPutQueueEnabled() ) {
|
||||
Object old = readElementByIndex( key );
|
||||
final Object old = readElementByIndex( key );
|
||||
if ( old != UNKNOWN ) {
|
||||
queueOperation( new Put( key, value, old ) );
|
||||
return old;
|
||||
}
|
||||
}
|
||||
initialize( true );
|
||||
Object old = map.put( key, value );
|
||||
final Object old = map.put( key, value );
|
||||
// would be better to use the element-type to determine
|
||||
// whether the old and the new are equal here; the problem being
|
||||
// we do not necessarily have access to the element type in all
|
||||
|
@ -189,12 +191,11 @@ public class PersistentMap extends AbstractPersistentCollection implements Map {
|
|||
return old;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.util.Map#remove(Object)
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Object remove(Object key) {
|
||||
if ( isPutQueueEnabled() ) {
|
||||
Object old = readElementByIndex( key );
|
||||
final Object old = readElementByIndex( key );
|
||||
if ( old != UNKNOWN ) {
|
||||
queueOperation( new Remove( key, old ) );
|
||||
return old;
|
||||
|
@ -208,23 +209,20 @@ public class PersistentMap extends AbstractPersistentCollection implements Map {
|
|||
return map.remove( key );
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.util.Map#putAll(java.util.Map puts)
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public void putAll(Map puts) {
|
||||
if ( puts.size()>0 ) {
|
||||
if ( puts.size() > 0 ) {
|
||||
initialize( true );
|
||||
Iterator itr = puts.entrySet().iterator();
|
||||
while ( itr.hasNext() ) {
|
||||
Map.Entry entry = ( Entry ) itr.next();
|
||||
for ( Object o : puts.entrySet() ) {
|
||||
final Entry entry = (Entry) o;
|
||||
put( entry.getKey(), entry.getValue() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.util.Map#clear()
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public void clear() {
|
||||
if ( isClearQueueEnabled() ) {
|
||||
queueOperation( new Clear() );
|
||||
|
@ -238,34 +236,35 @@ public class PersistentMap extends AbstractPersistentCollection implements Map {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.util.Map#keySet()
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Set keySet() {
|
||||
read();
|
||||
return new SetProxy( map.keySet() );
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.util.Map#values()
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Collection values() {
|
||||
read();
|
||||
return new SetProxy( map.values() );
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.util.Map#entrySet()
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Set entrySet() {
|
||||
read();
|
||||
return new EntrySetProxy( map.entrySet() );
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public boolean empty() {
|
||||
return map.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public String toString() {
|
||||
read();
|
||||
return map.toString();
|
||||
|
@ -273,6 +272,8 @@ public class PersistentMap extends AbstractPersistentCollection implements Map {
|
|||
|
||||
private transient List<Object[]> loadingEntries;
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Object readFrom(
|
||||
ResultSet rs,
|
||||
CollectionPersister persister,
|
||||
|
@ -301,75 +302,129 @@ public class PersistentMap extends AbstractPersistentCollection implements Map {
|
|||
return super.endRead();
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Iterator entries(CollectionPersister persister) {
|
||||
return map.entrySet().iterator();
|
||||
}
|
||||
|
||||
/** a wrapper for Map.Entry sets */
|
||||
/**
|
||||
* a wrapper for Map.Entry sets
|
||||
*/
|
||||
class EntrySetProxy implements Set {
|
||||
private final Set set;
|
||||
EntrySetProxy(Set set) {
|
||||
this.set=set;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public boolean add(Object entry) {
|
||||
//write(); -- doesn't
|
||||
return set.add(entry);
|
||||
return set.add( entry );
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public boolean addAll(Collection entries) {
|
||||
//write(); -- doesn't
|
||||
return set.addAll(entries);
|
||||
return set.addAll( entries );
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public void clear() {
|
||||
write();
|
||||
set.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public boolean contains(Object entry) {
|
||||
return set.contains(entry);
|
||||
return set.contains( entry );
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public boolean containsAll(Collection entries) {
|
||||
return set.containsAll(entries);
|
||||
return set.containsAll( entries );
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public boolean isEmpty() {
|
||||
return set.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Iterator iterator() {
|
||||
return new EntryIteratorProxy( set.iterator() );
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public boolean remove(Object entry) {
|
||||
write();
|
||||
return set.remove(entry);
|
||||
return set.remove( entry );
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public boolean removeAll(Collection entries) {
|
||||
write();
|
||||
return set.removeAll(entries);
|
||||
return set.removeAll( entries );
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public boolean retainAll(Collection entries) {
|
||||
write();
|
||||
return set.retainAll(entries);
|
||||
return set.retainAll( entries );
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public int size() {
|
||||
return set.size();
|
||||
}
|
||||
|
||||
// amazingly, these two will work because AbstractCollection
|
||||
// uses iterator() to fill the array
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Object[] toArray() {
|
||||
return set.toArray();
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Object[] toArray(Object[] array) {
|
||||
return set.toArray(array);
|
||||
return set.toArray( array );
|
||||
}
|
||||
}
|
||||
|
||||
final class EntryIteratorProxy implements Iterator {
|
||||
private final Iterator iter;
|
||||
EntryIteratorProxy(Iterator iter) {
|
||||
this.iter=iter;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public boolean hasNext() {
|
||||
return iter.hasNext();
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Object next() {
|
||||
return new MapEntryProxy( (Map.Entry) iter.next() );
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public void remove() {
|
||||
write();
|
||||
iter.remove();
|
||||
|
@ -381,21 +436,46 @@ public class PersistentMap extends AbstractPersistentCollection implements Map {
|
|||
MapEntryProxy( Map.Entry me ) {
|
||||
this.me = me;
|
||||
}
|
||||
public Object getKey() { return me.getKey(); }
|
||||
public Object getValue() { return me.getValue(); }
|
||||
public boolean equals(Object o) { return me.equals(o); }
|
||||
public int hashCode() { return me.hashCode(); }
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Object getKey() {
|
||||
return me.getKey();
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Object getValue() {
|
||||
return me.getValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({"unchecked", "EqualsWhichDoesntCheckParameterClass"})
|
||||
public boolean equals(Object o) {
|
||||
return me.equals( o );
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public int hashCode() {
|
||||
return me.hashCode();
|
||||
}
|
||||
|
||||
// finally, what it's all about...
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Object setValue(Object value) {
|
||||
write();
|
||||
return me.setValue(value);
|
||||
return me.setValue( value );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public void initializeFromCache(CollectionPersister persister, Serializable disassembled, Object owner)
|
||||
throws HibernateException {
|
||||
Serializable[] array = ( Serializable[] ) disassembled;
|
||||
int size = array.length;
|
||||
final Serializable[] array = (Serializable[]) disassembled;
|
||||
final int size = array.length;
|
||||
beforeInitialize( persister, size );
|
||||
for ( int i = 0; i < size; i+=2 ) {
|
||||
map.put(
|
||||
|
@ -405,13 +485,14 @@ public class PersistentMap extends AbstractPersistentCollection implements Map {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Serializable disassemble(CollectionPersister persister) throws HibernateException {
|
||||
|
||||
Serializable[] result = new Serializable[ map.size() * 2 ];
|
||||
Iterator iter = map.entrySet().iterator();
|
||||
final Serializable[] result = new Serializable[ map.size() * 2 ];
|
||||
final Iterator itr = map.entrySet().iterator();
|
||||
int i=0;
|
||||
while ( iter.hasNext() ) {
|
||||
Map.Entry e = (Map.Entry) iter.next();
|
||||
while ( itr.hasNext() ) {
|
||||
final Map.Entry e = (Map.Entry) itr.next();
|
||||
result[i++] = persister.getIndexType().disassemble( e.getKey(), getSession(), null );
|
||||
result[i++] = persister.getElementType().disassemble( e.getValue(), getSession(), null );
|
||||
}
|
||||
|
@ -419,74 +500,92 @@ public class PersistentMap extends AbstractPersistentCollection implements Map {
|
|||
|
||||
}
|
||||
|
||||
public Iterator getDeletes(CollectionPersister persister, boolean indexIsFormula)
|
||||
throws HibernateException {
|
||||
List deletes = new ArrayList();
|
||||
Iterator iter = ( (Map) getSnapshot() ).entrySet().iterator();
|
||||
while ( iter.hasNext() ) {
|
||||
Map.Entry e = (Map.Entry) iter.next();
|
||||
Object key = e.getKey();
|
||||
if ( e.getValue()!=null && map.get(key)==null ) {
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Iterator getDeletes(CollectionPersister persister, boolean indexIsFormula) throws HibernateException {
|
||||
final List deletes = new ArrayList();
|
||||
for ( Object o : ((Map) getSnapshot()).entrySet() ) {
|
||||
final Entry e = (Entry) o;
|
||||
final Object key = e.getKey();
|
||||
if ( e.getValue() != null && map.get( key ) == null ) {
|
||||
deletes.add( indexIsFormula ? e.getValue() : key );
|
||||
}
|
||||
}
|
||||
return deletes.iterator();
|
||||
}
|
||||
|
||||
public boolean needsInserting(Object entry, int i, Type elemType)
|
||||
throws HibernateException {
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public boolean needsInserting(Object entry, int i, Type elemType) throws HibernateException {
|
||||
final Map sn = (Map) getSnapshot();
|
||||
Map.Entry e = (Map.Entry) entry;
|
||||
return e.getValue()!=null && sn.get( e.getKey() )==null;
|
||||
final Map.Entry e = (Map.Entry) entry;
|
||||
return e.getValue() != null && sn.get( e.getKey() ) == null;
|
||||
}
|
||||
|
||||
public boolean needsUpdating(Object entry, int i, Type elemType)
|
||||
throws HibernateException {
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public boolean needsUpdating(Object entry, int i, Type elemType) throws HibernateException {
|
||||
final Map sn = (Map) getSnapshot();
|
||||
Map.Entry e = (Map.Entry) entry;
|
||||
Object snValue = sn.get( e.getKey() );
|
||||
return e.getValue()!=null &&
|
||||
snValue!=null &&
|
||||
elemType.isDirty( snValue, e.getValue(), getSession() );
|
||||
final Map.Entry e = (Map.Entry) entry;
|
||||
final Object snValue = sn.get( e.getKey() );
|
||||
return e.getValue() != null
|
||||
&& snValue != null
|
||||
&& elemType.isDirty( snValue, e.getValue(), getSession() );
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Object getIndex(Object entry, int i, CollectionPersister persister) {
|
||||
return ( (Map.Entry) entry ).getKey();
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Object getElement(Object entry) {
|
||||
return ( (Map.Entry) entry ).getValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Object getSnapshotElement(Object entry, int i) {
|
||||
final Map sn = (Map) getSnapshot();
|
||||
return sn.get( ( (Map.Entry) entry ).getKey() );
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({"unchecked", "EqualsWhichDoesntCheckParameterClass"})
|
||||
public boolean equals(Object other) {
|
||||
read();
|
||||
return map.equals(other);
|
||||
return map.equals( other );
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public int hashCode() {
|
||||
read();
|
||||
return map.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public boolean entryExists(Object entry, int i) {
|
||||
return ( (Map.Entry) entry ).getValue()!=null;
|
||||
return ( (Map.Entry) entry ).getValue() != null;
|
||||
}
|
||||
|
||||
final class Clear implements DelayedOperation {
|
||||
@Override
|
||||
public void operate() {
|
||||
map.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getAddedInstance() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getOrphan() {
|
||||
throw new UnsupportedOperationException("queued clear cannot be used with orphan delete");
|
||||
throw new UnsupportedOperationException( "queued clear cannot be used with orphan delete" );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -500,12 +599,21 @@ public class PersistentMap extends AbstractPersistentCollection implements Map {
|
|||
this.value = value;
|
||||
this.old = old;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public void operate() {
|
||||
map.put(index, value);
|
||||
map.put( index, value );
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Object getAddedInstance() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Object getOrphan() {
|
||||
return old;
|
||||
}
|
||||
|
@ -519,12 +627,19 @@ public class PersistentMap extends AbstractPersistentCollection implements Map {
|
|||
this.index = index;
|
||||
this.old = old;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public void operate() {
|
||||
map.remove(index);
|
||||
map.remove( index );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getAddedInstance() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getOrphan() {
|
||||
return old;
|
||||
}
|
||||
|
|
|
@ -48,7 +48,6 @@ import org.hibernate.type.Type;
|
|||
* @author Gavin King
|
||||
*/
|
||||
public class PersistentSet extends AbstractPersistentCollection implements java.util.Set {
|
||||
|
||||
protected Set set;
|
||||
protected transient List tempList;
|
||||
|
||||
|
@ -80,128 +79,127 @@ public class PersistentSet extends AbstractPersistentCollection implements java.
|
|||
* @param set The underlying set data.
|
||||
*/
|
||||
public PersistentSet(SessionImplementor session, java.util.Set set) {
|
||||
super(session);
|
||||
super( session );
|
||||
// Sets can be just a view of a part of another collection.
|
||||
// do we need to copy it to be sure it won't be changing
|
||||
// underneath us?
|
||||
// ie. this.set.addAll(set);
|
||||
this.set = set;
|
||||
setInitialized();
|
||||
setDirectlyAccessible(true);
|
||||
setDirectlyAccessible( true );
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
@SuppressWarnings( {"unchecked"})
|
||||
public Serializable getSnapshot(CollectionPersister persister) throws HibernateException {
|
||||
HashMap clonedSet = new HashMap( set.size() );
|
||||
final HashMap clonedSet = new HashMap( set.size() );
|
||||
for ( Object aSet : set ) {
|
||||
Object copied = persister.getElementType()
|
||||
.deepCopy( aSet, persister.getFactory() );
|
||||
final Object copied = persister.getElementType().deepCopy( aSet, persister.getFactory() );
|
||||
clonedSet.put( copied, copied );
|
||||
}
|
||||
return clonedSet;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection getOrphans(Serializable snapshot, String entityName) throws HibernateException {
|
||||
java.util.Map sn = (java.util.Map) snapshot;
|
||||
final java.util.Map sn = (java.util.Map) snapshot;
|
||||
return getOrphans( sn.keySet(), set, entityName, getSession() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equalsSnapshot(CollectionPersister persister) throws HibernateException {
|
||||
Type elementType = persister.getElementType();
|
||||
java.util.Map sn = (java.util.Map) getSnapshot();
|
||||
final Type elementType = persister.getElementType();
|
||||
final java.util.Map sn = (java.util.Map) getSnapshot();
|
||||
if ( sn.size()!=set.size() ) {
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
Iterator iter = set.iterator();
|
||||
while ( iter.hasNext() ) {
|
||||
Object test = iter.next();
|
||||
Object oldValue = sn.get(test);
|
||||
if ( oldValue==null || elementType.isDirty( oldValue, test, getSession() ) ) return false;
|
||||
for ( Object test : set ) {
|
||||
final Object oldValue = sn.get( test );
|
||||
if ( oldValue == null || elementType.isDirty( oldValue, test, getSession() ) ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSnapshotEmpty(Serializable snapshot) {
|
||||
return ( (java.util.Map) snapshot ).isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beforeInitialize(CollectionPersister persister, int anticipatedSize) {
|
||||
this.set = ( Set ) persister.getCollectionType().instantiate( anticipatedSize );
|
||||
this.set = (Set) persister.getCollectionType().instantiate( anticipatedSize );
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public void initializeFromCache(CollectionPersister persister, Serializable disassembled, Object owner)
|
||||
throws HibernateException {
|
||||
Serializable[] array = ( Serializable[] ) disassembled;
|
||||
int size = array.length;
|
||||
final Serializable[] array = (Serializable[]) disassembled;
|
||||
final int size = array.length;
|
||||
beforeInitialize( persister, size );
|
||||
for (int i = 0; i < size; i++ ) {
|
||||
Object element = persister.getElementType().assemble( array[i], getSession(), owner );
|
||||
if ( element != null ) {
|
||||
set.add( element );
|
||||
for ( Serializable arrayElement : array ) {
|
||||
final Object assembledArrayElement = persister.getElementType().assemble( arrayElement, getSession(), owner );
|
||||
if ( assembledArrayElement != null ) {
|
||||
set.add( assembledArrayElement );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean empty() {
|
||||
return set.isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.util.Set#size()
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public int size() {
|
||||
return readSize() ? getCachedSize() : set.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.util.Set#isEmpty()
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public boolean isEmpty() {
|
||||
return readSize() ? getCachedSize()==0 : set.isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.util.Set#contains(Object)
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings({"unchecked", "UnnecessaryUnboxing"})
|
||||
public boolean contains(Object object) {
|
||||
Boolean exists = readElementExistence(object);
|
||||
return exists==null ?
|
||||
set.contains(object) :
|
||||
exists.booleanValue();
|
||||
final Boolean exists = readElementExistence( object );
|
||||
return exists == null
|
||||
? set.contains( object )
|
||||
: exists.booleanValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.util.Set#iterator()
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Iterator iterator() {
|
||||
read();
|
||||
return new IteratorProxy( set.iterator() );
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.util.Set#toArray()
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Object[] toArray() {
|
||||
read();
|
||||
return set.toArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.util.Set#toArray(Object[])
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Object[] toArray(Object[] array) {
|
||||
read();
|
||||
return set.toArray(array);
|
||||
return set.toArray( array );
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.util.Set#add(Object)
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings({"unchecked", "UnnecessaryUnboxing"})
|
||||
public boolean add(Object value) {
|
||||
Boolean exists = isOperationQueueEnabled() ? readElementExistence( value ) : null;
|
||||
final Boolean exists = isOperationQueueEnabled() ? readElementExistence( value ) : null;
|
||||
if ( exists == null ) {
|
||||
initialize( true );
|
||||
if ( set.add( value ) ) {
|
||||
|
@ -216,17 +214,16 @@ public class PersistentSet extends AbstractPersistentCollection implements java.
|
|||
return false;
|
||||
}
|
||||
else {
|
||||
queueOperation( new SimpleAdd(value) );
|
||||
queueOperation( new SimpleAdd( value ) );
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.util.Set#remove(Object)
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings({"unchecked", "UnnecessaryUnboxing"})
|
||||
public boolean remove(Object value) {
|
||||
Boolean exists = isPutQueueEnabled() ? readElementExistence( value ) : null;
|
||||
if ( exists==null ) {
|
||||
final Boolean exists = isPutQueueEnabled() ? readElementExistence( value ) : null;
|
||||
if ( exists == null ) {
|
||||
initialize( true );
|
||||
if ( set.remove( value ) ) {
|
||||
dirty();
|
||||
|
@ -237,7 +234,7 @@ public class PersistentSet extends AbstractPersistentCollection implements java.
|
|||
}
|
||||
}
|
||||
else if ( exists.booleanValue() ) {
|
||||
queueOperation( new SimpleRemove(value) );
|
||||
queueOperation( new SimpleRemove( value ) );
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
|
@ -245,17 +242,15 @@ public class PersistentSet extends AbstractPersistentCollection implements java.
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.util.Set#containsAll(Collection)
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public boolean containsAll(Collection coll) {
|
||||
read();
|
||||
return set.containsAll(coll);
|
||||
return set.containsAll( coll );
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.util.Set#addAll(Collection)
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public boolean addAll(Collection coll) {
|
||||
if ( coll.size() > 0 ) {
|
||||
initialize( true );
|
||||
|
@ -272,9 +267,8 @@ public class PersistentSet extends AbstractPersistentCollection implements java.
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.util.Set#retainAll(Collection)
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public boolean retainAll(Collection coll) {
|
||||
initialize( true );
|
||||
if ( set.retainAll( coll ) ) {
|
||||
|
@ -286,9 +280,8 @@ public class PersistentSet extends AbstractPersistentCollection implements java.
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.util.Set#removeAll(Collection)
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public boolean removeAll(Collection coll) {
|
||||
if ( coll.size() > 0 ) {
|
||||
initialize( true );
|
||||
|
@ -305,9 +298,8 @@ public class PersistentSet extends AbstractPersistentCollection implements java.
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.util.Set#clear()
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public void clear() {
|
||||
if ( isClearQueueEnabled() ) {
|
||||
queueOperation( new Clear() );
|
||||
|
@ -321,129 +313,168 @@ public class PersistentSet extends AbstractPersistentCollection implements java.
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public String toString() {
|
||||
//if (needLoading) return "asleep";
|
||||
read();
|
||||
return set.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Object readFrom(
|
||||
ResultSet rs,
|
||||
CollectionPersister persister,
|
||||
CollectionAliases descriptor,
|
||||
Object owner) throws HibernateException, SQLException {
|
||||
Object element = persister.readElement( rs, owner, descriptor.getSuffixedElementAliases(), getSession() );
|
||||
if (element!=null) tempList.add(element);
|
||||
final Object element = persister.readElement( rs, owner, descriptor.getSuffixedElementAliases(), getSession() );
|
||||
if ( element != null ) {
|
||||
tempList.add( element );
|
||||
}
|
||||
return element;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public void beginRead() {
|
||||
super.beginRead();
|
||||
tempList = new ArrayList();
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public boolean endRead() {
|
||||
set.addAll(tempList);
|
||||
set.addAll( tempList );
|
||||
tempList = null;
|
||||
setInitialized();
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Iterator entries(CollectionPersister persister) {
|
||||
return set.iterator();
|
||||
}
|
||||
|
||||
public Serializable disassemble(CollectionPersister persister)
|
||||
throws HibernateException {
|
||||
|
||||
Serializable[] result = new Serializable[ set.size() ];
|
||||
Iterator iter = set.iterator();
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Serializable disassemble(CollectionPersister persister) throws HibernateException {
|
||||
final Serializable[] result = new Serializable[ set.size() ];
|
||||
final Iterator itr = set.iterator();
|
||||
int i=0;
|
||||
while ( iter.hasNext() ) {
|
||||
result[i++] = persister.getElementType().disassemble( iter.next(), getSession(), null );
|
||||
while ( itr.hasNext() ) {
|
||||
result[i++] = persister.getElementType().disassemble( itr.next(), getSession(), null );
|
||||
}
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Iterator getDeletes(CollectionPersister persister, boolean indexIsFormula) throws HibernateException {
|
||||
Type elementType = persister.getElementType();
|
||||
final Type elementType = persister.getElementType();
|
||||
final java.util.Map sn = (java.util.Map) getSnapshot();
|
||||
ArrayList deletes = new ArrayList( sn.size() );
|
||||
Iterator iter = sn.keySet().iterator();
|
||||
while ( iter.hasNext() ) {
|
||||
Object test = iter.next();
|
||||
if ( !set.contains(test) ) {
|
||||
final ArrayList deletes = new ArrayList( sn.size() );
|
||||
|
||||
Iterator itr = sn.keySet().iterator();
|
||||
while ( itr.hasNext() ) {
|
||||
final Object test = itr.next();
|
||||
if ( !set.contains( test ) ) {
|
||||
// the element has been removed from the set
|
||||
deletes.add(test);
|
||||
deletes.add( test );
|
||||
}
|
||||
}
|
||||
iter = set.iterator();
|
||||
while ( iter.hasNext() ) {
|
||||
Object test = iter.next();
|
||||
Object oldValue = sn.get(test);
|
||||
|
||||
itr = set.iterator();
|
||||
while ( itr.hasNext() ) {
|
||||
final Object test = itr.next();
|
||||
final Object oldValue = sn.get( test );
|
||||
if ( oldValue!=null && elementType.isDirty( test, oldValue, getSession() ) ) {
|
||||
// the element has changed
|
||||
deletes.add(oldValue);
|
||||
deletes.add( oldValue );
|
||||
}
|
||||
}
|
||||
|
||||
return deletes.iterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public boolean needsInserting(Object entry, int i, Type elemType) throws HibernateException {
|
||||
final java.util.Map sn = (java.util.Map) getSnapshot();
|
||||
Object oldValue = sn.get(entry);
|
||||
final Object oldValue = ( (java.util.Map) getSnapshot() ).get( entry );
|
||||
// note that it might be better to iterate the snapshot but this is safe,
|
||||
// assuming the user implements equals() properly, as required by the Set
|
||||
// contract!
|
||||
return oldValue==null || elemType.isDirty( oldValue, entry, getSession() );
|
||||
return oldValue == null || elemType.isDirty( oldValue, entry, getSession() );
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public boolean needsUpdating(Object entry, int i, Type elemType) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public boolean isRowUpdatePossible() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Object getIndex(Object entry, int i, CollectionPersister persister) {
|
||||
throw new UnsupportedOperationException("Sets don't have indexes");
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Object getElement(Object entry) {
|
||||
return entry;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Object getSnapshotElement(Object entry, int i) {
|
||||
throw new UnsupportedOperationException("Sets don't support updating by element");
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({"unchecked", "EqualsWhichDoesntCheckParameterClass"})
|
||||
public boolean equals(Object other) {
|
||||
read();
|
||||
return set.equals(other);
|
||||
return set.equals( other );
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public int hashCode() {
|
||||
read();
|
||||
return set.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public boolean entryExists(Object key, int i) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public boolean isWrapper(Object collection) {
|
||||
return set==collection;
|
||||
}
|
||||
|
||||
final class Clear implements DelayedOperation {
|
||||
@Override
|
||||
public void operate() {
|
||||
set.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getAddedInstance() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getOrphan() {
|
||||
throw new UnsupportedOperationException("queued clear cannot be used with orphan delete");
|
||||
}
|
||||
|
@ -455,12 +486,19 @@ public class PersistentSet extends AbstractPersistentCollection implements java.
|
|||
public SimpleAdd(Object value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public void operate() {
|
||||
set.add(value);
|
||||
set.add( value );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getAddedInstance() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getOrphan() {
|
||||
return null;
|
||||
}
|
||||
|
@ -472,12 +510,19 @@ public class PersistentSet extends AbstractPersistentCollection implements java.
|
|||
public SimpleRemove(Object value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public void operate() {
|
||||
set.remove(value);
|
||||
set.remove( value );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getAddedInstance() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getOrphan() {
|
||||
return value;
|
||||
}
|
||||
|
|
|
@ -26,7 +26,6 @@ package org.hibernate.collection.internal;
|
|||
import java.io.Serializable;
|
||||
import java.util.Collection;
|
||||
import java.util.Comparator;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.SortedMap;
|
||||
|
@ -45,167 +44,212 @@ import org.hibernate.persister.collection.BasicCollectionPersister;
|
|||
* @author <a href="mailto:doug.currie@alum.mit.edu">e</a>
|
||||
*/
|
||||
public class PersistentSortedMap extends PersistentMap implements SortedMap {
|
||||
|
||||
protected Comparator comparator;
|
||||
|
||||
/**
|
||||
* Constructs a PersistentSortedMap. This form needed for SOAP libraries, etc
|
||||
*/
|
||||
@SuppressWarnings("UnusedDeclaration")
|
||||
public PersistentSortedMap() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a PersistentSortedMap.
|
||||
*
|
||||
* @param session The session
|
||||
*/
|
||||
public PersistentSortedMap(SessionImplementor session) {
|
||||
super( session );
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a PersistentSortedMap.
|
||||
*
|
||||
* @param session The session
|
||||
* @param map The underlying map data
|
||||
*/
|
||||
public PersistentSortedMap(SessionImplementor session, SortedMap map) {
|
||||
super( session, map );
|
||||
comparator = map.comparator();
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked", "UnusedParameters"})
|
||||
protected Serializable snapshot(BasicCollectionPersister persister, EntityMode entityMode) throws HibernateException {
|
||||
TreeMap clonedMap = new TreeMap(comparator);
|
||||
Iterator iter = map.entrySet().iterator();
|
||||
while ( iter.hasNext() ) {
|
||||
Map.Entry e = (Map.Entry) iter.next();
|
||||
final TreeMap clonedMap = new TreeMap( comparator );
|
||||
for ( Object o : map.entrySet() ) {
|
||||
final Entry e = (Entry) o;
|
||||
clonedMap.put( e.getKey(), persister.getElementType().deepCopy( e.getValue(), persister.getFactory() ) );
|
||||
}
|
||||
return clonedMap;
|
||||
}
|
||||
|
||||
public PersistentSortedMap(SessionImplementor session) {
|
||||
super(session);
|
||||
}
|
||||
|
||||
public void setComparator(Comparator comparator) {
|
||||
this.comparator = comparator;
|
||||
}
|
||||
|
||||
public PersistentSortedMap(SessionImplementor session, SortedMap map) {
|
||||
super(session, map);
|
||||
comparator = map.comparator();
|
||||
}
|
||||
|
||||
public PersistentSortedMap() {} //needed for SOAP libraries, etc
|
||||
|
||||
/**
|
||||
* @see PersistentSortedMap#comparator()
|
||||
*/
|
||||
@Override
|
||||
public Comparator comparator() {
|
||||
return comparator;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see PersistentSortedMap#subMap(Object, Object)
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public SortedMap subMap(Object fromKey, Object toKey) {
|
||||
read();
|
||||
SortedMap m = ( (SortedMap) map ).subMap(fromKey, toKey);
|
||||
return new SortedSubMap(m);
|
||||
final SortedMap subMap = ( (SortedMap) map ).subMap( fromKey, toKey );
|
||||
return new SortedSubMap( subMap );
|
||||
}
|
||||
|
||||
/**
|
||||
* @see PersistentSortedMap#headMap(Object)
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public SortedMap headMap(Object toKey) {
|
||||
read();
|
||||
SortedMap m;
|
||||
m = ( (SortedMap) map ).headMap(toKey);
|
||||
return new SortedSubMap(m);
|
||||
final SortedMap headMap = ( (SortedMap) map ).headMap( toKey );
|
||||
return new SortedSubMap( headMap );
|
||||
}
|
||||
|
||||
/**
|
||||
* @see PersistentSortedMap#tailMap(Object)
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public SortedMap tailMap(Object fromKey) {
|
||||
read();
|
||||
SortedMap m;
|
||||
m = ( (SortedMap) map ).tailMap(fromKey);
|
||||
return new SortedSubMap(m);
|
||||
final SortedMap tailMap = ( (SortedMap) map ).tailMap( fromKey );
|
||||
return new SortedSubMap( tailMap );
|
||||
}
|
||||
|
||||
/**
|
||||
* @see PersistentSortedMap#firstKey()
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Object firstKey() {
|
||||
read();
|
||||
return ( (SortedMap) map ).firstKey();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see PersistentSortedMap#lastKey()
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Object lastKey() {
|
||||
read();
|
||||
return ( (SortedMap) map ).lastKey();
|
||||
}
|
||||
|
||||
class SortedSubMap implements SortedMap {
|
||||
SortedMap subMap;
|
||||
|
||||
SortedMap submap;
|
||||
|
||||
SortedSubMap(SortedMap m) {
|
||||
this.submap = m;
|
||||
SortedSubMap(SortedMap subMap) {
|
||||
this.subMap = subMap;
|
||||
}
|
||||
// from Map
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public int size() {
|
||||
return submap.size();
|
||||
return subMap.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public boolean isEmpty() {
|
||||
return submap.isEmpty();
|
||||
return subMap.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public boolean containsKey(Object key) {
|
||||
return submap.containsKey(key);
|
||||
return subMap.containsKey( key );
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public boolean containsValue(Object key) {
|
||||
return submap.containsValue(key) ;
|
||||
return subMap.containsValue( key ) ;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Object get(Object key) {
|
||||
return submap.get(key);
|
||||
return subMap.get( key );
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Object put(Object key, Object value) {
|
||||
write();
|
||||
return submap.put(key, value);
|
||||
return subMap.put( key, value );
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Object remove(Object key) {
|
||||
write();
|
||||
return submap.remove(key);
|
||||
return subMap.remove( key );
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public void putAll(Map other) {
|
||||
write();
|
||||
submap.putAll(other);
|
||||
subMap.putAll( other );
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public void clear() {
|
||||
write();
|
||||
submap.clear();
|
||||
subMap.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Set keySet() {
|
||||
return new SetProxy( submap.keySet() );
|
||||
return new SetProxy( subMap.keySet() );
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Collection values() {
|
||||
return new SetProxy( submap.values() );
|
||||
return new SetProxy( subMap.values() );
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Set entrySet() {
|
||||
return new EntrySetProxy( submap.entrySet() );
|
||||
return new EntrySetProxy( subMap.entrySet() );
|
||||
}
|
||||
// from SortedMap
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Comparator comparator() {
|
||||
return submap.comparator();
|
||||
return subMap.comparator();
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public SortedMap subMap(Object fromKey, Object toKey) {
|
||||
SortedMap m;
|
||||
m = submap.subMap(fromKey, toKey);
|
||||
return new SortedSubMap( m );
|
||||
final SortedMap subMap = this.subMap.subMap( fromKey, toKey );
|
||||
return new SortedSubMap( subMap );
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public SortedMap headMap(Object toKey) {
|
||||
SortedMap m;
|
||||
m = submap.headMap(toKey);
|
||||
return new SortedSubMap(m);
|
||||
final SortedMap headMap = subMap.headMap( toKey );
|
||||
return new SortedSubMap( headMap );
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public SortedMap tailMap(Object fromKey) {
|
||||
SortedMap m;
|
||||
m = submap.tailMap(fromKey);
|
||||
return new SortedSubMap(m);
|
||||
final SortedMap tailMap = subMap.tailMap( fromKey );
|
||||
return new SortedSubMap( tailMap );
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Object firstKey() {
|
||||
return submap.firstKey();
|
||||
return subMap.firstKey();
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Object lastKey() {
|
||||
return submap.lastKey();
|
||||
return subMap.lastKey();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -25,7 +25,6 @@ package org.hibernate.collection.internal;
|
|||
|
||||
import java.io.Serializable;
|
||||
import java.util.Comparator;
|
||||
import java.util.Iterator;
|
||||
import java.util.SortedSet;
|
||||
import java.util.TreeMap;
|
||||
|
||||
|
@ -42,17 +41,42 @@ import org.hibernate.persister.collection.BasicCollectionPersister;
|
|||
* @author <a href="mailto:doug.currie@alum.mit.edu">e</a>
|
||||
*/
|
||||
public class PersistentSortedSet extends PersistentSet implements SortedSet {
|
||||
|
||||
protected Comparator comparator;
|
||||
|
||||
/**
|
||||
* Constructs a PersistentSortedSet. This form needed for SOAP libraries, etc
|
||||
*/
|
||||
@SuppressWarnings("UnusedDeclaration")
|
||||
public PersistentSortedSet() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a PersistentSortedSet
|
||||
*
|
||||
* @param session The session
|
||||
*/
|
||||
public PersistentSortedSet(SessionImplementor session) {
|
||||
super( session );
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a PersistentSortedSet
|
||||
*
|
||||
* @param session The session
|
||||
* @param set The underlying set data
|
||||
*/
|
||||
public PersistentSortedSet(SessionImplementor session, SortedSet set) {
|
||||
super( session, set );
|
||||
comparator = set.comparator();
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked", "UnusedParameters"})
|
||||
protected Serializable snapshot(BasicCollectionPersister persister, EntityMode entityMode)
|
||||
throws HibernateException {
|
||||
//if (set==null) return new Set(session);
|
||||
TreeMap clonedSet = new TreeMap(comparator);
|
||||
Iterator iter = set.iterator();
|
||||
while ( iter.hasNext() ) {
|
||||
Object copy = persister.getElementType().deepCopy( iter.next(), persister.getFactory() );
|
||||
clonedSet.put(copy, copy);
|
||||
final TreeMap clonedSet = new TreeMap( comparator );
|
||||
for ( Object setElement : set ) {
|
||||
final Object copy = persister.getElementType().deepCopy( setElement, persister.getFactory() );
|
||||
clonedSet.put( copy, copy );
|
||||
}
|
||||
return clonedSet;
|
||||
}
|
||||
|
@ -61,106 +85,91 @@ public class PersistentSortedSet extends PersistentSet implements SortedSet {
|
|||
this.comparator = comparator;
|
||||
}
|
||||
|
||||
public PersistentSortedSet(SessionImplementor session) {
|
||||
super(session);
|
||||
}
|
||||
|
||||
public PersistentSortedSet(SessionImplementor session, SortedSet set) {
|
||||
super(session, set);
|
||||
comparator = set.comparator();
|
||||
}
|
||||
|
||||
public PersistentSortedSet() {} //needed for SOAP libraries, etc
|
||||
|
||||
/**
|
||||
* @see PersistentSortedSet#comparator()
|
||||
*/
|
||||
@Override
|
||||
public Comparator comparator() {
|
||||
return comparator;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see PersistentSortedSet#subSet(Object,Object)
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public SortedSet subSet(Object fromElement, Object toElement) {
|
||||
read();
|
||||
SortedSet s;
|
||||
s = ( (SortedSet) set ).subSet(fromElement, toElement);
|
||||
return new SubSetProxy(s);
|
||||
final SortedSet subSet = ( (SortedSet) set ).subSet( fromElement, toElement );
|
||||
return new SubSetProxy( subSet );
|
||||
}
|
||||
|
||||
/**
|
||||
* @see PersistentSortedSet#headSet(Object)
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public SortedSet headSet(Object toElement) {
|
||||
read();
|
||||
SortedSet s = ( (SortedSet) set ).headSet(toElement);
|
||||
return new SubSetProxy(s);
|
||||
final SortedSet headSet = ( (SortedSet) set ).headSet( toElement );
|
||||
return new SubSetProxy( headSet );
|
||||
}
|
||||
|
||||
/**
|
||||
* @see PersistentSortedSet#tailSet(Object)
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public SortedSet tailSet(Object fromElement) {
|
||||
read();
|
||||
SortedSet s = ( (SortedSet) set ).tailSet(fromElement);
|
||||
return new SubSetProxy(s);
|
||||
final SortedSet tailSet = ( (SortedSet) set ).tailSet( fromElement );
|
||||
return new SubSetProxy( tailSet );
|
||||
}
|
||||
|
||||
/**
|
||||
* @see PersistentSortedSet#first()
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Object first() {
|
||||
read();
|
||||
return ( (SortedSet) set ).first();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see PersistentSortedSet#last()
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Object last() {
|
||||
read();
|
||||
return ( (SortedSet) set ).last();
|
||||
}
|
||||
|
||||
/** wrapper for subSets to propagate write to its backing set */
|
||||
/**
|
||||
* wrapper for subSets to propagate write to its backing set
|
||||
*/
|
||||
class SubSetProxy extends SetProxy implements SortedSet {
|
||||
|
||||
SubSetProxy(SortedSet s) {
|
||||
super(s);
|
||||
super( s );
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Comparator comparator() {
|
||||
return ( (SortedSet) this.set ).comparator();
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Object first() {
|
||||
return ( (SortedSet) this.set ).first();
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public SortedSet headSet(Object toValue) {
|
||||
return new SubSetProxy( ( (SortedSet) this.set ).headSet(toValue) );
|
||||
return new SubSetProxy( ( (SortedSet) this.set ).headSet( toValue ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Object last() {
|
||||
return ( (SortedSet) this.set ).last();
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public SortedSet subSet(Object fromValue, Object toValue) {
|
||||
return new SubSetProxy( ( (SortedSet) this.set ).subSet(fromValue, toValue) );
|
||||
return new SubSetProxy( ( (SortedSet) this.set ).subSet( fromValue, toValue ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public SortedSet tailSet(Object fromValue) {
|
||||
return new SubSetProxy( ( (SortedSet) this.set ).tailSet(fromValue) );
|
||||
return new SubSetProxy( ( (SortedSet) this.set ).tailSet( fromValue ) );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/**
|
||||
* Internal implementations and support for persistent collections
|
||||
*/
|
||||
package org.hibernate.collection.internal;
|
|
@ -63,25 +63,35 @@ import org.hibernate.type.Type;
|
|||
* @author Gavin King
|
||||
*/
|
||||
public interface PersistentCollection {
|
||||
|
||||
/**
|
||||
* Get the owning entity. Note that the owner is only
|
||||
* set during the flush cycle, and when a new collection
|
||||
* wrapper is created while loading an entity.
|
||||
*
|
||||
* @return The owner
|
||||
*/
|
||||
public Object getOwner();
|
||||
|
||||
/**
|
||||
* Set the reference to the owning entity
|
||||
*
|
||||
* @param entity The owner
|
||||
*/
|
||||
public void setOwner(Object entity);
|
||||
|
||||
/**
|
||||
* Is the collection empty? (don't try to initialize the collection)
|
||||
*
|
||||
* @return {@code false} if the collection is non-empty; {@code true} otherwise.
|
||||
*/
|
||||
public boolean empty();
|
||||
|
||||
/**
|
||||
* After flushing, re-init snapshot state.
|
||||
*
|
||||
* @param key The collection instance key (fk value).
|
||||
* @param role The collection role
|
||||
* @param snapshot The snapshot state
|
||||
*/
|
||||
public void setSnapshot(Serializable key, String role, Serializable snapshot);
|
||||
|
||||
|
@ -92,7 +102,9 @@ public interface PersistentCollection {
|
|||
public void postAction();
|
||||
|
||||
/**
|
||||
* return the user-visible collection (or array) instance
|
||||
* Return the user-visible collection (or array) instance
|
||||
*
|
||||
* @return The underlying collection/array
|
||||
*/
|
||||
public Object getValue();
|
||||
|
||||
|
@ -103,70 +115,121 @@ public interface PersistentCollection {
|
|||
|
||||
/**
|
||||
* Called after reading all rows from the JDBC result set
|
||||
*
|
||||
* @return Whether to end the read.
|
||||
*/
|
||||
public boolean endRead();
|
||||
|
||||
/**
|
||||
* Called after initializing from cache
|
||||
*
|
||||
* @return ??
|
||||
*/
|
||||
public boolean afterInitialize();
|
||||
|
||||
/**
|
||||
* Could the application possibly have a direct reference to
|
||||
* the underlying collection implementation?
|
||||
*
|
||||
* @return {@code true} indicates that the application might have access to the underlying collection/array.
|
||||
*/
|
||||
public boolean isDirectlyAccessible();
|
||||
|
||||
/**
|
||||
* Disassociate this collection from the given session.
|
||||
*
|
||||
* @param currentSession The session we are disassociating from. Used for validations.
|
||||
*
|
||||
* @return true if this was currently associated with the given session
|
||||
*/
|
||||
public boolean unsetSession(SessionImplementor currentSession);
|
||||
|
||||
/**
|
||||
* Associate the collection with the given session.
|
||||
*
|
||||
* @param session The session to associate with
|
||||
*
|
||||
* @return false if the collection was already associated with the session
|
||||
*
|
||||
* @throws HibernateException if the collection was already associated
|
||||
* with another open session
|
||||
*/
|
||||
public boolean setCurrentSession(SessionImplementor session)
|
||||
throws HibernateException;
|
||||
public boolean setCurrentSession(SessionImplementor session) throws HibernateException;
|
||||
|
||||
/**
|
||||
* Read the state of the collection from a disassembled cached value
|
||||
*
|
||||
* @param persister The collection persister
|
||||
* @param disassembled The disassembled cached state
|
||||
* @param owner The collection owner
|
||||
*/
|
||||
public void initializeFromCache(CollectionPersister persister,
|
||||
Serializable disassembled, Object owner) throws HibernateException;
|
||||
public void initializeFromCache(CollectionPersister persister, Serializable disassembled, Object owner);
|
||||
|
||||
/**
|
||||
* Iterate all collection entries, during update of the database
|
||||
*
|
||||
* @param persister The collection persister.
|
||||
*
|
||||
* @return The iterator
|
||||
*/
|
||||
public Iterator entries(CollectionPersister persister);
|
||||
|
||||
/**
|
||||
* Read a row from the JDBC result set
|
||||
*
|
||||
* @param rs The JDBC ResultSet
|
||||
* @param role The collection role
|
||||
* @param descriptor The aliases used for the columns making up the collection
|
||||
* @param owner The collection owner
|
||||
*
|
||||
* @return The read object
|
||||
*
|
||||
* @throws HibernateException Generally indicates a problem resolving data read from the ResultSet
|
||||
* @throws SQLException Indicates a problem accessing the ResultSet
|
||||
*/
|
||||
public Object readFrom(ResultSet rs, CollectionPersister role, CollectionAliases descriptor, Object owner)
|
||||
throws HibernateException, SQLException;
|
||||
|
||||
/**
|
||||
* Get the index of the given collection entry
|
||||
* Get the identifier of the given collection entry. This refers to the collection identifier, not the
|
||||
* identifier of the (possibly) entity elements. This is only valid for invocation on the
|
||||
* {@code idbag} collection.
|
||||
*
|
||||
* @param entry The collection entry/element
|
||||
* @param i The assumed identifier (?)
|
||||
*
|
||||
* @return The identifier value
|
||||
*/
|
||||
public Object getIdentifier(Object entry, int i);
|
||||
|
||||
/**
|
||||
* Get the index of the given collection entry
|
||||
*
|
||||
* @param entry The collection entry/element
|
||||
* @param i The assumed index
|
||||
* @param persister it was more elegant before we added this...
|
||||
*
|
||||
* @return The index value
|
||||
*/
|
||||
public Object getIndex(Object entry, int i, CollectionPersister persister);
|
||||
|
||||
/**
|
||||
* Get the value of the given collection entry
|
||||
* Get the value of the given collection entry. Generally the given entry parameter value will just be returned.
|
||||
* Might get a different value for a duplicate entries in a Set.
|
||||
*
|
||||
* @param entry The object instance for which to get the collection element instance.
|
||||
*
|
||||
* @return The corresponding object that is part of the collection elements.
|
||||
*/
|
||||
public Object getElement(Object entry);
|
||||
|
||||
/**
|
||||
* Get the snapshot value of the given collection entry
|
||||
*
|
||||
* @param entry The entry
|
||||
* @param i The index
|
||||
*
|
||||
* @return The snapshot state for that element
|
||||
*/
|
||||
public Object getSnapshotElement(Object entry, int i);
|
||||
|
||||
|
@ -175,106 +238,168 @@ public interface PersistentCollection {
|
|||
* allowing appropriate initializations to occur.
|
||||
*
|
||||
* @param persister The underlying collection persister.
|
||||
* @param anticipatedSize The anticipated size of the collection after initilization is complete.
|
||||
* @param anticipatedSize The anticipated size of the collection after initialization is complete.
|
||||
*/
|
||||
public void beforeInitialize(CollectionPersister persister, int anticipatedSize);
|
||||
|
||||
/**
|
||||
* Does the current state exactly match the snapshot?
|
||||
*
|
||||
* @param persister The collection persister
|
||||
*
|
||||
* @return {@code true} if the current state and the snapshot state match.
|
||||
*
|
||||
*/
|
||||
public boolean equalsSnapshot(CollectionPersister persister)
|
||||
throws HibernateException;
|
||||
public boolean equalsSnapshot(CollectionPersister persister);
|
||||
|
||||
/**
|
||||
* Is the snapshot empty?
|
||||
*
|
||||
* @param snapshot The snapshot to check
|
||||
*
|
||||
* @return {@code true} if the given snapshot is empty
|
||||
*/
|
||||
public boolean isSnapshotEmpty(Serializable snapshot);
|
||||
|
||||
/**
|
||||
* Disassemble the collection, ready for the cache
|
||||
* Disassemble the collection to get it ready for the cache
|
||||
*
|
||||
* @param persister The collection persister
|
||||
*
|
||||
* @return The disassembled state
|
||||
*/
|
||||
public Serializable disassemble(CollectionPersister persister)
|
||||
throws HibernateException;
|
||||
public Serializable disassemble(CollectionPersister persister) ;
|
||||
|
||||
/**
|
||||
* Do we need to completely recreate this collection when it changes?
|
||||
*
|
||||
* @param persister The collection persister
|
||||
*
|
||||
* @return {@code true} if a change requires a recreate.
|
||||
*/
|
||||
public boolean needsRecreate(CollectionPersister persister);
|
||||
|
||||
/**
|
||||
* Return a new snapshot of the current state of the collection
|
||||
*
|
||||
* @param persister The collection persister
|
||||
*
|
||||
* @return The snapshot
|
||||
*/
|
||||
public Serializable getSnapshot(CollectionPersister persister)
|
||||
throws HibernateException;
|
||||
public Serializable getSnapshot(CollectionPersister persister);
|
||||
|
||||
/**
|
||||
* To be called internally by the session, forcing
|
||||
* immediate initialization.
|
||||
* To be called internally by the session, forcing immediate initialization.
|
||||
*/
|
||||
public void forceInitialization() throws HibernateException;
|
||||
public void forceInitialization();
|
||||
|
||||
/**
|
||||
* Does an element exist at this entry in the collection?
|
||||
* Does the given element/entry exist in the collection?
|
||||
*
|
||||
* @param entry The object to check if it exists as a collection element
|
||||
* @param i Unused
|
||||
*
|
||||
* @return {@code true} if the given entry is a collection element
|
||||
*/
|
||||
public boolean entryExists(Object entry, int i); //note that i parameter is now unused (delete it?)
|
||||
public boolean entryExists(Object entry, int i);
|
||||
|
||||
/**
|
||||
* Do we need to insert this element?
|
||||
*
|
||||
* @param entry The collection element to check
|
||||
* @param i The index (for indexed collections)
|
||||
* @param elemType The type for the element
|
||||
*
|
||||
* @return {@code true} if the element needs inserting
|
||||
*/
|
||||
public boolean needsInserting(Object entry, int i, Type elemType)
|
||||
throws HibernateException;
|
||||
public boolean needsInserting(Object entry, int i, Type elemType);
|
||||
|
||||
/**
|
||||
* Do we need to update this element?
|
||||
*
|
||||
* @param entry The collection element to check
|
||||
* @param i The index (for indexed collections)
|
||||
* @param elemType The type for the element
|
||||
*
|
||||
* @return {@code true} if the element needs updating
|
||||
*/
|
||||
public boolean needsUpdating(Object entry, int i, Type elemType)
|
||||
throws HibernateException;
|
||||
public boolean needsUpdating(Object entry, int i, Type elemType);
|
||||
|
||||
/**
|
||||
* Can each element in the collection be mapped unequivocally to a single row in the database? Generally
|
||||
* bags and sets are the only collections that cannot be.
|
||||
*
|
||||
* @return {@code true} if the row for each element is known
|
||||
*/
|
||||
public boolean isRowUpdatePossible();
|
||||
|
||||
/**
|
||||
* Get all the elements that need deleting
|
||||
*
|
||||
* @param persister The collection persister
|
||||
* @param indexIsFormula For indexed collections, tells whether the index is a formula (calculated value) mapping
|
||||
*
|
||||
* @return An iterator over the elements to delete
|
||||
*/
|
||||
public Iterator getDeletes(CollectionPersister persister, boolean indexIsFormula)
|
||||
throws HibernateException;
|
||||
public Iterator getDeletes(CollectionPersister persister, boolean indexIsFormula);
|
||||
|
||||
/**
|
||||
* Is this the wrapper for the given underlying collection instance?
|
||||
* Is this the wrapper for the given collection instance?
|
||||
*
|
||||
* @param collection The collection to check whether this is wrapping it
|
||||
*
|
||||
* @return {@code true} if this is a wrapper around that given collection instance.
|
||||
*/
|
||||
public boolean isWrapper(Object collection);
|
||||
|
||||
/**
|
||||
* Is this instance initialized?
|
||||
*
|
||||
* @return Was this collection initialized? Or is its data still not (fully) loaded?
|
||||
*/
|
||||
public boolean wasInitialized();
|
||||
|
||||
/**
|
||||
* Does this instance have any "queued" additions?
|
||||
* Does this instance have any "queued" operations?
|
||||
*
|
||||
* @return {@code true} indicates there are pending, queued, delayed operations
|
||||
*/
|
||||
public boolean hasQueuedOperations();
|
||||
|
||||
/**
|
||||
* Iterate the "queued" additions
|
||||
* Iterator over the "queued" additions
|
||||
*
|
||||
* @return The iterator
|
||||
*/
|
||||
public Iterator queuedAdditionIterator();
|
||||
|
||||
/**
|
||||
* Get the "queued" orphans
|
||||
*
|
||||
* @param entityName The name of the entity that makes up the elements
|
||||
*
|
||||
* @return The orphaned elements
|
||||
*/
|
||||
public Collection getQueuedOrphans(String entityName);
|
||||
|
||||
/**
|
||||
* Get the current collection key value
|
||||
*
|
||||
* @return the current collection key value
|
||||
*/
|
||||
public Serializable getKey();
|
||||
|
||||
/**
|
||||
* Get the current role name
|
||||
*
|
||||
* @return the collection role name
|
||||
*/
|
||||
public String getRole();
|
||||
|
||||
/**
|
||||
* Is the collection unreferenced?
|
||||
*
|
||||
* @return {@code true} if the collection is no longer referenced by an owner
|
||||
*/
|
||||
public boolean isUnreferenced();
|
||||
|
||||
|
@ -283,6 +408,8 @@ public interface PersistentCollection {
|
|||
* reliable during the flush cycle, after the
|
||||
* collection elements are dirty checked against
|
||||
* the snapshot.
|
||||
*
|
||||
* @return {@code true} if the collection is dirty
|
||||
*/
|
||||
public boolean isDirty();
|
||||
|
||||
|
@ -293,8 +420,9 @@ public interface PersistentCollection {
|
|||
public void clearDirty();
|
||||
|
||||
/**
|
||||
* Get the snapshot cached by the collection
|
||||
* instance
|
||||
* Get the snapshot cached by the collection instance
|
||||
*
|
||||
* @return The internally stored snapshot state
|
||||
*/
|
||||
public Serializable getStoredSnapshot();
|
||||
|
||||
|
@ -306,20 +434,28 @@ public interface PersistentCollection {
|
|||
/**
|
||||
* Called before inserting rows, to ensure that any surrogate keys
|
||||
* are fully generated
|
||||
*
|
||||
* @param persister The collection persister
|
||||
*/
|
||||
public void preInsert(CollectionPersister persister)
|
||||
throws HibernateException;
|
||||
public void preInsert(CollectionPersister persister);
|
||||
|
||||
/**
|
||||
* Called after inserting a row, to fetch the natively generated id
|
||||
*
|
||||
* @param persister The collection persister
|
||||
* @param entry The collection element just inserted
|
||||
* @param i The element position/index
|
||||
*/
|
||||
public void afterRowInsert(CollectionPersister persister, Object entry, int i)
|
||||
throws HibernateException;
|
||||
public void afterRowInsert(CollectionPersister persister, Object entry, int i);
|
||||
|
||||
/**
|
||||
* get all "orphaned" elements
|
||||
*
|
||||
* @param snapshot The snapshot state
|
||||
* @param entityName The name of the entity that are the elements of the collection
|
||||
*
|
||||
* @return The orphans
|
||||
*/
|
||||
public Collection getOrphans(Serializable snapshot, String entityName)
|
||||
throws HibernateException;
|
||||
public Collection getOrphans(Serializable snapshot, String entityName);
|
||||
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/**
|
||||
* SPI definitions for persistent collections
|
||||
*/
|
||||
package org.hibernate.collection.spi;
|
|
@ -33,11 +33,22 @@ import org.hibernate.HibernateException;
|
|||
* @author Steve Ebersole
|
||||
*/
|
||||
public class TenantIdentifierMismatchException extends HibernateException{
|
||||
/**
|
||||
* Constructs a TenantIdentifierMismatchException.
|
||||
*
|
||||
* @param message Message explaining the exception condition
|
||||
*/
|
||||
public TenantIdentifierMismatchException(String message) {
|
||||
super( message );
|
||||
}
|
||||
|
||||
public TenantIdentifierMismatchException(String message, Throwable root) {
|
||||
super( message, root );
|
||||
/**
|
||||
* Constructs a TenantIdentifierMismatchException.
|
||||
*
|
||||
* @param message Message explaining the exception condition
|
||||
* @param cause The underlying cause
|
||||
*/
|
||||
public TenantIdentifierMismatchException(String message, Throwable cause) {
|
||||
super( message, cause );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,47 +28,49 @@ import java.util.concurrent.ConcurrentHashMap;
|
|||
import javax.transaction.Synchronization;
|
||||
import javax.transaction.Transaction;
|
||||
import javax.transaction.TransactionManager;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import org.hibernate.ConnectionReleaseMode;
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.context.spi.AbstractCurrentSessionContext;
|
||||
import org.hibernate.context.spi.CurrentSessionContext;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.engine.transaction.internal.jta.JtaStatusHelper;
|
||||
import org.hibernate.engine.transaction.jta.platform.spi.JtaPlatform;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
|
||||
/**
|
||||
* An implementation of {@link CurrentSessionContext} which scopes the notion
|
||||
* of a current session to a JTA transaction. Because JTA gives us a nice
|
||||
* tie-in to clean up after ourselves, this implementation will generate
|
||||
* Sessions as needed provided a JTA transaction is in effect. If a session
|
||||
* is not already associated with the current JTA transaction at the time
|
||||
* {@link #currentSession()} is called, a new session will be opened and it
|
||||
* will be associated with that JTA transaction.
|
||||
* <p/>
|
||||
* Note that the sessions returned from this method are automatically configured with
|
||||
* both the {@link org.hibernate.cfg.Environment#FLUSH_BEFORE_COMPLETION auto-flush} and
|
||||
* {@link org.hibernate.cfg.Environment#AUTO_CLOSE_SESSION auto-close} attributes set to
|
||||
* true, meaning that the Session will be automatically flushed and closed
|
||||
* as part of the lifecycle for the JTA transaction to which it is associated.
|
||||
* Additionally, it will also be configured to aggressively release JDBC
|
||||
* connections after each statement is executed. These settings are governed
|
||||
* by the {@link #isAutoFlushEnabled()}, {@link #isAutoCloseEnabled()}, and
|
||||
* {@link #getConnectionReleaseMode()} methods; these are provided (along with
|
||||
* the {@link #buildOrObtainSession()} method) for easier subclassing for custom
|
||||
* JTA-based session tracking logic (like maybe long-session semantics).
|
||||
* An implementation of {@link org.hibernate.context.spi.CurrentSessionContext} which scopes the notion
|
||||
* of a current session to a JTA transaction. Because JTA gives us a nice tie-in to clean up after
|
||||
* ourselves, this implementation will generate Sessions as needed provided a JTA transaction is in
|
||||
* effect. If a session is not already associated with the current JTA transaction at the time
|
||||
* {@link #currentSession()} is called, a new session will be opened and it will be associated with that
|
||||
* JTA transaction.
|
||||
*
|
||||
* Note that the sessions returned from this method are automatically configured with both the
|
||||
* {@link org.hibernate.cfg.Environment#FLUSH_BEFORE_COMPLETION auto-flush} and
|
||||
* {@link org.hibernate.cfg.Environment#AUTO_CLOSE_SESSION auto-close} attributes set to true, meaning
|
||||
* that the Session will be automatically flushed and closed as part of the lifecycle for the JTA
|
||||
* transaction to which it is associated. Additionally, it will also be configured to aggressively
|
||||
* release JDBC connections after each statement is executed. These settings are governed by the
|
||||
* {@link #isAutoFlushEnabled()}, {@link #isAutoCloseEnabled()}, and {@link #getConnectionReleaseMode()}
|
||||
* methods; these are provided (along with the {@link #buildOrObtainSession()} method) for easier
|
||||
* subclassing for custom JTA-based session tracking logic (like maybe long-session semantics).
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class JTASessionContext extends AbstractCurrentSessionContext {
|
||||
private static final CoreMessageLogger LOG = Logger.getMessageLogger(CoreMessageLogger.class, JTASessionContext.class.getName());
|
||||
private static final CoreMessageLogger LOG = Logger.getMessageLogger(
|
||||
CoreMessageLogger.class,
|
||||
JTASessionContext.class.getName()
|
||||
);
|
||||
|
||||
private transient Map<Object, Session> currentSessionMap = new ConcurrentHashMap<Object, Session>();
|
||||
|
||||
/**
|
||||
* Constructs a JTASessionContext
|
||||
*
|
||||
* @param factory The factory this context will service
|
||||
*/
|
||||
public JTASessionContext(SessionFactoryImplementor factory) {
|
||||
super( factory );
|
||||
}
|
||||
|
@ -131,24 +133,23 @@ public class JTASessionContext extends AbstractCurrentSessionContext {
|
|||
}
|
||||
|
||||
/**
|
||||
* Builds a {@link CleanupSynch} capable of cleaning up the the current session map as an after transaction
|
||||
* Builds a {@link org.hibernate.context.internal.JTASessionContext.CleanupSync} capable of cleaning up the the current session map as an after transaction
|
||||
* callback.
|
||||
*
|
||||
* @param transactionIdentifier The transaction identifier under which the current session is registered.
|
||||
* @return The cleanup synch.
|
||||
*/
|
||||
private CleanupSynch buildCleanupSynch(Object transactionIdentifier) {
|
||||
return new CleanupSynch( transactionIdentifier, this );
|
||||
private CleanupSync buildCleanupSynch(Object transactionIdentifier) {
|
||||
return new CleanupSync( transactionIdentifier, this );
|
||||
}
|
||||
|
||||
/**
|
||||
* Strictly provided for subclassing purposes; specifically to allow long-session
|
||||
* support.
|
||||
* <p/>
|
||||
* This implementation always just opens a new session.
|
||||
* support. This implementation always just opens a new session.
|
||||
*
|
||||
* @return the built or (re)obtained session.
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
protected Session buildOrObtainSession() {
|
||||
return baseSessionBuilder()
|
||||
.autoClose( isAutoCloseEnabled() )
|
||||
|
@ -185,26 +186,22 @@ public class JTASessionContext extends AbstractCurrentSessionContext {
|
|||
}
|
||||
|
||||
/**
|
||||
* JTA transaction synch used for cleanup of the internal session map.
|
||||
* JTA transaction sync used for cleanup of the internal session map.
|
||||
*/
|
||||
protected static class CleanupSynch implements Synchronization {
|
||||
protected static class CleanupSync implements Synchronization {
|
||||
private Object transactionIdentifier;
|
||||
private JTASessionContext context;
|
||||
|
||||
public CleanupSynch(Object transactionIdentifier, JTASessionContext context) {
|
||||
public CleanupSync(Object transactionIdentifier, JTASessionContext context) {
|
||||
this.transactionIdentifier = transactionIdentifier;
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void beforeCompletion() {
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void afterCompletion(int i) {
|
||||
context.currentSessionMap.remove( transactionIdentifier );
|
||||
}
|
||||
|
|
|
@ -57,16 +57,20 @@ import org.hibernate.engine.spi.SessionFactoryImplementor;
|
|||
* @author Steve Ebersole
|
||||
*/
|
||||
public class ManagedSessionContext extends AbstractCurrentSessionContext {
|
||||
private static final ThreadLocal<Map<SessionFactory,Session>> CONTEXT_TL = new ThreadLocal<Map<SessionFactory,Session>>();
|
||||
|
||||
private static final ThreadLocal<Map<SessionFactory,Session>> context = new ThreadLocal<Map<SessionFactory,Session>>();
|
||||
|
||||
/**
|
||||
* Constructs a new ManagedSessionContext
|
||||
*
|
||||
* @param factory The factory this context will service
|
||||
*/
|
||||
public ManagedSessionContext(SessionFactoryImplementor factory) {
|
||||
super( factory );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Session currentSession() {
|
||||
Session current = existingSession( factory() );
|
||||
final Session current = existingSession( factory() );
|
||||
if ( current == null ) {
|
||||
throw new HibernateException( "No session currently bound to execution context" );
|
||||
}
|
||||
|
@ -106,8 +110,8 @@ public class ManagedSessionContext extends AbstractCurrentSessionContext {
|
|||
* @return The bound session if one, else null.
|
||||
*/
|
||||
public static Session unbind(SessionFactory factory) {
|
||||
final Map<SessionFactory,Session> sessionMap = sessionMap();
|
||||
Session existing = null;
|
||||
Map<SessionFactory,Session> sessionMap = sessionMap();
|
||||
if ( sessionMap != null ) {
|
||||
existing = sessionMap.remove( factory );
|
||||
doCleanup();
|
||||
|
@ -116,12 +120,12 @@ public class ManagedSessionContext extends AbstractCurrentSessionContext {
|
|||
}
|
||||
|
||||
private static Session existingSession(SessionFactory factory) {
|
||||
Map sessionMap = sessionMap();
|
||||
final Map sessionMap = sessionMap();
|
||||
if ( sessionMap == null ) {
|
||||
return null;
|
||||
}
|
||||
else {
|
||||
return ( Session ) sessionMap.get( factory );
|
||||
return (Session) sessionMap.get( factory );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -130,19 +134,19 @@ public class ManagedSessionContext extends AbstractCurrentSessionContext {
|
|||
}
|
||||
|
||||
private static synchronized Map<SessionFactory,Session> sessionMap(boolean createMap) {
|
||||
Map<SessionFactory,Session> sessionMap = context.get();
|
||||
Map<SessionFactory,Session> sessionMap = CONTEXT_TL.get();
|
||||
if ( sessionMap == null && createMap ) {
|
||||
sessionMap = new HashMap<SessionFactory,Session>();
|
||||
context.set( sessionMap );
|
||||
CONTEXT_TL.set( sessionMap );
|
||||
}
|
||||
return sessionMap;
|
||||
}
|
||||
|
||||
private static synchronized void doCleanup() {
|
||||
Map<SessionFactory,Session> sessionMap = sessionMap( false );
|
||||
final Map<SessionFactory,Session> sessionMap = sessionMap( false );
|
||||
if ( sessionMap != null ) {
|
||||
if ( sessionMap.isEmpty() ) {
|
||||
context.set( null );
|
||||
CONTEXT_TL.set( null );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,7 +42,6 @@ import org.hibernate.HibernateException;
|
|||
import org.hibernate.Session;
|
||||
import org.hibernate.SessionFactory;
|
||||
import org.hibernate.context.spi.AbstractCurrentSessionContext;
|
||||
import org.hibernate.context.spi.CurrentSessionContext;
|
||||
import org.hibernate.engine.jdbc.LobCreationContext;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.engine.spi.SessionImplementor;
|
||||
|
@ -51,35 +50,33 @@ import org.hibernate.event.spi.EventSource;
|
|||
import org.hibernate.internal.CoreMessageLogger;
|
||||
|
||||
/**
|
||||
* A {@link CurrentSessionContext} impl which scopes the notion of current
|
||||
* session by the current thread of execution. Unlike the JTA counterpart,
|
||||
* threads do not give us a nice hook to perform any type of cleanup making
|
||||
* it questionable for this impl to actually generate Session instances. In
|
||||
* the interest of usability, it was decided to have this default impl
|
||||
* actually generate a session upon first request and then clean it up
|
||||
* after the {@link org.hibernate.Transaction} associated with that session
|
||||
* is committed/rolled-back. In order for ensuring that happens, the sessions
|
||||
* generated here are unusable until after {@link Session#beginTransaction()}
|
||||
* has been called. If <tt>close()</tt> is called on a session managed by
|
||||
* this class, it will be automatically unbound.
|
||||
* <p/>
|
||||
* Additionally, the static {@link #bind} and {@link #unbind} methods are
|
||||
* provided to allow application code to explicitly control opening and
|
||||
* closing of these sessions. This, with some from of interception,
|
||||
* is the preferred approach. It also allows easy framework integration
|
||||
* and one possible approach for implementing long-sessions.
|
||||
* <p/>
|
||||
* The {@link #buildOrObtainSession}, {@link #isAutoCloseEnabled},
|
||||
* {@link #isAutoFlushEnabled}, {@link #getConnectionReleaseMode}, and
|
||||
* {@link #buildCleanupSynch} methods are all provided to allow easy
|
||||
* A {@link org.hibernate.context.spi.CurrentSessionContext} impl which scopes the notion of current
|
||||
* session by the current thread of execution. Unlike the JTA counterpart, threads do not give us a nice
|
||||
* hook to perform any type of cleanup making it questionable for this impl to actually generate Session
|
||||
* instances. In the interest of usability, it was decided to have this default impl actually generate
|
||||
* a session upon first request and then clean it up after the {@link org.hibernate.Transaction}
|
||||
* associated with that session is committed/rolled-back. In order for ensuring that happens, the
|
||||
* sessions generated here are unusable until after {@link Session#beginTransaction()} has been
|
||||
* called. If <tt>close()</tt> is called on a session managed by this class, it will be automatically
|
||||
* unbound.
|
||||
*
|
||||
* Additionally, the static {@link #bind} and {@link #unbind} methods are provided to allow application
|
||||
* code to explicitly control opening and closing of these sessions. This, with some from of interception,
|
||||
* is the preferred approach. It also allows easy framework integration and one possible approach for
|
||||
* implementing long-sessions.
|
||||
*
|
||||
* The {@link #buildOrObtainSession}, {@link #isAutoCloseEnabled}, {@link #isAutoFlushEnabled},
|
||||
* {@link #getConnectionReleaseMode}, and {@link #buildCleanupSynch} methods are all provided to allow easy
|
||||
* subclassing (for long-running session scenarios, for example).
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class ThreadLocalSessionContext extends AbstractCurrentSessionContext {
|
||||
private static final CoreMessageLogger LOG = Logger.getMessageLogger(
|
||||
CoreMessageLogger.class,
|
||||
ThreadLocalSessionContext.class.getName()
|
||||
);
|
||||
|
||||
private static final CoreMessageLogger LOG = Logger.getMessageLogger(CoreMessageLogger.class,
|
||||
ThreadLocalSessionContext.class.getName());
|
||||
private static final Class[] SESSION_PROXY_INTERFACES = new Class[] {
|
||||
Session.class,
|
||||
SessionImplementor.class,
|
||||
|
@ -91,11 +88,16 @@ public class ThreadLocalSessionContext extends AbstractCurrentSessionContext {
|
|||
/**
|
||||
* A ThreadLocal maintaining current sessions for the given execution thread.
|
||||
* The actual ThreadLocal variable is a java.util.Map to account for
|
||||
* the possibility for multiple SessionFactorys being used during execution
|
||||
* the possibility for multiple SessionFactory instances being used during execution
|
||||
* of the given thread.
|
||||
*/
|
||||
private static final ThreadLocal<Map> context = new ThreadLocal<Map>();
|
||||
private static final ThreadLocal<Map> CONTEXT_TL = new ThreadLocal<Map>();
|
||||
|
||||
/**
|
||||
* Constructs a ThreadLocal
|
||||
*
|
||||
* @param factory The factory this context will service
|
||||
*/
|
||||
public ThreadLocalSessionContext(SessionFactoryImplementor factory) {
|
||||
super( factory );
|
||||
}
|
||||
|
@ -122,10 +124,15 @@ public class ThreadLocalSessionContext extends AbstractCurrentSessionContext {
|
|||
|
||||
private boolean needsWrapping(Session session) {
|
||||
// try to make sure we don't wrap and already wrapped session
|
||||
return session != null
|
||||
&& ! Proxy.isProxyClass( session.getClass() )
|
||||
|| ( Proxy.getInvocationHandler( session ) != null
|
||||
&& ! ( Proxy.getInvocationHandler( session ) instanceof TransactionProtectionWrapper ) );
|
||||
if ( session != null ) {
|
||||
if ( Proxy.isProxyClass( session.getClass() ) ) {
|
||||
final InvocationHandler invocationHandler = Proxy.getInvocationHandler( session );
|
||||
if ( invocationHandler != null && TransactionProtectionWrapper.class.isInstance( invocationHandler ) ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -138,13 +145,14 @@ public class ThreadLocalSessionContext extends AbstractCurrentSessionContext {
|
|||
}
|
||||
|
||||
/**
|
||||
* Strictly provided for subclassing purposes; specifically to allow long-session
|
||||
* Strictly provided for sub-classing purposes; specifically to allow long-session
|
||||
* support.
|
||||
* <p/>
|
||||
* This implementation always just opens a new session.
|
||||
*
|
||||
* @return the built or (re)obtained session.
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
protected Session buildOrObtainSession() {
|
||||
return baseSessionBuilder()
|
||||
.autoClose( isAutoCloseEnabled() )
|
||||
|
@ -153,8 +161,8 @@ public class ThreadLocalSessionContext extends AbstractCurrentSessionContext {
|
|||
.openSession();
|
||||
}
|
||||
|
||||
protected CleanupSynch buildCleanupSynch() {
|
||||
return new CleanupSynch( factory() );
|
||||
protected CleanupSync buildCleanupSynch() {
|
||||
return new CleanupSync( factory() );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -185,8 +193,8 @@ public class ThreadLocalSessionContext extends AbstractCurrentSessionContext {
|
|||
}
|
||||
|
||||
protected Session wrap(Session session) {
|
||||
TransactionProtectionWrapper wrapper = new TransactionProtectionWrapper( session );
|
||||
Session wrapped = ( Session ) Proxy.newProxyInstance(
|
||||
final TransactionProtectionWrapper wrapper = new TransactionProtectionWrapper( session );
|
||||
final Session wrapped = (Session) Proxy.newProxyInstance(
|
||||
Session.class.getClassLoader(),
|
||||
SESSION_PROXY_INTERFACES,
|
||||
wrapper
|
||||
|
@ -202,13 +210,13 @@ public class ThreadLocalSessionContext extends AbstractCurrentSessionContext {
|
|||
* @param session The session to bind.
|
||||
*/
|
||||
public static void bind(org.hibernate.Session session) {
|
||||
SessionFactory factory = session.getSessionFactory();
|
||||
final SessionFactory factory = session.getSessionFactory();
|
||||
cleanupAnyOrphanedSession( factory );
|
||||
doBind( session, factory );
|
||||
}
|
||||
|
||||
private static void cleanupAnyOrphanedSession(SessionFactory factory) {
|
||||
Session orphan = doUnbind( factory, false );
|
||||
final Session orphan = doUnbind( factory, false );
|
||||
if ( orphan != null ) {
|
||||
LOG.alreadySessionBound();
|
||||
try {
|
||||
|
@ -239,7 +247,7 @@ public class ThreadLocalSessionContext extends AbstractCurrentSessionContext {
|
|||
}
|
||||
|
||||
private static Session existingSession(SessionFactory factory) {
|
||||
Map sessionMap = sessionMap();
|
||||
final Map sessionMap = sessionMap();
|
||||
if ( sessionMap == null ) {
|
||||
return null;
|
||||
}
|
||||
|
@ -247,7 +255,7 @@ public class ThreadLocalSessionContext extends AbstractCurrentSessionContext {
|
|||
}
|
||||
|
||||
protected static Map sessionMap() {
|
||||
return context.get();
|
||||
return CONTEXT_TL.get();
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
|
@ -255,42 +263,38 @@ public class ThreadLocalSessionContext extends AbstractCurrentSessionContext {
|
|||
Map sessionMap = sessionMap();
|
||||
if ( sessionMap == null ) {
|
||||
sessionMap = new HashMap();
|
||||
context.set( sessionMap );
|
||||
CONTEXT_TL.set( sessionMap );
|
||||
}
|
||||
sessionMap.put( factory, session );
|
||||
}
|
||||
|
||||
private static Session doUnbind(SessionFactory factory, boolean releaseMapIfEmpty) {
|
||||
Map sessionMap = sessionMap();
|
||||
Session session = null;
|
||||
final Map sessionMap = sessionMap();
|
||||
if ( sessionMap != null ) {
|
||||
session = ( Session ) sessionMap.remove( factory );
|
||||
session = (Session) sessionMap.remove( factory );
|
||||
if ( releaseMapIfEmpty && sessionMap.isEmpty() ) {
|
||||
context.set( null );
|
||||
CONTEXT_TL.set( null );
|
||||
}
|
||||
}
|
||||
return session;
|
||||
}
|
||||
|
||||
/**
|
||||
* JTA transaction synch used for cleanup of the internal session map.
|
||||
* Transaction sync used for cleanup of the internal session map.
|
||||
*/
|
||||
protected static class CleanupSynch implements Synchronization, Serializable {
|
||||
protected static class CleanupSync implements Synchronization, Serializable {
|
||||
protected final SessionFactory factory;
|
||||
|
||||
public CleanupSynch(SessionFactory factory) {
|
||||
public CleanupSync(SessionFactory factory) {
|
||||
this.factory = factory;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void beforeCompletion() {
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void afterCompletion(int i) {
|
||||
unbind( factory );
|
||||
}
|
||||
|
@ -304,9 +308,7 @@ public class ThreadLocalSessionContext extends AbstractCurrentSessionContext {
|
|||
this.realSession = realSession;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
|
||||
final String methodName = method.getName();
|
||||
try {
|
||||
|
@ -319,9 +321,9 @@ public class ThreadLocalSessionContext extends AbstractCurrentSessionContext {
|
|||
|| "hashCode".equals( methodName )
|
||||
|| "getStatistics".equals( methodName )
|
||||
|| "isOpen".equals( methodName )
|
||||
|| "getListeners".equals( methodName )
|
||||
) {
|
||||
|| "getListeners".equals( methodName ) ) {
|
||||
// allow these to go through the the real session no matter what
|
||||
LOG.tracef( "Allowing invocation [%s] to proceed to real session", methodName );
|
||||
}
|
||||
else if ( !realSession.isOpen() ) {
|
||||
// essentially, if the real session is closed allow any
|
||||
|
@ -329,6 +331,7 @@ public class ThreadLocalSessionContext extends AbstractCurrentSessionContext {
|
|||
// will complain by throwing an appropriate exception;
|
||||
// NOTE that allowing close() above has the same basic effect,
|
||||
// but we capture that there simply to doAfterTransactionCompletion the unbind...
|
||||
LOG.tracef( "Allowing invocation [%s] to proceed to real (closed) session", methodName );
|
||||
}
|
||||
else if ( !realSession.getTransaction().isActive() ) {
|
||||
// limit the methods available if no transaction is active
|
||||
|
@ -339,20 +342,23 @@ public class ThreadLocalSessionContext extends AbstractCurrentSessionContext {
|
|||
|| "getFactory".equals( methodName )
|
||||
|| "getSessionFactory".equals( methodName )
|
||||
|| "getTenantIdentifier".equals( methodName ) ) {
|
||||
LOG.tracev( "Allowing method [{0}] in non-transacted context", methodName );
|
||||
LOG.tracef( "Allowing invocation [%s] to proceed to real (non-transacted) session", methodName );
|
||||
}
|
||||
else if ( "reconnect".equals( methodName ) || "disconnect".equals( methodName ) ) {
|
||||
// allow these (deprecated) methods to pass through
|
||||
LOG.tracef( "Allowing invocation [%s] to proceed to real (non-transacted) session - deprecated methods", methodName );
|
||||
}
|
||||
else {
|
||||
throw new HibernateException( methodName + " is not valid without active transaction" );
|
||||
}
|
||||
}
|
||||
LOG.tracev( "Allowing proxied method [{0}] to proceed to real session", methodName );
|
||||
LOG.tracef( "Allowing proxy invocation [%s] to proceed to real session", methodName );
|
||||
return method.invoke( realSession, args );
|
||||
}
|
||||
catch ( InvocationTargetException e ) {
|
||||
if (e.getTargetException() instanceof RuntimeException) throw (RuntimeException)e.getTargetException();
|
||||
if (e.getTargetException() instanceof RuntimeException) {
|
||||
throw (RuntimeException)e.getTargetException();
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
/**
|
||||
* Internal implementations and support around "current session" handling.
|
||||
*/
|
||||
package org.hibernate.context.internal;
|
|
@ -0,0 +1,4 @@
|
|||
/**
|
||||
* Defines support for "current session" feature.
|
||||
*/
|
||||
package org.hibernate.context;
|
|
@ -41,6 +41,11 @@ public abstract class AbstractCurrentSessionContext implements CurrentSessionCon
|
|||
this.factory = factory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Access to the SessionFactory
|
||||
*
|
||||
* @return The SessionFactory being serviced by this context
|
||||
*/
|
||||
public SessionFactoryImplementor factory() {
|
||||
return factory;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
/**
|
||||
* SPI level contracts around "current session" support.
|
||||
*/
|
||||
package org.hibernate.context.spi;
|
|
@ -1,10 +1,10 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
|
||||
* Copyright (c) 2008, 2013, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Middleware LLC.
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
|
@ -20,7 +20,6 @@
|
|||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
package org.hibernate.criterion;
|
||||
import org.hibernate.Criteria;
|
||||
|
@ -37,7 +36,7 @@ import org.hibernate.type.CollectionType;
|
|||
import org.hibernate.type.Type;
|
||||
|
||||
/**
|
||||
* Implementation of AbstractEmptinessExpression.
|
||||
* Base expression implementation for (not) emptiness checking of collection properties
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
|
@ -51,21 +50,26 @@ public abstract class AbstractEmptinessExpression implements Criterion {
|
|||
this.propertyName = propertyName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Should empty rows be excluded?
|
||||
*
|
||||
* @return {@code true} Indicates the expression should be 'exists'; {@code false} indicates 'not exists'
|
||||
*/
|
||||
protected abstract boolean excludeEmpty();
|
||||
|
||||
@Override
|
||||
public final String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException {
|
||||
String entityName = criteriaQuery.getEntityName( criteria, propertyName );
|
||||
String actualPropertyName = criteriaQuery.getPropertyName( propertyName );
|
||||
String sqlAlias = criteriaQuery.getSQLAlias( criteria, propertyName );
|
||||
final String entityName = criteriaQuery.getEntityName( criteria, propertyName );
|
||||
final String actualPropertyName = criteriaQuery.getPropertyName( propertyName );
|
||||
final String sqlAlias = criteriaQuery.getSQLAlias( criteria, propertyName );
|
||||
|
||||
SessionFactoryImplementor factory = criteriaQuery.getFactory();
|
||||
QueryableCollection collectionPersister = getQueryableCollection( entityName, actualPropertyName, factory );
|
||||
final SessionFactoryImplementor factory = criteriaQuery.getFactory();
|
||||
final QueryableCollection collectionPersister = getQueryableCollection( entityName, actualPropertyName, factory );
|
||||
|
||||
String[] collectionKeys = collectionPersister.getKeyColumnNames();
|
||||
String[] ownerKeys = ( ( Loadable ) factory.getEntityPersister( entityName ) ).getIdentifierColumnNames();
|
||||
final String[] collectionKeys = collectionPersister.getKeyColumnNames();
|
||||
final String[] ownerKeys = ( (Loadable) factory.getEntityPersister( entityName ) ).getIdentifierColumnNames();
|
||||
|
||||
String innerSelect = "(select 1 from " + collectionPersister.getTableName()
|
||||
+ " where "
|
||||
final String innerSelect = "(select 1 from " + collectionPersister.getTableName() + " where "
|
||||
+ new ConditionFragment().setTableAlias( sqlAlias ).setCondition( ownerKeys, collectionKeys ).toFragmentString()
|
||||
+ ")";
|
||||
|
||||
|
@ -75,19 +79,21 @@ public abstract class AbstractEmptinessExpression implements Criterion {
|
|||
}
|
||||
|
||||
|
||||
protected QueryableCollection getQueryableCollection(String entityName, String propertyName, SessionFactoryImplementor factory)
|
||||
throws HibernateException {
|
||||
PropertyMapping ownerMapping = ( PropertyMapping ) factory.getEntityPersister( entityName );
|
||||
Type type = ownerMapping.toType( propertyName );
|
||||
protected QueryableCollection getQueryableCollection(
|
||||
String entityName,
|
||||
String propertyName,
|
||||
SessionFactoryImplementor factory) throws HibernateException {
|
||||
final PropertyMapping ownerMapping = (PropertyMapping) factory.getEntityPersister( entityName );
|
||||
final Type type = ownerMapping.toType( propertyName );
|
||||
if ( !type.isCollectionType() ) {
|
||||
throw new MappingException(
|
||||
"Property path [" + entityName + "." + propertyName + "] does not reference a collection"
|
||||
);
|
||||
}
|
||||
|
||||
String role = ( ( CollectionType ) type ).getRole();
|
||||
final String role = ( (CollectionType) type ).getRole();
|
||||
try {
|
||||
return ( QueryableCollection ) factory.getCollectionPersister( role );
|
||||
return (QueryableCollection) factory.getCollectionPersister( role );
|
||||
}
|
||||
catch ( ClassCastException cce ) {
|
||||
throw new QueryException( "collection role is not queryable: " + role );
|
||||
|
@ -97,11 +103,13 @@ public abstract class AbstractEmptinessExpression implements Criterion {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final TypedValue[] getTypedValues(Criteria criteria, CriteriaQuery criteriaQuery)
|
||||
throws HibernateException {
|
||||
return NO_VALUES;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String toString() {
|
||||
return propertyName + ( excludeEmpty() ? " is not empty" : " is empty" );
|
||||
}
|
||||
|
|
|
@ -52,13 +52,7 @@ public class AggregateProjection extends SimpleProjection {
|
|||
return propertyName;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return functionName + "(" + propertyName + ')';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public Type[] getTypes(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException {
|
||||
return new Type[] {
|
||||
getFunction( criteriaQuery ).getReturnType(
|
||||
|
@ -68,9 +62,7 @@ public class AggregateProjection extends SimpleProjection {
|
|||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public String toSqlString(Criteria criteria, int loc, CriteriaQuery criteriaQuery) throws HibernateException {
|
||||
final String functionFragment = getFunction( criteriaQuery ).render(
|
||||
criteriaQuery.getType( criteria, getPropertyName() ),
|
||||
|
@ -85,7 +77,7 @@ public class AggregateProjection extends SimpleProjection {
|
|||
}
|
||||
|
||||
protected SQLFunction getFunction(String functionName, CriteriaQuery criteriaQuery) {
|
||||
SQLFunction function = criteriaQuery.getFactory()
|
||||
final SQLFunction function = criteriaQuery.getFactory()
|
||||
.getSqlFunctionRegistry()
|
||||
.findSQLFunction( functionName );
|
||||
if ( function == null ) {
|
||||
|
@ -101,4 +93,10 @@ public class AggregateProjection extends SimpleProjection {
|
|||
protected List buildFunctionParameterList(String column) {
|
||||
return Collections.singletonList( column );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return functionName + "(" + propertyName + ')';
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
|
||||
* Copyright (c) 2008, 2013, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Middleware LLC.
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
|
@ -20,7 +20,6 @@
|
|||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
package org.hibernate.criterion;
|
||||
import org.hibernate.Criteria;
|
||||
|
@ -28,71 +27,80 @@ import org.hibernate.HibernateException;
|
|||
import org.hibernate.type.Type;
|
||||
|
||||
/**
|
||||
* Represents a projection that specifies an alias
|
||||
*
|
||||
* @author Gavin King
|
||||
*/
|
||||
public class AliasedProjection implements EnhancedProjection {
|
||||
|
||||
private final Projection projection;
|
||||
private final String alias;
|
||||
|
||||
public String toString() {
|
||||
return projection.toString() + " as " + alias;
|
||||
}
|
||||
|
||||
protected AliasedProjection(Projection projection, String alias) {
|
||||
this.projection = projection;
|
||||
this.alias = alias;
|
||||
}
|
||||
|
||||
public String toSqlString(Criteria criteria, int position, CriteriaQuery criteriaQuery)
|
||||
throws HibernateException {
|
||||
return projection.toSqlString(criteria, position, criteriaQuery);
|
||||
@Override
|
||||
public String toSqlString(Criteria criteria, int position, CriteriaQuery criteriaQuery) throws HibernateException {
|
||||
return projection.toSqlString( criteria, position, criteriaQuery );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toGroupSqlString(Criteria criteria, CriteriaQuery criteriaQuery) {
|
||||
return projection.toGroupSqlString(criteria, criteriaQuery);
|
||||
return projection.toGroupSqlString( criteria, criteriaQuery );
|
||||
}
|
||||
|
||||
public Type[] getTypes(Criteria criteria, CriteriaQuery criteriaQuery)
|
||||
throws HibernateException {
|
||||
return projection.getTypes(criteria, criteriaQuery);
|
||||
@Override
|
||||
public Type[] getTypes(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException {
|
||||
return projection.getTypes( criteria, criteriaQuery );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getColumnAliases(int loc) {
|
||||
return projection.getColumnAliases(loc);
|
||||
return projection.getColumnAliases( loc );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getColumnAliases(int loc, Criteria criteria, CriteriaQuery criteriaQuery) {
|
||||
return projection instanceof EnhancedProjection ?
|
||||
( ( EnhancedProjection ) projection ).getColumnAliases( loc, criteria, criteriaQuery ) :
|
||||
getColumnAliases( loc );
|
||||
return projection instanceof EnhancedProjection
|
||||
? ( (EnhancedProjection) projection ).getColumnAliases( loc, criteria, criteriaQuery )
|
||||
: getColumnAliases( loc );
|
||||
}
|
||||
|
||||
public Type[] getTypes(String alias, Criteria criteria, CriteriaQuery criteriaQuery)
|
||||
throws HibernateException {
|
||||
return this.alias.equals(alias) ?
|
||||
getTypes(criteria, criteriaQuery) :
|
||||
null;
|
||||
@Override
|
||||
public Type[] getTypes(String alias, Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException {
|
||||
return this.alias.equals( alias )
|
||||
? getTypes( criteria, criteriaQuery )
|
||||
: null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getColumnAliases(String alias, int loc) {
|
||||
return this.alias.equals(alias) ?
|
||||
getColumnAliases(loc) :
|
||||
null;
|
||||
return this.alias.equals( alias )
|
||||
? getColumnAliases( loc )
|
||||
: null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getColumnAliases(String alias, int loc, Criteria criteria, CriteriaQuery criteriaQuery) {
|
||||
return this.alias.equals(alias) ?
|
||||
getColumnAliases( loc, criteria, criteriaQuery ) :
|
||||
null;
|
||||
return this.alias.equals( alias )
|
||||
? getColumnAliases( loc, criteria, criteriaQuery )
|
||||
: null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getAliases() {
|
||||
return new String[]{ alias };
|
||||
return new String[] { alias };
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isGrouped() {
|
||||
return projection.isGrouped();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return projection.toString() + " as " + alias;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -23,14 +23,18 @@
|
|||
*/
|
||||
package org.hibernate.criterion;
|
||||
|
||||
|
||||
/**
|
||||
* An avg() projection
|
||||
*
|
||||
* @author Gavin King
|
||||
*/
|
||||
public class AvgProjection extends AggregateProjection {
|
||||
/**
|
||||
* Constructs the AvgProjection
|
||||
*
|
||||
* @param propertyName The name of the property to average
|
||||
*/
|
||||
public AvgProjection(String propertyName) {
|
||||
super("avg", propertyName);
|
||||
super( "avg", propertyName );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
|
||||
* Copyright (c) 2008, 2013, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Middleware LLC.
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
|
@ -20,9 +20,9 @@
|
|||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
package org.hibernate.criterion;
|
||||
|
||||
import org.hibernate.Criteria;
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.engine.spi.TypedValue;
|
||||
|
@ -30,10 +30,10 @@ import org.hibernate.internal.util.StringHelper;
|
|||
|
||||
/**
|
||||
* Constrains a property to between two values
|
||||
*
|
||||
* @author Gavin King
|
||||
*/
|
||||
public class BetweenExpression implements Criterion {
|
||||
|
||||
private final String propertyName;
|
||||
private final Object lo;
|
||||
private final Object hi;
|
||||
|
@ -44,24 +44,22 @@ public class BetweenExpression implements Criterion {
|
|||
this.hi = hi;
|
||||
}
|
||||
|
||||
public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery)
|
||||
throws HibernateException {
|
||||
return StringHelper.join(
|
||||
" and ",
|
||||
StringHelper.suffix( criteriaQuery.findColumns(propertyName, criteria), " between ? and ?" )
|
||||
);
|
||||
|
||||
//TODO: get SQL rendering out of this package!
|
||||
@Override
|
||||
public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException {
|
||||
final String[] columns = criteriaQuery.findColumns( propertyName, criteria );
|
||||
final String[] expressions = StringHelper.suffix( columns, " between ? and ?" );
|
||||
return StringHelper.join( " and ", expressions );
|
||||
}
|
||||
|
||||
public TypedValue[] getTypedValues(Criteria criteria, CriteriaQuery criteriaQuery)
|
||||
throws HibernateException {
|
||||
@Override
|
||||
public TypedValue[] getTypedValues(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException {
|
||||
return new TypedValue[] {
|
||||
criteriaQuery.getTypedValue(criteria, propertyName, lo),
|
||||
criteriaQuery.getTypedValue(criteria, propertyName, hi)
|
||||
criteriaQuery.getTypedValue( criteria, propertyName, lo ),
|
||||
criteriaQuery.getTypedValue( criteria, propertyName, hi )
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return propertyName + " between " + lo + " and " + hi;
|
||||
}
|
||||
|
|
|
@ -24,10 +24,22 @@
|
|||
package org.hibernate.criterion;
|
||||
|
||||
/**
|
||||
* Defines a conjunction (AND series).
|
||||
*
|
||||
* @author Gavin King
|
||||
* @author Steve Ebersole
|
||||
*
|
||||
* @see Disjunction
|
||||
*/
|
||||
public class Conjunction extends Junction {
|
||||
/**
|
||||
* Constructs a Conjunction
|
||||
*/
|
||||
public Conjunction() {
|
||||
super( Nature.AND );
|
||||
}
|
||||
|
||||
protected Conjunction(Criterion... criterion) {
|
||||
super( Nature.AND, criterion );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,16 +29,50 @@ import java.util.List;
|
|||
import org.hibernate.Criteria;
|
||||
|
||||
/**
|
||||
* A count
|
||||
* A count projection
|
||||
*
|
||||
* @author Gavin King
|
||||
*/
|
||||
public class CountProjection extends AggregateProjection {
|
||||
private boolean distinct;
|
||||
|
||||
/**
|
||||
* Constructs the count projection.
|
||||
*
|
||||
* @param prop The property name
|
||||
*
|
||||
* @see Projections#count(String)
|
||||
* @see Projections#countDistinct(String)
|
||||
*/
|
||||
protected CountProjection(String prop) {
|
||||
super("count", prop);
|
||||
super( "count", prop );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List buildFunctionParameterList(Criteria criteria, CriteriaQuery criteriaQuery) {
|
||||
final String[] cols = criteriaQuery.getColumns( propertyName, criteria );
|
||||
return ( distinct ? buildCountDistinctParameterList( cols ) : Arrays.asList( cols ) );
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private List buildCountDistinctParameterList(String[] cols) {
|
||||
final List params = new ArrayList( cols.length + 1 );
|
||||
params.add( "distinct" );
|
||||
params.addAll( Arrays.asList( cols ) );
|
||||
return params;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the count as being distinct
|
||||
*
|
||||
* @return {@code this}, for method chaining
|
||||
*/
|
||||
public CountProjection setDistinct() {
|
||||
distinct = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
if ( distinct ) {
|
||||
return "distinct " + super.toString();
|
||||
|
@ -48,20 +82,4 @@ public class CountProjection extends AggregateProjection {
|
|||
}
|
||||
}
|
||||
|
||||
protected List buildFunctionParameterList(Criteria criteria, CriteriaQuery criteriaQuery) {
|
||||
String cols[] = criteriaQuery.getColumns( propertyName, criteria );
|
||||
return ( distinct ? buildCountDistinctParameterList( cols ) : Arrays.asList( cols ) );
|
||||
}
|
||||
|
||||
private List buildCountDistinctParameterList(String[] cols) {
|
||||
List params = new ArrayList( cols.length + 1 );
|
||||
params.add( "distinct" );
|
||||
params.addAll( Arrays.asList( cols ) );
|
||||
return params;
|
||||
}
|
||||
|
||||
public CountProjection setDistinct() {
|
||||
distinct = true;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
|
||||
* Copyright (c) 2008, 2013, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Middleware LLC.
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
|
@ -20,9 +20,9 @@
|
|||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
package org.hibernate.criterion;
|
||||
|
||||
import org.hibernate.Criteria;
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
|
@ -38,93 +38,183 @@ import org.hibernate.type.Type;
|
|||
* @author Gavin King
|
||||
*/
|
||||
public interface CriteriaQuery {
|
||||
/**
|
||||
* Provides access to the SessionFactory
|
||||
*
|
||||
* @return The SessionFactory
|
||||
*/
|
||||
public SessionFactoryImplementor getFactory();
|
||||
|
||||
/**
|
||||
* Get the names of the columns mapped by a property path,
|
||||
* ignoring projection aliases
|
||||
* @throws org.hibernate.QueryException if the property maps to more than 1 column
|
||||
* Resolve a property path to the name of the column it maps to. Ignores projection aliases.
|
||||
*
|
||||
* @param criteria The overall criteria
|
||||
* @param propertyPath The property path to resolve
|
||||
*
|
||||
* @return The column name
|
||||
*
|
||||
* @throws HibernateException if the property maps to more than 1 column, or if the property could not be resolved
|
||||
*
|
||||
* @see #getColumns
|
||||
*/
|
||||
public String getColumn(Criteria criteria, String propertyPath)
|
||||
throws HibernateException;
|
||||
public String getColumn(Criteria criteria, String propertyPath) throws HibernateException;
|
||||
|
||||
/**
|
||||
* Get the names of the columns mapped by a property path,
|
||||
* ignoring projection aliases
|
||||
* Resolve a property path to the names of the columns it maps to. Ignores projection aliases
|
||||
*
|
||||
* @param criteria The criteria
|
||||
* @param propertyPath The property path to resolve
|
||||
*
|
||||
* @return The column names
|
||||
*
|
||||
* @throws HibernateException if the property maps to more than 1 column, or if the property could not be resolved
|
||||
*/
|
||||
public String[] getColumns(String propertyPath, Criteria criteria)
|
||||
throws HibernateException;
|
||||
public String[] getColumns(String propertyPath, Criteria criteria) throws HibernateException;
|
||||
|
||||
/**
|
||||
* Get the names of the columns mapped by a property path; if the
|
||||
* property path is not found in criteria, try the "outer" query.
|
||||
* Projection aliases are ignored.
|
||||
* Get the names of the columns mapped by a property path; if the property path is not found in criteria, try
|
||||
* the "outer" query. Projection aliases are ignored.
|
||||
*
|
||||
* @param criteria The criteria
|
||||
* @param propertyPath The property path to resolve
|
||||
*
|
||||
* @return The column names
|
||||
*
|
||||
* @throws HibernateException if the property could not be resolved
|
||||
*/
|
||||
public String[] findColumns(String propertyPath, Criteria criteria)
|
||||
throws HibernateException;
|
||||
public String[] findColumns(String propertyPath, Criteria criteria) throws HibernateException;
|
||||
|
||||
/**
|
||||
* Get the type of a property path, ignoring projection aliases
|
||||
* Get the type of a property path.
|
||||
*
|
||||
* @param criteria The criteria
|
||||
* @param propertyPath The property path to resolve
|
||||
*
|
||||
* @return The type
|
||||
*
|
||||
* @throws HibernateException if the property could not be resolved
|
||||
*/
|
||||
public Type getType(Criteria criteria, String propertyPath)
|
||||
throws HibernateException;
|
||||
public Type getType(Criteria criteria, String propertyPath) throws HibernateException;
|
||||
|
||||
/**
|
||||
* Get the names of the columns mapped by a property path
|
||||
* Get the names of the columns mapped by a property path. Here, the property path can refer to
|
||||
* a projection alias.
|
||||
*
|
||||
* @param criteria The criteria
|
||||
* @param propertyPath The property path to resolve or projection alias
|
||||
*
|
||||
* @return The column names
|
||||
*
|
||||
* @throws HibernateException if the property/alias could not be resolved
|
||||
*/
|
||||
public String[] getColumnsUsingProjection(Criteria criteria, String propertyPath)
|
||||
throws HibernateException;
|
||||
public String[] getColumnsUsingProjection(Criteria criteria, String propertyPath) throws HibernateException;
|
||||
|
||||
/**
|
||||
* Get the type of a property path
|
||||
* Get the type of a property path. Here, the property path can refer to a projection alias.
|
||||
*
|
||||
* @param criteria The criteria
|
||||
* @param propertyPath The property path to resolve or projection alias
|
||||
*
|
||||
* @return The type
|
||||
*
|
||||
* @throws HibernateException if the property/alias could not be resolved
|
||||
*/
|
||||
public Type getTypeUsingProjection(Criteria criteria, String propertyPath)
|
||||
throws HibernateException;
|
||||
public Type getTypeUsingProjection(Criteria criteria, String propertyPath) throws HibernateException;
|
||||
|
||||
/**
|
||||
* Get the a typed value for the given property value.
|
||||
* Build a typed-value for the property/value combo. Essentially the same as manually building a TypedValue
|
||||
* using the given value and the resolved type using {@link #getTypeUsingProjection}.
|
||||
*
|
||||
* @param criteria The criteria query
|
||||
* @param propertyPath The property path/alias to resolve to type.
|
||||
* @param value The value
|
||||
*
|
||||
* @return The TypedValue
|
||||
*
|
||||
* @throws HibernateException if the property/alias could not be resolved
|
||||
*/
|
||||
public TypedValue getTypedValue(Criteria criteria, String propertyPath, Object value)
|
||||
throws HibernateException;
|
||||
public TypedValue getTypedValue(Criteria criteria, String propertyPath, Object value) throws HibernateException;
|
||||
|
||||
/**
|
||||
* Get the entity name of an entity
|
||||
*
|
||||
* @param criteria The criteria
|
||||
*
|
||||
* @return The entity name
|
||||
*/
|
||||
public String getEntityName(Criteria criteria);
|
||||
|
||||
/**
|
||||
* Get the entity name of an entity, taking into account
|
||||
* the qualifier of the property path
|
||||
* Get the entity name of an entity, taking into account the qualifier of the property path
|
||||
*
|
||||
* @param criteria The criteria
|
||||
* @param propertyPath The property path that (supposedly) references an entity
|
||||
*
|
||||
* @return The entity name
|
||||
*/
|
||||
public String getEntityName(Criteria criteria, String propertyPath);
|
||||
|
||||
/**
|
||||
* Get the root table alias of an entity
|
||||
*
|
||||
* @param criteria The criteria
|
||||
*
|
||||
* @return The SQL table alias for the given criteria
|
||||
*/
|
||||
public String getSQLAlias(Criteria subcriteria);
|
||||
public String getSQLAlias(Criteria criteria);
|
||||
|
||||
/**
|
||||
* Get the root table alias of an entity, taking into account
|
||||
* the qualifier of the property path
|
||||
*
|
||||
* @param criteria The criteria
|
||||
* @param propertyPath The property path whose SQL alias should be returned.
|
||||
*
|
||||
* @return The SQL table alias for the given criteria
|
||||
*/
|
||||
public String getSQLAlias(Criteria criteria, String propertyPath);
|
||||
|
||||
/**
|
||||
* Get the property name, given a possibly qualified property name
|
||||
*
|
||||
* @param propertyName The (possibly qualified) property name
|
||||
*
|
||||
* @return The simple property name
|
||||
*/
|
||||
public String getPropertyName(String propertyName);
|
||||
|
||||
/**
|
||||
* Get the identifier column names of this entity
|
||||
*
|
||||
* @param criteria The criteria
|
||||
*
|
||||
* @return The identifier column names
|
||||
*/
|
||||
public String[] getIdentifierColumns(Criteria subcriteria);
|
||||
public String[] getIdentifierColumns(Criteria criteria);
|
||||
|
||||
/**
|
||||
* Get the identifier type of this entity
|
||||
*
|
||||
* @param criteria The criteria
|
||||
*
|
||||
* @return The identifier type.
|
||||
*/
|
||||
public Type getIdentifierType(Criteria subcriteria);
|
||||
public Type getIdentifierType(Criteria criteria);
|
||||
|
||||
public TypedValue getTypedIdentifierValue(Criteria subcriteria, Object value);
|
||||
/**
|
||||
* Build a TypedValue for the given identifier value.
|
||||
*
|
||||
* @param criteria The criteria whose identifier is referenced.
|
||||
* @param value The identifier value
|
||||
*
|
||||
* @return The TypedValue
|
||||
*/
|
||||
public TypedValue getTypedIdentifierValue(Criteria criteria, Object value);
|
||||
|
||||
/**
|
||||
* Generate a unique SQL alias
|
||||
*
|
||||
* @return The generated alias
|
||||
*/
|
||||
public String generateSQLAlias();
|
||||
}
|
|
@ -1,10 +1,10 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
|
||||
* Copyright (c) 2008, 2013, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Middleware LLC.
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
|
@ -20,9 +20,9 @@
|
|||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
package org.hibernate.criterion;
|
||||
|
||||
import org.hibernate.sql.JoinType;
|
||||
import org.hibernate.transform.AliasToEntityMapResultTransformer;
|
||||
import org.hibernate.transform.DistinctRootEntityResultTransformer;
|
||||
|
@ -31,6 +31,8 @@ import org.hibernate.transform.ResultTransformer;
|
|||
import org.hibernate.transform.RootEntityResultTransformer;
|
||||
|
||||
/**
|
||||
* Commonality between different types of Criteria.
|
||||
*
|
||||
* @author Gavin King
|
||||
*/
|
||||
public interface CriteriaSpecification {
|
||||
|
@ -62,24 +64,27 @@ public interface CriteriaSpecification {
|
|||
|
||||
/**
|
||||
* Specifies joining to an entity based on an inner join.
|
||||
* @deprecated use {@link JoinType#INNER_JOIN}
|
||||
*
|
||||
* @deprecated use {@link org.hibernate.sql.JoinType#INNER_JOIN}
|
||||
*/
|
||||
@Deprecated
|
||||
public static final int INNER_JOIN = org.hibernate.sql.JoinFragment.INNER_JOIN;
|
||||
public static final int INNER_JOIN = JoinType.INNER_JOIN.getJoinTypeValue();
|
||||
|
||||
/**
|
||||
* Specifies joining to an entity based on a full join.
|
||||
* @deprecated use {@link JoinType#FULL_JOIN}
|
||||
*
|
||||
* @deprecated use {@link org.hibernate.sql.JoinType#FULL_JOIN}
|
||||
*/
|
||||
@Deprecated
|
||||
public static final int FULL_JOIN = org.hibernate.sql.JoinFragment.FULL_JOIN;
|
||||
public static final int FULL_JOIN = JoinType.FULL_JOIN.getJoinTypeValue();
|
||||
|
||||
/**
|
||||
* Specifies joining to an entity based on a left outer join.
|
||||
* @deprecated use {@link JoinType#LEFT_OUTER_JOIN}
|
||||
*
|
||||
* @deprecated use {@link org.hibernate.sql.JoinType#LEFT_OUTER_JOIN}
|
||||
*/
|
||||
@Deprecated
|
||||
public static final int LEFT_JOIN = org.hibernate.sql.JoinFragment.LEFT_OUTER_JOIN;
|
||||
public static final int LEFT_JOIN = JoinType.LEFT_OUTER_JOIN.getJoinTypeValue();
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
|
||||
* Copyright (c) 2008, 2013, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Middleware LLC.
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
|
@ -20,14 +20,13 @@
|
|||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
package org.hibernate.criterion;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.hibernate.Criteria;
|
||||
import org.hibernate.FetchMode;
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.LockMode;
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.engine.spi.SessionImplementor;
|
||||
|
@ -36,29 +35,36 @@ import org.hibernate.sql.JoinType;
|
|||
import org.hibernate.transform.ResultTransformer;
|
||||
|
||||
/**
|
||||
* Some applications need to create criteria queries in "detached
|
||||
* mode", where the Hibernate session is not available. This class
|
||||
* may be instantiated anywhere, and then a <literal>Criteria</literal>
|
||||
* may be obtained by passing a session to
|
||||
* <literal>getExecutableCriteria()</literal>. All methods have the
|
||||
* same semantics and behavior as the corresponding methods of the
|
||||
* <literal>Criteria</literal> interface.
|
||||
* Models a detached form of a Criteria (not associated with a Session).
|
||||
*
|
||||
* Some applications need to create criteria queries in "detached mode", where the Hibernate Session is
|
||||
* not available. Applications would create a DetachableCriteria to describe the query, and then later
|
||||
* associated it with a Session to obtain the "executable" Criteria:
|
||||
* <code>
|
||||
* DetachedCriteria detached = new DetachedCriteria();
|
||||
* ...
|
||||
* Criteria criteria = detached.getExecutableCriteria( session );
|
||||
* ...
|
||||
* criteria.list();
|
||||
* </code>
|
||||
*
|
||||
* All methods have the same semantics and behavior as the corresponding methods of the Criteria interface.
|
||||
*
|
||||
* @author Gavin King
|
||||
*
|
||||
* @see org.hibernate.Criteria
|
||||
* @author Gavin King
|
||||
*/
|
||||
public class DetachedCriteria implements CriteriaSpecification, Serializable {
|
||||
|
||||
private final CriteriaImpl impl;
|
||||
private final Criteria criteria;
|
||||
|
||||
protected DetachedCriteria(String entityName) {
|
||||
impl = new CriteriaImpl(entityName, null);
|
||||
impl = new CriteriaImpl( entityName, null );
|
||||
criteria = impl;
|
||||
}
|
||||
|
||||
protected DetachedCriteria(String entityName, String alias) {
|
||||
impl = new CriteriaImpl(entityName, alias, null);
|
||||
impl = new CriteriaImpl( entityName, alias, null );
|
||||
criteria = impl;
|
||||
}
|
||||
|
||||
|
@ -68,154 +74,373 @@ public class DetachedCriteria implements CriteriaSpecification, Serializable {
|
|||
}
|
||||
|
||||
/**
|
||||
* Get an executable instance of <literal>Criteria</literal>,
|
||||
* to actually run the query.
|
||||
* Get an executable instance of Criteria to actually run the query.
|
||||
*
|
||||
* @param session The session to associate the built Criteria with
|
||||
*
|
||||
* @return The "executable" Criteria
|
||||
*/
|
||||
public Criteria getExecutableCriteria(Session session) {
|
||||
impl.setSession( ( SessionImplementor ) session );
|
||||
impl.setSession( (SessionImplementor) session );
|
||||
return impl;
|
||||
}
|
||||
|
||||
public static DetachedCriteria forEntityName(String entityName) {
|
||||
return new DetachedCriteria(entityName);
|
||||
}
|
||||
|
||||
public static DetachedCriteria forEntityName(String entityName, String alias) {
|
||||
return new DetachedCriteria(entityName, alias);
|
||||
}
|
||||
|
||||
public static DetachedCriteria forClass(Class clazz) {
|
||||
return new DetachedCriteria( clazz.getName() );
|
||||
}
|
||||
|
||||
public static DetachedCriteria forClass(Class clazz, String alias) {
|
||||
return new DetachedCriteria( clazz.getName() , alias );
|
||||
}
|
||||
|
||||
public DetachedCriteria add(Criterion criterion) {
|
||||
criteria.add(criterion);
|
||||
return this;
|
||||
}
|
||||
|
||||
public DetachedCriteria addOrder(Order order) {
|
||||
criteria.addOrder(order);
|
||||
return this;
|
||||
}
|
||||
|
||||
public DetachedCriteria createAlias(String associationPath, String alias)
|
||||
throws HibernateException {
|
||||
criteria.createAlias(associationPath, alias);
|
||||
return this;
|
||||
}
|
||||
|
||||
public DetachedCriteria createCriteria(String associationPath, String alias)
|
||||
throws HibernateException {
|
||||
return new DetachedCriteria( impl, criteria.createCriteria(associationPath, alias) );
|
||||
}
|
||||
|
||||
public DetachedCriteria createCriteria(String associationPath)
|
||||
throws HibernateException {
|
||||
return new DetachedCriteria( impl, criteria.createCriteria(associationPath) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtain the alias associated with this DetachedCriteria
|
||||
*
|
||||
* @return The alias
|
||||
*/
|
||||
public String getAlias() {
|
||||
return criteria.getAlias();
|
||||
}
|
||||
|
||||
public DetachedCriteria setFetchMode(String associationPath, FetchMode mode)
|
||||
throws HibernateException {
|
||||
criteria.setFetchMode(associationPath, mode);
|
||||
return this;
|
||||
}
|
||||
|
||||
public DetachedCriteria setProjection(Projection projection) {
|
||||
criteria.setProjection(projection);
|
||||
return this;
|
||||
}
|
||||
|
||||
public DetachedCriteria setResultTransformer(ResultTransformer resultTransformer) {
|
||||
criteria.setResultTransformer(resultTransformer);
|
||||
return this;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "DetachableCriteria(" + criteria.toString() + ')';
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the CriteriaImpl used internally to hold the DetachedCriteria state
|
||||
*
|
||||
* @return The internally maintained CriteriaImpl
|
||||
*/
|
||||
CriteriaImpl getCriteriaImpl() {
|
||||
return impl;
|
||||
}
|
||||
|
||||
public DetachedCriteria createAlias(String associationPath, String alias, JoinType joinType) throws HibernateException {
|
||||
criteria.createAlias(associationPath, alias, joinType);
|
||||
return this;
|
||||
}
|
||||
|
||||
public DetachedCriteria createAlias(String associationPath, String alias, JoinType joinType, Criterion withClause) throws HibernateException {
|
||||
criteria.createAlias(associationPath, alias, joinType, withClause);
|
||||
return this;
|
||||
}
|
||||
|
||||
public DetachedCriteria createCriteria(String associationPath, JoinType joinType) throws HibernateException {
|
||||
return new DetachedCriteria(impl, criteria.createCriteria(associationPath, joinType));
|
||||
}
|
||||
|
||||
public DetachedCriteria createCriteria(String associationPath, String alias, JoinType joinType) throws HibernateException {
|
||||
return new DetachedCriteria(impl, criteria.createCriteria(associationPath, alias, joinType));
|
||||
}
|
||||
|
||||
public DetachedCriteria createCriteria(String associationPath, String alias, JoinType joinType, Criterion withClause) throws HibernateException {
|
||||
return new DetachedCriteria(impl, criteria.createCriteria(associationPath, alias, joinType, withClause));
|
||||
/**
|
||||
* Static builder to create a DetachedCriteria for the given entity.
|
||||
*
|
||||
* @param entityName The name of the entity to create a DetachedCriteria for
|
||||
*
|
||||
* @return The DetachedCriteria
|
||||
*/
|
||||
@SuppressWarnings("UnusedDeclaration")
|
||||
public static DetachedCriteria forEntityName(String entityName) {
|
||||
return new DetachedCriteria( entityName );
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an ordering
|
||||
*
|
||||
* @param order The ordering
|
||||
*
|
||||
* @return {@code this}, for method chaining
|
||||
*/
|
||||
public DetachedCriteria addOrder(Order order) {
|
||||
criteria.addOrder( order );
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the fetch mode for a given association
|
||||
*
|
||||
* @param associationPath The association path
|
||||
* @param mode The fetch mode to apply
|
||||
*
|
||||
* @return {@code this}, for method chaining
|
||||
*/
|
||||
public DetachedCriteria setFetchMode(String associationPath, FetchMode mode) {
|
||||
criteria.setFetchMode( associationPath, mode );
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the projection to use.
|
||||
*
|
||||
* @param projection The projection to use
|
||||
*
|
||||
* @return {@code this}, for method chaining
|
||||
*/
|
||||
public DetachedCriteria setProjection(Projection projection) {
|
||||
criteria.setProjection( projection );
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the result transformer to use.
|
||||
*
|
||||
* @param resultTransformer The result transformer to use
|
||||
*
|
||||
* @return {@code this}, for method chaining
|
||||
*/
|
||||
public DetachedCriteria setResultTransformer(ResultTransformer resultTransformer) {
|
||||
criteria.setResultTransformer( resultTransformer );
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an association path alias within this DetachedCriteria. The alias can then be used in further
|
||||
* alias creations or restrictions, etc.
|
||||
*
|
||||
* @param associationPath The association path
|
||||
* @param alias The alias to apply to that association path
|
||||
*
|
||||
* @return {@code this}, for method chaining
|
||||
*/
|
||||
public DetachedCriteria createAlias(String associationPath, String alias) {
|
||||
criteria.createAlias( associationPath, alias );
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an association path alias within this DetachedCriteria specifying the type of join. The alias
|
||||
* can then be used in further alias creations or restrictions, etc.
|
||||
*
|
||||
* @param associationPath The association path
|
||||
* @param alias The alias to apply to that association path
|
||||
* @param joinType The type of join to use
|
||||
*
|
||||
* @return {@code this}, for method chaining
|
||||
*/
|
||||
public DetachedCriteria createAlias(String associationPath, String alias, JoinType joinType) {
|
||||
criteria.createAlias( associationPath, alias, joinType );
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an association path alias within this DetachedCriteria specifying the type of join. The alias
|
||||
* can then be used in further alias creations or restrictions, etc.
|
||||
*
|
||||
* @param associationPath The association path
|
||||
* @param alias The alias to apply to that association path
|
||||
* @param joinType The type of join to use
|
||||
* @param withClause An additional restriction on the join
|
||||
*
|
||||
* @return {@code this}, for method chaining
|
||||
*/
|
||||
public DetachedCriteria createAlias(String associationPath, String alias, JoinType joinType, Criterion withClause) {
|
||||
criteria.createAlias( associationPath, alias, joinType, withClause );
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deprecated!
|
||||
*
|
||||
* @param associationPath The association path
|
||||
* @param alias The alias to apply to that association path
|
||||
* @param joinType The type of join to use
|
||||
*
|
||||
* @return {@code this}, for method chaining
|
||||
*
|
||||
* @deprecated use {@link #createAlias(String, String, JoinType)}
|
||||
*/
|
||||
@Deprecated
|
||||
public DetachedCriteria createAlias(String associationPath, String alias, int joinType) throws HibernateException {
|
||||
public DetachedCriteria createAlias(String associationPath, String alias, int joinType) {
|
||||
return createAlias( associationPath, alias, JoinType.parse( joinType ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Deprecated!
|
||||
*
|
||||
* @param associationPath The association path
|
||||
* @param alias The alias to apply to that association path
|
||||
* @param joinType The type of join to use
|
||||
* @param withClause An additional restriction on the join
|
||||
*
|
||||
* @return {@code this}, for method chaining
|
||||
*
|
||||
* @deprecated use {@link #createAlias(String, String, JoinType, Criterion)}
|
||||
*/
|
||||
@Deprecated
|
||||
public DetachedCriteria createAlias(String associationPath, String alias, int joinType, Criterion withClause) throws HibernateException {
|
||||
public DetachedCriteria createAlias(String associationPath, String alias, int joinType, Criterion withClause) {
|
||||
return createAlias( associationPath, alias, JoinType.parse( joinType ), withClause );
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an nested DetachedCriteria representing the association path.
|
||||
*
|
||||
* @param associationPath The association path
|
||||
* @param alias The alias to apply to that association path
|
||||
*
|
||||
* @return the newly created, nested DetachedCriteria
|
||||
*/
|
||||
public DetachedCriteria createCriteria(String associationPath, String alias) {
|
||||
return new DetachedCriteria( impl, criteria.createCriteria( associationPath, alias ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an nested DetachedCriteria representing the association path.
|
||||
*
|
||||
* @param associationPath The association path
|
||||
*
|
||||
* @return the newly created, nested DetachedCriteria
|
||||
*/
|
||||
public DetachedCriteria createCriteria(String associationPath) {
|
||||
return new DetachedCriteria( impl, criteria.createCriteria( associationPath ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an nested DetachedCriteria representing the association path, specifying the type of join to use.
|
||||
*
|
||||
* @param associationPath The association path
|
||||
* @param joinType The type of join to use
|
||||
*
|
||||
* @return the newly created, nested DetachedCriteria
|
||||
*/
|
||||
public DetachedCriteria createCriteria(String associationPath, JoinType joinType) {
|
||||
return new DetachedCriteria( impl, criteria.createCriteria( associationPath, joinType ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an nested DetachedCriteria representing the association path, specifying the type of join to use.
|
||||
*
|
||||
* @param associationPath The association path
|
||||
* @param alias The alias to associate with this "join".
|
||||
* @param joinType The type of join to use
|
||||
*
|
||||
* @return the newly created, nested DetachedCriteria
|
||||
*/
|
||||
public DetachedCriteria createCriteria(String associationPath, String alias, JoinType joinType) {
|
||||
return new DetachedCriteria( impl, criteria.createCriteria( associationPath, alias, joinType ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an nested DetachedCriteria representing the association path, specifying the type of join to use and
|
||||
* an additional join restriction.
|
||||
*
|
||||
* @param associationPath The association path
|
||||
* @param alias The alias to associate with this "join".
|
||||
* @param joinType The type of join to use
|
||||
* @param withClause The additional join restriction
|
||||
*
|
||||
* @return the newly created, nested DetachedCriteria
|
||||
*/
|
||||
public DetachedCriteria createCriteria(String associationPath, String alias, JoinType joinType, Criterion withClause) {
|
||||
return new DetachedCriteria(impl, criteria.createCriteria( associationPath, alias, joinType, withClause ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Deprecated!
|
||||
*
|
||||
* @param associationPath The association path
|
||||
* @param joinType The type of join to use
|
||||
*
|
||||
* @return the newly created, nested DetachedCriteria
|
||||
*
|
||||
* @deprecated use {@link #createCriteria(String, JoinType)}
|
||||
*/
|
||||
@Deprecated
|
||||
public DetachedCriteria createCriteria(String associationPath, int joinType) throws HibernateException {
|
||||
public DetachedCriteria createCriteria(String associationPath, int joinType) {
|
||||
return createCriteria( associationPath, JoinType.parse( joinType ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Deprecated!
|
||||
*
|
||||
* @param associationPath The association path
|
||||
* @param alias The alias
|
||||
* @param joinType The type of join to use
|
||||
*
|
||||
* @return the newly created, nested DetachedCriteria
|
||||
*
|
||||
* @deprecated use {@link #createCriteria(String, String, JoinType)}
|
||||
*/
|
||||
@Deprecated
|
||||
public DetachedCriteria createCriteria(String associationPath, String alias, int joinType) throws HibernateException {
|
||||
public DetachedCriteria createCriteria(String associationPath, String alias, int joinType) {
|
||||
return createCriteria( associationPath, alias, JoinType.parse( joinType ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Deprecated!
|
||||
*
|
||||
* @param associationPath The association path
|
||||
* @param alias The alias to associate with this "join".
|
||||
* @param joinType The type of join to use
|
||||
* @param withClause The additional join restriction
|
||||
*
|
||||
* @return the newly created, nested DetachedCriteria
|
||||
*
|
||||
* @deprecated use {@link #createCriteria(String, String, JoinType, Criterion)}
|
||||
*/
|
||||
@Deprecated
|
||||
public DetachedCriteria createCriteria(String associationPath, String alias, int joinType, Criterion withClause) throws HibernateException {
|
||||
public DetachedCriteria createCriteria(String associationPath, String alias, int joinType, Criterion withClause) {
|
||||
return createCriteria( associationPath, alias, JoinType.parse( joinType ), withClause );
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the SQL comment to use.
|
||||
*
|
||||
* @param comment The SQL comment to use
|
||||
*
|
||||
* @return {@code this}, for method chaining
|
||||
*/
|
||||
public DetachedCriteria setComment(String comment) {
|
||||
criteria.setComment(comment);
|
||||
criteria.setComment( comment );
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the lock mode to use.
|
||||
*
|
||||
* @param lockMode The lock mode to use
|
||||
*
|
||||
* @return {@code this}, for method chaining
|
||||
*/
|
||||
public DetachedCriteria setLockMode(LockMode lockMode) {
|
||||
criteria.setLockMode(lockMode);
|
||||
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);
|
||||
criteria.setLockMode( alias, lockMode );
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "DetachableCriteria(" + criteria.toString() + ')';
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -24,10 +24,22 @@
|
|||
package org.hibernate.criterion;
|
||||
|
||||
/**
|
||||
* Defines a disjunction (OR series).
|
||||
*
|
||||
* @author Gavin King
|
||||
* @author Steve Ebersole
|
||||
*
|
||||
* @see Conjunction
|
||||
*/
|
||||
public class Disjunction extends Junction {
|
||||
/**
|
||||
* Constructs a Disjunction
|
||||
*/
|
||||
protected Disjunction() {
|
||||
super( Nature.OR );
|
||||
}
|
||||
|
||||
protected Disjunction(Criterion[] conditions) {
|
||||
super( Nature.OR, conditions );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
|
||||
* Copyright (c) 2008, 2013, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Middleware LLC.
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
|
@ -20,73 +20,85 @@
|
|||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
package org.hibernate.criterion;
|
||||
|
||||
import org.hibernate.Criteria;
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.type.Type;
|
||||
|
||||
/**
|
||||
* A wrappedProjection that is a wrapper around other projections to apply distinction.
|
||||
*
|
||||
* @author Gavin King
|
||||
*/
|
||||
public class Distinct implements EnhancedProjection {
|
||||
private final Projection wrappedProjection;
|
||||
|
||||
private final Projection projection;
|
||||
|
||||
public Distinct(Projection proj) {
|
||||
this.projection = proj;
|
||||
/**
|
||||
* Constructs a Distinct
|
||||
*
|
||||
* @param wrappedProjection The wrapped projection
|
||||
*/
|
||||
public Distinct(Projection wrappedProjection) {
|
||||
this.wrappedProjection = wrappedProjection;
|
||||
}
|
||||
|
||||
public String toSqlString(Criteria criteria, int position, CriteriaQuery criteriaQuery)
|
||||
throws HibernateException {
|
||||
return "distinct " + projection.toSqlString(criteria, position, criteriaQuery);
|
||||
@Override
|
||||
public String toSqlString(Criteria criteria, int position, CriteriaQuery criteriaQuery) {
|
||||
return "distinct " + wrappedProjection.toSqlString( criteria, position, criteriaQuery );
|
||||
}
|
||||
|
||||
public String toGroupSqlString(Criteria criteria, CriteriaQuery criteriaQuery)
|
||||
throws HibernateException {
|
||||
return projection.toGroupSqlString(criteria, criteriaQuery);
|
||||
@Override
|
||||
public String toGroupSqlString(Criteria criteria, CriteriaQuery criteriaQuery) {
|
||||
return wrappedProjection.toGroupSqlString( criteria, criteriaQuery );
|
||||
}
|
||||
|
||||
public Type[] getTypes(Criteria criteria, CriteriaQuery criteriaQuery)
|
||||
throws HibernateException {
|
||||
return projection.getTypes(criteria, criteriaQuery);
|
||||
@Override
|
||||
public Type[] getTypes(Criteria criteria, CriteriaQuery criteriaQuery) {
|
||||
return wrappedProjection.getTypes( criteria, criteriaQuery );
|
||||
}
|
||||
|
||||
public Type[] getTypes(String alias, Criteria criteria, CriteriaQuery criteriaQuery)
|
||||
throws HibernateException {
|
||||
return projection.getTypes(alias, criteria, criteriaQuery);
|
||||
@Override
|
||||
public Type[] getTypes(String alias, Criteria criteria, CriteriaQuery criteriaQuery) {
|
||||
return wrappedProjection.getTypes( alias, criteria, criteriaQuery );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getColumnAliases(int loc) {
|
||||
return projection.getColumnAliases(loc);
|
||||
return wrappedProjection.getColumnAliases( loc );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getColumnAliases(int loc, Criteria criteria, CriteriaQuery criteriaQuery) {
|
||||
return projection instanceof EnhancedProjection ?
|
||||
( ( EnhancedProjection ) projection ).getColumnAliases( loc, criteria, criteriaQuery ) :
|
||||
getColumnAliases( loc );
|
||||
return wrappedProjection instanceof EnhancedProjection
|
||||
? ( (EnhancedProjection) wrappedProjection).getColumnAliases( loc, criteria, criteriaQuery )
|
||||
: getColumnAliases( loc );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getColumnAliases(String alias, int loc) {
|
||||
return projection.getColumnAliases(alias, loc);
|
||||
return wrappedProjection.getColumnAliases( alias, loc );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getColumnAliases(String alias, int loc, Criteria criteria, CriteriaQuery criteriaQuery) {
|
||||
return projection instanceof EnhancedProjection ?
|
||||
( ( EnhancedProjection ) projection ).getColumnAliases( alias, loc, criteria, criteriaQuery ) :
|
||||
getColumnAliases( alias, loc );
|
||||
return wrappedProjection instanceof EnhancedProjection
|
||||
? ( (EnhancedProjection) wrappedProjection).getColumnAliases( alias, loc, criteria, criteriaQuery )
|
||||
: getColumnAliases( alias, loc );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getAliases() {
|
||||
return projection.getAliases();
|
||||
return wrappedProjection.getAliases();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isGrouped() {
|
||||
return projection.isGrouped();
|
||||
return wrappedProjection.isGrouped();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "distinct " + projection.toString();
|
||||
return "distinct " + wrappedProjection.toString();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
|
||||
* Copyright (c) 2008, 2013, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Middleware LLC.
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
|
@ -20,22 +20,28 @@
|
|||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
package org.hibernate.criterion;
|
||||
|
||||
|
||||
/**
|
||||
* An expression asserting that a collection property is empty
|
||||
*
|
||||
* @author Gavin King
|
||||
*/
|
||||
public class EmptyExpression extends AbstractEmptinessExpression implements Criterion {
|
||||
|
||||
/**
|
||||
* Constructs an EmptyExpression
|
||||
*
|
||||
* @param propertyName The collection property name
|
||||
*
|
||||
* @see Restrictions#isEmpty
|
||||
*/
|
||||
protected EmptyExpression(String propertyName) {
|
||||
super( propertyName );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean excludeEmpty() {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
|
||||
* Copyright (c) 2008, 2013, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Middleware LLC.
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
|
@ -20,9 +20,9 @@
|
|||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
package org.hibernate.criterion;
|
||||
|
||||
import org.hibernate.Criteria;
|
||||
|
||||
/**
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.criterion;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
|
@ -30,7 +31,6 @@ import java.util.Set;
|
|||
|
||||
import org.hibernate.Criteria;
|
||||
import org.hibernate.EntityMode;
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.engine.spi.TypedValue;
|
||||
import org.hibernate.internal.util.StringHelper;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
|
@ -39,6 +39,7 @@ import org.hibernate.type.Type;
|
|||
|
||||
/**
|
||||
* Support for query by example.
|
||||
*
|
||||
* <pre>
|
||||
* List results = session.createCriteria(Parent.class)
|
||||
* .add( Example.create(parent).ignoreCase() )
|
||||
|
@ -46,68 +47,57 @@ import org.hibernate.type.Type;
|
|||
* .add( Example.create( parent.getChild() ) )
|
||||
* .list();
|
||||
* </pre>
|
||||
* "Examples" may be mixed and matched with "Expressions" in the same <tt>Criteria</tt>.
|
||||
*
|
||||
* "Examples" may be mixed and matched with "Expressions" in the same Criteria.
|
||||
*
|
||||
* @see org.hibernate.Criteria
|
||||
* @author Gavin King
|
||||
*/
|
||||
|
||||
public class Example implements Criterion {
|
||||
|
||||
private final Object entity;
|
||||
private final Set excludedProperties = new HashSet();
|
||||
private final Object exampleEntity;
|
||||
private PropertySelector selector;
|
||||
|
||||
private boolean isLikeEnabled;
|
||||
private Character escapeCharacter;
|
||||
private boolean isIgnoreCaseEnabled;
|
||||
private MatchMode matchMode;
|
||||
|
||||
private final Set<String> excludedProperties = new HashSet<String>();
|
||||
|
||||
/**
|
||||
* A strategy for choosing property values for inclusion in the query
|
||||
* criteria
|
||||
* Create a new Example criterion instance, which includes all non-null properties by default
|
||||
*
|
||||
* @param exampleEntity The example bean to use.
|
||||
*
|
||||
* @return a new instance of Example
|
||||
*/
|
||||
|
||||
public static interface PropertySelector extends Serializable {
|
||||
public boolean include(Object propertyValue, String propertyName, Type type);
|
||||
}
|
||||
|
||||
private static final PropertySelector NOT_NULL = new NotNullPropertySelector();
|
||||
private static final PropertySelector ALL = new AllPropertySelector();
|
||||
private static final PropertySelector NOT_NULL_OR_ZERO = new NotNullOrZeroPropertySelector();
|
||||
|
||||
static final class AllPropertySelector implements PropertySelector {
|
||||
public boolean include(Object object, String propertyName, Type type) {
|
||||
return true;
|
||||
}
|
||||
|
||||
private Object readResolve() {
|
||||
return ALL;
|
||||
}
|
||||
}
|
||||
|
||||
static final class NotNullPropertySelector implements PropertySelector {
|
||||
public boolean include(Object object, String propertyName, Type type) {
|
||||
return object!=null;
|
||||
}
|
||||
|
||||
private Object readResolve() {
|
||||
return NOT_NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static final class NotNullOrZeroPropertySelector implements PropertySelector {
|
||||
public boolean include(Object object, String propertyName, Type type) {
|
||||
return object!=null && (
|
||||
!(object instanceof Number) || ( (Number) object ).longValue()!=0
|
||||
);
|
||||
}
|
||||
|
||||
private Object readResolve() {
|
||||
return NOT_NULL_OR_ZERO;
|
||||
public static Example create(Object exampleEntity) {
|
||||
if ( exampleEntity == null ) {
|
||||
throw new NullPointerException( "null example entity" );
|
||||
}
|
||||
return new Example( exampleEntity, NotNullPropertySelector.INSTANCE );
|
||||
}
|
||||
|
||||
/**
|
||||
* Set escape character for "like" clause
|
||||
* Allow subclasses to instantiate as needed.
|
||||
*
|
||||
* @param exampleEntity The example bean
|
||||
* @param selector The property selector to use
|
||||
*/
|
||||
protected Example(Object exampleEntity, PropertySelector selector) {
|
||||
this.exampleEntity = exampleEntity;
|
||||
this.selector = selector;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set escape character for "like" clause if like matching was enabled
|
||||
*
|
||||
* @param escapeCharacter The escape character
|
||||
*
|
||||
* @return {@code this}, for method chaining
|
||||
*
|
||||
* @see #enableLike
|
||||
*/
|
||||
public Example setEscapeCharacter(Character escapeCharacter) {
|
||||
this.escapeCharacter = escapeCharacter;
|
||||
|
@ -115,7 +105,47 @@ public class Example implements Criterion {
|
|||
}
|
||||
|
||||
/**
|
||||
* Set the property selector
|
||||
* Use the "like" operator for all string-valued properties. This form implicitly uses {@link MatchMode#EXACT}
|
||||
*
|
||||
* @return {@code this}, for method chaining
|
||||
*/
|
||||
public Example enableLike() {
|
||||
return enableLike( MatchMode.EXACT );
|
||||
}
|
||||
|
||||
/**
|
||||
* Use the "like" operator for all string-valued properties
|
||||
*
|
||||
* @param matchMode The match mode to use.
|
||||
*
|
||||
* @return {@code this}, for method chaining
|
||||
*/
|
||||
public Example enableLike(MatchMode matchMode) {
|
||||
this.isLikeEnabled = true;
|
||||
this.matchMode = matchMode;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ignore case for all string-valued properties
|
||||
*
|
||||
* @return {@code this}, for method chaining
|
||||
*/
|
||||
public Example ignoreCase() {
|
||||
this.isIgnoreCaseEnabled = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the property selector to use.
|
||||
*
|
||||
* The property selector operates separate from excluding a property.
|
||||
*
|
||||
* @param selector The selector to use
|
||||
*
|
||||
* @return {@code this}, for method chaining
|
||||
*
|
||||
* @see #excludeProperty
|
||||
*/
|
||||
public Example setPropertySelector(PropertySelector selector) {
|
||||
this.selector = selector;
|
||||
|
@ -123,95 +153,63 @@ public class Example implements Criterion {
|
|||
}
|
||||
|
||||
/**
|
||||
* Exclude zero-valued properties
|
||||
* Exclude zero-valued properties.
|
||||
*
|
||||
* Equivalent to calling {@link #setPropertySelector} passing in {@link NotNullOrZeroPropertySelector#INSTANCE}
|
||||
*
|
||||
* @return {@code this}, for method chaining
|
||||
*
|
||||
* @see #setPropertySelector
|
||||
*/
|
||||
public Example excludeZeroes() {
|
||||
setPropertySelector(NOT_NULL_OR_ZERO);
|
||||
setPropertySelector( NotNullOrZeroPropertySelector.INSTANCE );
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Don't exclude null or zero-valued properties
|
||||
* Include all properties.
|
||||
*
|
||||
* Equivalent to calling {@link #setPropertySelector} passing in {@link AllPropertySelector#INSTANCE}
|
||||
*
|
||||
* @return {@code this}, for method chaining
|
||||
*
|
||||
* @see #setPropertySelector
|
||||
*/
|
||||
public Example excludeNone() {
|
||||
setPropertySelector(ALL);
|
||||
setPropertySelector( AllPropertySelector.INSTANCE );
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Use the "like" operator for all string-valued properties
|
||||
*/
|
||||
public Example enableLike(MatchMode matchMode) {
|
||||
isLikeEnabled = true;
|
||||
this.matchMode = matchMode;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Use the "like" operator for all string-valued properties
|
||||
*/
|
||||
public Example enableLike() {
|
||||
return enableLike(MatchMode.EXACT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ignore case for all string-valued properties
|
||||
*/
|
||||
public Example ignoreCase() {
|
||||
isIgnoreCaseEnabled = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Exclude a particular named property
|
||||
* Exclude a particular property by name.
|
||||
*
|
||||
* @param name The name of the property to exclude
|
||||
*
|
||||
* @return {@code this}, for method chaining
|
||||
*
|
||||
* @see #setPropertySelector
|
||||
*/
|
||||
public Example excludeProperty(String name) {
|
||||
excludedProperties.add(name);
|
||||
excludedProperties.add( name );
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new instance, which includes all non-null properties
|
||||
* by default
|
||||
* @param entity
|
||||
* @return a new instance of <tt>Example</tt>
|
||||
*/
|
||||
public static Example create(Object entity) {
|
||||
if (entity==null) throw new NullPointerException("null example");
|
||||
return new Example(entity, NOT_NULL);
|
||||
}
|
||||
@Override
|
||||
public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery) {
|
||||
final StringBuilder buf = new StringBuilder().append( '(' );
|
||||
final EntityPersister meta = criteriaQuery.getFactory().getEntityPersister(
|
||||
criteriaQuery.getEntityName( criteria )
|
||||
);
|
||||
final String[] propertyNames = meta.getPropertyNames();
|
||||
final Type[] propertyTypes = meta.getPropertyTypes();
|
||||
|
||||
protected Example(Object entity, PropertySelector selector) {
|
||||
this.entity = entity;
|
||||
this.selector = selector;
|
||||
}
|
||||
final Object[] propertyValues = meta.getPropertyValues( exampleEntity );
|
||||
for ( int i=0; i<propertyNames.length; i++ ) {
|
||||
final Object propertyValue = propertyValues[i];
|
||||
final String propertyName = propertyNames[i];
|
||||
|
||||
public String toString() {
|
||||
return "example (" + entity + ')';
|
||||
}
|
||||
|
||||
private boolean isPropertyIncluded(Object value, String name, Type type) {
|
||||
return !excludedProperties.contains(name) &&
|
||||
!type.isAssociationType() &&
|
||||
selector.include(value, name, type);
|
||||
}
|
||||
|
||||
public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery)
|
||||
throws HibernateException {
|
||||
|
||||
StringBuilder buf = new StringBuilder().append('(');
|
||||
EntityPersister meta = criteriaQuery.getFactory().getEntityPersister( criteriaQuery.getEntityName(criteria) );
|
||||
String[] propertyNames = meta.getPropertyNames();
|
||||
Type[] propertyTypes = meta.getPropertyTypes();
|
||||
//TODO: get all properties, not just the fetched ones!
|
||||
Object[] propertyValues = meta.getPropertyValues( entity );
|
||||
for (int i=0; i<propertyNames.length; i++) {
|
||||
Object propertyValue = propertyValues[i];
|
||||
String propertyName = propertyNames[i];
|
||||
|
||||
boolean isPropertyIncluded = i!=meta.getVersionProperty() &&
|
||||
isPropertyIncluded( propertyValue, propertyName, propertyTypes[i] );
|
||||
if (isPropertyIncluded) {
|
||||
final boolean isVersionProperty = i == meta.getVersionProperty();
|
||||
if ( ! isVersionProperty && isPropertyIncluded( propertyValue, propertyName, propertyTypes[i] ) ) {
|
||||
if ( propertyTypes[i].isComponentType() ) {
|
||||
appendComponentCondition(
|
||||
propertyName,
|
||||
|
@ -233,61 +231,72 @@ public class Example implements Criterion {
|
|||
}
|
||||
}
|
||||
}
|
||||
if ( buf.length()==1 ) buf.append("1=1"); //yuck!
|
||||
return buf.append(')').toString();
|
||||
|
||||
if ( buf.length()==1 ) {
|
||||
buf.append( "1=1" );
|
||||
}
|
||||
|
||||
private static final Object[] TYPED_VALUES = new TypedValue[0];
|
||||
return buf.append( ')' ).toString();
|
||||
}
|
||||
|
||||
public TypedValue[] getTypedValues(Criteria criteria, CriteriaQuery criteriaQuery)
|
||||
throws HibernateException {
|
||||
@SuppressWarnings("SimplifiableIfStatement")
|
||||
private boolean isPropertyIncluded(Object value, String name, Type type) {
|
||||
if ( excludedProperties.contains( name ) ) {
|
||||
// was explicitly excluded
|
||||
return false;
|
||||
}
|
||||
|
||||
EntityPersister meta = criteriaQuery.getFactory()
|
||||
.getEntityPersister( criteriaQuery.getEntityName(criteria) );
|
||||
String[] propertyNames = meta.getPropertyNames();
|
||||
Type[] propertyTypes = meta.getPropertyTypes();
|
||||
//TODO: get all properties, not just the fetched ones!
|
||||
Object[] values = meta.getPropertyValues( entity );
|
||||
List list = new ArrayList();
|
||||
for (int i=0; i<propertyNames.length; i++) {
|
||||
Object value = values[i];
|
||||
Type type = propertyTypes[i];
|
||||
String name = propertyNames[i];
|
||||
if ( type.isAssociationType() ) {
|
||||
// associations are implicitly excluded
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean isPropertyIncluded = i!=meta.getVersionProperty() &&
|
||||
isPropertyIncluded(value, name, type);
|
||||
return selector.include( value, name, type );
|
||||
}
|
||||
|
||||
if (isPropertyIncluded) {
|
||||
@Override
|
||||
public TypedValue[] getTypedValues(Criteria criteria, CriteriaQuery criteriaQuery) {
|
||||
final EntityPersister meta = criteriaQuery.getFactory().getEntityPersister(
|
||||
criteriaQuery.getEntityName( criteria )
|
||||
);
|
||||
final String[] propertyNames = meta.getPropertyNames();
|
||||
final Type[] propertyTypes = meta.getPropertyTypes();
|
||||
|
||||
final Object[] values = meta.getPropertyValues( exampleEntity );
|
||||
final List<TypedValue> list = new ArrayList<TypedValue>();
|
||||
for ( int i=0; i<propertyNames.length; i++ ) {
|
||||
final Object value = values[i];
|
||||
final Type type = propertyTypes[i];
|
||||
final String name = propertyNames[i];
|
||||
|
||||
final boolean isVersionProperty = i == meta.getVersionProperty();
|
||||
|
||||
if ( ! isVersionProperty && isPropertyIncluded( value, name, type ) ) {
|
||||
if ( propertyTypes[i].isComponentType() ) {
|
||||
addComponentTypedValues(name, value, (CompositeType) type, list, criteria, criteriaQuery);
|
||||
addComponentTypedValues( name, value, (CompositeType) type, list, criteria, criteriaQuery );
|
||||
}
|
||||
else {
|
||||
addPropertyTypedValue(value, type, list);
|
||||
addPropertyTypedValue( value, type, list );
|
||||
}
|
||||
}
|
||||
}
|
||||
return (TypedValue[]) list.toArray(TYPED_VALUES);
|
||||
}
|
||||
|
||||
private EntityMode getEntityMode(Criteria criteria, CriteriaQuery criteriaQuery) {
|
||||
EntityPersister meta = criteriaQuery.getFactory()
|
||||
.getEntityPersister( criteriaQuery.getEntityName(criteria) );
|
||||
EntityMode result = meta.getEntityMode();
|
||||
if ( ! meta.getEntityMetamodel().getTuplizer().isInstance( entity ) ) {
|
||||
throw new ClassCastException( entity.getClass().getName() );
|
||||
}
|
||||
return result;
|
||||
return list.toArray( new TypedValue[ list.size() ] );
|
||||
}
|
||||
|
||||
protected void addPropertyTypedValue(Object value, Type type, List list) {
|
||||
if ( value!=null ) {
|
||||
protected void addPropertyTypedValue(Object value, Type type, List<TypedValue> list) {
|
||||
if ( value != null ) {
|
||||
if ( value instanceof String ) {
|
||||
String string = (String) value;
|
||||
if (isIgnoreCaseEnabled) string = string.toLowerCase();
|
||||
if (isLikeEnabled) string = matchMode.toMatchString(string);
|
||||
if ( isIgnoreCaseEnabled ) {
|
||||
string = string.toLowerCase();
|
||||
}
|
||||
if ( isLikeEnabled ) {
|
||||
string = matchMode.toMatchString( string );
|
||||
}
|
||||
value = string;
|
||||
}
|
||||
list.add( new TypedValue(type, value) );
|
||||
list.add( new TypedValue( type, value ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -295,60 +304,73 @@ public class Example implements Criterion {
|
|||
String path,
|
||||
Object component,
|
||||
CompositeType type,
|
||||
List list,
|
||||
List<TypedValue> list,
|
||||
Criteria criteria,
|
||||
CriteriaQuery criteriaQuery)
|
||||
throws HibernateException {
|
||||
|
||||
if (component!=null) {
|
||||
String[] propertyNames = type.getPropertyNames();
|
||||
Type[] subtypes = type.getSubtypes();
|
||||
Object[] values = type.getPropertyValues( component, getEntityMode(criteria, criteriaQuery) );
|
||||
for (int i=0; i<propertyNames.length; i++) {
|
||||
Object value = values[i];
|
||||
Type subtype = subtypes[i];
|
||||
String subpath = StringHelper.qualify( path, propertyNames[i] );
|
||||
if ( isPropertyIncluded(value, subpath, subtype) ) {
|
||||
CriteriaQuery criteriaQuery) {
|
||||
if ( component != null ) {
|
||||
final String[] propertyNames = type.getPropertyNames();
|
||||
final Type[] subtypes = type.getSubtypes();
|
||||
final Object[] values = type.getPropertyValues( component, getEntityMode( criteria, criteriaQuery ) );
|
||||
for ( int i=0; i<propertyNames.length; i++ ) {
|
||||
final Object value = values[i];
|
||||
final Type subtype = subtypes[i];
|
||||
final String subpath = StringHelper.qualify( path, propertyNames[i] );
|
||||
if ( isPropertyIncluded( value, subpath, subtype ) ) {
|
||||
if ( subtype.isComponentType() ) {
|
||||
addComponentTypedValues(subpath, value, (CompositeType) subtype, list, criteria, criteriaQuery);
|
||||
addComponentTypedValues( subpath, value, (CompositeType) subtype, list, criteria, criteriaQuery );
|
||||
}
|
||||
else {
|
||||
addPropertyTypedValue(value, subtype, list);
|
||||
addPropertyTypedValue( value, subtype, list );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private EntityMode getEntityMode(Criteria criteria, CriteriaQuery criteriaQuery) {
|
||||
final EntityPersister meta = criteriaQuery.getFactory().getEntityPersister(
|
||||
criteriaQuery.getEntityName( criteria )
|
||||
);
|
||||
final EntityMode result = meta.getEntityMode();
|
||||
if ( ! meta.getEntityMetamodel().getTuplizer().isInstance( exampleEntity ) ) {
|
||||
throw new ClassCastException( exampleEntity.getClass().getName() );
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
protected void appendPropertyCondition(
|
||||
String propertyName,
|
||||
Object propertyValue,
|
||||
Criteria criteria,
|
||||
CriteriaQuery cq,
|
||||
StringBuilder buf)
|
||||
throws HibernateException {
|
||||
Criterion crit;
|
||||
if ( propertyValue!=null ) {
|
||||
boolean isString = propertyValue instanceof String;
|
||||
StringBuilder buf) {
|
||||
final Criterion condition;
|
||||
if ( propertyValue != null ) {
|
||||
final boolean isString = propertyValue instanceof String;
|
||||
if ( isLikeEnabled && isString ) {
|
||||
crit = new LikeExpression(
|
||||
condition = new LikeExpression(
|
||||
propertyName,
|
||||
( String ) propertyValue,
|
||||
(String) propertyValue,
|
||||
matchMode,
|
||||
escapeCharacter,
|
||||
isIgnoreCaseEnabled
|
||||
);
|
||||
}
|
||||
else {
|
||||
crit = new SimpleExpression( propertyName, propertyValue, "=", isIgnoreCaseEnabled && isString );
|
||||
condition = new SimpleExpression( propertyName, propertyValue, "=", isIgnoreCaseEnabled && isString );
|
||||
}
|
||||
}
|
||||
else {
|
||||
crit = new NullExpression(propertyName);
|
||||
condition = new NullExpression(propertyName);
|
||||
}
|
||||
|
||||
final String conditionFragment = condition.toSqlString( criteria, cq );
|
||||
if ( conditionFragment.trim().length() > 0 ) {
|
||||
if ( buf.length() > 1 ) {
|
||||
buf.append( " and " );
|
||||
}
|
||||
buf.append( conditionFragment );
|
||||
}
|
||||
String critCondition = crit.toSqlString(criteria, cq);
|
||||
if ( buf.length()>1 && critCondition.trim().length()>0 ) buf.append(" and ");
|
||||
buf.append(critCondition);
|
||||
}
|
||||
|
||||
protected void appendComponentCondition(
|
||||
|
@ -357,21 +379,19 @@ public class Example implements Criterion {
|
|||
CompositeType type,
|
||||
Criteria criteria,
|
||||
CriteriaQuery criteriaQuery,
|
||||
StringBuilder buf)
|
||||
throws HibernateException {
|
||||
|
||||
if (component!=null) {
|
||||
String[] propertyNames = type.getPropertyNames();
|
||||
Object[] values = type.getPropertyValues( component, getEntityMode(criteria, criteriaQuery) );
|
||||
Type[] subtypes = type.getSubtypes();
|
||||
for (int i=0; i<propertyNames.length; i++) {
|
||||
String subpath = StringHelper.qualify( path, propertyNames[i] );
|
||||
Object value = values[i];
|
||||
if ( isPropertyIncluded( value, subpath, subtypes[i] ) ) {
|
||||
Type subtype = subtypes[i];
|
||||
StringBuilder buf) {
|
||||
if ( component != null ) {
|
||||
final String[] propertyNames = type.getPropertyNames();
|
||||
final Object[] values = type.getPropertyValues( component, getEntityMode( criteria, criteriaQuery ) );
|
||||
final Type[] subtypes = type.getSubtypes();
|
||||
for ( int i=0; i<propertyNames.length; i++ ) {
|
||||
final String subPath = StringHelper.qualify( path, propertyNames[i] );
|
||||
final Object value = values[i];
|
||||
if ( isPropertyIncluded( value, subPath, subtypes[i] ) ) {
|
||||
final Type subtype = subtypes[i];
|
||||
if ( subtype.isComponentType() ) {
|
||||
appendComponentCondition(
|
||||
subpath,
|
||||
subPath,
|
||||
value,
|
||||
(CompositeType) subtype,
|
||||
criteria,
|
||||
|
@ -381,7 +401,7 @@ public class Example implements Criterion {
|
|||
}
|
||||
else {
|
||||
appendPropertyCondition(
|
||||
subpath,
|
||||
subPath,
|
||||
value,
|
||||
criteria,
|
||||
criteriaQuery,
|
||||
|
@ -392,4 +412,89 @@ public class Example implements Criterion {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
@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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,10 +1,10 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
|
||||
* Copyright (c) 2008, 2013, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Middleware LLC.
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
|
@ -20,21 +20,32 @@
|
|||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
package org.hibernate.criterion;
|
||||
|
||||
import org.hibernate.Criteria;
|
||||
|
||||
/**
|
||||
* Expression that checks the existence of rows in a sub-query
|
||||
*
|
||||
* @author Gavin King
|
||||
*/
|
||||
public class ExistsSubqueryExpression extends SubqueryExpression {
|
||||
/**
|
||||
* Constructs the ExistsSubqueryExpression
|
||||
*
|
||||
* @param quantifier The "exists"/"not exists" sub-query quantifier
|
||||
* @param dc The DetachedCriteria representing the sub-query
|
||||
*
|
||||
* @see Subqueries#exists
|
||||
* @see Subqueries#notExists
|
||||
*/
|
||||
protected ExistsSubqueryExpression(String quantifier, DetachedCriteria dc) {
|
||||
super( null, quantifier, dc );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String toLeftSqlString(Criteria criteria, CriteriaQuery outerQuery) {
|
||||
return "";
|
||||
}
|
||||
|
||||
protected ExistsSubqueryExpression(String quantifier, DetachedCriteria dc) {
|
||||
super(null, quantifier, dc);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
|
||||
* Copyright (c) 2008, 2013, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Middleware LLC.
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
|
@ -20,66 +20,72 @@
|
|||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
package org.hibernate.criterion;
|
||||
|
||||
import org.hibernate.internal.util.collections.ArrayHelper;
|
||||
import org.hibernate.type.Type;
|
||||
|
||||
/**
|
||||
* @deprecated Use <tt>Restrictions</tt>.
|
||||
* @see Restrictions
|
||||
* Factory for Criterion objects. Deprecated!
|
||||
*
|
||||
* @author Gavin King
|
||||
*
|
||||
* @see Restrictions
|
||||
*
|
||||
* @deprecated Use {@link Restrictions} instead
|
||||
*/
|
||||
@Deprecated
|
||||
public final class Expression extends Restrictions {
|
||||
/**
|
||||
* Apply a constraint expressed in SQL, with JDBC parameters. Any occurrences of <tt>{alias}</tt> will be
|
||||
* replaced by the table alias.
|
||||
*
|
||||
* @param sql The sql
|
||||
* @param values The parameter values
|
||||
* @param types The parameter types
|
||||
*
|
||||
* @return Criterion
|
||||
*
|
||||
* @deprecated use {@link org.hibernate.criterion.Restrictions#sqlRestriction(String, Object[], Type[])}
|
||||
*/
|
||||
@Deprecated
|
||||
public static Criterion sql(String sql, Object[] values, Type[] types) {
|
||||
return new SQLCriterion( sql, values, types );
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply a constraint expressed in SQL, with a JDBC parameter. Any occurrences of <tt>{alias}</tt> will be
|
||||
* replaced by the table alias.
|
||||
*
|
||||
* @param sql The sql
|
||||
* @param value The parameter value
|
||||
* @param type The parameter type
|
||||
*
|
||||
* @return Criterion
|
||||
*
|
||||
* @deprecated use {@link org.hibernate.criterion.Restrictions#sqlRestriction(String, Object, Type)}
|
||||
*/
|
||||
@Deprecated
|
||||
public static Criterion sql(String sql, Object value, Type type) {
|
||||
return new SQLCriterion( sql, value, type );
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply a constraint expressed in SQL with no parameters. Any occurrences of <tt>{alias}</tt> will be
|
||||
* replaced by the table alias.
|
||||
*
|
||||
* @param sql The sql
|
||||
*
|
||||
* @return Criterion
|
||||
*
|
||||
* @deprecated use {@link org.hibernate.criterion.Restrictions#sqlRestriction(String)}
|
||||
*/
|
||||
@Deprecated
|
||||
public static Criterion sql(String sql) {
|
||||
return new SQLCriterion( sql );
|
||||
}
|
||||
|
||||
private Expression() {
|
||||
//cannot be instantiated
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply a constraint expressed in SQL, with the given JDBC
|
||||
* parameters. Any occurrences of <tt>{alias}</tt> will be
|
||||
* replaced by the table alias.
|
||||
*
|
||||
* @deprecated use {@link org.hibernate.criterion.Restrictions#sqlRestriction(String, Object[], Type[])}
|
||||
* @param sql
|
||||
* @param values
|
||||
* @param types
|
||||
* @return Criterion
|
||||
*/
|
||||
@Deprecated
|
||||
public static Criterion sql(String sql, Object[] values, Type[] types) {
|
||||
return new SQLCriterion(sql, values, types);
|
||||
}
|
||||
/**
|
||||
* Apply a constraint expressed in SQL, with the given JDBC
|
||||
* parameter. Any occurrences of <tt>{alias}</tt> will be replaced
|
||||
* by the table alias.
|
||||
*
|
||||
* @deprecated use {@link org.hibernate.criterion.Restrictions#sqlRestriction(String, Object, Type)}
|
||||
* @param sql
|
||||
* @param value
|
||||
* @param type
|
||||
* @return Criterion
|
||||
*/
|
||||
@Deprecated
|
||||
public static Criterion sql(String sql, Object value, Type type) {
|
||||
return new SQLCriterion(sql, new Object[] { value }, new Type[] { type } );
|
||||
}
|
||||
/**
|
||||
* Apply a constraint expressed in SQL. Any occurrences of <tt>{alias}</tt>
|
||||
* will be replaced by the table alias.
|
||||
*
|
||||
* @deprecated use {@link org.hibernate.criterion.Restrictions#sqlRestriction(String)}
|
||||
* @param sql
|
||||
* @return Criterion
|
||||
*/
|
||||
@Deprecated
|
||||
public static Criterion sql(String sql) {
|
||||
return new SQLCriterion(sql, ArrayHelper.EMPTY_OBJECT_ARRAY, ArrayHelper.EMPTY_TYPE_ARRAY);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
|
||||
* Copyright (c) 2008, 2013, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Middleware LLC.
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
|
@ -20,46 +20,49 @@
|
|||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
package org.hibernate.criterion;
|
||||
|
||||
import org.hibernate.Criteria;
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.engine.spi.TypedValue;
|
||||
import org.hibernate.internal.util.StringHelper;
|
||||
|
||||
/**
|
||||
* An identifier constraint
|
||||
*
|
||||
* @author Gavin King
|
||||
*/
|
||||
public class IdentifierEqExpression implements Criterion {
|
||||
|
||||
private final Object value;
|
||||
|
||||
/**
|
||||
* Constructs an IdentifierEqExpression
|
||||
*
|
||||
* @param value The identifier value
|
||||
*
|
||||
* @see Restrictions#idEq
|
||||
*/
|
||||
protected IdentifierEqExpression(Object value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery)
|
||||
throws HibernateException {
|
||||
@Override
|
||||
public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery) {
|
||||
final String[] columns = criteriaQuery.getIdentifierColumns( criteria );
|
||||
|
||||
String[] columns = criteriaQuery.getIdentifierColumns(criteria);
|
||||
|
||||
String result = StringHelper.join(
|
||||
" and ",
|
||||
StringHelper.suffix( columns, " = ?" )
|
||||
);
|
||||
if (columns.length>1) result = '(' + result + ')';
|
||||
String result = StringHelper.join( " and ", StringHelper.suffix( columns, " = ?" ) );
|
||||
if ( columns.length > 1) {
|
||||
result = '(' + result + ')';
|
||||
}
|
||||
return result;
|
||||
|
||||
//TODO: get SQL rendering out of this package!
|
||||
}
|
||||
|
||||
public TypedValue[] getTypedValues(Criteria criteria, CriteriaQuery criteriaQuery)
|
||||
throws HibernateException {
|
||||
return new TypedValue[] { criteriaQuery.getTypedIdentifierValue(criteria, value) };
|
||||
@Override
|
||||
public TypedValue[] getTypedValues(Criteria criteria, CriteriaQuery criteriaQuery) {
|
||||
return new TypedValue[] { criteriaQuery.getTypedIdentifierValue( criteria, value ) };
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "id = " + value;
|
||||
}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
|
||||
* Copyright (c) 2008, 2013, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Middleware LLC.
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
|
@ -20,66 +20,77 @@
|
|||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
package org.hibernate.criterion;
|
||||
|
||||
import org.hibernate.Criteria;
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.internal.util.StringHelper;
|
||||
import org.hibernate.type.Type;
|
||||
|
||||
/**
|
||||
* A property value, or grouped property value
|
||||
*
|
||||
* @author Gavin King
|
||||
*/
|
||||
public class IdentifierProjection extends SimpleProjection {
|
||||
|
||||
private boolean grouped;
|
||||
|
||||
protected IdentifierProjection(boolean grouped) {
|
||||
/**
|
||||
* Constructs a non-grouped identifier projection
|
||||
*
|
||||
* @see Projections#id
|
||||
*/
|
||||
protected IdentifierProjection() {
|
||||
this( false );
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Not used externally
|
||||
*/
|
||||
private IdentifierProjection(boolean grouped) {
|
||||
this.grouped = grouped;
|
||||
}
|
||||
|
||||
protected IdentifierProjection() {
|
||||
this(false);
|
||||
@Override
|
||||
public Type[] getTypes(Criteria criteria, CriteriaQuery criteriaQuery) {
|
||||
return new Type[] { criteriaQuery.getIdentifierType( criteria ) };
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "id";
|
||||
}
|
||||
|
||||
public Type[] getTypes(Criteria criteria, CriteriaQuery criteriaQuery)
|
||||
throws HibernateException {
|
||||
return new Type[] { criteriaQuery.getIdentifierType(criteria) };
|
||||
}
|
||||
|
||||
public String toSqlString(Criteria criteria, int position, CriteriaQuery criteriaQuery)
|
||||
throws HibernateException {
|
||||
StringBuilder buf = new StringBuilder();
|
||||
String[] cols = criteriaQuery.getIdentifierColumns(criteria);
|
||||
@Override
|
||||
public String toSqlString(Criteria criteria, int position, CriteriaQuery criteriaQuery) {
|
||||
final StringBuilder buf = new StringBuilder();
|
||||
final String[] cols = criteriaQuery.getIdentifierColumns( criteria );
|
||||
for ( int i=0; i<cols.length; i++ ) {
|
||||
buf.append( cols[i] )
|
||||
.append(" as y")
|
||||
.append(position + i)
|
||||
.append('_');
|
||||
if (i < cols.length -1)
|
||||
buf.append(", ");
|
||||
.append( " as y" )
|
||||
.append( position + i )
|
||||
.append( '_' );
|
||||
if ( i < cols.length -1 ) {
|
||||
buf.append( ", " );
|
||||
}
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isGrouped() {
|
||||
return grouped;
|
||||
}
|
||||
|
||||
public String toGroupSqlString(Criteria criteria, CriteriaQuery criteriaQuery)
|
||||
throws HibernateException {
|
||||
if (!grouped) {
|
||||
return super.toGroupSqlString(criteria, criteriaQuery);
|
||||
@Override
|
||||
public String toGroupSqlString(Criteria criteria, CriteriaQuery criteriaQuery) {
|
||||
if ( !grouped ) {
|
||||
return super.toGroupSqlString( criteria, criteriaQuery );
|
||||
}
|
||||
else {
|
||||
return StringHelper.join( ", ", criteriaQuery.getIdentifierColumns(criteria) );
|
||||
return StringHelper.join( ", ", criteriaQuery.getIdentifierColumns( criteria ) );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "id";
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -31,13 +31,15 @@ import org.hibernate.dialect.PostgreSQL81Dialect;
|
|||
import org.hibernate.engine.spi.TypedValue;
|
||||
|
||||
/**
|
||||
* A case-insensitive "like"
|
||||
* A case-insensitive "like".
|
||||
*
|
||||
* @author Gavin King
|
||||
*
|
||||
* @deprecated Prefer {@link LikeExpression} which now has case-insensitivity capability.
|
||||
*/
|
||||
@Deprecated
|
||||
@SuppressWarnings({"deprecation", "UnusedDeclaration"})
|
||||
public class IlikeExpression implements Criterion {
|
||||
|
||||
private final String propertyName;
|
||||
private final Object value;
|
||||
|
||||
|
@ -50,10 +52,10 @@ public class IlikeExpression implements Criterion {
|
|||
this( propertyName, matchMode.toMatchString( value ) );
|
||||
}
|
||||
|
||||
public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery)
|
||||
throws HibernateException {
|
||||
Dialect dialect = criteriaQuery.getFactory().getDialect();
|
||||
String[] columns = criteriaQuery.findColumns( propertyName, criteria );
|
||||
@Override
|
||||
public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery) {
|
||||
final Dialect dialect = criteriaQuery.getFactory().getDialect();
|
||||
final String[] columns = criteriaQuery.findColumns( propertyName, criteria );
|
||||
if ( columns.length != 1 ) {
|
||||
throw new HibernateException( "ilike may only be used with single-column properties" );
|
||||
}
|
||||
|
@ -63,12 +65,10 @@ public class IlikeExpression implements Criterion {
|
|||
else {
|
||||
return dialect.getLowercaseFunction() + '(' + columns[0] + ") like ?";
|
||||
}
|
||||
|
||||
//TODO: get SQL rendering out of this package!
|
||||
}
|
||||
|
||||
public TypedValue[] getTypedValues(Criteria criteria, CriteriaQuery criteriaQuery)
|
||||
throws HibernateException {
|
||||
@Override
|
||||
public TypedValue[] getTypedValues(Criteria criteria, CriteriaQuery criteriaQuery) {
|
||||
return new TypedValue[] {
|
||||
criteriaQuery.getTypedValue(
|
||||
criteria,
|
||||
|
@ -78,6 +78,7 @@ public class IlikeExpression implements Criterion {
|
|||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return propertyName + " ilike " + value;
|
||||
}
|
||||
|
|
|
@ -22,11 +22,11 @@
|
|||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.criterion;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import org.hibernate.Criteria;
|
||||
import org.hibernate.EntityMode;
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.engine.spi.TypedValue;
|
||||
import org.hibernate.internal.util.StringHelper;
|
||||
import org.hibernate.type.CompositeType;
|
||||
|
@ -34,72 +34,82 @@ import org.hibernate.type.Type;
|
|||
|
||||
/**
|
||||
* Constrains the property to a specified list of values
|
||||
*
|
||||
* @author Gavin King
|
||||
*/
|
||||
public class InExpression implements Criterion {
|
||||
|
||||
private final String propertyName;
|
||||
private final Object[] values;
|
||||
|
||||
/**
|
||||
* Constructs an InExpression
|
||||
*
|
||||
* @param propertyName The property name to check
|
||||
* @param values The values to check against
|
||||
*
|
||||
* @see Restrictions#in(String, java.util.Collection)
|
||||
* @see Restrictions#in(String, Object[])
|
||||
*/
|
||||
protected InExpression(String propertyName, Object[] values) {
|
||||
this.propertyName = propertyName;
|
||||
this.values = values;
|
||||
}
|
||||
|
||||
public String toSqlString( Criteria criteria, CriteriaQuery criteriaQuery )
|
||||
throws HibernateException {
|
||||
String[] columns = criteriaQuery.findColumns(propertyName, criteria);
|
||||
if ( criteriaQuery.getFactory().getDialect()
|
||||
.supportsRowValueConstructorSyntaxInInList() || columns.length<=1) {
|
||||
|
||||
String singleValueParam = StringHelper.repeat( "?, ",
|
||||
columns.length - 1 )
|
||||
+ "?";
|
||||
if ( columns.length > 1 )
|
||||
@Override
|
||||
public String toSqlString( Criteria criteria, CriteriaQuery criteriaQuery ) {
|
||||
final String[] columns = criteriaQuery.findColumns( propertyName, criteria );
|
||||
if ( criteriaQuery.getFactory().getDialect().supportsRowValueConstructorSyntaxInInList() || columns.length <= 1 ) {
|
||||
String singleValueParam = StringHelper.repeat( "?, ", columns.length - 1 ) + "?";
|
||||
if ( columns.length > 1 ) {
|
||||
singleValueParam = '(' + singleValueParam + ')';
|
||||
String params = values.length > 0 ? StringHelper.repeat(
|
||||
singleValueParam + ", ", values.length - 1 )
|
||||
+ singleValueParam : "";
|
||||
}
|
||||
final String params = values.length > 0
|
||||
? StringHelper.repeat( singleValueParam + ", ", values.length - 1 ) + singleValueParam
|
||||
: "";
|
||||
String cols = StringHelper.join( ", ", columns );
|
||||
if ( columns.length > 1 )
|
||||
if ( columns.length > 1 ) {
|
||||
cols = '(' + cols + ')';
|
||||
}
|
||||
return cols + " in (" + params + ')';
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
String cols = " ( " + StringHelper.join( " = ? and ", columns ) + "= ? ) ";
|
||||
cols = values.length > 0 ? StringHelper.repeat( cols
|
||||
+ "or ", values.length - 1 )
|
||||
+ cols : "";
|
||||
cols = values.length > 0
|
||||
? StringHelper.repeat( cols + "or ", values.length - 1 ) + cols
|
||||
: "";
|
||||
cols = " ( " + cols + " ) ";
|
||||
return cols;
|
||||
}
|
||||
}
|
||||
|
||||
public TypedValue[] getTypedValues(Criteria criteria, CriteriaQuery criteriaQuery)
|
||||
throws HibernateException {
|
||||
ArrayList list = new ArrayList();
|
||||
Type type = criteriaQuery.getTypeUsingProjection(criteria, propertyName);
|
||||
@Override
|
||||
public TypedValue[] getTypedValues(Criteria criteria, CriteriaQuery criteriaQuery) {
|
||||
final ArrayList<TypedValue> list = new ArrayList<TypedValue>();
|
||||
final Type type = criteriaQuery.getTypeUsingProjection( criteria, propertyName );
|
||||
if ( type.isComponentType() ) {
|
||||
CompositeType actype = (CompositeType) type;
|
||||
Type[] types = actype.getSubtypes();
|
||||
for ( int j=0; j<values.length; j++ ) {
|
||||
for ( int i=0; i<types.length; i++ ) {
|
||||
Object subval = values[j]==null ?
|
||||
null :
|
||||
actype.getPropertyValues( values[j], EntityMode.POJO )[i];
|
||||
list.add( new TypedValue( types[i], subval ) );
|
||||
final CompositeType compositeType = (CompositeType) type;
|
||||
final Type[] subTypes = compositeType.getSubtypes();
|
||||
for ( Object value : values ) {
|
||||
for ( int i = 0; i < subTypes.length; i++ ) {
|
||||
final Object subValue = value == null
|
||||
? null
|
||||
: compositeType.getPropertyValues( value, EntityMode.POJO )[i];
|
||||
list.add( new TypedValue( subTypes[i], subValue ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
for ( int j=0; j<values.length; j++ ) {
|
||||
list.add( new TypedValue( type, values[j] ) );
|
||||
for ( Object value : values ) {
|
||||
list.add( new TypedValue( type, value ) );
|
||||
}
|
||||
}
|
||||
return (TypedValue[]) list.toArray( new TypedValue[ list.size() ] );
|
||||
}
|
||||
|
||||
return list.toArray( new TypedValue[ list.size() ] );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return propertyName + " in (" + StringHelper.toString(values) + ')';
|
||||
return propertyName + " in (" + StringHelper.toString( values ) + ')';
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
|
||||
* Copyright (c) 2008, 2013, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Middleware LLC.
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
|
@ -20,9 +20,9 @@
|
|||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
package org.hibernate.criterion;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
|
@ -38,6 +38,7 @@ import org.hibernate.internal.util.StringHelper;
|
|||
* associative logical operator
|
||||
*
|
||||
* @author Gavin King
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class Junction implements Criterion {
|
||||
private final Nature nature;
|
||||
|
@ -47,6 +48,18 @@ public class Junction implements Criterion {
|
|||
this.nature = nature;
|
||||
}
|
||||
|
||||
protected Junction(Nature nature, Criterion... criterion) {
|
||||
this( nature );
|
||||
Collections.addAll( conditions, criterion );
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a criterion to the junction (and/or)
|
||||
*
|
||||
* @param criterion The criterion to add
|
||||
*
|
||||
* @return {@code this}, for method chaining
|
||||
*/
|
||||
public Junction add(Criterion criterion) {
|
||||
conditions.add( criterion );
|
||||
return this;
|
||||
|
@ -56,15 +69,20 @@ public class Junction implements Criterion {
|
|||
return nature;
|
||||
}
|
||||
|
||||
/**
|
||||
* Access the conditions making up the junction
|
||||
*
|
||||
* @return the criterion
|
||||
*/
|
||||
public Iterable<Criterion> conditions() {
|
||||
return conditions;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypedValue[] getTypedValues(Criteria crit, CriteriaQuery criteriaQuery) throws HibernateException {
|
||||
ArrayList<TypedValue> typedValues = new ArrayList<TypedValue>();
|
||||
final ArrayList<TypedValue> typedValues = new ArrayList<TypedValue>();
|
||||
for ( Criterion condition : conditions ) {
|
||||
TypedValue[] subValues = condition.getTypedValues( crit, criteriaQuery );
|
||||
final TypedValue[] subValues = condition.getTypedValues( crit, criteriaQuery );
|
||||
Collections.addAll( typedValues, subValues );
|
||||
}
|
||||
return typedValues.toArray( new TypedValue[ typedValues.size() ] );
|
||||
|
@ -76,15 +94,18 @@ public class Junction implements Criterion {
|
|||
return "1=1";
|
||||
}
|
||||
|
||||
StringBuilder buffer = new StringBuilder().append( '(' );
|
||||
Iterator itr = conditions.iterator();
|
||||
final StringBuilder buffer = new StringBuilder().append( '(' );
|
||||
final Iterator itr = conditions.iterator();
|
||||
while ( itr.hasNext() ) {
|
||||
buffer.append( ( (Criterion) itr.next() ).toSqlString( crit, criteriaQuery ) );
|
||||
if ( itr.hasNext() ) {
|
||||
buffer.append(' ').append( nature.getOperator() ).append(' ');
|
||||
buffer.append( ' ' )
|
||||
.append( nature.getOperator() )
|
||||
.append( ' ' );
|
||||
}
|
||||
}
|
||||
return buffer.append(')').toString();
|
||||
|
||||
return buffer.append( ')' ).toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -92,11 +113,24 @@ public class Junction implements Criterion {
|
|||
return '(' + StringHelper.join( ' ' + nature.getOperator() + ' ', conditions.iterator() ) + ')';
|
||||
}
|
||||
|
||||
/**
|
||||
* The type of junction
|
||||
*/
|
||||
public static enum Nature {
|
||||
/**
|
||||
* An AND
|
||||
*/
|
||||
AND,
|
||||
OR
|
||||
;
|
||||
/**
|
||||
* An OR
|
||||
*/
|
||||
OR;
|
||||
|
||||
/**
|
||||
* The corresponding SQL operator
|
||||
*
|
||||
* @return SQL operator
|
||||
*/
|
||||
public String getOperator() {
|
||||
return name().toLowerCase();
|
||||
}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
|
||||
* Copyright (c) 2008, 2013, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Middleware LLC.
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
|
@ -20,9 +20,9 @@
|
|||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
package org.hibernate.criterion;
|
||||
|
||||
import org.hibernate.Criteria;
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.dialect.Dialect;
|
||||
|
@ -51,16 +51,12 @@ public class LikeExpression implements Criterion {
|
|||
this.ignoreCase = ignoreCase;
|
||||
}
|
||||
|
||||
protected LikeExpression(
|
||||
String propertyName,
|
||||
String value) {
|
||||
protected LikeExpression(String propertyName, String value) {
|
||||
this( propertyName, value, null, false );
|
||||
}
|
||||
|
||||
protected LikeExpression(
|
||||
String propertyName,
|
||||
String value,
|
||||
MatchMode matchMode) {
|
||||
@SuppressWarnings("UnusedDeclaration")
|
||||
protected LikeExpression(String propertyName, String value, MatchMode matchMode) {
|
||||
this( propertyName, matchMode.toMatchString( value ) );
|
||||
}
|
||||
|
||||
|
@ -73,16 +69,16 @@ public class LikeExpression implements Criterion {
|
|||
this( propertyName, matchMode.toMatchString( value ), escapeChar, ignoreCase );
|
||||
}
|
||||
|
||||
public String toSqlString(
|
||||
Criteria criteria,
|
||||
CriteriaQuery criteriaQuery) throws HibernateException {
|
||||
Dialect dialect = criteriaQuery.getFactory().getDialect();
|
||||
String[] columns = criteriaQuery.findColumns(propertyName, criteria);
|
||||
@Override
|
||||
public String toSqlString(Criteria criteria,CriteriaQuery criteriaQuery) {
|
||||
final Dialect dialect = criteriaQuery.getFactory().getDialect();
|
||||
final String[] columns = criteriaQuery.findColumns( propertyName, criteria );
|
||||
if ( columns.length != 1 ) {
|
||||
throw new HibernateException( "Like may only be used with single-column properties" );
|
||||
}
|
||||
String escape = escapeChar == null ? "" : " escape \'" + escapeChar + "\'";
|
||||
String column = columns[0];
|
||||
|
||||
final String escape = escapeChar == null ? "" : " escape \'" + escapeChar + "\'";
|
||||
final String column = columns[0];
|
||||
if ( ignoreCase ) {
|
||||
if ( dialect.supportsCaseInsensitiveLike() ) {
|
||||
return column +" " + dialect.getCaseInsensitiveLike() + " ?" + escape;
|
||||
|
@ -96,11 +92,10 @@ public class LikeExpression implements Criterion {
|
|||
}
|
||||
}
|
||||
|
||||
public TypedValue[] getTypedValues(
|
||||
Criteria criteria,
|
||||
CriteriaQuery criteriaQuery) throws HibernateException {
|
||||
return new TypedValue[] {
|
||||
criteriaQuery.getTypedValue( criteria, propertyName, ignoreCase ? value.toString().toLowerCase() : value.toString() )
|
||||
};
|
||||
@Override
|
||||
public TypedValue[] getTypedValues(Criteria criteria, CriteriaQuery criteriaQuery) {
|
||||
final String matchValue = ignoreCase ? value.toString().toLowerCase() : value.toString();
|
||||
|
||||
return new TypedValue[] { criteriaQuery.getTypedValue( criteria, propertyName, matchValue ) };
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
|
||||
* Copyright (c) 2008, 2013, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Middleware LLC.
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
|
@ -20,19 +20,18 @@
|
|||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
package org.hibernate.criterion;
|
||||
|
||||
import org.hibernate.Criteria;
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.engine.spi.TypedValue;
|
||||
|
||||
/**
|
||||
* Superclass of binary logical expressions
|
||||
*
|
||||
* @author Gavin King
|
||||
*/
|
||||
public class LogicalExpression implements Criterion {
|
||||
|
||||
private final Criterion lhs;
|
||||
private final Criterion rhs;
|
||||
private final String op;
|
||||
|
@ -43,33 +42,33 @@ public class LogicalExpression implements Criterion {
|
|||
this.op = op;
|
||||
}
|
||||
|
||||
public TypedValue[] getTypedValues(Criteria criteria, CriteriaQuery criteriaQuery)
|
||||
throws HibernateException {
|
||||
@Override
|
||||
public TypedValue[] getTypedValues(Criteria criteria, CriteriaQuery criteriaQuery) {
|
||||
final TypedValue[] lhsTypedValues = lhs.getTypedValues( criteria, criteriaQuery );
|
||||
final TypedValue[] rhsTypedValues = rhs.getTypedValues( criteria, criteriaQuery );
|
||||
|
||||
TypedValue[] lhstv = lhs.getTypedValues(criteria, criteriaQuery);
|
||||
TypedValue[] rhstv = rhs.getTypedValues(criteria, criteriaQuery);
|
||||
TypedValue[] result = new TypedValue[ lhstv.length + rhstv.length ];
|
||||
System.arraycopy(lhstv, 0, result, 0, lhstv.length);
|
||||
System.arraycopy(rhstv, 0, result, lhstv.length, rhstv.length);
|
||||
final TypedValue[] result = new TypedValue[ lhsTypedValues.length + rhsTypedValues.length ];
|
||||
System.arraycopy( lhsTypedValues, 0, result, 0, lhsTypedValues.length );
|
||||
System.arraycopy( rhsTypedValues, 0, result, lhsTypedValues.length, rhsTypedValues.length );
|
||||
return result;
|
||||
}
|
||||
|
||||
public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery)
|
||||
throws HibernateException {
|
||||
|
||||
return '(' +
|
||||
lhs.toSqlString(criteria, criteriaQuery) +
|
||||
' ' +
|
||||
getOp() +
|
||||
' ' +
|
||||
rhs.toSqlString(criteria, criteriaQuery) +
|
||||
')';
|
||||
@Override
|
||||
public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery) {
|
||||
return '('
|
||||
+ lhs.toSqlString( criteria, criteriaQuery )
|
||||
+ ' '
|
||||
+ getOp()
|
||||
+ ' '
|
||||
+ rhs.toSqlString( criteria, criteriaQuery )
|
||||
+ ')';
|
||||
}
|
||||
|
||||
public String getOp() {
|
||||
return op;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return lhs.toString() + ' ' + getOp() + ' ' + rhs.toString();
|
||||
}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
|
||||
* Copyright (c) 2008, 2013, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Middleware LLC.
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
|
@ -20,7 +20,6 @@
|
|||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
package org.hibernate.criterion;
|
||||
|
||||
|
@ -36,6 +35,7 @@ public enum MatchMode {
|
|||
* Match the entire string to the pattern
|
||||
*/
|
||||
EXACT {
|
||||
@Override
|
||||
public String toMatchString(String pattern) {
|
||||
return pattern;
|
||||
}
|
||||
|
@ -45,6 +45,7 @@ public enum MatchMode {
|
|||
* Match the start of the string to the pattern
|
||||
*/
|
||||
START {
|
||||
@Override
|
||||
public String toMatchString(String pattern) {
|
||||
return pattern + '%';
|
||||
}
|
||||
|
@ -54,6 +55,7 @@ public enum MatchMode {
|
|||
* Match the end of the string to the pattern
|
||||
*/
|
||||
END {
|
||||
@Override
|
||||
public String toMatchString(String pattern) {
|
||||
return '%' + pattern;
|
||||
}
|
||||
|
@ -63,13 +65,18 @@ public enum MatchMode {
|
|||
* Match the pattern anywhere in the string
|
||||
*/
|
||||
ANYWHERE {
|
||||
@Override
|
||||
public String toMatchString(String pattern) {
|
||||
return '%' + pattern + '%';
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* convert the pattern, by appending/prepending "%"
|
||||
* Convert the pattern, by appending/prepending "%"
|
||||
*
|
||||
* @param pattern The pattern for convert according to the mode
|
||||
*
|
||||
* @return The converted pattern
|
||||
*/
|
||||
public abstract String toMatchString(String pattern);
|
||||
|
||||
|
|
|
@ -28,27 +28,37 @@ import java.util.concurrent.ConcurrentHashMap;
|
|||
|
||||
import org.hibernate.Criteria;
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.engine.spi.TypedValue;
|
||||
|
||||
/**
|
||||
* An expression pertaining to an entity's defined natural identifier
|
||||
*
|
||||
* @author Gavin King
|
||||
* @see Session#byNaturalId(Class)
|
||||
* @see Session#byNaturalId(String)
|
||||
* @see Session#bySimpleNaturalId(Class)
|
||||
* @see Session#bySimpleNaturalId(String)
|
||||
*
|
||||
* @see org.hibernate.Session#byNaturalId(Class)
|
||||
* @see org.hibernate.Session#byNaturalId(String)
|
||||
* @see org.hibernate.Session#bySimpleNaturalId(Class)
|
||||
* @see org.hibernate.Session#bySimpleNaturalId(String)
|
||||
*/
|
||||
public class NaturalIdentifier implements Criterion {
|
||||
private final Conjunction conjunction = new Conjunction();
|
||||
|
||||
@Override
|
||||
public TypedValue[] getTypedValues(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException {
|
||||
return conjunction.getTypedValues( criteria, criteriaQuery );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException {
|
||||
return conjunction.toSqlString( criteria, criteriaQuery );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a map of set of the natural identifier values set on this criterion (for composite natural identifiers
|
||||
* this need not be the full set of properties).
|
||||
*
|
||||
* @return The value map.
|
||||
*/
|
||||
public Map<String, Object> getNaturalIdValues() {
|
||||
final Map<String, Object> naturalIdValueMap = new ConcurrentHashMap<String, Object>();
|
||||
for ( Criterion condition : conjunction.conditions() ) {
|
||||
|
@ -65,6 +75,14 @@ public class NaturalIdentifier implements Criterion {
|
|||
return naturalIdValueMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a natural identifier value for this expression
|
||||
*
|
||||
* @param property The specific property name
|
||||
* @param value The value to use
|
||||
*
|
||||
* @return {@code this}, for method chaining
|
||||
*/
|
||||
public NaturalIdentifier set(String property, Object value) {
|
||||
conjunction.add( Restrictions.eq( property, value ) );
|
||||
return this;
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
|
||||
* Copyright (c) 2008, 2013, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Middleware LLC.
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
|
@ -20,20 +20,27 @@
|
|||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
package org.hibernate.criterion;
|
||||
|
||||
|
||||
/**
|
||||
* An expression asserting that a collection property is empty
|
||||
*
|
||||
* @author Gavin King
|
||||
*/
|
||||
public class NotEmptyExpression extends AbstractEmptinessExpression implements Criterion {
|
||||
|
||||
/**
|
||||
* Constructs an EmptyExpression
|
||||
*
|
||||
* @param propertyName The collection property name
|
||||
*
|
||||
* @see Restrictions#isNotEmpty
|
||||
*/
|
||||
protected NotEmptyExpression(String propertyName) {
|
||||
super( propertyName );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean excludeEmpty() {
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -28,29 +28,37 @@ import org.hibernate.HibernateException;
|
|||
import org.hibernate.engine.spi.TypedValue;
|
||||
|
||||
/**
|
||||
* Negates another criterion
|
||||
* A criterion that is a wrapper for another, negating the wrapped one.
|
||||
*
|
||||
* @author Gavin King
|
||||
* @author Brett Meyer
|
||||
*/
|
||||
public class NotExpression implements Criterion {
|
||||
|
||||
private Criterion criterion;
|
||||
|
||||
/**
|
||||
* Constructs a NotExpression
|
||||
*
|
||||
* @param criterion The expression to wrap and negate
|
||||
*
|
||||
* @see Restrictions#not
|
||||
*/
|
||||
protected NotExpression(Criterion criterion) {
|
||||
this.criterion = criterion;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException {
|
||||
return criteriaQuery.getFactory().getDialect().getNotExpression(
|
||||
criterion.toSqlString( criteria, criteriaQuery ) );
|
||||
criterion.toSqlString( criteria, criteriaQuery )
|
||||
);
|
||||
}
|
||||
|
||||
public TypedValue[] getTypedValues(
|
||||
Criteria criteria, CriteriaQuery criteriaQuery)
|
||||
throws HibernateException {
|
||||
return criterion.getTypedValues(criteria, criteriaQuery);
|
||||
@Override
|
||||
public TypedValue[] getTypedValues(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException {
|
||||
return criterion.getTypedValues( criteria, criteriaQuery );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "not " + criterion.toString();
|
||||
}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
|
||||
* Copyright (c) 2008, 2013, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Middleware LLC.
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
|
@ -20,9 +20,9 @@
|
|||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
package org.hibernate.criterion;
|
||||
|
||||
import org.hibernate.Criteria;
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.engine.spi.TypedValue;
|
||||
|
@ -30,36 +30,37 @@ import org.hibernate.internal.util.StringHelper;
|
|||
|
||||
/**
|
||||
* Constrains a property to be non-null
|
||||
*
|
||||
* @author Gavin King
|
||||
*/
|
||||
public class NotNullExpression implements Criterion {
|
||||
private static final TypedValue[] NO_VALUES = new TypedValue[0];
|
||||
|
||||
private final String propertyName;
|
||||
|
||||
private static final TypedValue[] NO_VALUES = new TypedValue[0];
|
||||
|
||||
protected NotNullExpression(String propertyName) {
|
||||
this.propertyName = propertyName;
|
||||
}
|
||||
|
||||
public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery)
|
||||
throws HibernateException {
|
||||
String[] columns = criteriaQuery.findColumns(propertyName, criteria);
|
||||
@Override
|
||||
public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException {
|
||||
final String[] columns = criteriaQuery.findColumns( propertyName, criteria );
|
||||
String result = StringHelper.join(
|
||||
" or ",
|
||||
StringHelper.suffix( columns, " is not null" )
|
||||
);
|
||||
if (columns.length>1) result = '(' + result + ')';
|
||||
if ( columns.length > 1 ) {
|
||||
result = '(' + result + ')';
|
||||
}
|
||||
return result;
|
||||
|
||||
//TODO: get SQL rendering out of this package!
|
||||
}
|
||||
|
||||
public TypedValue[] getTypedValues(Criteria criteria, CriteriaQuery criteriaQuery)
|
||||
throws HibernateException {
|
||||
@Override
|
||||
public TypedValue[] getTypedValues(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException {
|
||||
return NO_VALUES;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return propertyName + " is not null";
|
||||
}
|
||||
|
|
|
@ -30,36 +30,44 @@ import org.hibernate.internal.util.StringHelper;
|
|||
|
||||
/**
|
||||
* Constrains a property to be null
|
||||
*
|
||||
* @author Gavin King
|
||||
*/
|
||||
public class NullExpression implements Criterion {
|
||||
private static final TypedValue[] NO_VALUES = new TypedValue[0];
|
||||
|
||||
private final String propertyName;
|
||||
|
||||
private static final TypedValue[] NO_VALUES = new TypedValue[0];
|
||||
|
||||
/**
|
||||
* Constructs a NullExpression
|
||||
*
|
||||
* @param propertyName The name of the property to check for null
|
||||
*
|
||||
* @see Restrictions#isNull
|
||||
*/
|
||||
protected NullExpression(String propertyName) {
|
||||
this.propertyName = propertyName;
|
||||
}
|
||||
|
||||
public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery)
|
||||
throws HibernateException {
|
||||
String[] columns = criteriaQuery.findColumns(propertyName, criteria);
|
||||
@Override
|
||||
public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException {
|
||||
final String[] columns = criteriaQuery.findColumns( propertyName, criteria );
|
||||
String result = StringHelper.join(
|
||||
" and ",
|
||||
StringHelper.suffix( columns, " is null" )
|
||||
);
|
||||
if (columns.length>1) result = '(' + result + ')';
|
||||
if ( columns.length > 1 ) {
|
||||
result = '(' + result + ')';
|
||||
}
|
||||
return result;
|
||||
|
||||
//TODO: get SQL rendering out of this package!
|
||||
}
|
||||
|
||||
public TypedValue[] getTypedValues(Criteria criteria, CriteriaQuery criteriaQuery)
|
||||
throws HibernateException {
|
||||
@Override
|
||||
public TypedValue[] getTypedValues(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException {
|
||||
return NO_VALUES;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return propertyName + " is null";
|
||||
}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
|
||||
* Copyright (c) 2008, 2013, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Middleware LLC.
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
|
@ -20,24 +20,22 @@
|
|||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
package org.hibernate.criterion;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.sql.Types;
|
||||
|
||||
import org.hibernate.Criteria;
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.NullPrecedence;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.type.Type;
|
||||
|
||||
/**
|
||||
* Represents an order imposed upon a <tt>Criteria</tt> result set
|
||||
* Represents an ordering imposed upon the results of a Criteria
|
||||
*
|
||||
* @author Gavin King
|
||||
* @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com)
|
||||
* @author Brett Meyer
|
||||
*/
|
||||
public class Order implements Serializable {
|
||||
private boolean ascending;
|
||||
|
@ -45,22 +43,33 @@ public class Order implements Serializable {
|
|||
private String propertyName;
|
||||
private NullPrecedence nullPrecedence;
|
||||
|
||||
public String toString() {
|
||||
return propertyName + ' ' + ( ascending ? "asc" : "desc" ) + ( nullPrecedence != null ? ' ' + nullPrecedence.name().toLowerCase() : "" );
|
||||
}
|
||||
|
||||
public Order ignoreCase() {
|
||||
ignoreCase = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Order nulls(NullPrecedence nullPrecedence) {
|
||||
this.nullPrecedence = nullPrecedence;
|
||||
return this;
|
||||
/**
|
||||
* Ascending order
|
||||
*
|
||||
* @param propertyName The property to order on
|
||||
*
|
||||
* @return The build Order instance
|
||||
*/
|
||||
public static Order asc(String propertyName) {
|
||||
return new Order( propertyName, true );
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor for Order.
|
||||
* Descending order.
|
||||
*
|
||||
* @param propertyName The property to order on
|
||||
*
|
||||
* @return The build Order instance
|
||||
*/
|
||||
public static Order desc(String propertyName) {
|
||||
return new Order( propertyName, false );
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor for Order. Order instances are generally created by factory methods.
|
||||
*
|
||||
* @see #asc
|
||||
* @see #desc
|
||||
*/
|
||||
protected Order(String propertyName, boolean ascending) {
|
||||
this.propertyName = propertyName;
|
||||
|
@ -68,74 +77,96 @@ public class Order implements Serializable {
|
|||
}
|
||||
|
||||
/**
|
||||
* Render the SQL fragment
|
||||
* Should this ordering ignore case? Has no effect on non-character properties.
|
||||
*
|
||||
* @return {@code this}, for method chaining
|
||||
*/
|
||||
public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery)
|
||||
throws HibernateException {
|
||||
String[] columns = criteriaQuery.getColumnsUsingProjection(criteria, propertyName);
|
||||
Type type = criteriaQuery.getTypeUsingProjection(criteria, propertyName);
|
||||
StringBuilder fragment = new StringBuilder();
|
||||
for ( int i=0; i<columns.length; i++ ) {
|
||||
final StringBuilder expression = new StringBuilder();
|
||||
SessionFactoryImplementor factory = criteriaQuery.getFactory();
|
||||
boolean lower = false;
|
||||
if ( ignoreCase ) {
|
||||
int sqlType = type.sqlTypes( factory )[i];
|
||||
lower = sqlType == Types.VARCHAR
|
||||
|| sqlType == Types.CHAR
|
||||
|| sqlType == Types.LONGVARCHAR;
|
||||
public Order ignoreCase() {
|
||||
ignoreCase = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
if (lower) {
|
||||
expression.append( factory.getDialect().getLowercaseFunction() ).append('(');
|
||||
}
|
||||
expression.append( columns[i] );
|
||||
if (lower) expression.append(')');
|
||||
fragment.append(
|
||||
factory.getDialect()
|
||||
.renderOrderByElement(
|
||||
expression.toString(),
|
||||
null,
|
||||
ascending ? "asc" : "desc",
|
||||
nullPrecedence != null ? nullPrecedence : factory.getSettings().getDefaultNullPrecedence()
|
||||
)
|
||||
);
|
||||
if ( i<columns.length-1 ) fragment.append(", ");
|
||||
}
|
||||
return fragment.toString();
|
||||
/**
|
||||
* Defines precedence for nulls.
|
||||
*
|
||||
* @param nullPrecedence The null precedence to use
|
||||
*
|
||||
* @return {@code this}, for method chaining
|
||||
*/
|
||||
public Order nulls(NullPrecedence nullPrecedence) {
|
||||
this.nullPrecedence = nullPrecedence;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getPropertyName() {
|
||||
return propertyName;
|
||||
}
|
||||
|
||||
@SuppressWarnings("UnusedDeclaration")
|
||||
public boolean isAscending() {
|
||||
return ascending;
|
||||
}
|
||||
|
||||
@SuppressWarnings("UnusedDeclaration")
|
||||
public boolean isIgnoreCase() {
|
||||
return ignoreCase;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ascending order
|
||||
*
|
||||
* @param propertyName
|
||||
* @return Order
|
||||
*/
|
||||
public static Order asc(String propertyName) {
|
||||
return new Order(propertyName, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Descending order
|
||||
* Render the SQL fragment
|
||||
*
|
||||
* @param propertyName
|
||||
* @return Order
|
||||
* @param criteria The criteria
|
||||
* @param criteriaQuery The overall query
|
||||
*
|
||||
* @return The ORDER BY fragment for this ordering
|
||||
*/
|
||||
public static Order desc(String propertyName) {
|
||||
return new Order(propertyName, false);
|
||||
public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery) {
|
||||
final String[] columns = criteriaQuery.getColumnsUsingProjection( criteria, propertyName );
|
||||
final Type type = criteriaQuery.getTypeUsingProjection( criteria, propertyName );
|
||||
final SessionFactoryImplementor factory = criteriaQuery.getFactory();
|
||||
final int[] sqlTypes = type.sqlTypes( factory );
|
||||
|
||||
final StringBuilder fragment = new StringBuilder();
|
||||
for ( int i=0; i<columns.length; i++ ) {
|
||||
final StringBuilder expression = new StringBuilder();
|
||||
boolean lower = false;
|
||||
if ( ignoreCase ) {
|
||||
final 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() : "" );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
|
||||
* Copyright (c) 2008, 2013, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Middleware LLC.
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
|
@ -20,9 +20,9 @@
|
|||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
package org.hibernate.criterion;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.hibernate.Criteria;
|
||||
|
@ -36,6 +36,7 @@ import org.hibernate.type.Type;
|
|||
*
|
||||
* @author Gavin King
|
||||
* @author Steve Ebersole
|
||||
*
|
||||
* @see Projections
|
||||
* @see Criteria
|
||||
*/
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
|
||||
* Copyright (c) 2008, 2013, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Middleware LLC.
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
|
@ -20,159 +20,223 @@
|
|||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
package org.hibernate.criterion;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.Criteria;
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.internal.util.collections.ArrayHelper;
|
||||
import org.hibernate.type.Type;
|
||||
|
||||
/**
|
||||
* A projection that wraps other projections to allow selecting multiple values.
|
||||
*
|
||||
* @author Gavin King
|
||||
*/
|
||||
public class ProjectionList implements EnhancedProjection {
|
||||
private List<Projection> elements = new ArrayList<Projection>();
|
||||
|
||||
private List elements = new ArrayList();
|
||||
|
||||
protected ProjectionList() {}
|
||||
/**
|
||||
* Constructs a ProjectionList
|
||||
*
|
||||
* @see Projections#projectionList()
|
||||
*/
|
||||
protected ProjectionList() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Lol
|
||||
*
|
||||
* @return duh
|
||||
*
|
||||
* @deprecated an instance factory method does not make sense
|
||||
*
|
||||
* @see Projections#projectionList()
|
||||
*/
|
||||
@Deprecated
|
||||
public ProjectionList create() {
|
||||
return new ProjectionList();
|
||||
}
|
||||
|
||||
public ProjectionList add(Projection proj) {
|
||||
elements.add(proj);
|
||||
/**
|
||||
* Add a projection to this list of projections
|
||||
*
|
||||
* @param projection The projection to add
|
||||
*
|
||||
* @return {@code this}, for method chaining
|
||||
*/
|
||||
public ProjectionList add(Projection projection) {
|
||||
elements.add( projection );
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a projection to this list of projections after wrapping it with an alias
|
||||
*
|
||||
* @param projection The projection to add
|
||||
* @param alias The alias to apply to the projection
|
||||
*
|
||||
* @return {@code this}, for method chaining
|
||||
*
|
||||
* @see Projections#alias
|
||||
*/
|
||||
public ProjectionList add(Projection projection, String alias) {
|
||||
return add( Projections.alias( projection, alias ) );
|
||||
}
|
||||
|
||||
public Type[] getTypes(Criteria criteria, CriteriaQuery criteriaQuery)
|
||||
throws HibernateException {
|
||||
List types = new ArrayList( getLength() );
|
||||
for ( int i=0; i<getLength(); i++ ) {
|
||||
Type[] elemTypes = getProjection(i).getTypes(criteria, criteriaQuery);
|
||||
ArrayHelper.addAll(types, elemTypes);
|
||||
@Override
|
||||
public boolean isGrouped() {
|
||||
for ( Projection projection : elements ) {
|
||||
if ( projection.isGrouped() ) {
|
||||
return true;
|
||||
}
|
||||
return ArrayHelper.toTypeArray(types);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
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(", ");
|
||||
@Override
|
||||
public Type[] getTypes(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException {
|
||||
final List<Type> types = new ArrayList<Type>( getLength() );
|
||||
for ( Projection projection : elements ) {
|
||||
final Type[] elemTypes = projection.getTypes( criteria, criteriaQuery );
|
||||
Collections.addAll( types, elemTypes );
|
||||
}
|
||||
return types.toArray( new Type[types.size()] );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toSqlString(Criteria criteria, int loc, CriteriaQuery criteriaQuery) throws HibernateException {
|
||||
final StringBuilder buf = new StringBuilder();
|
||||
String separator = "";
|
||||
|
||||
for ( Projection projection : elements ) {
|
||||
buf.append( separator ).append( projection.toSqlString( criteria, loc, criteriaQuery ) );
|
||||
loc += getColumnAliases( loc, criteria, criteriaQuery, projection ).length;
|
||||
separator = ", ";
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
public String toGroupSqlString(Criteria criteria, CriteriaQuery criteriaQuery)
|
||||
throws HibernateException {
|
||||
StringBuilder buf = new StringBuilder();
|
||||
for ( int i=0; i<getLength(); i++ ) {
|
||||
Projection proj = getProjection(i);
|
||||
if ( proj.isGrouped() ) {
|
||||
buf.append( proj.toGroupSqlString(criteria, criteriaQuery) )
|
||||
.append(", ");
|
||||
@Override
|
||||
public String toGroupSqlString(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException {
|
||||
final StringBuilder buf = new StringBuilder();
|
||||
String separator = "";
|
||||
for ( Projection projection : elements ) {
|
||||
if ( ! projection.isGrouped() ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
buf.append( separator ).append( projection.toGroupSqlString( criteria, criteriaQuery ) );
|
||||
separator = ", ";
|
||||
}
|
||||
if ( buf.length()>2 ) buf.setLength( buf.length()-2 ); //pull off the last ", "
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
public String[] getColumnAliases(int loc) {
|
||||
List result = new ArrayList( getLength() );
|
||||
for ( int i=0; i<getLength(); i++ ) {
|
||||
String[] colAliases = getProjection(i).getColumnAliases(loc);
|
||||
ArrayHelper.addAll(result, colAliases);
|
||||
loc+=colAliases.length;
|
||||
@Override
|
||||
public String[] getColumnAliases(final int loc) {
|
||||
int position = loc;
|
||||
final List<String> result = new ArrayList<String>( getLength() );
|
||||
for ( Projection projection : elements ) {
|
||||
final String[] aliases = projection.getColumnAliases( position );
|
||||
Collections.addAll( result, aliases );
|
||||
position += aliases.length;
|
||||
}
|
||||
return ArrayHelper.toStringArray(result);
|
||||
return result.toArray( new String[ result.size() ] );
|
||||
}
|
||||
|
||||
public String[] getColumnAliases(int loc, Criteria criteria, CriteriaQuery criteriaQuery) {
|
||||
List result = new ArrayList( getLength() );
|
||||
for ( int i=0; i<getLength(); i++ ) {
|
||||
String[] colAliases = getColumnAliases( loc, criteria, criteriaQuery, getProjection( i ) );
|
||||
ArrayHelper.addAll(result, colAliases);
|
||||
loc+=colAliases.length;
|
||||
@Override
|
||||
public String[] getColumnAliases(final int loc, Criteria criteria, CriteriaQuery criteriaQuery) {
|
||||
int position = loc;
|
||||
final List<String> result = new ArrayList<String>( getLength() );
|
||||
for ( Projection projection : elements ) {
|
||||
final String[] aliases = getColumnAliases( position, criteria, criteriaQuery, projection );
|
||||
Collections.addAll( result, aliases );
|
||||
position += aliases.length;
|
||||
}
|
||||
return ArrayHelper.toStringArray(result);
|
||||
return result.toArray( new String[result.size()] );
|
||||
}
|
||||
|
||||
public String[] getColumnAliases(String alias, int loc) {
|
||||
for ( int i=0; i<getLength(); i++ ) {
|
||||
String[] result = getProjection(i).getColumnAliases(alias, loc);
|
||||
if (result!=null) return result;
|
||||
loc += getProjection(i).getColumnAliases(loc).length;
|
||||
@Override
|
||||
public String[] getColumnAliases(String alias, final int loc) {
|
||||
int position = loc;
|
||||
for ( Projection projection : elements ) {
|
||||
final String[] aliases = projection.getColumnAliases( alias, position );
|
||||
if ( aliases != null ) {
|
||||
return aliases;
|
||||
}
|
||||
position += projection.getColumnAliases( position ).length;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getColumnAliases(String alias, int loc, Criteria criteria, CriteriaQuery criteriaQuery) {
|
||||
for ( int i=0; i<getLength(); i++ ) {
|
||||
String[] result = getColumnAliases( alias, loc, criteria, criteriaQuery, getProjection(i) );
|
||||
if (result!=null) return result;
|
||||
loc += getColumnAliases( loc, criteria, criteriaQuery, getProjection( i ) ).length;
|
||||
int position = loc;
|
||||
for ( Projection projection : elements ) {
|
||||
final String[] aliases = getColumnAliases( alias, position, criteria, criteriaQuery, projection );
|
||||
if ( aliases != null ) {
|
||||
return aliases;
|
||||
}
|
||||
position += getColumnAliases( position, criteria, criteriaQuery, projection ).length;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static String[] getColumnAliases(int loc, Criteria criteria, CriteriaQuery criteriaQuery, Projection projection) {
|
||||
return projection instanceof EnhancedProjection ?
|
||||
( ( EnhancedProjection ) projection ).getColumnAliases( loc, criteria, criteriaQuery ) :
|
||||
projection.getColumnAliases( loc );
|
||||
return projection instanceof EnhancedProjection
|
||||
? ( (EnhancedProjection) projection ).getColumnAliases( loc, criteria, criteriaQuery )
|
||||
: projection.getColumnAliases( loc );
|
||||
}
|
||||
|
||||
private static String[] getColumnAliases(String alias, int loc, Criteria criteria, CriteriaQuery criteriaQuery, Projection projection) {
|
||||
return projection instanceof EnhancedProjection ?
|
||||
( ( EnhancedProjection ) projection ).getColumnAliases( alias, loc, criteria, criteriaQuery ) :
|
||||
projection.getColumnAliases( alias, loc );
|
||||
return projection instanceof EnhancedProjection
|
||||
? ( (EnhancedProjection) projection ).getColumnAliases( alias, loc, criteria, criteriaQuery )
|
||||
: projection.getColumnAliases( alias, loc );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type[] getTypes(String alias, Criteria criteria, CriteriaQuery criteriaQuery) {
|
||||
for ( int i=0; i<getLength(); i++ ) {
|
||||
Type[] result = getProjection(i).getTypes(alias, criteria, criteriaQuery);
|
||||
if (result!=null) return result;
|
||||
for ( Projection projection : elements ) {
|
||||
final Type[] types = projection.getTypes( alias, criteria, criteriaQuery );
|
||||
if ( types != null ) {
|
||||
return types;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getAliases() {
|
||||
List result = new ArrayList( getLength() );
|
||||
for ( int i=0; i<getLength(); i++ ) {
|
||||
String[] aliases = getProjection(i).getAliases();
|
||||
ArrayHelper.addAll( result, aliases );
|
||||
final List<String> result = new ArrayList<String>( getLength() );
|
||||
for ( Projection projection : elements ) {
|
||||
final String[] aliases = projection.getAliases();
|
||||
Collections.addAll( result, aliases );
|
||||
}
|
||||
return ArrayHelper.toStringArray(result);
|
||||
|
||||
return result.toArray( new String[result.size()] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Access a wrapped projection by index
|
||||
*
|
||||
* @param i The index of the projection to return
|
||||
*
|
||||
* @return The projection
|
||||
*/
|
||||
@SuppressWarnings("UnusedDeclaration")
|
||||
public Projection getProjection(int i) {
|
||||
return (Projection) elements.get(i);
|
||||
return elements.get( i );
|
||||
}
|
||||
|
||||
public int getLength() {
|
||||
return elements.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return elements.toString();
|
||||
}
|
||||
|
||||
public boolean isGrouped() {
|
||||
for ( int i=0; i<getLength(); i++ ) {
|
||||
if ( getProjection(i).isGrouped() ) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
|
||||
* Copyright (c) 2008, 2013, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Middleware LLC.
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
|
@ -20,38 +20,81 @@
|
|||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
package org.hibernate.criterion;
|
||||
|
||||
import org.hibernate.type.Type;
|
||||
|
||||
/**
|
||||
* The <tt>criterion</tt> package may be used by applications as a framework for building
|
||||
* new kinds of <tt>Projection</tt>. However, it is intended that most applications will
|
||||
* simply use the built-in projection types via the static factory methods of this class.<br/>
|
||||
* <br/>
|
||||
* simply use the built-in projection types via the static factory methods of this class.
|
||||
*
|
||||
* The factory methods that take an alias allow the projected value to be referred to by
|
||||
* criterion and order instances.
|
||||
*
|
||||
* @see org.hibernate.Criteria
|
||||
* @see Restrictions factory methods for <tt>Criterion</tt> instances
|
||||
* See also the {@link Restrictions} factory methods for generating {@link Criterion} instances
|
||||
*
|
||||
* @author Gavin King
|
||||
* @author Steve Ebersole
|
||||
*
|
||||
* @see org.hibernate.Criteria
|
||||
*/
|
||||
public final class Projections {
|
||||
|
||||
private Projections() {
|
||||
//cannot be instantiated
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a distinct projection from a projection
|
||||
* A property value projection
|
||||
*
|
||||
* @param propertyName The name of the property whose values should be projected
|
||||
*
|
||||
* @return The property projection
|
||||
*
|
||||
* @see PropertyProjection
|
||||
*/
|
||||
public static Projection distinct(Projection proj) {
|
||||
return new Distinct(proj);
|
||||
public static PropertyProjection property(String propertyName) {
|
||||
return new PropertyProjection( propertyName );
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new projection list
|
||||
* A grouping property value projection
|
||||
*
|
||||
* @param propertyName The name of the property to group
|
||||
*
|
||||
* @return The grouped projection
|
||||
*
|
||||
* @see PropertyProjection
|
||||
*/
|
||||
public static PropertyProjection groupProperty(String propertyName) {
|
||||
return new PropertyProjection( propertyName, true );
|
||||
}
|
||||
|
||||
/**
|
||||
* An identifier value projection.
|
||||
*
|
||||
* @return The identifier projection
|
||||
*
|
||||
* @see IdentifierProjection
|
||||
*/
|
||||
public static IdentifierProjection id() {
|
||||
return new IdentifierProjection();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a distinct projection from a projection.
|
||||
*
|
||||
* @param projection The project to treat distinctly
|
||||
*
|
||||
* @return The distinct projection
|
||||
*
|
||||
* @see Distinct
|
||||
*/
|
||||
public static Projection distinct(Projection projection) {
|
||||
return new Distinct( projection );
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new projection list.
|
||||
*
|
||||
* @return The projection list
|
||||
*/
|
||||
public static ProjectionList projectionList() {
|
||||
return new ProjectionList();
|
||||
|
@ -59,92 +102,141 @@ public final class Projections {
|
|||
|
||||
/**
|
||||
* The query row count, ie. <tt>count(*)</tt>
|
||||
*
|
||||
* @return The projection representing the row count
|
||||
*
|
||||
* @see RowCountProjection
|
||||
*/
|
||||
public static Projection rowCount() {
|
||||
return new RowCountProjection();
|
||||
}
|
||||
|
||||
/**
|
||||
* A property value count
|
||||
* A property value count projection
|
||||
*
|
||||
* @param propertyName The name of the property to count over
|
||||
*
|
||||
* @return The count projection
|
||||
*
|
||||
* @see CountProjection
|
||||
*/
|
||||
public static CountProjection count(String propertyName) {
|
||||
return new CountProjection(propertyName);
|
||||
return new CountProjection( propertyName );
|
||||
}
|
||||
|
||||
/**
|
||||
* A distinct property value count
|
||||
* A distinct property value count projection
|
||||
*
|
||||
* @param propertyName The name of the property to count over
|
||||
*
|
||||
* @return The count projection
|
||||
*
|
||||
* @see CountProjection
|
||||
*/
|
||||
public static CountProjection countDistinct(String propertyName) {
|
||||
return new CountProjection(propertyName).setDistinct();
|
||||
return new CountProjection( propertyName ).setDistinct();
|
||||
}
|
||||
|
||||
/**
|
||||
* A property maximum value
|
||||
* A property maximum value projection
|
||||
*
|
||||
* @param propertyName The property for which to find the max
|
||||
*
|
||||
* @return the max projection
|
||||
*
|
||||
* @see AggregateProjection
|
||||
*/
|
||||
public static AggregateProjection max(String propertyName) {
|
||||
return new AggregateProjection("max", propertyName);
|
||||
return new AggregateProjection( "max", propertyName );
|
||||
}
|
||||
|
||||
/**
|
||||
* A property minimum value
|
||||
* A property minimum value projection
|
||||
*
|
||||
* @param propertyName The property for which to find the min
|
||||
*
|
||||
* @return the min projection
|
||||
*
|
||||
* @see AggregateProjection
|
||||
*/
|
||||
public static AggregateProjection min(String propertyName) {
|
||||
return new AggregateProjection("min", propertyName);
|
||||
return new AggregateProjection( "min", propertyName );
|
||||
}
|
||||
|
||||
/**
|
||||
* A property average value
|
||||
* A property average value projection
|
||||
*
|
||||
* @param propertyName The property over which to find the average
|
||||
*
|
||||
* @return the avg projection
|
||||
*
|
||||
* @see AvgProjection
|
||||
*/
|
||||
public static AggregateProjection avg(String propertyName) {
|
||||
return new AvgProjection(propertyName);
|
||||
return new AvgProjection( propertyName );
|
||||
}
|
||||
|
||||
/**
|
||||
* A property value sum
|
||||
* A property value sum projection
|
||||
*
|
||||
* @param propertyName The property over which to sum
|
||||
*
|
||||
* @return the sum projection
|
||||
*
|
||||
* @see AggregateProjection
|
||||
*/
|
||||
public static AggregateProjection sum(String propertyName) {
|
||||
return new AggregateProjection("sum", propertyName);
|
||||
}
|
||||
|
||||
/**
|
||||
* A SQL projection, a typed select clause fragment
|
||||
*/
|
||||
public static Projection sqlProjection(String sql, String[] columnAliases, Type[] types) {
|
||||
return new SQLProjection(sql, columnAliases, types);
|
||||
}
|
||||
|
||||
/**
|
||||
* A grouping SQL projection, specifying both select clause and group by clause fragments
|
||||
*/
|
||||
public static Projection sqlGroupProjection(String sql, String groupBy, String[] columnAliases, Type[] types) {
|
||||
return new SQLProjection(sql, groupBy, columnAliases, types);
|
||||
}
|
||||
|
||||
/**
|
||||
* A grouping property value
|
||||
*/
|
||||
public static PropertyProjection groupProperty(String propertyName) {
|
||||
return new PropertyProjection(propertyName, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* A projected property value
|
||||
*/
|
||||
public static PropertyProjection property(String propertyName) {
|
||||
return new PropertyProjection(propertyName);
|
||||
}
|
||||
|
||||
/**
|
||||
* A projected identifier value
|
||||
*/
|
||||
public static IdentifierProjection id() {
|
||||
return new IdentifierProjection();
|
||||
return new AggregateProjection( "sum", propertyName );
|
||||
}
|
||||
|
||||
/**
|
||||
* Assign an alias to a projection, by wrapping it
|
||||
*
|
||||
* @param projection The projection to be aliased
|
||||
* @param alias The alias to apply
|
||||
*
|
||||
* @return The aliased projection
|
||||
*
|
||||
* @see AliasedProjection
|
||||
*/
|
||||
public static Projection alias(Projection projection, String alias) {
|
||||
return new AliasedProjection(projection, alias);
|
||||
return new AliasedProjection( projection, alias );
|
||||
}
|
||||
|
||||
/**
|
||||
* A SQL projection, a typed select clause fragment
|
||||
*
|
||||
* @param sql The SQL fragment
|
||||
* @param columnAliases The column aliases
|
||||
* @param types The resulting types
|
||||
*
|
||||
* @return The SQL projection
|
||||
*
|
||||
* @see SQLProjection
|
||||
*/
|
||||
public static Projection sqlProjection(String sql, String[] columnAliases, Type[] types) {
|
||||
return new SQLProjection( sql, columnAliases, types );
|
||||
}
|
||||
|
||||
/**
|
||||
* A grouping SQL projection, specifying both select clause and group by clause fragments
|
||||
*
|
||||
* @param sql The SQL SELECT fragment
|
||||
* @param groupBy The SQL GROUP BY fragment
|
||||
* @param columnAliases The column aliases
|
||||
* @param types The resulting types
|
||||
*
|
||||
* @return The SQL projection
|
||||
*
|
||||
* @see SQLProjection
|
||||
*/
|
||||
@SuppressWarnings("UnusedDeclaration")
|
||||
public static Projection sqlGroupProjection(String sql, String groupBy, String[] columnAliases, Type[] types) {
|
||||
return new SQLProjection(sql, groupBy, columnAliases, types);
|
||||
}
|
||||
|
||||
private Projections() {
|
||||
//cannot be instantiated
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,3 +1,26 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2013, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.criterion;
|
||||
|
||||
import org.hibernate.Criteria;
|
||||
|
@ -5,6 +28,7 @@ import org.hibernate.internal.util.StringHelper;
|
|||
|
||||
/**
|
||||
* A comparison between several properties value in the outer query and the result of a multicolumn subquery.
|
||||
*
|
||||
* @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com)
|
||||
*/
|
||||
public class PropertiesSubqueryExpression extends SubqueryExpression {
|
||||
|
@ -17,7 +41,7 @@ public class PropertiesSubqueryExpression extends SubqueryExpression {
|
|||
|
||||
@Override
|
||||
protected String toLeftSqlString(Criteria criteria, CriteriaQuery outerQuery) {
|
||||
StringBuilder left = new StringBuilder( "(" );
|
||||
final StringBuilder left = new StringBuilder( "(" );
|
||||
final String[] sqlColumnNames = new String[propertyNames.length];
|
||||
for ( int i = 0; i < sqlColumnNames.length; ++i ) {
|
||||
sqlColumnNames[i] = outerQuery.getColumn( criteria, propertyNames[i] );
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
|
||||
* Copyright (c) 2008, 2013, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Middleware LLC.
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
|
@ -20,244 +20,737 @@
|
|||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
package org.hibernate.criterion;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* A factory for property-specific criterion and projection instances
|
||||
*
|
||||
* @author Gavin King
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class Property extends PropertyProjection {
|
||||
//private String propertyName;
|
||||
/**
|
||||
* Factory for Property instances.
|
||||
*
|
||||
* @param propertyName The name of the property.
|
||||
*
|
||||
* @return The Property instance
|
||||
*/
|
||||
public static Property forName(String propertyName) {
|
||||
return new Property( propertyName );
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a Property. non-private to allow subclassing.
|
||||
*
|
||||
* @param propertyName The property name.
|
||||
*/
|
||||
protected Property(String propertyName) {
|
||||
super(propertyName);
|
||||
super( propertyName );
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a BETWEEN restriction for this property between the given min and max
|
||||
*
|
||||
* @param min The minimum
|
||||
* @param max The maximum
|
||||
*
|
||||
* @return The BETWEEN restriction
|
||||
*
|
||||
* @see Restrictions#between(String, Object, Object)
|
||||
*/
|
||||
public Criterion between(Object min, Object max) {
|
||||
return Restrictions.between(getPropertyName(), min, max);
|
||||
return Restrictions.between( getPropertyName(), min, max );
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an IN restriction for this property based on the given list of literals
|
||||
*
|
||||
* @param values The literal values
|
||||
*
|
||||
* @return The IN restriction
|
||||
*
|
||||
* @see Restrictions#in(String, Collection)
|
||||
*/
|
||||
public Criterion in(Collection values) {
|
||||
return Restrictions.in(getPropertyName(), values);
|
||||
return Restrictions.in( getPropertyName(), values );
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an IN restriction for this property based on the given list of literals
|
||||
*
|
||||
* @param values The literal values
|
||||
*
|
||||
* @return The IN restriction
|
||||
*
|
||||
* @see Restrictions#in(String, Object[])
|
||||
*/
|
||||
public Criterion in(Object[] values) {
|
||||
return Restrictions.in(getPropertyName(), values);
|
||||
return Restrictions.in( getPropertyName(), values );
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a LIKE restriction for this property
|
||||
*
|
||||
* @param value The value to like compare with
|
||||
*
|
||||
* @return The LIKE restriction
|
||||
*
|
||||
* @see Restrictions#like(String, Object)
|
||||
*/
|
||||
public SimpleExpression like(Object value) {
|
||||
return Restrictions.like(getPropertyName(), value);
|
||||
return Restrictions.like( getPropertyName(), value );
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a LIKE restriction for this property
|
||||
*
|
||||
* @param value The value to like compare with
|
||||
* @param matchMode The match mode to apply to the LIKE
|
||||
*
|
||||
* @return The LIKE restriction
|
||||
*
|
||||
* @see Restrictions#like(String, String, MatchMode)
|
||||
*/
|
||||
public SimpleExpression like(String value, MatchMode matchMode) {
|
||||
return Restrictions.like(getPropertyName(), value, matchMode);
|
||||
return Restrictions.like( getPropertyName(), value, matchMode );
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an equality restriction.
|
||||
*
|
||||
* @param value The value to check against
|
||||
*
|
||||
* @return The equality restriction.
|
||||
*
|
||||
* @see Restrictions#eq(String, Object)
|
||||
*/
|
||||
public SimpleExpression eq(Object value) {
|
||||
return Restrictions.eq(getPropertyName(), value);
|
||||
return Restrictions.eq( getPropertyName(), value );
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an equality restriction capable of also rendering as IS NULL if the given value is {@code null}
|
||||
*
|
||||
* @param value The value to check against
|
||||
*
|
||||
* @return The equality restriction.
|
||||
*
|
||||
* @see Restrictions#eqOrIsNull(String, Object)
|
||||
* @see #eq
|
||||
* @see #isNull
|
||||
*/
|
||||
@SuppressWarnings("UnusedDeclaration")
|
||||
public Criterion eqOrIsNull(Object value) {
|
||||
return Restrictions.eqOrIsNull(getPropertyName(), value);
|
||||
return Restrictions.eqOrIsNull( getPropertyName(), value );
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an non-equality restriction.
|
||||
*
|
||||
* @param value The value to check against
|
||||
*
|
||||
* @return The non-equality restriction.
|
||||
*
|
||||
* @see Restrictions#ne(String, Object)
|
||||
*/
|
||||
public SimpleExpression ne(Object value) {
|
||||
return Restrictions.ne(getPropertyName(), value);
|
||||
return Restrictions.ne( getPropertyName(), value );
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an non-equality restriction capable of also rendering as IS NOT NULL if the given value is {@code null}
|
||||
*
|
||||
* @param value The value to check against
|
||||
*
|
||||
* @return The non-equality restriction.
|
||||
*
|
||||
* @see Restrictions#neOrIsNotNull(String, Object)
|
||||
* @see #ne
|
||||
* @see #isNotNull
|
||||
*/
|
||||
@SuppressWarnings("UnusedDeclaration")
|
||||
public Criterion neOrIsNotNull(Object value) {
|
||||
return Restrictions.neOrIsNotNull(getPropertyName(), value);
|
||||
return Restrictions.neOrIsNotNull( getPropertyName(), value );
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a greater-than restriction based on this property
|
||||
*
|
||||
* @param value The value to check against
|
||||
*
|
||||
* @return The greater-than restriction
|
||||
*
|
||||
* @see Restrictions#gt(String, Object)
|
||||
*/
|
||||
public SimpleExpression gt(Object value) {
|
||||
return Restrictions.gt(getPropertyName(), value);
|
||||
return Restrictions.gt( getPropertyName(), value );
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a less-than restriction based on this property
|
||||
*
|
||||
* @param value The value to check against
|
||||
*
|
||||
* @return The less-than restriction
|
||||
*
|
||||
* @see Restrictions#lt(String, Object)
|
||||
*/
|
||||
public SimpleExpression lt(Object value) {
|
||||
return Restrictions.lt(getPropertyName(), value);
|
||||
return Restrictions.lt( getPropertyName(), value );
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a less-than-or-equal-to restriction based on this property
|
||||
*
|
||||
* @param value The value to check against
|
||||
*
|
||||
* @return The less-than-or-equal-to restriction
|
||||
*
|
||||
* @see Restrictions#le(String, Object)
|
||||
*/
|
||||
public SimpleExpression le(Object value) {
|
||||
return Restrictions.le(getPropertyName(), value);
|
||||
return Restrictions.le( getPropertyName(), value );
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a greater-than-or-equal-to restriction based on this property
|
||||
*
|
||||
* @param value The value to check against
|
||||
*
|
||||
* @return The greater-than-or-equal-to restriction
|
||||
*
|
||||
* @see Restrictions#ge(String, Object)
|
||||
*/
|
||||
public SimpleExpression ge(Object value) {
|
||||
return Restrictions.ge(getPropertyName(), value);
|
||||
return Restrictions.ge( getPropertyName(), value );
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an equality restriction between 2 properties
|
||||
*
|
||||
* @param other The other property to compare against
|
||||
*
|
||||
* @return The restriction
|
||||
*
|
||||
* @see Restrictions#eqProperty(String, String)
|
||||
*/
|
||||
@SuppressWarnings("UnusedDeclaration")
|
||||
public PropertyExpression eqProperty(Property other) {
|
||||
return Restrictions.eqProperty( getPropertyName(), other.getPropertyName() );
|
||||
}
|
||||
|
||||
public PropertyExpression neProperty(Property other) {
|
||||
return Restrictions.neProperty( getPropertyName(), other.getPropertyName() );
|
||||
}
|
||||
|
||||
public PropertyExpression leProperty(Property other) {
|
||||
return Restrictions.leProperty( getPropertyName(), other.getPropertyName() );
|
||||
}
|
||||
|
||||
public PropertyExpression geProperty(Property other) {
|
||||
return Restrictions.geProperty( getPropertyName(), other.getPropertyName() );
|
||||
}
|
||||
|
||||
public PropertyExpression ltProperty(Property other) {
|
||||
return Restrictions.ltProperty( getPropertyName(), other.getPropertyName() );
|
||||
}
|
||||
|
||||
public PropertyExpression gtProperty(Property other) {
|
||||
return Restrictions.gtProperty( getPropertyName(), other.getPropertyName() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an equality restriction between 2 properties
|
||||
*
|
||||
* @param other The other property to compare against
|
||||
*
|
||||
* @return The restriction
|
||||
*
|
||||
* @see Restrictions#eqProperty(String, String)
|
||||
*/
|
||||
@SuppressWarnings("UnusedDeclaration")
|
||||
public PropertyExpression eqProperty(String other) {
|
||||
return Restrictions.eqProperty( getPropertyName(), other );
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an non-equality restriction between 2 properties
|
||||
*
|
||||
* @param other The other property to compare against
|
||||
*
|
||||
* @return The restriction
|
||||
*
|
||||
* @see Restrictions#neProperty(String, String)
|
||||
*/
|
||||
@SuppressWarnings("UnusedDeclaration")
|
||||
public PropertyExpression neProperty(Property other) {
|
||||
return Restrictions.neProperty( getPropertyName(), other.getPropertyName() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an non-equality restriction between 2 properties
|
||||
*
|
||||
* @param other The other property to compare against
|
||||
*
|
||||
* @return The restriction
|
||||
*
|
||||
* @see Restrictions#neProperty(String, String)
|
||||
*/
|
||||
@SuppressWarnings("UnusedDeclaration")
|
||||
public PropertyExpression neProperty(String other) {
|
||||
return Restrictions.neProperty( getPropertyName(), other );
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an less-than-or-equal-to restriction between 2 properties
|
||||
*
|
||||
* @param other The other property to compare against
|
||||
*
|
||||
* @return The restriction
|
||||
*
|
||||
* @see Restrictions#leProperty(String, String)
|
||||
*/
|
||||
@SuppressWarnings("UnusedDeclaration")
|
||||
public PropertyExpression leProperty(Property other) {
|
||||
return Restrictions.leProperty( getPropertyName(), other.getPropertyName() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an less-than-or-equal-to restriction between 2 properties
|
||||
*
|
||||
* @param other The other property to compare against
|
||||
*
|
||||
* @return The restriction
|
||||
*
|
||||
* @see Restrictions#leProperty(String, String)
|
||||
*/
|
||||
@SuppressWarnings("UnusedDeclaration")
|
||||
public PropertyExpression leProperty(String other) {
|
||||
return Restrictions.leProperty( getPropertyName(), other );
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an greater-than-or-equal-to restriction between 2 properties
|
||||
*
|
||||
* @param other The other property to compare against
|
||||
*
|
||||
* @return The restriction
|
||||
*
|
||||
* @see Restrictions#geProperty(String, String)
|
||||
*/
|
||||
@SuppressWarnings("UnusedDeclaration")
|
||||
public PropertyExpression geProperty(Property other) {
|
||||
return Restrictions.geProperty( getPropertyName(), other.getPropertyName() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an greater-than-or-equal-to restriction between 2 properties
|
||||
*
|
||||
* @param other The other property to compare against
|
||||
*
|
||||
* @return The restriction
|
||||
*
|
||||
* @see Restrictions#geProperty(String, String)
|
||||
*/
|
||||
@SuppressWarnings("UnusedDeclaration")
|
||||
public PropertyExpression geProperty(String other) {
|
||||
return Restrictions.geProperty( getPropertyName(), other );
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an less-than restriction between 2 properties
|
||||
*
|
||||
* @param other The other property to compare against
|
||||
*
|
||||
* @return The restriction
|
||||
*
|
||||
* @see Restrictions#ltProperty(String, String)
|
||||
*/
|
||||
@SuppressWarnings("UnusedDeclaration")
|
||||
public PropertyExpression ltProperty(Property other) {
|
||||
return Restrictions.ltProperty( getPropertyName(), other.getPropertyName() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an less-than restriction between 2 properties
|
||||
*
|
||||
* @param other The other property to compare against
|
||||
*
|
||||
* @return The restriction
|
||||
*
|
||||
* @see Restrictions#ltProperty(String, String)
|
||||
*/
|
||||
@SuppressWarnings("UnusedDeclaration")
|
||||
public PropertyExpression ltProperty(String other) {
|
||||
return Restrictions.ltProperty( getPropertyName(), other );
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an greater-than restriction between 2 properties
|
||||
*
|
||||
* @param other The other property to compare against
|
||||
*
|
||||
* @return The restriction
|
||||
*
|
||||
* @see Restrictions#geProperty(String, String)
|
||||
*/
|
||||
@SuppressWarnings("UnusedDeclaration")
|
||||
public PropertyExpression gtProperty(Property other) {
|
||||
return Restrictions.gtProperty( getPropertyName(), other.getPropertyName() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an greater-than restriction between 2 properties
|
||||
*
|
||||
* @param other The other property to compare against
|
||||
*
|
||||
* @return The restriction
|
||||
*
|
||||
* @see Restrictions#geProperty(String, String)
|
||||
*/
|
||||
@SuppressWarnings("UnusedDeclaration")
|
||||
public PropertyExpression gtProperty(String other) {
|
||||
return Restrictions.gtProperty( getPropertyName(), other );
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a NULL restriction
|
||||
*
|
||||
* @return The restriction
|
||||
*
|
||||
* @see Restrictions#isNull(String)
|
||||
*/
|
||||
public Criterion isNull() {
|
||||
return Restrictions.isNull(getPropertyName());
|
||||
}
|
||||
|
||||
public Criterion isNotNull() {
|
||||
return Restrictions.isNotNull(getPropertyName());
|
||||
}
|
||||
|
||||
public Criterion isEmpty() {
|
||||
return Restrictions.isEmpty(getPropertyName());
|
||||
}
|
||||
|
||||
public Criterion isNotEmpty() {
|
||||
return Restrictions.isNotEmpty(getPropertyName());
|
||||
}
|
||||
|
||||
public CountProjection count() {
|
||||
return Projections.count(getPropertyName());
|
||||
}
|
||||
|
||||
public AggregateProjection max() {
|
||||
return Projections.max(getPropertyName());
|
||||
}
|
||||
|
||||
public AggregateProjection min() {
|
||||
return Projections.min(getPropertyName());
|
||||
}
|
||||
|
||||
public AggregateProjection avg() {
|
||||
return Projections.avg(getPropertyName());
|
||||
}
|
||||
|
||||
/*public PropertyProjection project() {
|
||||
return Projections.property(getPropertyName());
|
||||
}*/
|
||||
|
||||
public PropertyProjection group() {
|
||||
return Projections.groupProperty(getPropertyName());
|
||||
}
|
||||
|
||||
public Order asc() {
|
||||
return Order.asc(getPropertyName());
|
||||
}
|
||||
|
||||
public Order desc() {
|
||||
return Order.desc(getPropertyName());
|
||||
}
|
||||
|
||||
public static Property forName(String propertyName) {
|
||||
return new Property(propertyName);
|
||||
return Restrictions.isNull( getPropertyName() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a component attribute of this property
|
||||
* Creates a NOT NULL restriction
|
||||
*
|
||||
* @return The restriction
|
||||
*
|
||||
* @see Restrictions#isNotNull(String)
|
||||
*/
|
||||
public Criterion isNotNull() {
|
||||
return Restrictions.isNotNull( getPropertyName() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a restriction to check that a collection is empty
|
||||
*
|
||||
* @return The restriction
|
||||
*
|
||||
* @see Restrictions#isEmpty(String)
|
||||
*/
|
||||
public Criterion isEmpty() {
|
||||
return Restrictions.isEmpty( getPropertyName() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a restriction to check that a collection is not empty
|
||||
*
|
||||
* @return The restriction
|
||||
*
|
||||
* @see Restrictions#isNotEmpty(String)
|
||||
*/
|
||||
public Criterion isNotEmpty() {
|
||||
return Restrictions.isNotEmpty( getPropertyName() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a property count projection
|
||||
*
|
||||
* @return The projection
|
||||
*
|
||||
* @see Projections#count
|
||||
*/
|
||||
public CountProjection count() {
|
||||
return Projections.count( getPropertyName() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a property max projection
|
||||
*
|
||||
* @return The projection
|
||||
*
|
||||
* @see Projections#max
|
||||
*/
|
||||
public AggregateProjection max() {
|
||||
return Projections.max( getPropertyName() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a property min projection
|
||||
*
|
||||
* @return The projection
|
||||
*
|
||||
* @see Projections#min
|
||||
*/
|
||||
public AggregateProjection min() {
|
||||
return Projections.min( getPropertyName() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a property avg projection
|
||||
*
|
||||
* @return The projection
|
||||
*
|
||||
* @see Projections#avg
|
||||
*/
|
||||
public AggregateProjection avg() {
|
||||
return Projections.avg( getPropertyName() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a projection for this property as a group expression
|
||||
*
|
||||
* @return The group projection
|
||||
*
|
||||
* @see Projections#groupProperty
|
||||
*/
|
||||
public PropertyProjection group() {
|
||||
return Projections.groupProperty( getPropertyName() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an ascending ordering for this property
|
||||
*
|
||||
* @return The order
|
||||
*/
|
||||
public Order asc() {
|
||||
return Order.asc( getPropertyName() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a descending ordering for this property
|
||||
*
|
||||
* @return The order
|
||||
*/
|
||||
public Order desc() {
|
||||
return Order.desc( getPropertyName() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a component attribute of this property.
|
||||
*
|
||||
* @param propertyName The sub property name
|
||||
*
|
||||
* @return The property
|
||||
*/
|
||||
public Property getProperty(String propertyName) {
|
||||
return forName( getPropertyName() + '.' + propertyName );
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a sub-query equality expression for this property
|
||||
*
|
||||
* @param subselect The sub-query
|
||||
*
|
||||
* @return The expression
|
||||
*
|
||||
* @see Subqueries#propertyEq(String, DetachedCriteria)
|
||||
*/
|
||||
public Criterion eq(DetachedCriteria subselect) {
|
||||
return Subqueries.propertyEq( getPropertyName(), subselect );
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a sub-query non-equality expression for this property
|
||||
*
|
||||
* @param subselect The sub-query
|
||||
*
|
||||
* @return The expression
|
||||
*
|
||||
* @see Subqueries#propertyNe(String, DetachedCriteria)
|
||||
*/
|
||||
public Criterion ne(DetachedCriteria subselect) {
|
||||
return Subqueries.propertyNe( getPropertyName(), subselect );
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a sub-query less-than expression for this property
|
||||
*
|
||||
* @param subselect The sub-query
|
||||
*
|
||||
* @return The expression
|
||||
*
|
||||
* @see Subqueries#propertyLt(String, DetachedCriteria)
|
||||
*/
|
||||
public Criterion lt(DetachedCriteria subselect) {
|
||||
return Subqueries.propertyLt( getPropertyName(), subselect );
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a sub-query less-than-or-equal-to expression for this property
|
||||
*
|
||||
* @param subselect The sub-query
|
||||
*
|
||||
* @return The expression
|
||||
*
|
||||
* @see Subqueries#propertyLe(String, DetachedCriteria)
|
||||
*/
|
||||
public Criterion le(DetachedCriteria subselect) {
|
||||
return Subqueries.propertyLe( getPropertyName(), subselect );
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a sub-query greater-than expression for this property
|
||||
*
|
||||
* @param subselect The sub-query
|
||||
*
|
||||
* @return The expression
|
||||
*
|
||||
* @see Subqueries#propertyGt(String, DetachedCriteria)
|
||||
*/
|
||||
public Criterion gt(DetachedCriteria subselect) {
|
||||
return Subqueries.propertyGt( getPropertyName(), subselect );
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a sub-query greater-than-or-equal-to expression for this property
|
||||
*
|
||||
* @param subselect The sub-query
|
||||
*
|
||||
* @return The expression
|
||||
*
|
||||
* @see Subqueries#propertyGe(String, DetachedCriteria)
|
||||
*/
|
||||
public Criterion ge(DetachedCriteria subselect) {
|
||||
return Subqueries.propertyGe( getPropertyName(), subselect );
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a sub-query NOT IN expression for this property. I.e., {@code [prop] NOT IN [subquery]}
|
||||
*
|
||||
* @param subselect The sub-query
|
||||
*
|
||||
* @return The expression
|
||||
*
|
||||
* @see Subqueries#propertyNotIn(String, DetachedCriteria)
|
||||
*/
|
||||
@SuppressWarnings("UnusedDeclaration")
|
||||
public Criterion notIn(DetachedCriteria subselect) {
|
||||
return Subqueries.propertyNotIn( getPropertyName(), subselect );
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a sub-query IN expression for this property. I.e., {@code [prop] IN [subquery]}
|
||||
*
|
||||
* @param subselect The sub-query
|
||||
*
|
||||
* @return The expression
|
||||
*
|
||||
* @see Subqueries#propertyIn(String, DetachedCriteria)
|
||||
*/
|
||||
public Criterion in(DetachedCriteria subselect) {
|
||||
return Subqueries.propertyIn( getPropertyName(), subselect );
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a equals-all sub-query expression for this property. I.e., {@code [prop] = ALL [subquery]}
|
||||
*
|
||||
* @param subselect The sub-query
|
||||
*
|
||||
* @return The expression
|
||||
*
|
||||
* @see Subqueries#propertyEqAll(String, DetachedCriteria)
|
||||
*/
|
||||
public Criterion eqAll(DetachedCriteria subselect) {
|
||||
return Subqueries.propertyEqAll( getPropertyName(), subselect );
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a greater-than-all sub-query expression for this property. I.e., {@code [prop] > ALL [subquery]}
|
||||
*
|
||||
* @param subselect The sub-query
|
||||
*
|
||||
* @return The expression
|
||||
*
|
||||
* @see Subqueries#propertyGtAll(String, DetachedCriteria)
|
||||
*/
|
||||
@SuppressWarnings("UnusedDeclaration")
|
||||
public Criterion gtAll(DetachedCriteria subselect) {
|
||||
return Subqueries.propertyGtAll( getPropertyName(), subselect );
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a less-than-all sub-query expression for this property. I.e., {@code [prop] < ALL [subquery]}
|
||||
*
|
||||
* @param subselect The sub-query
|
||||
*
|
||||
* @return The expression
|
||||
*
|
||||
* @see Subqueries#propertyLtAll(String, DetachedCriteria)
|
||||
*/
|
||||
@SuppressWarnings("UnusedDeclaration")
|
||||
public Criterion ltAll(DetachedCriteria subselect) {
|
||||
return Subqueries.propertyLtAll( getPropertyName(), subselect );
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a less-than-or-equal-to-all sub-query expression for this property. I.e., {@code [prop] <= ALL [subquery]}
|
||||
*
|
||||
* @param subselect The sub-query
|
||||
*
|
||||
* @return The expression
|
||||
*
|
||||
* @see Subqueries#propertyLeAll(String, DetachedCriteria)
|
||||
*/
|
||||
@SuppressWarnings("UnusedDeclaration")
|
||||
public Criterion leAll(DetachedCriteria subselect) {
|
||||
return Subqueries.propertyLeAll( getPropertyName(), subselect );
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a greater-than-or-equal-to-all sub-query expression for this property. I.e., {@code [prop] >= ALL [subquery]}
|
||||
*
|
||||
* @param subselect The sub-query
|
||||
*
|
||||
* @return The expression
|
||||
*
|
||||
* @see Subqueries#propertyGeAll(String, DetachedCriteria)
|
||||
*/
|
||||
@SuppressWarnings("UnusedDeclaration")
|
||||
public Criterion geAll(DetachedCriteria subselect) {
|
||||
return Subqueries.propertyGeAll( getPropertyName(), subselect );
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a greater-than-some sub-query expression for this property. I.e., {@code [prop] > SOME [subquery]}
|
||||
*
|
||||
* @param subselect The sub-query
|
||||
*
|
||||
* @return The expression
|
||||
*
|
||||
* @see Subqueries#propertyGtSome(String, DetachedCriteria)
|
||||
*/
|
||||
@SuppressWarnings("UnusedDeclaration")
|
||||
public Criterion gtSome(DetachedCriteria subselect) {
|
||||
return Subqueries.propertyGtSome( getPropertyName(), subselect );
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a less-than-some sub-query expression for this property. I.e., {@code [prop] < SOME [subquery]}
|
||||
*
|
||||
* @param subselect The sub-query
|
||||
*
|
||||
* @return The expression
|
||||
*
|
||||
* @see Subqueries#propertyLtSome(String, DetachedCriteria)
|
||||
*/
|
||||
@SuppressWarnings("UnusedDeclaration")
|
||||
public Criterion ltSome(DetachedCriteria subselect) {
|
||||
return Subqueries.propertyLtSome( getPropertyName(), subselect );
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a less-than-or-equal-to-some sub-query expression for this property. I.e., {@code [prop] <= SOME [subquery]}
|
||||
*
|
||||
* @param subselect The sub-query
|
||||
*
|
||||
* @return The expression
|
||||
*
|
||||
* @see Subqueries#propertyLeSome(String, DetachedCriteria)
|
||||
*/
|
||||
@SuppressWarnings("UnusedDeclaration")
|
||||
public Criterion leSome(DetachedCriteria subselect) {
|
||||
return Subqueries.propertyLeSome( getPropertyName(), subselect );
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a greater-than-or-equal-to-some sub-query expression for this property. I.e., {@code [prop] >= SOME [subquery]}
|
||||
*
|
||||
* @param subselect The sub-query
|
||||
*
|
||||
* @return The expression
|
||||
*
|
||||
* @see Subqueries#propertyGeSome(String, DetachedCriteria)
|
||||
*/
|
||||
@SuppressWarnings("UnusedDeclaration")
|
||||
public Criterion geSome(DetachedCriteria subselect) {
|
||||
return Subqueries.propertyGeSome( getPropertyName(), subselect );
|
||||
}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
|
||||
* Copyright (c) 2008, 2013, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Middleware LLC.
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
|
@ -20,9 +20,9 @@
|
|||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
package org.hibernate.criterion;
|
||||
|
||||
import org.hibernate.Criteria;
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.engine.spi.TypedValue;
|
||||
|
@ -30,46 +30,48 @@ import org.hibernate.internal.util.StringHelper;
|
|||
|
||||
/**
|
||||
* superclass for comparisons between two properties (with SQL binary operators)
|
||||
*
|
||||
* @author Gavin King
|
||||
*/
|
||||
public class PropertyExpression implements Criterion {
|
||||
private static final TypedValue[] NO_TYPED_VALUES = new TypedValue[0];
|
||||
|
||||
private final String propertyName;
|
||||
private final String otherPropertyName;
|
||||
private final String op;
|
||||
|
||||
private static final TypedValue[] NO_TYPED_VALUES = new TypedValue[0];
|
||||
|
||||
protected PropertyExpression(String propertyName, String otherPropertyName, String op) {
|
||||
this.propertyName = propertyName;
|
||||
this.otherPropertyName = otherPropertyName;
|
||||
this.op = op;
|
||||
}
|
||||
|
||||
public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery)
|
||||
throws HibernateException {
|
||||
String[] xcols = criteriaQuery.findColumns(propertyName, criteria);
|
||||
String[] ycols = criteriaQuery.findColumns(otherPropertyName, criteria);
|
||||
String result = StringHelper.join(
|
||||
" and ",
|
||||
StringHelper.add( xcols, getOp(), ycols )
|
||||
);
|
||||
if (xcols.length>1) result = '(' + result + ')';
|
||||
return result;
|
||||
//TODO: get SQL rendering out of this package!
|
||||
}
|
||||
|
||||
public TypedValue[] getTypedValues(Criteria criteria, CriteriaQuery criteriaQuery)
|
||||
throws HibernateException {
|
||||
return NO_TYPED_VALUES;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return propertyName + getOp() + otherPropertyName;
|
||||
}
|
||||
|
||||
public String getOp() {
|
||||
return op;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException {
|
||||
final String[] lhsColumns = criteriaQuery.findColumns( propertyName, criteria );
|
||||
final String[] rhsColumns = criteriaQuery.findColumns( otherPropertyName, criteria );
|
||||
|
||||
final String[] comparisons = StringHelper.add( lhsColumns, getOp(), rhsColumns );
|
||||
if ( comparisons.length > 1 ) {
|
||||
return '(' + StringHelper.join( " and ", comparisons ) + ')';
|
||||
}
|
||||
else {
|
||||
return comparisons[0];
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypedValue[] getTypedValues(Criteria criteria, CriteriaQuery criteriaQuery) {
|
||||
return NO_TYPED_VALUES;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return propertyName + getOp() + otherPropertyName;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -30,10 +30,11 @@ import org.hibernate.type.Type;
|
|||
|
||||
/**
|
||||
* A property value, or grouped property value
|
||||
*
|
||||
* @author Gavin King
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class PropertyProjection extends SimpleProjection {
|
||||
|
||||
private String propertyName;
|
||||
private boolean grouped;
|
||||
|
||||
|
@ -43,49 +44,52 @@ public class PropertyProjection extends SimpleProjection {
|
|||
}
|
||||
|
||||
protected PropertyProjection(String prop) {
|
||||
this(prop, false);
|
||||
this( prop, false );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isGrouped() {
|
||||
return grouped;
|
||||
}
|
||||
|
||||
public String getPropertyName() {
|
||||
return propertyName;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return propertyName;
|
||||
@Override
|
||||
public Type[] getTypes(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException {
|
||||
return new Type[] { criteriaQuery.getType( criteria, 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 );
|
||||
@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(", ");
|
||||
.append( " as y" )
|
||||
.append( position + i )
|
||||
.append( '_' );
|
||||
if (i < cols.length -1) {
|
||||
buf.append( ", " );
|
||||
}
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
public boolean isGrouped() {
|
||||
return grouped;
|
||||
}
|
||||
|
||||
public String toGroupSqlString(Criteria criteria, CriteriaQuery criteriaQuery)
|
||||
throws HibernateException {
|
||||
if (!grouped) {
|
||||
return super.toGroupSqlString(criteria, criteriaQuery);
|
||||
@Override
|
||||
public String toGroupSqlString(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException {
|
||||
if ( !grouped ) {
|
||||
return super.toGroupSqlString( criteria, criteriaQuery );
|
||||
}
|
||||
else {
|
||||
return StringHelper.join( ", ", criteriaQuery.getColumns( propertyName, criteria ) );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return propertyName;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
|
||||
* Copyright (c) 2008, 2013, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Middleware LLC.
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
|
@ -20,26 +20,28 @@
|
|||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
package org.hibernate.criterion;
|
||||
|
||||
import org.hibernate.Criteria;
|
||||
|
||||
/**
|
||||
* A comparison between a property value in the outer query and the
|
||||
* result of a subquery
|
||||
* A comparison between a property value in the outer query and the result of a subquery
|
||||
*
|
||||
* @author Gavin King
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class PropertySubqueryExpression extends SubqueryExpression {
|
||||
private String propertyName;
|
||||
|
||||
protected PropertySubqueryExpression(String propertyName, String op, String quantifier, DetachedCriteria dc) {
|
||||
super(op, quantifier, dc);
|
||||
super( op, quantifier, dc );
|
||||
this.propertyName = propertyName;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String toLeftSqlString(Criteria criteria, CriteriaQuery criteriaQuery) {
|
||||
return criteriaQuery.getColumn(criteria, propertyName);
|
||||
return criteriaQuery.getColumn( criteria, propertyName );
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
|
||||
* Copyright (c) 2008, 2013, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Middleware LLC.
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
|
@ -20,16 +20,12 @@
|
|||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
package org.hibernate.criterion;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.internal.util.collections.ArrayHelper;
|
||||
import org.hibernate.type.Type;
|
||||
|
||||
/**
|
||||
|
@ -37,105 +33,130 @@ import org.hibernate.type.Type;
|
|||
* new kinds of <tt>Criterion</tt>. However, it is intended that most applications will
|
||||
* simply use the built-in criterion types via the static factory methods of this class.
|
||||
*
|
||||
* @see org.hibernate.Criteria
|
||||
* @see Projections factory methods for <tt>Projection</tt> instances
|
||||
* See also the {@link Projections} factory methods for generating {@link Projection} instances
|
||||
*
|
||||
* @author Gavin King
|
||||
* @author Steve Ebersole
|
||||
*
|
||||
* @see org.hibernate.Criteria
|
||||
*/
|
||||
public class Restrictions {
|
||||
|
||||
Restrictions() {
|
||||
//cannot be instantiated
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply an "equal" constraint to the identifier property
|
||||
* @param value
|
||||
*
|
||||
* @param value The value to use in comparison
|
||||
*
|
||||
* @return Criterion
|
||||
*
|
||||
* @see IdentifierEqExpression
|
||||
*/
|
||||
public static Criterion idEq(Object value) {
|
||||
return new IdentifierEqExpression(value);
|
||||
return new IdentifierEqExpression( value );
|
||||
}
|
||||
/**
|
||||
* Apply an "equal" constraint to the named property
|
||||
* @param propertyName
|
||||
* @param value
|
||||
*
|
||||
* @param propertyName The name of the property
|
||||
* @param value The value to use in comparison
|
||||
*
|
||||
* @return SimpleExpression
|
||||
*
|
||||
* @see SimpleExpression
|
||||
*/
|
||||
public static SimpleExpression eq(String propertyName, Object value) {
|
||||
return new SimpleExpression(propertyName, value, "=");
|
||||
}
|
||||
/**
|
||||
* Apply an "equal" constraint to the named property. If the value
|
||||
* is null, instead apply "is null".
|
||||
* @param propertyName
|
||||
* @param value
|
||||
* @return Criterion
|
||||
*/
|
||||
public static Criterion eqOrIsNull(String propertyName, Object value) {
|
||||
if (value == null) {
|
||||
return isNull(propertyName);
|
||||
}
|
||||
return new SimpleExpression(propertyName, value, "=");
|
||||
}
|
||||
/**
|
||||
* Apply a "not equal" constraint to the named property
|
||||
* @param propertyName
|
||||
* @param value
|
||||
* @return SimpleExpression
|
||||
*/
|
||||
public static SimpleExpression ne(String propertyName, Object value) {
|
||||
return new SimpleExpression(propertyName, value, "<>");
|
||||
}
|
||||
/**
|
||||
* Apply a "not equal" constraint to the named property. If the value
|
||||
* is null, instead apply "is not null".
|
||||
* @param propertyName
|
||||
* @param value
|
||||
* @return Criterion
|
||||
*/
|
||||
public static Criterion neOrIsNotNull(String propertyName, Object value) {
|
||||
if (value == null) {
|
||||
return isNotNull(propertyName);
|
||||
}
|
||||
return new SimpleExpression(propertyName, value, "<>");
|
||||
}
|
||||
/**
|
||||
* Apply a "like" constraint to the named property
|
||||
* @param propertyName
|
||||
* @param value
|
||||
* @return Criterion
|
||||
*/
|
||||
public static SimpleExpression like(String propertyName, Object value) {
|
||||
return new SimpleExpression(propertyName, value, " like ");
|
||||
}
|
||||
/**
|
||||
* Apply a "like" constraint to the named property
|
||||
* @param propertyName
|
||||
* @param value
|
||||
* @return Criterion
|
||||
*/
|
||||
public static SimpleExpression like(String propertyName, String value, MatchMode matchMode) {
|
||||
return new SimpleExpression(propertyName, matchMode.toMatchString(value), " like " );
|
||||
return new SimpleExpression( propertyName, value, "=" );
|
||||
}
|
||||
|
||||
/**
|
||||
* A case-insensitive "like", similar to Postgres <tt>ilike</tt>
|
||||
* operator
|
||||
* Apply an "equal" constraint to the named property. If the value
|
||||
* is null, instead apply "is null".
|
||||
*
|
||||
* @param propertyName
|
||||
* @param value
|
||||
* @return Criterion
|
||||
* @param propertyName The name of the property
|
||||
* @param value The value to use in comparison
|
||||
*
|
||||
* @return The Criterion
|
||||
*
|
||||
* @see #eq
|
||||
* @see #isNull
|
||||
*/
|
||||
public static Criterion ilike(String propertyName, String value, MatchMode matchMode) {
|
||||
return new LikeExpression(propertyName, value, matchMode, null, true);
|
||||
public static Criterion eqOrIsNull(String propertyName, Object value) {
|
||||
return value == null
|
||||
? isNull( propertyName )
|
||||
: eq( propertyName, value );
|
||||
}
|
||||
|
||||
/**
|
||||
* A case-insensitive "like", similar to Postgres <tt>ilike</tt>
|
||||
* operator
|
||||
* Apply a "not equal" constraint to the named property
|
||||
*
|
||||
* @param propertyName
|
||||
* @param value
|
||||
* @return Criterion
|
||||
* @param propertyName The name of the property
|
||||
* @param value The value to use in comparison
|
||||
*
|
||||
* @return The Criterion
|
||||
|
||||
* @see SimpleExpression
|
||||
*/
|
||||
public static SimpleExpression ne(String propertyName, Object value) {
|
||||
return new SimpleExpression( propertyName, value, "<>" );
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply a "not equal" constraint to the named property. If the value
|
||||
* is null, instead apply "is not null".
|
||||
*
|
||||
* @param propertyName The name of the property
|
||||
* @param value The value to use in comparison
|
||||
*
|
||||
* @return The Criterion
|
||||
*
|
||||
* @see #ne
|
||||
* @see #isNotNull
|
||||
*/
|
||||
public static Criterion neOrIsNotNull(String propertyName, Object value) {
|
||||
return value == null
|
||||
? isNotNull( propertyName )
|
||||
: ne( propertyName, value );
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply a "like" constraint to the named property
|
||||
*
|
||||
* @param propertyName The name of the property
|
||||
* @param value The value to use in comparison
|
||||
*
|
||||
* @return The Criterion
|
||||
*
|
||||
* @see SimpleExpression
|
||||
*/
|
||||
public static SimpleExpression like(String propertyName, Object value) {
|
||||
// todo : update this to use LikeExpression
|
||||
return new SimpleExpression( propertyName, value, " like " );
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply a "like" constraint to the named property using the provided match mode
|
||||
*
|
||||
* @param propertyName The name of the property
|
||||
* @param value The value to use in comparison
|
||||
* @param matchMode The match mode to use in comparison
|
||||
*
|
||||
* @return The Criterion
|
||||
*
|
||||
* @see SimpleExpression
|
||||
*/
|
||||
public static SimpleExpression like(String propertyName, String value, MatchMode matchMode) {
|
||||
// todo : update this to use LikeExpression
|
||||
return new SimpleExpression( propertyName, matchMode.toMatchString( value ), " like " );
|
||||
}
|
||||
|
||||
/**
|
||||
* A case-insensitive "like" (similar to Postgres <tt>ilike</tt> operator)
|
||||
*
|
||||
* @param propertyName The name of the property
|
||||
* @param value The value to use in comparison
|
||||
*
|
||||
* @return The Criterion
|
||||
*
|
||||
* @see LikeExpression
|
||||
*/
|
||||
public static Criterion ilike(String propertyName, Object value) {
|
||||
if ( value == null ) {
|
||||
|
@ -144,126 +165,239 @@ public class Restrictions {
|
|||
return ilike( propertyName, value.toString(), MatchMode.EXACT );
|
||||
}
|
||||
|
||||
/**
|
||||
* A case-insensitive "like" (similar to Postgres <tt>ilike</tt> operator) using the provided match mode
|
||||
*
|
||||
* @param propertyName The name of the property
|
||||
* @param value The value to use in comparison
|
||||
* @param matchMode The match mode to use in comparison
|
||||
*
|
||||
* @return The Criterion
|
||||
*
|
||||
* @see LikeExpression
|
||||
*/
|
||||
public static Criterion ilike(String propertyName, String value, MatchMode matchMode) {
|
||||
if ( value == null ) {
|
||||
throw new IllegalArgumentException( "Comparison value passed to ilike cannot be null" );
|
||||
}
|
||||
return new LikeExpression( propertyName, value, matchMode, null, true );
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply a "greater than" constraint to the named property
|
||||
* @param propertyName
|
||||
* @param value
|
||||
* @return Criterion
|
||||
*
|
||||
* @param propertyName The name of the property
|
||||
* @param value The value to use in comparison
|
||||
*
|
||||
* @return The Criterion
|
||||
*
|
||||
* @see SimpleExpression
|
||||
*/
|
||||
public static SimpleExpression gt(String propertyName, Object value) {
|
||||
return new SimpleExpression(propertyName, value, ">");
|
||||
return new SimpleExpression( propertyName, value, ">" );
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply a "less than" constraint to the named property
|
||||
* @param propertyName
|
||||
* @param value
|
||||
* @return Criterion
|
||||
*
|
||||
* @param propertyName The name of the property
|
||||
* @param value The value to use in comparison
|
||||
*
|
||||
* @return The Criterion
|
||||
*
|
||||
* @see SimpleExpression
|
||||
*/
|
||||
public static SimpleExpression lt(String propertyName, Object value) {
|
||||
return new SimpleExpression(propertyName, value, "<");
|
||||
return new SimpleExpression( propertyName, value, "<" );
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply a "less than or equal" constraint to the named property
|
||||
* @param propertyName
|
||||
* @param value
|
||||
* @return Criterion
|
||||
*
|
||||
* @param propertyName The name of the property
|
||||
* @param value The value to use in comparison
|
||||
*
|
||||
* @return The Criterion
|
||||
*
|
||||
* @see SimpleExpression
|
||||
*/
|
||||
public static SimpleExpression le(String propertyName, Object value) {
|
||||
return new SimpleExpression(propertyName, value, "<=");
|
||||
return new SimpleExpression( propertyName, value, "<=" );
|
||||
}
|
||||
/**
|
||||
* Apply a "greater than or equal" constraint to the named property
|
||||
* @param propertyName
|
||||
* @param value
|
||||
* @return Criterion
|
||||
*
|
||||
* @param propertyName The name of the property
|
||||
* @param value The value to use in comparison
|
||||
*
|
||||
* @return The Criterion
|
||||
*
|
||||
* @see SimpleExpression
|
||||
*/
|
||||
public static SimpleExpression ge(String propertyName, Object value) {
|
||||
return new SimpleExpression(propertyName, value, ">=");
|
||||
return new SimpleExpression( propertyName, value, ">=" );
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply a "between" constraint to the named property
|
||||
* @param propertyName
|
||||
* @param lo value
|
||||
* @param hi value
|
||||
* @return Criterion
|
||||
*
|
||||
* @param propertyName The name of the property
|
||||
* @param lo The low value
|
||||
* @param hi The high value
|
||||
*
|
||||
* @return The Criterion
|
||||
*
|
||||
* @see BetweenExpression
|
||||
*/
|
||||
public static Criterion between(String propertyName, Object lo, Object hi) {
|
||||
return new BetweenExpression(propertyName, lo, hi);
|
||||
return new BetweenExpression( propertyName, lo, hi );
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply an "in" constraint to the named property
|
||||
* @param propertyName
|
||||
* @param values
|
||||
* @return Criterion
|
||||
* Apply an "in" constraint to the named property.
|
||||
*
|
||||
* @param propertyName The name of the property
|
||||
* @param values The literal values to use in the IN restriction
|
||||
*
|
||||
* @return The Criterion
|
||||
*
|
||||
* @see InExpression
|
||||
*/
|
||||
public static Criterion in(String propertyName, Object[] values) {
|
||||
return new InExpression(propertyName, values);
|
||||
return new InExpression( propertyName, values );
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply an "in" constraint to the named property
|
||||
* @param propertyName
|
||||
* @param values
|
||||
* @return Criterion
|
||||
* Apply an "in" constraint to the named property.
|
||||
*
|
||||
* @param propertyName The name of the property
|
||||
* @param values The literal values to use in the IN restriction
|
||||
*
|
||||
* @return The Criterion
|
||||
*
|
||||
* @see InExpression
|
||||
*/
|
||||
public static Criterion in(String propertyName, Collection values) {
|
||||
return new InExpression( propertyName, values.toArray() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply an "is null" constraint to the named property
|
||||
*
|
||||
* @param propertyName The name of the property
|
||||
*
|
||||
* @return Criterion
|
||||
*
|
||||
* @see NullExpression
|
||||
*/
|
||||
public static Criterion isNull(String propertyName) {
|
||||
return new NullExpression(propertyName);
|
||||
}
|
||||
/**
|
||||
* Apply an "equal" constraint to two properties
|
||||
*/
|
||||
public static PropertyExpression eqProperty(String propertyName, String otherPropertyName) {
|
||||
return new PropertyExpression(propertyName, otherPropertyName, "=");
|
||||
}
|
||||
/**
|
||||
* Apply a "not equal" constraint to two properties
|
||||
*/
|
||||
public static PropertyExpression neProperty(String propertyName, String otherPropertyName) {
|
||||
return new PropertyExpression(propertyName, otherPropertyName, "<>");
|
||||
}
|
||||
/**
|
||||
* Apply a "less than" constraint to two properties
|
||||
*/
|
||||
public static PropertyExpression ltProperty(String propertyName, String otherPropertyName) {
|
||||
return new PropertyExpression(propertyName, otherPropertyName, "<");
|
||||
}
|
||||
/**
|
||||
* Apply a "less than or equal" constraint to two properties
|
||||
*/
|
||||
public static PropertyExpression leProperty(String propertyName, String otherPropertyName) {
|
||||
return new PropertyExpression(propertyName, otherPropertyName, "<=");
|
||||
}
|
||||
/**
|
||||
* Apply a "greater than" constraint to two properties
|
||||
*/
|
||||
public static PropertyExpression gtProperty(String propertyName, String otherPropertyName) {
|
||||
return new PropertyExpression(propertyName, otherPropertyName, ">");
|
||||
}
|
||||
/**
|
||||
* Apply a "greater than or equal" constraint to two properties
|
||||
*/
|
||||
public static PropertyExpression geProperty(String propertyName, String otherPropertyName) {
|
||||
return new PropertyExpression(propertyName, otherPropertyName, ">=");
|
||||
return new NullExpression( propertyName );
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply an "is not null" constraint to the named property
|
||||
* @return Criterion
|
||||
*
|
||||
* @param propertyName The property name
|
||||
*
|
||||
* @return The Criterion
|
||||
*
|
||||
* @see NotNullExpression
|
||||
*/
|
||||
public static Criterion isNotNull(String propertyName) {
|
||||
return new NotNullExpression(propertyName);
|
||||
return new NotNullExpression( propertyName );
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply an "equal" constraint to two properties
|
||||
*
|
||||
* @param propertyName One property name
|
||||
* @param otherPropertyName The other property name
|
||||
*
|
||||
* @return The Criterion
|
||||
*
|
||||
* @see PropertyExpression
|
||||
*/
|
||||
public static PropertyExpression eqProperty(String propertyName, String otherPropertyName) {
|
||||
return new PropertyExpression( propertyName, otherPropertyName, "=" );
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply a "not equal" constraint to two properties
|
||||
*
|
||||
* @param propertyName One property name
|
||||
* @param otherPropertyName The other property name
|
||||
*
|
||||
* @return The Criterion
|
||||
*
|
||||
* @see PropertyExpression
|
||||
*/
|
||||
public static PropertyExpression neProperty(String propertyName, String otherPropertyName) {
|
||||
return new PropertyExpression( propertyName, otherPropertyName, "<>" );
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply a "less than" constraint to two properties
|
||||
*
|
||||
* @param propertyName One property name
|
||||
* @param otherPropertyName The other property name
|
||||
*
|
||||
* @return The Criterion
|
||||
*
|
||||
* @see PropertyExpression
|
||||
*/
|
||||
public static PropertyExpression ltProperty(String propertyName, String otherPropertyName) {
|
||||
return new PropertyExpression( propertyName, otherPropertyName, "<" );
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply a "less than or equal" constraint to two properties
|
||||
*
|
||||
* @param propertyName One property name
|
||||
* @param otherPropertyName The other property name
|
||||
*
|
||||
* @return The Criterion
|
||||
*
|
||||
* @see PropertyExpression
|
||||
*/
|
||||
public static PropertyExpression leProperty(String propertyName, String otherPropertyName) {
|
||||
return new PropertyExpression( propertyName, otherPropertyName, "<=" );
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply a "greater than" constraint to two properties
|
||||
*
|
||||
* @param propertyName One property name
|
||||
* @param otherPropertyName The other property name
|
||||
*
|
||||
* @return The Criterion
|
||||
*
|
||||
* @see PropertyExpression
|
||||
*/
|
||||
public static PropertyExpression gtProperty(String propertyName, String otherPropertyName) {
|
||||
return new PropertyExpression( propertyName, otherPropertyName, ">" );
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply a "greater than or equal" constraint to two properties
|
||||
*
|
||||
* @param propertyName One property name
|
||||
* @param otherPropertyName The other property name
|
||||
*
|
||||
* @return The Criterion
|
||||
*
|
||||
* @see PropertyExpression
|
||||
*/
|
||||
public static PropertyExpression geProperty(String propertyName, String otherPropertyName) {
|
||||
return new PropertyExpression( propertyName, otherPropertyName, ">=" );
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the conjuction of two expressions
|
||||
*
|
||||
* @param lhs
|
||||
* @param rhs
|
||||
* @return Criterion
|
||||
* @param lhs One expression
|
||||
* @param rhs The other expression
|
||||
*
|
||||
* @return The Criterion
|
||||
*/
|
||||
public static LogicalExpression and(Criterion lhs, Criterion rhs) {
|
||||
return new LogicalExpression(lhs, rhs, "and");
|
||||
|
@ -276,24 +410,21 @@ public class Restrictions {
|
|||
* @return The conjunction
|
||||
*/
|
||||
public static Conjunction and(Criterion... predicates) {
|
||||
Conjunction conjunction = conjunction();
|
||||
if ( predicates != null ) {
|
||||
for ( Criterion predicate : predicates ) {
|
||||
conjunction.add( predicate );
|
||||
}
|
||||
}
|
||||
return conjunction;
|
||||
return conjunction( predicates );
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the disjuction of two expressions
|
||||
*
|
||||
* @param lhs
|
||||
* @param rhs
|
||||
* @return Criterion
|
||||
* @param lhs One expression
|
||||
* @param rhs The other expression
|
||||
*
|
||||
* @return The Criterion
|
||||
*/
|
||||
public static LogicalExpression or(Criterion lhs, Criterion rhs) {
|
||||
return new LogicalExpression(lhs, rhs, "or");
|
||||
return new LogicalExpression( lhs, rhs, "or" );
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the disjuction of multiple expressions
|
||||
*
|
||||
|
@ -302,62 +433,72 @@ public class Restrictions {
|
|||
* @return The conjunction
|
||||
*/
|
||||
public static Disjunction or(Criterion... predicates) {
|
||||
Disjunction disjunction = disjunction();
|
||||
if ( predicates != null ) {
|
||||
for ( Criterion predicate : predicates ) {
|
||||
disjunction.add( predicate );
|
||||
}
|
||||
}
|
||||
return disjunction;
|
||||
}
|
||||
/**
|
||||
* Return the negation of an expression
|
||||
*
|
||||
* @param expression
|
||||
* @return Criterion
|
||||
*/
|
||||
public static Criterion not(Criterion expression) {
|
||||
return new NotExpression(expression);
|
||||
}
|
||||
/**
|
||||
* Apply a constraint expressed in SQL, with the given JDBC
|
||||
* parameters. Any occurrences of <tt>{alias}</tt> will be
|
||||
* replaced by the table alias.
|
||||
*
|
||||
* @param sql
|
||||
* @param values
|
||||
* @param types
|
||||
* @return Criterion
|
||||
*/
|
||||
public static Criterion sqlRestriction(String sql, Object[] values, Type[] types) {
|
||||
return new SQLCriterion(sql, values, types);
|
||||
}
|
||||
/**
|
||||
* Apply a constraint expressed in SQL, with the given JDBC
|
||||
* parameter. Any occurrences of <tt>{alias}</tt> will be replaced
|
||||
* by the table alias.
|
||||
*
|
||||
* @param sql
|
||||
* @param value
|
||||
* @param type
|
||||
* @return Criterion
|
||||
*/
|
||||
public static Criterion sqlRestriction(String sql, Object value, Type type) {
|
||||
return new SQLCriterion(sql, new Object[] { value }, new Type[] { type } );
|
||||
}
|
||||
/**
|
||||
* Apply a constraint expressed in SQL. Any occurrences of <tt>{alias}</tt>
|
||||
* will be replaced by the table alias.
|
||||
*
|
||||
* @param sql
|
||||
* @return Criterion
|
||||
*/
|
||||
public static Criterion sqlRestriction(String sql) {
|
||||
return new SQLCriterion(sql, ArrayHelper.EMPTY_OBJECT_ARRAY, ArrayHelper.EMPTY_TYPE_ARRAY);
|
||||
return disjunction( predicates );
|
||||
}
|
||||
|
||||
/**
|
||||
* Group expressions together in a single conjunction (A and B and C...)
|
||||
* Return the negation of an expression
|
||||
*
|
||||
* @param expression The expression to be negated
|
||||
*
|
||||
* @return Criterion
|
||||
*
|
||||
* @see NotExpression
|
||||
*/
|
||||
public static Criterion not(Criterion expression) {
|
||||
return new NotExpression( expression );
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a restriction expressed in SQL with JDBC parameters. Any occurrences of <tt>{alias}</tt> will be
|
||||
* replaced by the table alias.
|
||||
*
|
||||
* @param sql The SQL restriction
|
||||
* @param values The parameter values
|
||||
* @param types The parameter types
|
||||
*
|
||||
* @return The Criterion
|
||||
*
|
||||
* @see SQLCriterion
|
||||
*/
|
||||
public static Criterion sqlRestriction(String sql, Object[] values, Type[] types) {
|
||||
return new SQLCriterion( sql, values, types );
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a restriction expressed in SQL with one JDBC parameter. Any occurrences of <tt>{alias}</tt> will be
|
||||
* replaced by the table alias.
|
||||
*
|
||||
* @param sql The SQL restriction
|
||||
* @param value The parameter value
|
||||
* @param type The parameter type
|
||||
*
|
||||
* @return The Criterion
|
||||
*
|
||||
* @see SQLCriterion
|
||||
*/
|
||||
public static Criterion sqlRestriction(String sql, Object value, Type type) {
|
||||
return new SQLCriterion( sql, value, type );
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply a constraint expressed in SQL with no JDBC parameters. Any occurrences of <tt>{alias}</tt> will be
|
||||
* replaced by the table alias.
|
||||
*
|
||||
* @param sql The SQL restriction
|
||||
*
|
||||
* @return The Criterion
|
||||
*
|
||||
* @see SQLCriterion
|
||||
*/
|
||||
public static Criterion sqlRestriction(String sql) {
|
||||
return new SQLCriterion( sql );
|
||||
}
|
||||
|
||||
/**
|
||||
* Group expressions together in a single conjunction (A and B and C...).
|
||||
*
|
||||
* This form creates an empty conjunction. See {@link Conjunction#add(Criterion)}
|
||||
*
|
||||
* @return Conjunction
|
||||
*/
|
||||
|
@ -366,7 +507,20 @@ public class Restrictions {
|
|||
}
|
||||
|
||||
/**
|
||||
* Group expressions together in a single disjunction (A or B or C...)
|
||||
* Group expressions together in a single conjunction (A and B and C...).
|
||||
*
|
||||
* @param conditions The initial set of conditions to put into the Conjunction
|
||||
*
|
||||
* @return Conjunction
|
||||
*/
|
||||
public static Conjunction conjunction(Criterion... conditions) {
|
||||
return new Conjunction( conditions );
|
||||
}
|
||||
|
||||
/**
|
||||
* Group expressions together in a single disjunction (A or B or C...).
|
||||
*
|
||||
* This form creates an empty disjunction. See {@link Disjunction#add(Criterion)}
|
||||
*
|
||||
* @return Conjunction
|
||||
*/
|
||||
|
@ -375,89 +529,169 @@ public class Restrictions {
|
|||
}
|
||||
|
||||
/**
|
||||
* Apply an "equals" constraint to each property in the
|
||||
* key set of a <tt>Map</tt>
|
||||
* Group expressions together in a single disjunction (A or B or C...).
|
||||
*
|
||||
* @param conditions The initial set of conditions to put into the Disjunction
|
||||
*
|
||||
* @return Conjunction
|
||||
*/
|
||||
public static Disjunction disjunction(Criterion... conditions) {
|
||||
return new Disjunction( conditions );
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply an "equals" constraint to each property in the key set of a <tt>Map</tt>
|
||||
*
|
||||
* @param propertyNameValues a map from property names to values
|
||||
*
|
||||
* @return Criterion
|
||||
*
|
||||
* @see Conjunction
|
||||
*/
|
||||
public static Criterion allEq(Map propertyNameValues) {
|
||||
Conjunction conj = conjunction();
|
||||
Iterator iter = propertyNameValues.entrySet().iterator();
|
||||
while ( iter.hasNext() ) {
|
||||
Map.Entry me = (Map.Entry) iter.next();
|
||||
conj.add( eq( (String) me.getKey(), me.getValue() ) );
|
||||
@SuppressWarnings("UnusedDeclaration")
|
||||
public static Criterion allEq(Map<String,?> propertyNameValues) {
|
||||
final Conjunction conj = conjunction();
|
||||
|
||||
for ( Map.Entry<String,?> entry : propertyNameValues.entrySet() ) {
|
||||
conj.add( eq( entry.getKey(), entry.getValue() ) );
|
||||
}
|
||||
return conj;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constrain a collection valued property to be empty
|
||||
*
|
||||
* @param propertyName The name of the collection property
|
||||
*
|
||||
* @return The Criterion
|
||||
*
|
||||
* @see EmptyExpression
|
||||
*/
|
||||
public static Criterion isEmpty(String propertyName) {
|
||||
return new EmptyExpression(propertyName);
|
||||
return new EmptyExpression( propertyName );
|
||||
}
|
||||
|
||||
/**
|
||||
* Constrain a collection valued property to be non-empty
|
||||
*
|
||||
* @param propertyName The name of the collection property
|
||||
*
|
||||
* @return The Criterion
|
||||
*
|
||||
* @see NotEmptyExpression
|
||||
*/
|
||||
public static Criterion isNotEmpty(String propertyName) {
|
||||
return new NotEmptyExpression(propertyName);
|
||||
return new NotEmptyExpression( propertyName );
|
||||
}
|
||||
|
||||
/**
|
||||
* Constrain a collection valued property by size
|
||||
*
|
||||
* @param propertyName The name of the collection property
|
||||
* @param size The size to use in comparison
|
||||
*
|
||||
* @return The Criterion
|
||||
*
|
||||
* @see SizeExpression
|
||||
*/
|
||||
public static Criterion sizeEq(String propertyName, int size) {
|
||||
return new SizeExpression(propertyName, size, "=");
|
||||
return new SizeExpression( propertyName, size, "=" );
|
||||
}
|
||||
|
||||
/**
|
||||
* Constrain a collection valued property by size
|
||||
*
|
||||
* @param propertyName The name of the collection property
|
||||
* @param size The size to use in comparison
|
||||
*
|
||||
* @return The Criterion
|
||||
*
|
||||
* @see SizeExpression
|
||||
*/
|
||||
@SuppressWarnings("UnusedDeclaration")
|
||||
public static Criterion sizeNe(String propertyName, int size) {
|
||||
return new SizeExpression(propertyName, size, "<>");
|
||||
return new SizeExpression( propertyName, size, "<>" );
|
||||
}
|
||||
|
||||
/**
|
||||
* Constrain a collection valued property by size
|
||||
*
|
||||
* @param propertyName The name of the collection property
|
||||
* @param size The size to use in comparison
|
||||
*
|
||||
* @return The Criterion
|
||||
*
|
||||
* @see SizeExpression
|
||||
*/
|
||||
@SuppressWarnings("UnusedDeclaration")
|
||||
public static Criterion sizeGt(String propertyName, int size) {
|
||||
return new SizeExpression(propertyName, size, "<");
|
||||
return new SizeExpression( propertyName, size, "<" );
|
||||
}
|
||||
|
||||
/**
|
||||
* Constrain a collection valued property by size
|
||||
*
|
||||
* @param propertyName The name of the collection property
|
||||
* @param size The size to use in comparison
|
||||
*
|
||||
* @return The Criterion
|
||||
*
|
||||
* @see SizeExpression
|
||||
*/
|
||||
@SuppressWarnings("UnusedDeclaration")
|
||||
public static Criterion sizeLt(String propertyName, int size) {
|
||||
return new SizeExpression(propertyName, size, ">");
|
||||
return new SizeExpression( propertyName, size, ">" );
|
||||
}
|
||||
|
||||
/**
|
||||
* Constrain a collection valued property by size
|
||||
*
|
||||
* @param propertyName The name of the collection property
|
||||
* @param size The size to use in comparison
|
||||
*
|
||||
* @return The Criterion
|
||||
*
|
||||
* @see SizeExpression
|
||||
*/
|
||||
@SuppressWarnings("UnusedDeclaration")
|
||||
public static Criterion sizeGe(String propertyName, int size) {
|
||||
return new SizeExpression(propertyName, size, "<=");
|
||||
return new SizeExpression( propertyName, size, "<=" );
|
||||
}
|
||||
|
||||
/**
|
||||
* Constrain a collection valued property by size
|
||||
*
|
||||
* @param propertyName The name of the collection property
|
||||
* @param size The size to use in comparison
|
||||
*
|
||||
* @return The Criterion
|
||||
*
|
||||
* @see SizeExpression
|
||||
*/
|
||||
@SuppressWarnings("UnusedDeclaration")
|
||||
public static Criterion sizeLe(String propertyName, int size) {
|
||||
return new SizeExpression(propertyName, size, ">=");
|
||||
return new SizeExpression( propertyName, size, ">=" );
|
||||
}
|
||||
|
||||
/**
|
||||
* Consider using any of the natural id based loading stuff from session instead, especially in cases
|
||||
* where the restriction is the full set of natural id values.
|
||||
*
|
||||
* @see Session#byNaturalId(Class)
|
||||
* @see Session#byNaturalId(String)
|
||||
* @see Session#bySimpleNaturalId(Class)
|
||||
* @see Session#bySimpleNaturalId(String)
|
||||
* @return The Criterion
|
||||
*
|
||||
* @see NaturalIdentifier
|
||||
*
|
||||
* @see org.hibernate.Session#byNaturalId(Class)
|
||||
* @see org.hibernate.Session#byNaturalId(String)
|
||||
* @see org.hibernate.Session#bySimpleNaturalId(Class)
|
||||
* @see org.hibernate.Session#bySimpleNaturalId(String)
|
||||
*/
|
||||
public static NaturalIdentifier naturalId() {
|
||||
return new NaturalIdentifier();
|
||||
}
|
||||
|
||||
protected Restrictions() {
|
||||
// cannot be instantiated, but needs to be protected so Expression can extend it
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2010, Red Hat Inc. or third-party contributors as
|
||||
* Copyright (c) 2010, 2013, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
|
@ -22,11 +22,13 @@
|
|||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.criterion;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.Criteria;
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.dialect.function.SQLFunction;
|
||||
import org.hibernate.dialect.function.SQLFunctionRegistry;
|
||||
import org.hibernate.type.Type;
|
||||
|
||||
/**
|
||||
|
@ -35,30 +37,30 @@ import org.hibernate.type.Type;
|
|||
* @author Gavin King
|
||||
*/
|
||||
public class RowCountProjection extends SimpleProjection {
|
||||
private static List ARGS = java.util.Collections.singletonList( "*" );
|
||||
|
||||
public String toString() {
|
||||
return "count(*)";
|
||||
}
|
||||
private static final List ARGS = java.util.Collections.singletonList( "*" );
|
||||
|
||||
@Override
|
||||
public Type[] getTypes(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException {
|
||||
return new Type[] {
|
||||
getFunction( criteriaQuery ).getReturnType( null, criteriaQuery.getFactory() )
|
||||
};
|
||||
final Type countFunctionReturnType = getFunction( criteriaQuery ).getReturnType( null, criteriaQuery.getFactory() );
|
||||
return new Type[] { countFunctionReturnType };
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toSqlString(Criteria criteria, int position, CriteriaQuery criteriaQuery) throws HibernateException {
|
||||
return getFunction( criteriaQuery ).render( null, ARGS, criteriaQuery.getFactory() )
|
||||
+ " as y" + position + '_';
|
||||
return getFunction( criteriaQuery ).render( null, ARGS, criteriaQuery.getFactory() ) + " as y" + position + '_';
|
||||
}
|
||||
|
||||
protected SQLFunction getFunction(CriteriaQuery criteriaQuery) {
|
||||
SQLFunction function = criteriaQuery.getFactory()
|
||||
.getSqlFunctionRegistry()
|
||||
.findSQLFunction( "count" );
|
||||
final SQLFunctionRegistry sqlFunctionRegistry = criteriaQuery.getFactory().getSqlFunctionRegistry();
|
||||
final SQLFunction function = sqlFunctionRegistry.findSQLFunction( "count" );
|
||||
if ( function == null ) {
|
||||
throw new HibernateException( "Unable to locate count function mapping" );
|
||||
}
|
||||
return function;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "count(*)";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
|
||||
* Copyright (c) 2008, 2013, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Middleware LLC.
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
|
@ -20,12 +20,10 @@
|
|||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
package org.hibernate.criterion;
|
||||
|
||||
import org.hibernate.Criteria;
|
||||
import org.hibernate.EntityMode;
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.engine.spi.TypedValue;
|
||||
import org.hibernate.internal.util.StringHelper;
|
||||
import org.hibernate.type.Type;
|
||||
|
@ -35,32 +33,39 @@ import org.hibernate.type.Type;
|
|||
* alias of the root entity.
|
||||
*/
|
||||
public class SQLCriterion implements Criterion {
|
||||
|
||||
private final String sql;
|
||||
private final TypedValue[] typedValues;
|
||||
|
||||
public String toSqlString(
|
||||
Criteria criteria,
|
||||
CriteriaQuery criteriaQuery)
|
||||
throws HibernateException {
|
||||
return StringHelper.replace( sql, "{alias}", criteriaQuery.getSQLAlias( criteria ) );
|
||||
}
|
||||
|
||||
public TypedValue[] getTypedValues(Criteria criteria, CriteriaQuery criteriaQuery)
|
||||
throws HibernateException {
|
||||
return typedValues;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return sql;
|
||||
}
|
||||
|
||||
protected SQLCriterion(String sql, Object[] values, Type[] types) {
|
||||
this.sql = sql;
|
||||
typedValues = new TypedValue[values.length];
|
||||
this.typedValues = new TypedValue[values.length];
|
||||
for ( int i=0; i<typedValues.length; i++ ) {
|
||||
typedValues[i] = new TypedValue( types[i], values[i] );
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
|
||||
* Copyright (c) 2008, 2013, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Middleware LLC.
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
|
@ -20,11 +20,10 @@
|
|||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
package org.hibernate.criterion;
|
||||
|
||||
import org.hibernate.Criteria;
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.internal.util.StringHelper;
|
||||
import org.hibernate.type.Type;
|
||||
|
||||
|
@ -33,7 +32,6 @@ import org.hibernate.type.Type;
|
|||
* alias of the root entity.
|
||||
*/
|
||||
public class SQLProjection implements Projection {
|
||||
|
||||
private final String sql;
|
||||
private final String groupBy;
|
||||
private final Type[] types;
|
||||
|
@ -41,30 +39,8 @@ public class SQLProjection implements Projection {
|
|||
private String[] columnAliases;
|
||||
private boolean grouped;
|
||||
|
||||
public String toSqlString(
|
||||
Criteria criteria,
|
||||
int loc,
|
||||
CriteriaQuery criteriaQuery)
|
||||
throws HibernateException {
|
||||
return StringHelper.replace( sql, "{alias}", criteriaQuery.getSQLAlias(criteria) );
|
||||
}
|
||||
|
||||
public String toGroupSqlString(Criteria criteria, CriteriaQuery criteriaQuery)
|
||||
throws HibernateException {
|
||||
return StringHelper.replace( groupBy, "{alias}", criteriaQuery.getSQLAlias( criteria ) );
|
||||
}
|
||||
|
||||
public Type[] getTypes(Criteria crit, CriteriaQuery criteriaQuery)
|
||||
throws HibernateException {
|
||||
return types;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return sql;
|
||||
}
|
||||
|
||||
protected SQLProjection(String sql, String[] columnAliases, Type[] types) {
|
||||
this(sql, null, columnAliases, types);
|
||||
this( sql, null, columnAliases, types );
|
||||
}
|
||||
|
||||
protected SQLProjection(String sql, String groupBy, String[] columnAliases, Type[] types) {
|
||||
|
@ -76,23 +52,48 @@ public class SQLProjection implements Projection {
|
|||
this.groupBy = groupBy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toSqlString(Criteria criteria, int loc, CriteriaQuery criteriaQuery) {
|
||||
return StringHelper.replace( sql, "{alias}", criteriaQuery.getSQLAlias( criteria ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toGroupSqlString(Criteria criteria, CriteriaQuery criteriaQuery) {
|
||||
return StringHelper.replace( groupBy, "{alias}", criteriaQuery.getSQLAlias( criteria ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type[] getTypes(Criteria crit, CriteriaQuery criteriaQuery) {
|
||||
return types;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return sql;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getAliases() {
|
||||
return aliases;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getColumnAliases(int loc) {
|
||||
return columnAliases;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isGrouped() {
|
||||
return grouped;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type[] getTypes(String alias, Criteria crit, CriteriaQuery criteriaQuery) {
|
||||
return null; //unsupported
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getColumnAliases(String alias, int loc) {
|
||||
return null; //unsupported
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2008-2012, Red Hat Inc. or third-party contributors as
|
||||
* Copyright (c) 2008, 2012, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
|
@ -55,55 +55,6 @@ public class SimpleExpression implements Criterion {
|
|||
this.op = op;
|
||||
}
|
||||
|
||||
public SimpleExpression ignoreCase() {
|
||||
ignoreCase = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery)
|
||||
throws HibernateException {
|
||||
|
||||
String[] columns = criteriaQuery.findColumns( propertyName, criteria );
|
||||
Type type = criteriaQuery.getTypeUsingProjection( criteria, propertyName );
|
||||
StringBuilder fragment = new StringBuilder();
|
||||
if ( columns.length > 1 ) {
|
||||
fragment.append( '(' );
|
||||
}
|
||||
SessionFactoryImplementor factory = criteriaQuery.getFactory();
|
||||
int[] sqlTypes = type.sqlTypes( factory );
|
||||
for ( int i = 0; i < columns.length; i++ ) {
|
||||
boolean lower = ignoreCase &&
|
||||
(sqlTypes[i] == Types.VARCHAR || sqlTypes[i] == Types.CHAR);
|
||||
if ( lower ) {
|
||||
fragment.append( factory.getDialect().getLowercaseFunction() )
|
||||
.append( '(' );
|
||||
}
|
||||
fragment.append( columns[i] );
|
||||
if ( lower ) {
|
||||
fragment.append( ')' );
|
||||
}
|
||||
fragment.append( getOp() ).append( "?" );
|
||||
if ( i < columns.length - 1 ) {
|
||||
fragment.append( " and " );
|
||||
}
|
||||
}
|
||||
if ( columns.length > 1 ) {
|
||||
fragment.append( ')' );
|
||||
}
|
||||
return fragment.toString();
|
||||
|
||||
}
|
||||
|
||||
public TypedValue[] getTypedValues(Criteria criteria, CriteriaQuery criteriaQuery)
|
||||
throws HibernateException {
|
||||
Object icvalue = ignoreCase ? value.toString().toLowerCase() : value;
|
||||
return new TypedValue[] {criteriaQuery.getTypedValue( criteria, propertyName, icvalue )};
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return propertyName + getOp() + value;
|
||||
}
|
||||
|
||||
protected final String getOp() {
|
||||
return op;
|
||||
}
|
||||
|
@ -115,4 +66,58 @@ public class SimpleExpression implements Criterion {
|
|||
public Object getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make case insensitive. No effect for non-String values
|
||||
*
|
||||
* @return {@code this}, for method chaining
|
||||
*/
|
||||
public SimpleExpression ignoreCase() {
|
||||
ignoreCase = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException {
|
||||
final String[] columns = criteriaQuery.findColumns( propertyName, criteria );
|
||||
final Type type = criteriaQuery.getTypeUsingProjection( criteria, propertyName );
|
||||
final StringBuilder fragment = new StringBuilder();
|
||||
|
||||
if ( columns.length > 1 ) {
|
||||
fragment.append( '(' );
|
||||
}
|
||||
final SessionFactoryImplementor factory = criteriaQuery.getFactory();
|
||||
final int[] sqlTypes = type.sqlTypes( factory );
|
||||
for ( int i = 0; i < columns.length; i++ ) {
|
||||
final boolean lower = ignoreCase && (sqlTypes[i] == Types.VARCHAR || sqlTypes[i] == Types.CHAR);
|
||||
if ( lower ) {
|
||||
fragment.append( factory.getDialect().getLowercaseFunction() ).append( '(' );
|
||||
}
|
||||
fragment.append( columns[i] );
|
||||
if ( lower ) {
|
||||
fragment.append( ')' );
|
||||
}
|
||||
|
||||
fragment.append( getOp() ).append( "?" );
|
||||
if ( i < columns.length - 1 ) {
|
||||
fragment.append( " and " );
|
||||
}
|
||||
}
|
||||
if ( columns.length > 1 ) {
|
||||
fragment.append( ')' );
|
||||
}
|
||||
return fragment.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypedValue[] getTypedValues(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException {
|
||||
final Object casedValue = ignoreCase ? value.toString().toLowerCase() : value;
|
||||
return new TypedValue[] { criteriaQuery.getTypedValue( criteria, propertyName, casedValue ) };
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return propertyName + getOp() + value;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue