merge master

This commit is contained in:
Strong Liu 2013-04-06 12:30:53 +08:00
commit 68720548c8
50 changed files with 2883 additions and 1096 deletions

View File

@ -90,7 +90,6 @@ subprojects { subProject ->
} }
ext.toolsJar = file("${System.getProperty('java.home')}/../lib/tools.jar")
// appropriately inject the common dependencies into each sub-project // appropriately inject the common dependencies into each sub-project
dependencies { dependencies {
compile( libraries.logging ) compile( libraries.logging )
@ -117,12 +116,17 @@ subprojects { subProject ->
jaxb( libraries.jaxb2_jaxb_xjc ) jaxb( libraries.jaxb2_jaxb_xjc )
deployerJars "org.apache.maven.wagon:wagon-http:1.0" deployerJars "org.apache.maven.wagon:wagon-http:1.0"
} }
ext.toolsJar = file("${System.getProperty('java.home')}/../lib/tools.jar")
if ( ext.toolsJar.exists() ) { if ( ext.toolsJar.exists() ) {
dependencies{ dependencies{
testCompile files( toolsJar ) testCompile files( toolsJar )
} }
} }
task compile
compile.dependsOn compileJava, compileTestJava
sourceSets.main { sourceSets.main {
compileClasspath += configurations.provided compileClasspath += configurations.provided
} }
@ -133,7 +137,7 @@ subprojects { subProject ->
java.srcDir generatedLoggingSrcDir java.srcDir generatedLoggingSrcDir
} }
task generateMainLoggingClasses(type: Compile) { task generateMainLoggingClasses(type: JavaCompile) {
ext.aptDumpDir = subProject.file( "${buildDir}/tmp/apt/logging" ) ext.aptDumpDir = subProject.file( "${buildDir}/tmp/apt/logging" )
classpath = compileJava.classpath + configurations.jbossLoggingTool classpath = compileJava.classpath + configurations.jbossLoggingTool
source = sourceSets.main.originalJavaSrcDirs source = sourceSets.main.originalJavaSrcDirs
@ -163,6 +167,9 @@ subprojects { subProject ->
// for the time being eat the annoying output from running the annotation processors // for the time being eat the annoying output from running the annotation processors
generateMainLoggingClasses.logging.captureStandardError(LogLevel.INFO) generateMainLoggingClasses.logging.captureStandardError(LogLevel.INFO)
task generateSources( type: Task )
generateSources.dependsOn generateMainLoggingClasses
compileJava.dependsOn generateMainLoggingClasses compileJava.dependsOn generateMainLoggingClasses
compileJava.options.define(compilerArgs: ["-proc:none", "-encoding", "UTF-8"]) compileJava.options.define(compilerArgs: ["-proc:none", "-encoding", "UTF-8"])
compileTestJava.options.define(compilerArgs: ["-proc:none", "-encoding", "UTF-8"]) compileTestJava.options.define(compilerArgs: ["-proc:none", "-encoding", "UTF-8"])
@ -282,8 +289,8 @@ subprojects { subProject ->
// elements used to customize the generated POM used during upload // elements used to customize the generated POM used during upload
def pomConfig = { def pomConfig = {
name 'A Hibernate Core Module' name 'A Hibernate O/RM Module'
description 'A module of the Hibernate Core project' description 'A module of the Hibernate O/RM project'
url 'http://hibernate.org' url 'http://hibernate.org'
organization { organization {
name 'Hibernate.org' name 'Hibernate.org'
@ -345,7 +352,6 @@ subprojects { subProject ->
} }
} }
dependsOnChildren()
// This is a task that generates the gradlew scripts, allowing users to run gradle without having gradle installed // This is a task that generates the gradlew scripts, allowing users to run gradle without having gradle installed
// on their system. // on their system.
@ -354,5 +360,5 @@ dependsOnChildren()
// 2) /gradlew.bat which is the windows bat script for for executing builds // 2) /gradlew.bat which is the windows bat script for for executing builds
// 3) /wrapper which is a directory named by the "jarPath" config which contains other needed files. // 3) /wrapper which is a directory named by the "jarPath" config which contains other needed files.
task wrapper(type: Wrapper) { task wrapper(type: Wrapper) {
gradleVersion = '1.1' gradleVersion = '1.5'
} }

View File

@ -5,8 +5,245 @@ 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 refer to the particular case on JIRA using the issue tracking number to learn
more about each case. more about each case.
Changes in version 4.3.0.Beta1 (2012.07.12)
------------------------------------------------------------------------------------------------------------------------
https://hibernate.atlassian.net/browse/HHH/fixforversion/12152
** Sub-task
* [HHH-7941] - Script OSGi manifest creation in Gradle
* [HHH-7942] - Create Hibernate OSGi bundle activator and class loader services
* [HHH-7966] - Remove external use of internal impls
* [HHH-7968] - Upgrade to JACC 1.0.2.Final -- needed for OSGi manifests
* [HHH-7981] - Load (now) locally defined orm.xsd while processing orm.xml files
* [HHH-7982] - Revisist discrepancy between <join-table> and @JoinTable after discussion with EG
* [HHH-7991] - Correct all instances of Thread.currentThread().getContextClassLoader()
* [HHH-7994] - Improve OsgiClassLoader performance
* [HHH-7997] - Integrate changes to EntityGraphs
* [HHH-8010] - Ensure Hibernate manifests allow user bundle managed SF/EMF
* [HHH-8077] - Add MDC usage into attribute walking to help decode logs from recursive calls
* [HHH-8098] - JTA 1.2
* [HHH-8099] - CDI 1.1
* [HHH-8100] - BV 1.1
** Bug
* [HHH-995] - Order.ignoreCase() only works for VARCHAR types, not CHAR types
* [HHH-1168] - Problem combining locking and paging on Oracle
* [HHH-1283] - ScrollableResults JoinFetch don't set child collection correctly after the second parent object
* [HHH-1570] - criteria-api: filtering by key-many-to-one causes invalid sql
* [HHH-1904] - Identifier too long
* [HHH-2045] - in () result in "unexpected end of subtree"
* [HHH-2721] - PostgreSQLDialect: function md5() always returns a string value
* [HHH-3788] - FirebirdDialect: current_date() function
* [HHH-3862] - Wrong link in documentation tutorial chapter 1
* [HHH-4084] - @UniqueConstraint(columnNames="") causes StringIndexOutOfBoundsException
* [HHH-4150] - EntityManager.createQuery does not recognize COUNT CASE statement
* [HHH-4459] - Query with Composite Primary Key parameter crashes when query cache is on
* [HHH-4562] - Some kind of typo in chapter 7.3.1
* [HHH-4635] - Oracle ORA-24816 inserting and updating data for entities containg LOB attributes
* [HHH-5188] - Use provided enum type ordinal/string when reading
* [HHH-5209] - org.hibernate.hql.ast.QuerySyntaxException when running a JPQL query with a MEMBER OF on an @ElementCollection
* [HHH-5267] - NPE when updating a detached entity with a one-to-one association changed to null that is mapped with delete-orphan
* [HHH-5376] - Tests contain invalid SQL
* [HHH-5732] - @OrderColumn not updated if @OneToMany has mappedby defined
* [HHH-5836] - Mapping collection of entities with same name and notnull constraints from two different entities results in duplicate property mapping of Backref
* [HHH-5973] - Typo in documentation about Interceptors
* [HHH-6043] - PostLoad method invoked before collection initialised
* [HHH-6349] - AuditJoinTable rows missing when detached entities with collections are merged into the persistence context
* [HHH-6496] - ClassCastException inside proxy without explicit casting in application code
* [HHH-6643] - Criteria doesn't support a chaining of 2 not restrictions (sql = not not criterion)
* [HHH-6655] - trim function on DB2 is broken
* [HHH-6972] - Support PostgreSQL and Oracle LOBs
* [HHH-7029] - Javadoc says the opposite as in code example
* [HHH-7203] - IdentityGenerator fails with JOINED Inheritance when inserting entity to PosgtreSQL
* [HHH-7233] - unmuck EntityManager#getSingleResult wrt auto-setting of max results
* [HHH-7304] - NaturalIdResolutionCache not correctly filled on first persist when @GeneratedValue-@Id
* [HHH-7308] - beforeTransactionCompletion() not getting called in the same scenarios as afterTransactionCompletion() in the TransactionObserver for child Sessions
* [HHH-7309] - Natural-id not cached in shared cache after insert
* [HHH-7359] - Trace logging causes numerous test errors
* [HHH-7377] - NullPointerException in conjunction with natural IDs after Session.clear()
* [HHH-7398] - Transaction timeouts are not properly enforced
* [HHH-7437] - Classcast issue with new property auditing feature of Envers(withModifiedFlag)
* [HHH-7479] - getForUpdateString() of HSQLDialect returns empty string.
* [HHH-7487] - org.hibernate.type.EnumType incorrectly logs binded values
* [HHH-7519] - Upgrade byteman version
* [HHH-7524] - Enabling AvailableSettings.ENABLE_LAZY_LOAD_NO_TRANS results in leaking DB-connections
* [HHH-7541] - When using HSQLDB, inserting any CLOB value larger than 16Mb always fails with an exception
* [HHH-7557] - Map entries get deleted
* [HHH-7561] - PersistenceUnitUtil.getIdentifier returning null for a persisted proxy
* [HHH-7563] - Fallback for JBossAppServerJtaPlatform.locateUserTransaction() to look at "java:jboss" if "java:comp" not available
* [HHH-7566] - Activating JOIN fetch profile involving self-referential associations causes StackOverflowError
* [HHH-7567] - Better checking when @Enumerated involved
* [HHH-7568] - Add JPA1.0 compound key compatability when orm descriptor file used to override annotations.
* [HHH-7569] - Correct test-only failures in hibernate-core-master-matrix CI job
* [HHH-7575] - Hibernate Getting Started Guide refers to incorrect tutorial directory for annotations tutoral
* [HHH-7577] - Dialect's supportsNotNullUnique not working when false
* [HHH-7578] - Sybase does not support "unique not null"
* [HHH-7579] - Oracle does not support "unique not null"
* [HHH-7580] - Complete 2-phase SessionFactory building design
* [HHH-7584] - Sybase dialects attempting to use BLOB types
* [HHH-7586] - Re-architect Type or TypeFactory dynamic descriptors
* [HHH-7603] - NullPointerException being thrown instead of LazyInitializationException with collection reattach change
* [HHH-7608] - @OrderBy in combination with @Formula fails
* [HHH-7643] - java.io.NotSerializableException org.hibernate.type.EnumType
* [HHH-7644] - Correct memory leak introduced by HHH-7557
* [HHH-7645] - Enum property defined within orm.xml using enum-type string does not work
* [HHH-7669] - JtaTransaction test fails on Oracle RAC
* [HHH-7674] - DB locks not cleared on LazyLoadingTest#testLazyCollectionLoadingWithClearedSession
* [HHH-7692] - Postgres 9 and 9.1 use 8.1 dialect instead of 8.2 by default
* [HHH-7693] - SQL Server 2012 gets the SQL Server 2000 dialect by default
* [HHH-7711] - SchemaExport doesn't create file with script if both parameters exportToDatabase and scriptToConsole are false
* [HHH-7716] - Update CUBRID dialect and test cases
* [HHH-7717] - Reserved keywords are used in unit tests' column names
* [HHH-7721] - SQLFunctionRegistry findSQLFunction does not honor case sensitivity
* [HHH-7724] - JpaLargeBlobTest failing on multiple DBs
* [HHH-7730] - SchemaExportManagedConnectionTest#testGenerateDdlToFile failing on Oracle & Sybase
* [HHH-7732] - QueryTest#testMemberOfSyntax failing on Oracle
* [HHH-7733] - NativeSQLQueriesTest failing on Postgres
* [HHH-7734] - SerializableTypeTest#testNewSerializableType failing for Oracle 11G R1
* [HHH-7748] - EnumType crashes because of unsupported JDBC API in Oracle
* [HHH-7757] - NOT IN handled incorrectly with tuples for dialects that do not support tuple syntax
* [HHH-7767] - JoinWalker creates ".." substring in association path
* [HHH-7768] - Names of invalid named queries incorrectly concatenated
* [HHH-7769] - Define short-names for built-in MultiTableBulkIdStrategy impls
* [HHH-7785] - Schema export does not generate unique constraints for HSQLDialect any more
* [HHH-7797] - Inconsistent logic by uses of Dialect#supportsNotNullUnique
* [HHH-7800] - maximize() builds incorrect query if used inside an AuditDisjunction
* [HHH-7816] - DDL opertations will incorrectly commit current transaction on Oracle XA
* [HHH-7819] - Correct test issues found in CI hibernate-core-master-matrix job
* [HHH-7821] - NPE after upgrade from 4.1.6 to 4.1.8
* [HHH-7825] - org.hibernate.type.descriptor.java.DataHelper is incompatible with FireBird JDBC
* [HHH-7829] - NullPointerException when manually flushing One-To-One relationship with orphan removal
* [HHH-7839] - Documentation bug at SimpleNaturalIdLoadAccess.getReference(Object naturalIdValue)
* [HHH-7849] - Unable to join on an embedded field
* [HHH-7889] - Sybase jConnect driver cannot use ResultSet.getClob(String) method
* [HHH-7890] - Quoting identifiers breaks @UniqueConstraint
* [HHH-7910] - Transaction timeout can cause non-threadsafe session access by reaper thread
* [HHH-7911] - NPE in TwoPhaseLoad#initializeEntity
* [HHH-7923] - Revert to Javassist 3.15
* [HHH-7928] - Regression caused by HHH-6361
* [HHH-7930] - Hibernate will crash with (custom) enum types when running with a logback.xml in debug mode
* [HHH-7933] - boolean is broken on SQLServerDialect
* [HHH-7948] - Merging CollectionChangeWorkUnit with ModWorkUnit ended with incorrect values of modified flags
* [HHH-7970] - @javax.persistence.Cacheable is never wired up
* [HHH-7984] - Prepared statement for callable returning cursor not closed
* [HHH-7990] - Bootstrapping Hibernate fails if javax.validation API is on classpath but no provider
* [HHH-8002] - TransactionTimeoutTest#testTransactionTimeoutSuccess failing on Oracle
* [HHH-8003] - Create "sqlDropString" method in Dialect to handle "if exists" correctly
* [HHH-8005] - Sybase 15 - nullable column are not nullable (when created by SchemaExport)
* [HHH-8006] - MergeCollectionEventTest & BadMergeHandlingTest fail on MySQL
* [HHH-8007] - Update SQLServer2005LimitHandler to handle multiselects (*, table.*)
* [HHH-8017] - Correct SybaseDialect's getNullColumnString
* [HHH-8019] - Multiple tests creating identifiers too long for Oracle
* [HHH-8022] - Return REFCURSOR on native named query: regression on 4.2.0 CR1
* [HHH-8025] - Binary compatibility broken between 4.1.9 -> 4.1.10 for Restrictions.eq and Restrictions.ne
* [HHH-8026] - Duplicate constraint names with unique=true
* [HHH-8036] - Envers projection max causes mysql syntax error
* [HHH-8037] - Empty SQL statements with custom UniqueDelegate
* [HHH-8053] - HibernateBundleActivator should not register itself as a PersistenceProvider
* [HHH-8061] - tests failing on master-matrix CI
* [HHH-8067] - Hibernate's ManagedType#getDeclaredAttribute fails to find plural attributes
* [HHH-8072] - envers @ElementCollection Map support failing -- nullable KEY
* [HHH-8073] - Column#getAlias logic incorrectly uses Dialect#getMaxAliasLength
* [HHH-8082] - HQLScrollFetchTest.testScroll hangs on DB2-97
* [HHH-8085] - QueryCacheTest.testGetByCompositeId fails on db2-97 -- DB2 SQL Error: SQLCODE=-613
* [HHH-8086] - Allow explicit package naming in persistence.xml via <class/>
* [HHH-8087] - Envers delete doesn't insert a new row with revtype=2 for unidirectional manytomany collections
* [HHH-8092] - Configuration#generateSchemaUpdateScript does not create unique constraints
* [HHH-8107] - JandexHelper.getValue() returns Boolean instead of boolean, causing ClassCastException
* [HHH-8136] - Correct "to_char" function in HSQL
** Deprecation
* [HHH-7777] - Deprecate XmlRepresentableType
* [HHH-7856] - Deprecate TableHiLoGenerator and TableGenerator
** Improvement
* [HHH-465] - order by nulls first / last
* [HHH-1123] - Cannot put more than 1000 elements in a InExpression
* [HHH-1775] - collection batch fetching
* [HHH-1917] - Bulk Delete on the owning side of a ManyToMany relation needs to delete corresponding rows from the JoinTable
* [HHH-2448] - Generate identical column aliases among cluster
* [HHH-2805] - The class Order does not contain getters
* [HHH-2951] - Restrictions.eq when passed null, should create a NullRestriction
* [HHH-3458] - Register postgres random() function as "rand" in PostgresSQLDialect
* [HHH-4412] - bulk update with native sql queries
* [HHH-5951] - Strategy for deciding JtaPlatform when an explicit one not specified
* [HHH-6452] - PostgreSQL Dialect does not fully implement NOWAIT locking
* [HHH-6682] - add support for oracle "bitand" function to Oracle Dialect
* [HHH-6823] - Short-name config values
* [HHH-6841] - Allow multiple @SkipForDialect annotations
* [HHH-7462] - Make JACC service
* [HHH-7520] - BlobProxy.invoke Javadoc is incorrect
* [HHH-7550] - Fix UP-TO-DATE checking for APT-based tasks
* [HHH-7626] - Add javadoc to annotations
* [HHH-7631] - Improve performance of UpdateTimestampsCache
* [HHH-7633] - Improve performance of IdentityMap
* [HHH-7667] - Initial improved bytecode enhancement support
* [HHH-7683] - Optimize performance of AbstractLazyInitializer.prepareForPossibleSpecialSpecjInitialization()
* [HHH-7698] - In efficient LOB creations backed by streams
* [HHH-7714] - Add support for EntityMode.MAP to JPA Criteria API
* [HHH-7725] - Make handling multi-table bulk HQL operations more pluggable
* [HHH-7728] - Add equals method in the table class
* [HHH-7746] - Investigate alternative batch loading algorithms
* [HHH-7806] - Failure of lazy initialization of collection no longer reports role
* [HHH-7811] - grammar error in devguide for HB
* [HHH-7813] - mistake in code examples in devguide for HB
* [HHH-7826] - Generate 'unique' constraints in stable order
* [HHH-7835] - Inefficient implementation of JarVisitorFactory.getBytesFromInputStream
* [HHH-7840] - org.hibernate.id.IncrementGenerator very slow
* [HHH-7866] - Avoid redundant log level checking in StandardQueryCache
* [HHH-7869] - bad performance problem with org.hibernate.internal.util.StringHelper#firstIndexOfChar
* [HHH-7872] - Improved L2 cache storage of "reference" data
* [HHH-7902] - Replace JDBC proxies with a set of contracts/helpers
* [HHH-7912] - Define edge-case behavior for Session.evict
* [HHH-7947] - remove not maintained 2LC provider from Doc
* [HHH-7952] - Missing Deprecated Javadoc For TableGenerator/TableHiLoGenerator
* [HHH-7965] - Redesign DialectResolver contract
* [HHH-7992] - Add a base Session delegator implementation
* [HHH-7999] - Oracle test failures due to lack of support for various syntax
* [HHH-8029] - Improve SimpleNationalizedTest
* [HHH-8071] - Add debug/trace logging to HibernatePersistenceProvider
* [HHH-8076] - javax.security and javax.validation should be optional in OSGi manifest
* [HHH-8088] - Redesign Scanner contract
* [HHH-8096] - Re-work the OSGi class loading concepts
* [HHH-8113] - Persistence.createEntityManagerFactory() should run schema export if JPA properties are set
* [HHH-8121] - Make property-able JPA settings defined in persistence.xml available in EMF.getProperties()
* [HHH-8122] - Scrub known-sensitive settings from EMF.getProperties()
** New Feature
* [HHH-5869] - Add suport for nationalized character mappings
* [HHH-6613] - Support for audited @ElementCollection / collection of elements
* [HHH-6736] - Support for SELECT ... FOR UPDATE SKIP LOCKED / read past locking
* [HHH-7402] - Improve performance of named query registry
* [HHH-7552] - New StrategySelectorService
* [HHH-7723] - Adding mssql2012 DBAllocator label
* [HHH-7827] - [ENVERS] Create ability to get the latest revision of all instances for a requested Entity Class
** Patch
* [HHH-3869] - Improve toString on SessionStatistics
* [HHH-6361] - Collection events may contain wrong stored snapshot after merging a detached entity into the persistencecontext
** Task
* [HHH-7387] - Integrate Draft 6 of the JPA 2.1 spec
* [HHH-7451] - Integrate Draft 7 of the JPA 2.1 spec
* [HHH-7521] - JBoss 7 / JPA 2.1 integration work
* [HHH-7620] - allow ValidatorFactory to be passed into EntityManagerFactoryBuilder
* [HHH-7621] - allow DataSource to be passed into EntityManagerFactoryBuilder
* [HHH-7727] - Mark Envers demo as test source
* [HHH-7749] - Allow setting system properties for tests on gradle command line
* [HHH-7782] - Deprecate PersistentElementHolder, PersistentIndexedElementHolder, PersistentListElementHolder and PersistentMapElementHolder
* [HHH-7914] - Improve new stored procedure call support
* [HHH-7957] - Integrate Latest draft(s) of the JPA 2.1 spec
* [HHH-7978] - Document new feature from HHH-5869
* [HHH-8044] - Remove mention of unsupported cache providers from Developer Guide
* [HHH-8095] - Upgrade to JTA API 1.0.1
* [HHH-8097] - Pull in new EE7 apis for integration
* [HHH-8129] - Unify BaseQueryImpl and AbstractQueryImpl hierarchies
Changes in version 4.1.5.SP1 (2012.07.12) Changes in version 4.1.5.SP1 (2012.07.12)
------------------------------------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------------------------------------
https://hibernate.atlassian.net/browse/HHH/fixforversion/12155
** Bug ** Bug
* [HHH-7447] - ValueHolder used in NaturalIdCacheKey is not Serializable * [HHH-7447] - ValueHolder used in NaturalIdCacheKey is not Serializable

Binary file not shown.

View File

@ -1,6 +1,6 @@
#Thu Sep 01 02:41:24 CST 2011 #Thu Apr 04 13:01:06 CDT 2013
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists
distributionUrl=http\://services.gradle.org/distributions/gradle-1.1-bin.zip distributionUrl=http\://services.gradle.org/distributions/gradle-1.5-bin.zip

94
gradlew vendored
View File

@ -1,16 +1,16 @@
#!/bin/bash #!/usr/bin/env bash
############################################################################## ##############################################################################
## ## ##
## Gradle wrapper script for UN*X ## ## Gradle start up script for UN*X
## ## ##
############################################################################## ##############################################################################
# Uncomment those lines to set JVM options. GRADLE_OPTS and JAVA_OPTS can be used together. # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
# GRADLE_OPTS="$GRADLE_OPTS -Xmx512m" DEFAULT_JVM_OPTS=""
# JAVA_OPTS="$JAVA_OPTS -Xmx512m"
GRADLE_APP_NAME=Gradle APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Use the maximum available, or set MAX_FD != -1 to use that value. # Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum" MAX_FD="maximum"
@ -42,35 +42,32 @@ case "`uname`" in
;; ;;
esac esac
# Attempt to set JAVA_HOME if it's not already set.
if [ -z "$JAVA_HOME" ] ; then
if $darwin ; then
[ -z "$JAVA_HOME" -a -d "/Library/Java/Home" ] && export JAVA_HOME="/Library/Java/Home"
[ -z "$JAVA_HOME" -a -d "/System/Library/Frameworks/JavaVM.framework/Home" ] && export JAVA_HOME="/System/Library/Frameworks/JavaVM.framework/Home"
else
javaExecutable="`which javac`"
[ -z "$javaExecutable" -o "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ] && die "JAVA_HOME not set and cannot find javac to deduce location, please set JAVA_HOME."
# readlink(1) is not available as standard on Solaris 10.
readLink=`which readlink`
[ `expr "$readLink" : '\([^ ]*\)'` = "no" ] && die "JAVA_HOME not set and readlink not available, please set JAVA_HOME."
javaExecutable="`readlink -f \"$javaExecutable\"`"
javaHome="`dirname \"$javaExecutable\"`"
javaHome=`expr "$javaHome" : '\(.*\)/bin'`
export JAVA_HOME="$javaHome"
fi
fi
# For Cygwin, ensure paths are in UNIX format before anything is touched. # For Cygwin, ensure paths are in UNIX format before anything is touched.
if $cygwin ; then if $cygwin ; then
[ -n "$JAVACMD" ] && JAVACMD=`cygpath --unix "$JAVACMD"`
[ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
fi fi
STARTER_MAIN_CLASS=org.gradle.wrapper.GradleWrapperMain # Attempt to set APP_HOME
CLASSPATH=`dirname "$0"`/gradle/wrapper/gradle-wrapper.jar # Resolve links: $0 may be a link
WRAPPER_PROPERTIES=`dirname "$0"`/gradle/wrapper/gradle-wrapper.properties PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >&-
APP_HOME="`pwd -P`"
cd "$SAVED" >&-
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM. # Determine the Java command to use to start the JVM.
if [ -z "$JAVACMD" ] ; then
if [ -n "$JAVA_HOME" ] ; then if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables # IBM's JDK on AIX uses strange locations for the executables
@ -78,18 +75,18 @@ if [ -z "$JAVACMD" ] ; then
else else
JAVACMD="$JAVA_HOME/bin/java" JAVACMD="$JAVA_HOME/bin/java"
fi fi
else
JAVACMD="java"
fi
fi
if [ ! -x "$JAVACMD" ] ; then if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the Please set the JAVA_HOME variable in your environment to match the
location of your Java installation." location of your Java installation."
fi fi
if [ -z "$JAVA_HOME" ] ; then else
warn "JAVA_HOME environment variable is not set" JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi fi
# Increase the maximum file descriptors if we can. # Increase the maximum file descriptors if we can.
@ -104,19 +101,18 @@ if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD" warn "Could not set maximum file descriptor limit: $MAX_FD"
fi fi
else else
warn "Could not query businessSystem maximum file descriptor limit: $MAX_FD_LIMIT" warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi fi
fi fi
# For Darwin, add GRADLE_APP_NAME to the JAVA_OPTS as -Xdock:name # For Darwin, add options to specify how the application appears in the dock
if $darwin; then if $darwin; then
JAVA_OPTS="$JAVA_OPTS -Xdock:name=$GRADLE_APP_NAME" GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
# we may also want to set -Xdock:image
fi fi
# For Cygwin, switch paths to Windows format before running java # For Cygwin, switch paths to Windows format before running java
if $cygwin ; then if $cygwin ; then
JAVA_HOME=`cygpath --path --mixed "$JAVA_HOME"` APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
# We build the pattern for arguments to be converted via cygpath # We build the pattern for arguments to be converted via cygpath
@ -158,11 +154,11 @@ if $cygwin ; then
esac esac
fi fi
GRADLE_APP_BASE_NAME=`basename "$0"` # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
function splitJvmOpts() {
JVM_OPTS=("$@")
}
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
exec "$JAVACMD" $JAVA_OPTS $GRADLE_OPTS \ exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
-classpath "$CLASSPATH" \
-Dorg.gradle.appname="$GRADLE_APP_BASE_NAME" \
-Dorg.gradle.wrapper.properties="$WRAPPER_PROPERTIES" \
$STARTER_MAIN_CLASS \
"$@"

52
gradlew.bat vendored
View File

@ -1,24 +1,37 @@
@if "%DEBUG%" == "" @echo off @if "%DEBUG%" == "" @echo off
@rem ########################################################################## @rem ##########################################################################
@rem ## @rem
@rem Gradle startup script for Windows ## @rem Gradle startup script for Windows
@rem ## @rem
@rem ########################################################################## @rem ##########################################################################
@rem Set local scope for the variables with windows NT shell @rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal if "%OS%"=="Windows_NT" setlocal
@rem Uncomment those lines to set JVM options. GRADLE_OPTS and JAVA_OPTS can be used together. @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
@rem set GRADLE_OPTS=%GRADLE_OPTS% -Xmx512m set DEFAULT_JVM_OPTS=
@rem set JAVA_OPTS=%JAVA_OPTS% -Xmx512m
set DIRNAME=%~dp0 set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.\ if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Find java.exe @rem Find java.exe
set JAVA_EXE=java.exe if defined JAVA_HOME goto findJavaFromJavaHome
if not defined JAVA_HOME goto init
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=% set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe set JAVA_EXE=%JAVA_HOME%/bin/java.exe
@ -29,14 +42,14 @@ echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo. echo.
echo Please set the JAVA_HOME variable in your environment to match the echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation. echo location of your Java installation.
echo.
goto end goto fail
:init :init
@rem Get command-line arguments, handling Windowz variants @rem Get command-line arguments, handling Windowz variants
if not "%OS%" == "Windows_NT" goto win9xME_args if not "%OS%" == "Windows_NT" goto win9xME_args
if "%eval[2+2]" == "4" goto 4NT_args if "%@eval[2+2]" == "4" goto 4NT_args
:win9xME_args :win9xME_args
@rem Slurp the command line arguments. @rem Slurp the command line arguments.
@ -56,25 +69,20 @@ set CMD_LINE_ARGS=%$
:execute :execute
@rem Setup the command line @rem Setup the command line
set STARTER_MAIN_CLASS=org.gradle.wrapper.GradleWrapperMain set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
set CLASSPATH=%DIRNAME%\gradle\wrapper\gradle-wrapper.jar
set WRAPPER_PROPERTIES=%DIRNAME%\gradle\wrapper\gradle-wrapper.properties
set GRADLE_OPTS=%JAVA_OPTS% %GRADLE_OPTS% -Dorg.gradle.wrapper.properties="%WRAPPER_PROPERTIES%"
@rem Execute Gradle @rem Execute Gradle
"%JAVA_EXE%" %GRADLE_OPTS% -classpath "%CLASSPATH%" %STARTER_MAIN_CLASS% %CMD_LINE_ARGS% "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
:end :end
@rem End local scope for the variables with windows NT shell @rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd if "%ERRORLEVEL%"=="0" goto mainEnd
if not "%OS%"=="Windows_NT" echo 1 > nul | choice /n /c:1 :fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code! rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit "%ERRORLEVEL%" if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b "%ERRORLEVEL%" exit /b 1
:mainEnd :mainEnd
if "%OS%"=="Windows_NT" endlocal if "%OS%"=="Windows_NT" endlocal

View File

@ -135,8 +135,13 @@ task jaxb {
} }
} }
generateMainLoggingClasses.dependsOn jaxb generateMainLoggingClasses.dependsOn jaxb
generateMainLoggingClasses.dependsOn generateGrammarSource generateMainLoggingClasses.dependsOn generateGrammarSource
generateSources.dependsOn jaxb
generateSources.dependsOn generateGrammarSource
compileJava.dependsOn jaxb compileJava.dependsOn jaxb

View File

@ -143,7 +143,7 @@ public class HSQLDialect extends Dialect {
registerFunction( "reverse", new StandardSQLFunction( "reverse" ) ); registerFunction( "reverse", new StandardSQLFunction( "reverse" ) );
registerFunction( "space", new StandardSQLFunction( "space", StandardBasicTypes.STRING ) ); registerFunction( "space", new StandardSQLFunction( "space", StandardBasicTypes.STRING ) );
registerFunction( "str", new SQLFunctionTemplate( StandardBasicTypes.STRING, "cast(?1 as varchar(256))" ) ); registerFunction( "str", new SQLFunctionTemplate( StandardBasicTypes.STRING, "cast(?1 as varchar(256))" ) );
registerFunction( "to_char", new StandardSQLFunction( "to_char" ) ); registerFunction( "to_char", new StandardSQLFunction( "to_char", StandardBasicTypes.STRING ) );
registerFunction( "rawtohex", new StandardSQLFunction( "rawtohex" ) ); registerFunction( "rawtohex", new StandardSQLFunction( "rawtohex" ) );
registerFunction( "hextoraw", new StandardSQLFunction( "hextoraw" ) ); registerFunction( "hextoraw", new StandardSQLFunction( "hextoraw" ) );

View File

@ -34,6 +34,8 @@ import org.hibernate.internal.util.StringHelper;
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public class DDLFormatterImpl implements Formatter { public class DDLFormatterImpl implements Formatter {
public static final DDLFormatterImpl INSTANCE = new DDLFormatterImpl();
/** /**
* Format an SQL statement using simple rules<ul> * Format an SQL statement using simple rules<ul>
* <li>Insert newline after each comma</li> * <li>Insert newline after each comma</li>

View File

@ -1659,4 +1659,8 @@ public interface CoreMessageLogger extends BasicLogger {
"@Access has to be placed on the field with an access type of AccessType.FIELD. " + "@Access has to be placed on the field with an access type of AccessType.FIELD. " +
"Using AccessType.PROPERTY on the field has no effect", id = 457) "Using AccessType.PROPERTY on the field has no effect", id = 457)
String accessTypeOverrideShouldBeField( String className ); String accessTypeOverrideShouldBeField( String className );
@LogMessage(level = WARN)
@Message(value = "Exception while loading a class or resource found during scanning", id = 458)
void unableToLoadScannedClassOrResource(@Cause Exception e);
} }

View File

@ -78,7 +78,7 @@ public interface ParameterRegistration<T> {
* *
* @return The parameter binding * @return The parameter binding
*/ */
public ParameterBind getParameterBind(); public ParameterBind<T> getBind();
/** /**
* Bind a value to the parameter. How this value is bound to the underlying JDBC CallableStatement is * Bind a value to the parameter. How this value is bound to the underlying JDBC CallableStatement is

View File

@ -128,7 +128,7 @@ public abstract class AbstractParameterRegistrationImpl<T> implements ParameterR
} }
@Override @Override
public ParameterBind getParameterBind() { public ParameterBind<T> getBind() {
return bind; return bind;
} }

View File

@ -23,6 +23,13 @@
*/ */
package org.hibernate.test.annotations.entity; package org.hibernate.test.annotations.entity;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.Currency; import java.util.Currency;
import java.util.Date; import java.util.Date;
@ -30,8 +37,6 @@ import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.Set; import java.util.Set;
import org.junit.Test;
import org.hibernate.AnnotationException; import org.hibernate.AnnotationException;
import org.hibernate.Hibernate; import org.hibernate.Hibernate;
import org.hibernate.HibernateException; import org.hibernate.HibernateException;
@ -45,13 +50,7 @@ import org.hibernate.testing.FailureExpectedWithNewMetamodel;
import org.hibernate.testing.RequiresDialectFeature; import org.hibernate.testing.RequiresDialectFeature;
import org.hibernate.testing.ServiceRegistryBuilder; import org.hibernate.testing.ServiceRegistryBuilder;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
/** /**
* @author Emmanuel Bernard * @author Emmanuel Bernard

View File

@ -52,7 +52,7 @@ sourceSets.test {
ext.generatedJpaMetamodelSrcDir = file( "${buildDir}/generated-src/jpamodelgen/${name}" ) ext.generatedJpaMetamodelSrcDir = file( "${buildDir}/generated-src/jpamodelgen/${name}" )
java.srcDir generatedJpaMetamodelSrcDir java.srcDir generatedJpaMetamodelSrcDir
} }
task generateTestJpaMetamodelClasses(type: Compile) { task generateTestJpaMetamodelClasses(type: JavaCompile) {
ext.aptDumpDir = file( "${buildDir}/tmp/apt/jpamodelgen" ) ext.aptDumpDir = file( "${buildDir}/tmp/apt/jpamodelgen" )
classpath = compileTestJava.classpath + configurations.hibernateJpaModelGenTool classpath = compileTestJava.classpath + configurations.hibernateJpaModelGenTool
source = sourceSets.test.originalJavaSrcDirs source = sourceSets.test.originalJavaSrcDirs
@ -77,6 +77,8 @@ generateTestJpaMetamodelClasses.logging.captureStandardError(LogLevel.INFO)
compileTestJava.dependsOn generateTestJpaMetamodelClasses compileTestJava.dependsOn generateTestJpaMetamodelClasses
compileTestJava.options.define(compilerArgs: ["-proc:none"]) compileTestJava.options.define(compilerArgs: ["-proc:none"])
generateSources.dependsOn generateTestJpaMetamodelClasses
//////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////
// Process 'bundle resources' for the packaging tests // Process 'bundle resources' for the packaging tests

View File

@ -68,7 +68,7 @@ public enum SchemaGenAction {
* @throws IllegalArgumentException If the incoming value is unrecognized * @throws IllegalArgumentException If the incoming value is unrecognized
*/ */
public static SchemaGenAction interpret(String value) { public static SchemaGenAction interpret(String value) {
if ( StringHelper.isEmpty( value ) ) { if ( StringHelper.isEmpty( value ) || NONE.externalName.equals( value ) ) {
// default is NONE // default is NONE
return NONE; return NONE;
} }

View File

@ -108,7 +108,6 @@ import org.hibernate.jpa.boot.scan.spi.ScanOptions;
import org.hibernate.jpa.boot.scan.spi.ScanResult; import org.hibernate.jpa.boot.scan.spi.ScanResult;
import org.hibernate.jpa.boot.scan.spi.Scanner; import org.hibernate.jpa.boot.scan.spi.Scanner;
import org.hibernate.jpa.spi.IdentifierGeneratorStrategyProvider; import org.hibernate.jpa.spi.IdentifierGeneratorStrategyProvider;
import org.hibernate.metamodel.Metadata;
import org.hibernate.metamodel.MetadataBuilder; import org.hibernate.metamodel.MetadataBuilder;
import org.hibernate.metamodel.SessionFactoryBuilder; import org.hibernate.metamodel.SessionFactoryBuilder;
import org.hibernate.metamodel.internal.source.annotations.util.JPADotNames; import org.hibernate.metamodel.internal.source.annotations.util.JPADotNames;
@ -995,7 +994,7 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil
@Override @Override
public EntityManagerFactoryImpl perform() { public EntityManagerFactoryImpl perform() {
hibernateConfiguration = buildHibernateConfiguration( serviceRegistry ); hibernateConfiguration = buildHibernateConfiguration( serviceRegistry );
JpaSchemaGenerator.performGeneration( hibernateConfiguration, serviceRegistry );
SessionFactoryImplementor sessionFactory; SessionFactoryImplementor sessionFactory;
try { try {
sessionFactory = (SessionFactoryImplementor) hibernateConfiguration.buildSessionFactory( sessionFactory = (SessionFactoryImplementor) hibernateConfiguration.buildSessionFactory(
@ -1093,13 +1092,21 @@ public class EntityManagerFactoryBuilderImpl implements EntityManagerFactoryBuil
private void applyJdbcConnectionProperties() { private void applyJdbcConnectionProperties() {
if ( dataSource != null ) { if ( dataSource != null ) {
serviceRegistryBuilder.applySetting( Environment.DATASOURCE, dataSource ); serviceRegistryBuilder.applySetting( org.hibernate.cfg.AvailableSettings.DATASOURCE, dataSource );
} }
else if ( persistenceUnit.getJtaDataSource() != null ) { else if ( persistenceUnit.getJtaDataSource() != null ) {
serviceRegistryBuilder.applySetting( Environment.DATASOURCE, persistenceUnit.getJtaDataSource() ); if ( ! serviceRegistryBuilder.getSettings().containsKey( org.hibernate.cfg.AvailableSettings.DATASOURCE ) ) {
serviceRegistryBuilder.applySetting( org.hibernate.cfg.AvailableSettings.DATASOURCE, persistenceUnit.getJtaDataSource() );
// HHH-8121 : make the PU-defined value available to EMF.getProperties()
configurationValues.put( AvailableSettings.JTA_DATASOURCE, persistenceUnit.getJtaDataSource() );
}
} }
else if ( persistenceUnit.getNonJtaDataSource() != null ) { else if ( persistenceUnit.getNonJtaDataSource() != null ) {
serviceRegistryBuilder.applySetting( Environment.DATASOURCE, persistenceUnit.getNonJtaDataSource() ); if ( ! serviceRegistryBuilder.getSettings().containsKey( org.hibernate.cfg.AvailableSettings.DATASOURCE ) ) {
serviceRegistryBuilder.applySetting( org.hibernate.cfg.AvailableSettings.DATASOURCE, persistenceUnit.getNonJtaDataSource() );
// HHH-8121 : make the PU-defined value available to EMF.getProperties()
configurationValues.put( AvailableSettings.NON_JTA_DATASOURCE, persistenceUnit.getNonJtaDataSource() );
}
} }
else { else {
final String driver = (String) configurationValues.get( AvailableSettings.JDBC_DRIVER ); final String driver = (String) configurationValues.get( AvailableSettings.JDBC_DRIVER );

View File

@ -427,6 +427,7 @@ public class CriteriaQueryImpl<T> extends AbstractNode implements CriteriaQuery<
} }
return new CriteriaQueryTypeQueryAdapter( return new CriteriaQueryTypeQueryAdapter(
entityManager,
jpaqlQuery, jpaqlQuery,
parameterMetadata.explicitParameterMapping(), parameterMetadata.explicitParameterMapping(),
parameterMetadata.explicitParameterNameMapping() parameterMetadata.explicitParameterNameMapping()

View File

@ -38,19 +38,23 @@ import java.util.Set;
import org.hibernate.Query; import org.hibernate.Query;
import org.hibernate.ejb.HibernateQuery; import org.hibernate.ejb.HibernateQuery;
import org.hibernate.jpa.internal.QueryImpl; import org.hibernate.jpa.internal.QueryImpl;
import org.hibernate.jpa.spi.HibernateEntityManagerImplementor;
/** /**
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public class CriteriaQueryTypeQueryAdapter<X> implements TypedQuery<X>, HibernateQuery { public class CriteriaQueryTypeQueryAdapter<X> implements TypedQuery<X>, HibernateQuery {
private final HibernateEntityManagerImplementor entityManager;
private final QueryImpl<X> jpaqlQuery; private final QueryImpl<X> jpaqlQuery;
private final Map<ParameterExpression<?>, String> explicitParameterMapping; private final Map<ParameterExpression<?>, String> explicitParameterMapping;
private final Map<String, ParameterExpression<?>> explicitParameterNameMapping; private final Map<String, ParameterExpression<?>> explicitParameterNameMapping;
public CriteriaQueryTypeQueryAdapter( public CriteriaQueryTypeQueryAdapter(
HibernateEntityManagerImplementor entityManager,
QueryImpl<X> jpaqlQuery, QueryImpl<X> jpaqlQuery,
Map<ParameterExpression<?>, String> explicitParameterMapping, Map<ParameterExpression<?>, String> explicitParameterMapping,
Map<String, ParameterExpression<?>> explicitParameterNameMapping) { Map<String, ParameterExpression<?>> explicitParameterNameMapping) {
this.entityManager = entityManager;
this.jpaqlQuery = jpaqlQuery; this.jpaqlQuery = jpaqlQuery;
this.explicitParameterMapping = explicitParameterMapping; this.explicitParameterMapping = explicitParameterMapping;
this.explicitParameterNameMapping = explicitParameterNameMapping; this.explicitParameterNameMapping = explicitParameterNameMapping;
@ -116,20 +120,24 @@ public class CriteriaQueryTypeQueryAdapter<X> implements TypedQuery<X>, Hibernat
@SuppressWarnings({ "unchecked" }) @SuppressWarnings({ "unchecked" })
public Set getParameters() { public Set getParameters() {
entityManager.checkOpen( false );
return explicitParameterMapping.keySet(); return explicitParameterMapping.keySet();
} }
public boolean isBound(Parameter<?> param) { public boolean isBound(Parameter<?> param) {
entityManager.checkOpen( false );
return jpaqlQuery.isBound( param ); return jpaqlQuery.isBound( param );
} }
@SuppressWarnings({ "unchecked" }) @SuppressWarnings({ "unchecked" })
public <T> T getParameterValue(Parameter<T> param) { public <T> T getParameterValue(Parameter<T> param) {
entityManager.checkOpen( false );
return ( T ) jpaqlQuery.getParameterValue( mapToNamedParameter( param ) ); return ( T ) jpaqlQuery.getParameterValue( mapToNamedParameter( param ) );
} }
@SuppressWarnings({ "unchecked" }) @SuppressWarnings({ "unchecked" })
public <T> TypedQuery<X> setParameter(Parameter<T> param, T t) { public <T> TypedQuery<X> setParameter(Parameter<T> param, T t) {
entityManager.checkOpen( false );
jpaqlQuery.setParameter( mapToNamedParameter( param ), t ); jpaqlQuery.setParameter( mapToNamedParameter( param ), t );
return this; return this;
} }
@ -143,12 +151,14 @@ public class CriteriaQueryTypeQueryAdapter<X> implements TypedQuery<X>, Hibernat
@SuppressWarnings({ "unchecked" }) @SuppressWarnings({ "unchecked" })
public TypedQuery<X> setParameter(Parameter<Calendar> param, Calendar calendar, TemporalType temporalType) { public TypedQuery<X> setParameter(Parameter<Calendar> param, Calendar calendar, TemporalType temporalType) {
entityManager.checkOpen( false );
jpaqlQuery.setParameter( mapToNamedParameter( param ), calendar, temporalType ); jpaqlQuery.setParameter( mapToNamedParameter( param ), calendar, temporalType );
return this; return this;
} }
@SuppressWarnings({ "unchecked" }) @SuppressWarnings({ "unchecked" })
public TypedQuery<X> setParameter(Parameter<Date> param, Date date, TemporalType temporalType) { public TypedQuery<X> setParameter(Parameter<Date> param, Date date, TemporalType temporalType) {
entityManager.checkOpen( false );
jpaqlQuery.setParameter( mapToNamedParameter( param ), date, temporalType ); jpaqlQuery.setParameter( mapToNamedParameter( param ), date, temporalType );
return this; return this;
} }
@ -159,6 +169,7 @@ public class CriteriaQueryTypeQueryAdapter<X> implements TypedQuery<X>, Hibernat
@SuppressWarnings({ "unchecked" }) @SuppressWarnings({ "unchecked" })
public Object getParameterValue(String name) { public Object getParameterValue(String name) {
entityManager.checkOpen( false );
return getParameterValue( resolveExplicitCriteriaParameterName( name ) ); return getParameterValue( resolveExplicitCriteriaParameterName( name ) );
} }
@ -171,11 +182,13 @@ public class CriteriaQueryTypeQueryAdapter<X> implements TypedQuery<X>, Hibernat
} }
public Parameter<?> getParameter(String name) { public Parameter<?> getParameter(String name) {
entityManager.checkOpen( false );
return mapToNamedParameter( resolveExplicitCriteriaParameterName( name ) ); return mapToNamedParameter( resolveExplicitCriteriaParameterName( name ) );
} }
@SuppressWarnings({ "unchecked" }) @SuppressWarnings({ "unchecked" })
public <T> Parameter<T> getParameter(String name, Class<T> type) { public <T> Parameter<T> getParameter(String name, Class<T> type) {
entityManager.checkOpen( false );
Parameter parameter = resolveExplicitCriteriaParameterName( name ); Parameter parameter = resolveExplicitCriteriaParameterName( name );
if ( type.isAssignableFrom( parameter.getParameterType() ) ) { if ( type.isAssignableFrom( parameter.getParameterType() ) ) {
return parameter; return parameter;
@ -188,6 +201,7 @@ public class CriteriaQueryTypeQueryAdapter<X> implements TypedQuery<X>, Hibernat
@SuppressWarnings({ "unchecked" }) @SuppressWarnings({ "unchecked" })
public TypedQuery<X> setParameter(String name, Object value) { public TypedQuery<X> setParameter(String name, Object value) {
entityManager.checkOpen( true );
setParameter( setParameter(
resolveExplicitCriteriaParameterName( name, value ), resolveExplicitCriteriaParameterName( name, value ),
value value
@ -212,6 +226,7 @@ public class CriteriaQueryTypeQueryAdapter<X> implements TypedQuery<X>, Hibernat
@SuppressWarnings({ "unchecked" }) @SuppressWarnings({ "unchecked" })
public TypedQuery<X> setParameter(String name, Calendar calendar, TemporalType temporalType) { public TypedQuery<X> setParameter(String name, Calendar calendar, TemporalType temporalType) {
entityManager.checkOpen( true );
Parameter parameter = resolveExplicitCriteriaParameterName( name ); Parameter parameter = resolveExplicitCriteriaParameterName( name );
if ( ! Calendar.class.isAssignableFrom( parameter.getParameterType() ) ) { if ( ! Calendar.class.isAssignableFrom( parameter.getParameterType() ) ) {
throw new IllegalArgumentException( throw new IllegalArgumentException(
@ -226,6 +241,7 @@ public class CriteriaQueryTypeQueryAdapter<X> implements TypedQuery<X>, Hibernat
@SuppressWarnings({ "unchecked" }) @SuppressWarnings({ "unchecked" })
public TypedQuery<X> setParameter(String name, Date date, TemporalType temporalType) { public TypedQuery<X> setParameter(String name, Date date, TemporalType temporalType) {
entityManager.checkOpen( true );
Parameter parameter = resolveExplicitCriteriaParameterName( name ); Parameter parameter = resolveExplicitCriteriaParameterName( name );
if ( ! Date.class.isAssignableFrom( parameter.getParameterType() ) ) { if ( ! Date.class.isAssignableFrom( parameter.getParameterType() ) ) {
throw new IllegalArgumentException( throw new IllegalArgumentException(

View File

@ -27,7 +27,6 @@ import javax.persistence.EntityGraph;
import javax.persistence.PersistenceContextType; import javax.persistence.PersistenceContextType;
import javax.persistence.PersistenceException; import javax.persistence.PersistenceException;
import javax.persistence.SynchronizationType; import javax.persistence.SynchronizationType;
import javax.persistence.metamodel.EntityType;
import javax.persistence.spi.PersistenceUnitTransactionType; import javax.persistence.spi.PersistenceUnitTransactionType;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -97,17 +96,35 @@ public class EntityManagerImpl extends AbstractEntityManagerImpl implements Sess
} }
@Override @Override
public Session getSession() { protected void checkOpen() {
if ( !open ) { checkOpen( true );
}
@Override
public void checkOpen(boolean markForRollbackIfClosed) {
if( ! isOpen() ) {
if ( markForRollbackIfClosed ) {
markAsRollback();
}
throw new IllegalStateException( "EntityManager is closed" ); throw new IllegalStateException( "EntityManager is closed" );
} }
return getRawSession(); }
@Override
public Session getSession() {
checkOpen();
return internalGetSession();
} }
@Override @Override
protected Session getRawSession() { protected Session getRawSession() {
return internalGetSession();
}
@Override
protected Session internalGetSession() {
if ( session == null ) { if ( session == null ) {
SessionBuilderImplementor sessionBuilder = getEntityManagerFactory().getSessionFactory().withOptions(); SessionBuilderImplementor sessionBuilder = internalGetEntityManagerFactory().getSessionFactory().withOptions();
sessionBuilder.owner( this ); sessionBuilder.owner( this );
if (sessionInterceptorClass != null) { if (sessionInterceptorClass != null) {
try { try {
@ -135,9 +152,8 @@ public class EntityManagerImpl extends AbstractEntityManagerImpl implements Sess
public void close() { public void close() {
checkEntityManagerFactory(); checkEntityManagerFactory();
if ( !open ) { checkOpen();
throw new IllegalStateException( "EntityManager is closed" );
}
if ( discardOnClose || !isTransactionInProgress() ) { if ( discardOnClose || !isTransactionInProgress() ) {
//close right now //close right now
if ( session != null ) { if ( session != null ) {
@ -153,7 +169,7 @@ public class EntityManagerImpl extends AbstractEntityManagerImpl implements Sess
checkEntityManagerFactory(); checkEntityManagerFactory();
try { try {
if ( open ) { if ( open ) {
getSession().isOpen(); //to force enlistment in tx internalGetSession().isOpen(); //to force enlistment in tx
} }
return open; return open;
} }
@ -165,11 +181,13 @@ public class EntityManagerImpl extends AbstractEntityManagerImpl implements Sess
@Override @Override
public <T> EntityGraph<T> createEntityGraph(Class<T> rootType) { public <T> EntityGraph<T> createEntityGraph(Class<T> rootType) {
checkOpen();
return new EntityGraphImpl<T>( null, getMetamodel().entity( rootType ), getEntityManagerFactory() ); return new EntityGraphImpl<T>( null, getMetamodel().entity( rootType ), getEntityManagerFactory() );
} }
@Override @Override
public EntityGraph<?> createEntityGraph(String graphName) { public EntityGraph<?> createEntityGraph(String graphName) {
checkOpen();
final EntityGraphImpl named = getEntityManagerFactory().findEntityGraphByName( graphName ); final EntityGraphImpl named = getEntityManagerFactory().findEntityGraphByName( graphName );
if ( named == null ) { if ( named == null ) {
return null; return null;
@ -180,6 +198,7 @@ public class EntityManagerImpl extends AbstractEntityManagerImpl implements Sess
@Override @Override
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public <T> EntityGraph<T> getEntityGraph(String graphName) { public <T> EntityGraph<T> getEntityGraph(String graphName) {
checkOpen();
final EntityGraphImpl named = getEntityManagerFactory().findEntityGraphByName( graphName ); final EntityGraphImpl named = getEntityManagerFactory().findEntityGraphByName( graphName );
if ( named == null ) { if ( named == null ) {
throw new IllegalArgumentException( "Could not locate EntityGraph with given name : " + graphName ); throw new IllegalArgumentException( "Could not locate EntityGraph with given name : " + graphName );
@ -189,6 +208,7 @@ public class EntityManagerImpl extends AbstractEntityManagerImpl implements Sess
@Override @Override
public <T> List<EntityGraph<? super T>> getEntityGraphs(Class<T> entityClass) { public <T> List<EntityGraph<? super T>> getEntityGraphs(Class<T> entityClass) {
checkOpen();
return getEntityManagerFactory().findEntityGraphsByType( entityClass ); return getEntityManagerFactory().findEntityGraphsByType( entityClass );
} }
@ -198,7 +218,7 @@ public class EntityManagerImpl extends AbstractEntityManagerImpl implements Sess
} }
private void checkEntityManagerFactory() { private void checkEntityManagerFactory() {
if (! getEntityManagerFactory().isOpen()) { if ( ! internalGetEntityManagerFactory().isOpen() ) {
open = false; open = false;
} }
} }

View File

@ -25,11 +25,10 @@ package org.hibernate.jpa.internal;
import javax.persistence.NoResultException; import javax.persistence.NoResultException;
import javax.persistence.NonUniqueResultException; import javax.persistence.NonUniqueResultException;
import javax.persistence.Parameter; import javax.persistence.ParameterMode;
import javax.persistence.PersistenceException; import javax.persistence.PersistenceException;
import javax.persistence.Query; import javax.persistence.Query;
import javax.persistence.TemporalType; import javax.persistence.TemporalType;
import javax.persistence.TransactionRequiredException;
import javax.persistence.TypedQuery; import javax.persistence.TypedQuery;
import java.util.Calendar; import java.util.Calendar;
import java.util.Collection; import java.util.Collection;
@ -46,11 +45,10 @@ import org.hibernate.CacheMode;
import org.hibernate.FlushMode; import org.hibernate.FlushMode;
import org.hibernate.HibernateException; import org.hibernate.HibernateException;
import org.hibernate.LockMode; import org.hibernate.LockMode;
import org.hibernate.QueryParameterException;
import org.hibernate.SQLQuery;
import org.hibernate.TypeMismatchException; import org.hibernate.TypeMismatchException;
import org.hibernate.engine.query.spi.NamedParameterDescriptor; import org.hibernate.engine.query.spi.NamedParameterDescriptor;
import org.hibernate.engine.query.spi.OrdinalParameterDescriptor; import org.hibernate.engine.query.spi.OrdinalParameterDescriptor;
import org.hibernate.engine.query.spi.ParameterMetadata;
import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.hql.internal.QueryExecutionRequestException; import org.hibernate.hql.internal.QueryExecutionRequestException;
import org.hibernate.internal.SQLQueryImpl; import org.hibernate.internal.SQLQueryImpl;
@ -78,7 +76,6 @@ public class QueryImpl<X> extends AbstractQueryImpl<X> implements TypedQuery<X>,
private org.hibernate.Query query; private org.hibernate.Query query;
private Set<Integer> jpaPositionalIndices; private Set<Integer> jpaPositionalIndices;
private Set<Parameter<?>> parameters;
public QueryImpl(org.hibernate.Query query, AbstractEntityManagerImpl em) { public QueryImpl(org.hibernate.Query query, AbstractEntityManagerImpl em) {
this( query, em, Collections.<String, Class>emptyMap() ); this( query, em, Collections.<String, Class>emptyMap() );
@ -99,13 +96,11 @@ public class QueryImpl<X> extends AbstractQueryImpl<X> implements TypedQuery<X>,
throw new IllegalStateException( "Unknown query type for parameter extraction" ); throw new IllegalStateException( "Unknown query type for parameter extraction" );
} }
HashSet<Parameter<?>> parameters = new HashSet<Parameter<?>>(); final ParameterMetadata parameterMetadata = org.hibernate.internal.AbstractQueryImpl.class.cast( query ).getParameterMetadata();
org.hibernate.internal.AbstractQueryImpl queryImpl = org.hibernate.internal.AbstractQueryImpl.class.cast( query );
// extract named params // extract named params
for ( String name : (Set<String>) queryImpl.getParameterMetadata().getNamedParameterNames() ) { for ( String name : (Set<String>) parameterMetadata.getNamedParameterNames() ) {
final NamedParameterDescriptor descriptor = final NamedParameterDescriptor descriptor = parameterMetadata.getNamedParameterDescriptor( name );
queryImpl.getParameterMetadata().getNamedParameterDescriptor( name );
Class javaType = namedParameterTypeRedefinition.get( name ); Class javaType = namedParameterTypeRedefinition.get( name );
if ( javaType != null && mightNeedRedefinition( javaType ) ) { if ( javaType != null && mightNeedRedefinition( javaType ) ) {
descriptor.resetExpectedType( descriptor.resetExpectedType(
@ -115,8 +110,7 @@ public class QueryImpl<X> extends AbstractQueryImpl<X> implements TypedQuery<X>,
else if ( descriptor.getExpectedType() != null ) { else if ( descriptor.getExpectedType() != null ) {
javaType = descriptor.getExpectedType().getReturnedClass(); javaType = descriptor.getExpectedType().getReturnedClass();
} }
final ParameterImpl parameter = new ParameterImpl( name, javaType ); registerParameter( new ParameterRegistrationImpl( query, name, javaType ) );
parameters.add( parameter );
if ( descriptor.isJpaStyle() ) { if ( descriptor.isJpaStyle() ) {
if ( jpaPositionalIndices == null ) { if ( jpaPositionalIndices == null ) {
jpaPositionalIndices = new HashSet<Integer>(); jpaPositionalIndices = new HashSet<Integer>();
@ -126,21 +120,15 @@ public class QueryImpl<X> extends AbstractQueryImpl<X> implements TypedQuery<X>,
} }
// extract positional parameters // extract positional parameters
for ( int i = 0, max = queryImpl.getParameterMetadata().getOrdinalParameterCount(); i < max; i++ ) { for ( int i = 0, max = parameterMetadata.getOrdinalParameterCount(); i < max; i++ ) {
final OrdinalParameterDescriptor descriptor = final OrdinalParameterDescriptor descriptor = parameterMetadata.getOrdinalParameterDescriptor( i + 1 );
queryImpl.getParameterMetadata().getOrdinalParameterDescriptor( i+1 ); Class javaType = descriptor.getExpectedType() == null ? null : descriptor.getExpectedType().getReturnedClass();
ParameterImpl parameter = new ParameterImpl( registerParameter( new ParameterRegistrationImpl( query, i+1, javaType ) );
i + 1,
descriptor.getExpectedType() == null
? null
: descriptor.getExpectedType().getReturnedClass()
);
parameters.add( parameter );
Integer position = descriptor.getOrdinalPosition(); Integer position = descriptor.getOrdinalPosition();
if (jpaPositionalIndices != null && jpaPositionalIndices.contains(position)) LOG.parameterPositionOccurredAsBothJpaAndHibernatePositionalParameter(position); if ( jpaPositionalIndices != null && jpaPositionalIndices.contains(position) ) {
LOG.parameterPositionOccurredAsBothJpaAndHibernatePositionalParameter(position);
}
} }
this.parameters = java.util.Collections.unmodifiableSet( parameters );
} }
private SessionFactoryImplementor sfi() { private SessionFactoryImplementor sfi() {
@ -152,34 +140,142 @@ public class QueryImpl<X> extends AbstractQueryImpl<X> implements TypedQuery<X>,
return java.util.Date.class.isAssignableFrom( javaType ); return java.util.Date.class.isAssignableFrom( javaType );
} }
private static class ParameterImpl implements Parameter {
private static class ParameterRegistrationImpl<T> implements ParameterRegistration<T> {
private final org.hibernate.Query query;
private final String name; private final String name;
private final Integer position; private final Integer position;
private final Class javaType; private final Class<T> javaType;
private ParameterImpl(String name, Class javaType) { private ParameterBind<T> bind;
private ParameterRegistrationImpl(org.hibernate.Query query, String name, Class<T> javaType) {
this.query = query;
this.name = name; this.name = name;
this.javaType = javaType; this.javaType = javaType;
this.position = null; this.position = null;
} }
private ParameterImpl(Integer position, Class javaType) { private ParameterRegistrationImpl(org.hibernate.Query query, Integer position, Class<T> javaType) {
this.query = query;
this.position = position; this.position = position;
this.javaType = javaType; this.javaType = javaType;
this.name = null; this.name = null;
} }
@Override
public String getName() { public String getName() {
return name; return name;
} }
@Override
public Integer getPosition() { public Integer getPosition() {
return position; return position;
} }
public Class getParameterType() { @Override
public Class<T> getParameterType() {
return javaType; return javaType;
} }
@Override
public ParameterMode getMode() {
// implicitly
return ParameterMode.IN;
}
@Override
public boolean isBindable() {
// again, implicitly
return true;
}
@Override
public void bindValue(T value) {
validateBinding( getParameterType(), value, null );
if ( name != null ) {
if ( value instanceof Collection ) {
query.setParameterList( name, (Collection) value );
}
else {
query.setParameter( name, value );
}
}
else {
query.setParameter( position-1, value );
}
bind = new ParameterBindImpl<T>( value, null );
}
@Override
public void bindValue(T value, TemporalType specifiedTemporalType) {
validateBinding( getParameterType(), value, specifiedTemporalType );
if ( Date.class.isInstance( value ) ) {
if ( name != null ) {
if ( specifiedTemporalType == DATE ) {
query.setDate( name, (Date) value );
}
else if ( specifiedTemporalType == TIME ) {
query.setTime( name, (Date) value );
}
else if ( specifiedTemporalType == TIMESTAMP ) {
query.setTimestamp( name, (Date) value );
}
}
else {
if ( specifiedTemporalType == DATE ) {
query.setDate( position-1, (Date) value );
}
else if ( specifiedTemporalType == TIME ) {
query.setTime( position-1, (Date) value );
}
else if ( specifiedTemporalType == TIMESTAMP ) {
query.setTimestamp( position-1, (Date) value );
}
}
}
else if ( Calendar.class.isInstance( value ) ) {
if ( name != null ) {
if ( specifiedTemporalType == DATE ) {
query.setCalendarDate( name, (Calendar) value );
}
else if ( specifiedTemporalType == TIME ) {
throw new IllegalArgumentException( "not yet implemented" );
}
else if ( specifiedTemporalType == TIMESTAMP ) {
query.setCalendar( name, (Calendar) value );
}
}
else {
if ( specifiedTemporalType == DATE ) {
query.setCalendarDate( position-1, (Calendar) value );
}
else if ( specifiedTemporalType == TIME ) {
throw new IllegalArgumentException( "not yet implemented" );
}
else if ( specifiedTemporalType == TIMESTAMP ) {
query.setCalendar( position-1, (Calendar) value );
}
}
}
else {
throw new IllegalArgumentException(
"Unexpected type [" + value + "] passed with TemporalType; expecting Date or Calendar"
);
}
bind = new ParameterBindImpl<T>( value, specifiedTemporalType );
}
@Override
public ParameterBind<T> getBind() {
return bind;
}
} }
public org.hibernate.Query getHibernateQuery() { public org.hibernate.Query getHibernateQuery() {
@ -202,61 +298,67 @@ public class QueryImpl<X> extends AbstractQueryImpl<X> implements TypedQuery<X>,
} }
@Override @Override
protected void applyTimeout(int timeout) { protected boolean applyTimeoutHint(int timeout) {
query.setTimeout( timeout ); query.setTimeout( timeout );
return true;
} }
@Override @Override
protected void applyComment(String comment) { protected boolean applyCommentHint(String comment) {
query.setComment( comment ); query.setComment( comment );
return true;
} }
@Override @Override
protected void applyFetchSize(int fetchSize) { protected boolean applyFetchSizeHint(int fetchSize) {
query.setFetchSize( fetchSize ); query.setFetchSize( fetchSize );
return true;
} }
@Override @Override
protected void applyCacheable(boolean isCacheable) { protected boolean applyCacheableHint(boolean isCacheable) {
query.setCacheable( isCacheable ); query.setCacheable( isCacheable );
return true;
} }
@Override @Override
protected void applyCacheRegion(String regionName) { protected boolean applyCacheRegionHint(String regionName) {
query.setCacheRegion( regionName ); query.setCacheRegion( regionName );
return true;
} }
@Override @Override
protected void applyReadOnly(boolean isReadOnly) { protected boolean applyReadOnlyHint(boolean isReadOnly) {
query.setReadOnly( isReadOnly ); query.setReadOnly( isReadOnly );
return true;
} }
@Override @Override
protected void applyCacheMode(CacheMode cacheMode) { protected boolean applyCacheModeHint(CacheMode cacheMode) {
query.setCacheMode( cacheMode ); query.setCacheMode( cacheMode );
return true;
} }
@Override @Override
protected void applyFlushMode(FlushMode flushMode) { protected boolean applyFlushModeHint(FlushMode flushMode) {
query.setFlushMode( flushMode ); query.setFlushMode( flushMode );
return true;
} }
@Override @Override
protected boolean canApplyLockModes() { protected boolean canApplyAliasSpecificLockModeHints() {
return org.hibernate.internal.QueryImpl.class.isInstance( query ) return org.hibernate.internal.QueryImpl.class.isInstance( query ) || SQLQueryImpl.class.isInstance( query );
|| SQLQueryImpl.class.isInstance( query );
} }
@Override @Override
protected void applyAliasSpecificLockMode(String alias, LockMode lockMode) { protected void applyAliasSpecificLockModeHint(String alias, LockMode lockMode) {
query.getLockOptions().setAliasSpecificLockMode( alias, lockMode ); query.getLockOptions().setAliasSpecificLockMode( alias, lockMode );
} }
/** @Override
* {@inheritDoc}
*/
@SuppressWarnings({ "unchecked", "RedundantCast" }) @SuppressWarnings({ "unchecked", "RedundantCast" })
public List<X> getResultList() { public List<X> getResultList() {
getEntityManager().checkOpen( true );
try { try {
return query.list(); return query.list();
} }
@ -271,11 +373,10 @@ public class QueryImpl<X> extends AbstractQueryImpl<X> implements TypedQuery<X>,
} }
} }
/** @Override
* {@inheritDoc}
*/
@SuppressWarnings({ "unchecked", "RedundantCast" }) @SuppressWarnings({ "unchecked", "RedundantCast" })
public X getSingleResult() { public X getSingleResult() {
getEntityManager().checkOpen( true );
try { try {
final List<X> result = query.list(); final List<X> result = query.list();
@ -310,284 +411,12 @@ public class QueryImpl<X> extends AbstractQueryImpl<X> implements TypedQuery<X>,
} }
} }
public <T> TypedQuery<X> setParameter(Parameter<T> param, T value) { @Override
if ( ! parameters.contains( param ) ) { protected boolean isJpaPositionalParameter(int position) {
throw new IllegalArgumentException( "Specified parameter was not found in query" );
}
if ( param.getName() != null ) {
// a named param, for not delegate out. Eventually delegate *into* this method...
setParameter( param.getName(), value );
}
else {
setParameter( param.getPosition(), value );
}
return this;
}
public TypedQuery<X> setParameter(Parameter<Date> param, Date value, TemporalType temporalType) {
if ( ! parameters.contains( param ) ) {
throw new IllegalArgumentException( "Specified parameter was not found in query" );
}
if ( param.getName() != null ) {
// a named param, for not delegate out. Eventually delegate *into* this method...
setParameter( param.getName(), value, temporalType );
}
else {
setParameter( param.getPosition(), value, temporalType );
}
return this;
}
public TypedQuery<X> setParameter(Parameter<Calendar> param, Calendar value, TemporalType temporalType) {
if ( ! parameters.contains( param ) ) {
throw new IllegalArgumentException( "Specified parameter was not found in query" );
}
if ( param.getName() != null ) {
// a named param, for not delegate out. Eventually delegate *into* this method...
setParameter( param.getName(), value, temporalType );
}
else {
setParameter( param.getPosition(), value, temporalType );
}
return this;
}
/**
* {@inheritDoc}
*/
public TypedQuery<X> setParameter(String name, Object value) {
try {
if ( value instanceof Collection ) {
query.setParameterList( name, (Collection) value );
}
else {
query.setParameter( name, value );
}
registerParameterBinding( getParameter( name ), value );
return this;
}
catch (QueryParameterException e) {
throw new IllegalArgumentException( e );
}
catch (HibernateException he) {
throw getEntityManager().convert( he );
}
}
/**
* {@inheritDoc}
*/
public TypedQuery<X> setParameter(String name, Date value, TemporalType temporalType) {
try {
if ( temporalType == DATE ) {
query.setDate( name, value );
}
else if ( temporalType == TIME ) {
query.setTime( name, value );
}
else if ( temporalType == TIMESTAMP ) {
query.setTimestamp( name, value );
}
registerParameterBinding( getParameter( name ), value );
return this;
}
catch (QueryParameterException e) {
throw new IllegalArgumentException( e );
}
catch (HibernateException he) {
throw getEntityManager().convert( he );
}
}
/**
* {@inheritDoc}
*/
public TypedQuery<X> setParameter(String name, Calendar value, TemporalType temporalType) {
try {
if ( temporalType == DATE ) {
query.setCalendarDate( name, value );
}
else if ( temporalType == TIME ) {
throw new IllegalArgumentException( "not yet implemented" );
}
else if ( temporalType == TIMESTAMP ) {
query.setCalendar( name, value );
}
registerParameterBinding( getParameter(name), value );
return this;
}
catch (QueryParameterException e) {
throw new IllegalArgumentException( e );
}
catch (HibernateException he) {
throw getEntityManager().convert( he );
}
}
/**
* {@inheritDoc}
*/
public TypedQuery<X> setParameter(int position, Object value) {
try {
if ( isJpaPositionalParameter( position ) ) {
this.setParameter( Integer.toString( position ), value );
}
else {
query.setParameter( position - 1, value );
registerParameterBinding( getParameter( position ), value );
}
return this;
}
catch (QueryParameterException e) {
throw new IllegalArgumentException( e );
}
catch (HibernateException he) {
throw getEntityManager().convert( he );
}
}
private boolean isJpaPositionalParameter(int position) {
return jpaPositionalIndices != null && jpaPositionalIndices.contains( position ); return jpaPositionalIndices != null && jpaPositionalIndices.contains( position );
} }
/** @Override
* {@inheritDoc}
*/
public TypedQuery<X> setParameter(int position, Date value, TemporalType temporalType) {
try {
if ( isJpaPositionalParameter( position ) ) {
String name = Integer.toString( position );
this.setParameter( name, value, temporalType );
}
else {
if ( temporalType == DATE ) {
query.setDate( position - 1, value );
}
else if ( temporalType == TIME ) {
query.setTime( position - 1, value );
}
else if ( temporalType == TIMESTAMP ) {
query.setTimestamp( position - 1, value );
}
registerParameterBinding( getParameter( position ), value );
}
return this;
}
catch (QueryParameterException e) {
throw new IllegalArgumentException( e );
}
catch (HibernateException he) {
throw getEntityManager().convert( he );
}
}
/**
* {@inheritDoc}
*/
public TypedQuery<X> setParameter(int position, Calendar value, TemporalType temporalType) {
try {
if ( isJpaPositionalParameter( position ) ) {
String name = Integer.toString( position );
this.setParameter( name, value, temporalType );
}
else {
if ( temporalType == DATE ) {
query.setCalendarDate( position - 1, value );
}
else if ( temporalType == TIME ) {
throw new IllegalArgumentException( "not yet implemented" );
}
else if ( temporalType == TIMESTAMP ) {
query.setCalendar( position - 1, value );
}
registerParameterBinding( getParameter( position ), value );
}
return this;
}
catch (QueryParameterException e) {
throw new IllegalArgumentException( e );
}
catch (HibernateException he) {
throw getEntityManager().convert( he );
}
}
/**
* {@inheritDoc}
*/
public Set<Parameter<?>> getParameters() {
return parameters;
}
/**
* {@inheritDoc}
*/
public Parameter<?> getParameter(String name) {
if ( name == null ) {
throw new IllegalArgumentException( "Name of parameter to locate cannot be null" );
}
for ( Parameter parameter : parameters ) {
if ( name.equals( parameter.getName() ) ) {
return parameter;
}
}
throw new IllegalArgumentException( "Unable to locate parameter named [" + name + "]" );
}
/**
* {@inheritDoc}
*/
public Parameter<?> getParameter(int position) {
if ( isJpaPositionalParameter( position ) ) {
return getParameter( Integer.toString( position ) );
}
else {
for ( Parameter parameter : parameters ) {
if ( parameter.getPosition() != null && position == parameter.getPosition() ) {
return parameter;
}
}
throw new IllegalArgumentException( "Unable to locate parameter with position [" + position + "]" );
}
}
/**
* {@inheritDoc}
*/
@SuppressWarnings({ "unchecked" })
public <T> Parameter<T> getParameter(String name, Class<T> type) {
Parameter param = getParameter( name );
if ( param.getParameterType() != null ) {
// we were able to determine the expected type during analysis, so validate it here
throw new IllegalArgumentException(
"Parameter type [" + param.getParameterType().getName() +
"] is not assignment compatible with requested type [" +
type.getName() + "]"
);
}
return param;
}
/**
* {@inheritDoc}
*/
@SuppressWarnings({ "unchecked" })
public <T> Parameter<T> getParameter(int position, Class<T> type) {
Parameter param = getParameter( position );
if ( param.getParameterType() != null ) {
// we were able to determine the expected type during analysis, so validate it here
throw new IllegalArgumentException(
"Parameter type [" + param.getParameterType().getName() +
"] is not assignment compatible with requested type [" +
type.getName() + "]"
);
}
return param;
}
/**
* {@inheritDoc}
*/
@SuppressWarnings({ "unchecked" }) @SuppressWarnings({ "unchecked" })
public <T> T unwrap(Class<T> tClass) { public <T> T unwrap(Class<T> tClass) {
if ( org.hibernate.Query.class.isAssignableFrom( tClass ) ) { if ( org.hibernate.Query.class.isAssignableFrom( tClass ) ) {
@ -608,33 +437,19 @@ public class QueryImpl<X> extends AbstractQueryImpl<X> implements TypedQuery<X>,
} }
} }
private javax.persistence.LockModeType jpaLockMode = javax.persistence.LockModeType.NONE;
@Override @Override
@SuppressWarnings({ "unchecked" }) protected void internalApplyLockMode(javax.persistence.LockModeType lockModeType) {
public TypedQuery<X> setLockMode(javax.persistence.LockModeType lockModeType) {
if (! getEntityManager().isTransactionInProgress()) {
throw new TransactionRequiredException( "no transaction is in progress" );
}
if ( ! canApplyLockModes() ) {
throw new IllegalStateException( "Not a JPAQL/Criteria query" );
}
this.jpaLockMode = lockModeType;
query.getLockOptions().setLockMode( LockModeTypeHelper.getLockMode( lockModeType ) ); query.getLockOptions().setLockMode( LockModeTypeHelper.getLockMode( lockModeType ) );
if ( getHints() != null && getHints().containsKey( AvailableSettings.LOCK_TIMEOUT ) ) { if ( getHints() != null && getHints().containsKey( AvailableSettings.LOCK_TIMEOUT ) ) {
applyLockTimeout( ConfigurationHelper.getInteger( getHints().get( AvailableSettings.LOCK_TIMEOUT ) ) ); applyLockTimeoutHint( ConfigurationHelper.getInteger( getHints().get( AvailableSettings.LOCK_TIMEOUT ) ) );
} }
return this;
} }
@Override @Override
protected void applyLockTimeout(int timeout) { protected boolean applyLockTimeoutHint(int timeout) {
query.getLockOptions().setTimeOut( timeout ); query.getLockOptions().setTimeOut( timeout );
return true;
} }
@Override
public javax.persistence.LockModeType getLockMode() {
return jpaLockMode;
}
} }

View File

@ -96,34 +96,27 @@ public class StoredProcedureQueryImpl extends BaseQueryImpl implements StoredPro
@Override @Override
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public StoredProcedureQuery registerStoredProcedureParameter(int position, Class type, ParameterMode mode) { public StoredProcedureQuery registerStoredProcedureParameter(int position, Class type, ParameterMode mode) {
procedureCall.registerParameter( position, type, mode ); entityManager().checkOpen( true );
registerParameter(
new ParameterRegistrationImpl(
procedureCall.registerParameter( position, type, mode )
)
);
return this; return this;
} }
@Override @Override
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public StoredProcedureQuery registerStoredProcedureParameter(String parameterName, Class type, ParameterMode mode) { public StoredProcedureQuery registerStoredProcedureParameter(String parameterName, Class type, ParameterMode mode) {
procedureCall.registerParameter( parameterName, type, mode ); entityManager().checkOpen( true );
registerParameter(
new ParameterRegistrationImpl(
procedureCall.registerParameter( parameterName, type, mode )
)
);
return this; return this;
} }
@Override
protected void validateParameterBindingTypes(ParameterImplementor parameter, ParameterValue bindValue) {
}
// covariant returns ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@Override
public StoredProcedureQueryImpl setFlushMode(FlushModeType jpaFlushMode) {
return (StoredProcedureQueryImpl) super.setFlushMode( jpaFlushMode );
}
@Override
public StoredProcedureQueryImpl setHint(String hintName, Object value) {
return (StoredProcedureQueryImpl) super.setHint( hintName, value );
}
@Override @Override
public <T> StoredProcedureQueryImpl setParameter(Parameter<T> param, T value) { public <T> StoredProcedureQueryImpl setParameter(Parameter<T> param, T value) {
return (StoredProcedureQueryImpl) super.setParameter( param, value ); return (StoredProcedureQueryImpl) super.setParameter( param, value );
@ -170,6 +163,19 @@ public class StoredProcedureQueryImpl extends BaseQueryImpl implements StoredPro
} }
// covariant returns ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@Override
public StoredProcedureQueryImpl setFlushMode(FlushModeType jpaFlushMode) {
return (StoredProcedureQueryImpl) super.setFlushMode( jpaFlushMode );
}
@Override
public StoredProcedureQueryImpl setHint(String hintName, Object value) {
return (StoredProcedureQueryImpl) super.setHint( hintName, value );
}
// outputs ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // outputs ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
private ProcedureResult outputs() { private ProcedureResult outputs() {
@ -261,7 +267,7 @@ public class StoredProcedureQueryImpl extends BaseQueryImpl implements StoredPro
} }
@Override @Override
protected boolean canApplyLockModesHints() { protected boolean canApplyAliasSpecificLockModeHints() {
return false; return false;
} }
@ -280,7 +286,81 @@ public class StoredProcedureQueryImpl extends BaseQueryImpl implements StoredPro
} }
@Override @Override
protected boolean applyFetchSize(int fetchSize) { protected boolean applyFetchSizeHint(int fetchSize) {
return false; return false;
} }
// parameters ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@Override
protected boolean isJpaPositionalParameter(int position) {
return false;
}
private static class ParameterRegistrationImpl<T> implements ParameterRegistration<T> {
private final org.hibernate.procedure.ParameterRegistration<T> nativeParamRegistration;
private ParameterBind<T> bind;
private ParameterRegistrationImpl(org.hibernate.procedure.ParameterRegistration<T> nativeParamRegistration) {
this.nativeParamRegistration = nativeParamRegistration;
}
@Override
public String getName() {
return nativeParamRegistration.getName();
}
@Override
public Integer getPosition() {
return nativeParamRegistration.getPosition();
}
@Override
public Class<T> getParameterType() {
return nativeParamRegistration.getType();
}
@Override
public ParameterMode getMode() {
return nativeParamRegistration.getMode();
}
@Override
public boolean isBindable() {
return getMode() == ParameterMode.IN || getMode() == ParameterMode.INOUT;
}
@Override
public void bindValue(T value) {
bindValue( value, null );
}
@Override
public void bindValue(T value, TemporalType specifiedTemporalType) {
validateBinding( getParameterType(), value, specifiedTemporalType );
nativeParamRegistration.bindValue( value,specifiedTemporalType );
if ( bind == null ) {
bind = new ParameterBind<T>() {
@Override
public T getValue() {
return nativeParamRegistration.getBind().getValue();
}
@Override
public TemporalType getSpecifiedTemporalType() {
return nativeParamRegistration.getBind().getExplicitTemporalType();
}
};
}
}
@Override
public ParameterBind<T> getBind() {
return bind;
}
}
} }

View File

@ -47,6 +47,8 @@ import org.hibernate.mapping.OneToMany;
import org.hibernate.mapping.PersistentClass; import org.hibernate.mapping.PersistentClass;
import org.hibernate.mapping.Property; import org.hibernate.mapping.Property;
import org.hibernate.mapping.Value; import org.hibernate.mapping.Value;
import org.hibernate.property.Getter;
import org.hibernate.property.MapAccessor;
import org.hibernate.tuple.entity.EntityMetamodel; import org.hibernate.tuple.entity.EntityMetamodel;
import org.hibernate.type.ComponentType; import org.hibernate.type.ComponentType;
import org.hibernate.type.EmbeddedComponentType; import org.hibernate.type.EmbeddedComponentType;
@ -580,9 +582,14 @@ public class AttributeFactory {
this.ownerType = ownerType; this.ownerType = ownerType;
this.member = member; this.member = member;
this.persistentAttributeType = persistentAttributeType; this.persistentAttributeType = persistentAttributeType;
final Class declaredType; final Class declaredType;
// we can support method or field members here. Is there really any other valid type?
if ( Field.class.isInstance( member ) ) { if ( member == null ) {
// assume we have a MAP entity-mode "class"
declaredType = propertyMapping.getType().getReturnedClass();
}
else if ( Field.class.isInstance( member ) ) {
declaredType = ( (Field) member ).getType(); declaredType = ( (Field) member ).getType();
} }
else if ( Method.class.isInstance( member ) ) { else if ( Method.class.isInstance( member ) ) {
@ -896,24 +903,23 @@ public class AttributeFactory {
} }
private final MemberResolver EMBEDDED_MEMBER_RESOLVER = new MemberResolver() { private final MemberResolver EMBEDDED_MEMBER_RESOLVER = new MemberResolver() {
/** @Override
* {@inheritDoc}
*/
public Member resolveMember(AttributeContext attributeContext) { public Member resolveMember(AttributeContext attributeContext) {
final EmbeddableTypeImpl embeddableType = ( EmbeddableTypeImpl<?> ) attributeContext.getOwnerType(); final EmbeddableTypeImpl embeddableType = ( EmbeddableTypeImpl<?> ) attributeContext.getOwnerType();
final String attributeName = attributeContext.getPropertyMapping().getName(); final String attributeName = attributeContext.getPropertyMapping().getName();
return embeddableType.getHibernateType()
final Getter getter = embeddableType.getHibernateType()
.getComponentTuplizer() .getComponentTuplizer()
.getGetter( embeddableType.getHibernateType().getPropertyIndex( attributeName ) ) .getGetter( embeddableType.getHibernateType().getPropertyIndex( attributeName ) );
.getMember(); return MapAccessor.MapGetter.class.isInstance( getter )
? new MapMember( attributeName, attributeContext.getPropertyMapping().getType().getReturnedClass() )
: getter.getMember();
} }
}; };
private final MemberResolver VIRTUAL_IDENTIFIER_MEMBER_RESOLVER = new MemberResolver() { private final MemberResolver VIRTUAL_IDENTIFIER_MEMBER_RESOLVER = new MemberResolver() {
/** @Override
* {@inheritDoc}
*/
public Member resolveMember(AttributeContext attributeContext) { public Member resolveMember(AttributeContext attributeContext) {
final AbstractIdentifiableType identifiableType = (AbstractIdentifiableType) attributeContext.getOwnerType(); final AbstractIdentifiableType identifiableType = (AbstractIdentifiableType) attributeContext.getOwnerType();
final EntityMetamodel entityMetamodel = getDeclarerEntityMetamodel( identifiableType ); final EntityMetamodel entityMetamodel = getDeclarerEntityMetamodel( identifiableType );
@ -927,9 +933,13 @@ public class AttributeFactory {
final EmbeddedComponentType componentType = (EmbeddedComponentType) type; final EmbeddedComponentType componentType = (EmbeddedComponentType) type;
final String attributeName = attributeContext.getPropertyMapping().getName(); final String attributeName = attributeContext.getPropertyMapping().getName();
return componentType.getComponentTuplizer()
.getGetter( componentType.getPropertyIndex( attributeName ) ) final Getter getter = componentType.getComponentTuplizer()
.getMember(); .getGetter( componentType.getPropertyIndex( attributeName ) );
return MapAccessor.MapGetter.class.isInstance( getter )
? new MapMember( attributeName, attributeContext.getPropertyMapping().getType().getReturnedClass() )
: getter.getMember();
} }
}; };
@ -937,9 +947,7 @@ public class AttributeFactory {
* A {@link Member} resolver for normal attributes. * A {@link Member} resolver for normal attributes.
*/ */
private final MemberResolver NORMAL_MEMBER_RESOLVER = new MemberResolver() { private final MemberResolver NORMAL_MEMBER_RESOLVER = new MemberResolver() {
/** @Override
* {@inheritDoc}
*/
public Member resolveMember(AttributeContext attributeContext) { public Member resolveMember(AttributeContext attributeContext) {
final AbstractManagedType ownerType = attributeContext.getOwnerType(); final AbstractManagedType ownerType = attributeContext.getOwnerType();
final Property property = attributeContext.getPropertyMapping(); final Property property = attributeContext.getPropertyMapping();
@ -958,9 +966,10 @@ public class AttributeFactory {
return VIRTUAL_IDENTIFIER_MEMBER_RESOLVER.resolveMember( attributeContext ); return VIRTUAL_IDENTIFIER_MEMBER_RESOLVER.resolveMember( attributeContext );
} }
else { else {
return entityMetamodel.getTuplizer() final Getter getter = entityMetamodel.getTuplizer().getGetter( index );
.getGetter( index ) return MapAccessor.MapGetter.class.isInstance( getter )
.getMember(); ? new MapMember( propertyName, property.getType().getReturnedClass() )
: getter.getMember();
} }
} }
else { else {
@ -970,6 +979,7 @@ public class AttributeFactory {
}; };
private final MemberResolver IDENTIFIER_MEMBER_RESOLVER = new MemberResolver() { private final MemberResolver IDENTIFIER_MEMBER_RESOLVER = new MemberResolver() {
@Override
public Member resolveMember(AttributeContext attributeContext) { public Member resolveMember(AttributeContext attributeContext) {
final AbstractIdentifiableType identifiableType = (AbstractIdentifiableType) attributeContext.getOwnerType(); final AbstractIdentifiableType identifiableType = (AbstractIdentifiableType) attributeContext.getOwnerType();
final EntityMetamodel entityMetamodel = getDeclarerEntityMetamodel( identifiableType ); final EntityMetamodel entityMetamodel = getDeclarerEntityMetamodel( identifiableType );
@ -978,11 +988,18 @@ public class AttributeFactory {
// this *should* indicate processing part of an IdClass... // this *should* indicate processing part of an IdClass...
return VIRTUAL_IDENTIFIER_MEMBER_RESOLVER.resolveMember( attributeContext ); return VIRTUAL_IDENTIFIER_MEMBER_RESOLVER.resolveMember( attributeContext );
} }
return entityMetamodel.getTuplizer().getIdentifierGetter().getMember(); final Getter getter = entityMetamodel.getTuplizer().getIdentifierGetter();
return MapAccessor.MapGetter.class.isInstance( getter )
? new MapMember(
entityMetamodel.getIdentifierProperty().getName(),
entityMetamodel.getIdentifierProperty().getType().getReturnedClass()
)
: getter.getMember();
} }
}; };
private final MemberResolver VERSION_MEMBER_RESOLVER = new MemberResolver() { private final MemberResolver VERSION_MEMBER_RESOLVER = new MemberResolver() {
@Override
public Member resolveMember(AttributeContext attributeContext) { public Member resolveMember(AttributeContext attributeContext) {
final AbstractIdentifiableType identifiableType = (AbstractIdentifiableType) attributeContext.getOwnerType(); final AbstractIdentifiableType identifiableType = (AbstractIdentifiableType) attributeContext.getOwnerType();
final EntityMetamodel entityMetamodel = getDeclarerEntityMetamodel( identifiableType ); final EntityMetamodel entityMetamodel = getDeclarerEntityMetamodel( identifiableType );
@ -991,7 +1008,11 @@ public class AttributeFactory {
// this should never happen, but to be safe... // this should never happen, but to be safe...
throw new IllegalArgumentException( "Given property did not match declared version property" ); throw new IllegalArgumentException( "Given property did not match declared version property" );
} }
return entityMetamodel.getTuplizer().getVersionGetter().getMember();
final Getter getter = entityMetamodel.getTuplizer().getVersionGetter();
return MapAccessor.MapGetter.class.isInstance( getter )
? new MapMember( versionPropertyName, attributeContext.getPropertyMapping().getType().getReturnedClass() )
: getter.getMember();
} }
}; };
} }

View File

@ -350,6 +350,10 @@ class MetadataContext {
private <X> void populateStaticMetamodel(AbstractManagedType<X> managedType) { private <X> void populateStaticMetamodel(AbstractManagedType<X> managedType) {
final Class<X> managedTypeClass = managedType.getJavaType(); final Class<X> managedTypeClass = managedType.getJavaType();
if ( managedTypeClass == null ) {
// should indicate MAP entity mode, skip...
return;
}
final String metamodelClassName = managedTypeClass.getName() + "_"; final String metamodelClassName = managedTypeClass.getName() + "_";
try { try {
final Class metamodelClass = Class.forName( metamodelClassName, true, managedTypeClass.getClassLoader() ); final Class metamodelClass = Class.forName( metamodelClassName, true, managedTypeClass.getClassLoader() );

View File

@ -57,11 +57,13 @@ class DatabaseTarget implements GenerationTarget {
for ( String command : commands ) { for ( String command : commands ) {
try { try {
jdbcConnectionContext.logSqlStatement( command );
jdbcStatement().execute( command ); jdbcStatement().execute( command );
} }
catch (SQLException e) { catch (SQLException e) {
throw new PersistenceException( throw new PersistenceException(
"Unable to execute JPA schema generation create command [" + command + "]" "Unable to execute JPA schema generation create command [" + command + "]",
e
); );
} }
} }
@ -87,12 +89,12 @@ class DatabaseTarget implements GenerationTarget {
for ( String command : commands ) { for ( String command : commands ) {
try { try {
jdbcConnectionContext.logSqlStatement( command );
jdbcStatement().execute( command ); jdbcStatement().execute( command );
} }
catch (SQLException e) { catch (SQLException e) {
throw new PersistenceException( // Just log the error because drop commands are often unsuccessful because the tables do not yet exist...
"Unable to execute JPA schema generation drop command [" + command + "]" log.warnf( "Unable to execute JPA schema generation drop command [" + command + "]", e );
);
} }
} }
} }

View File

@ -29,6 +29,8 @@ import java.sql.SQLException;
import org.hibernate.engine.jdbc.connections.spi.JdbcConnectionAccess; import org.hibernate.engine.jdbc.connections.spi.JdbcConnectionAccess;
import org.hibernate.engine.jdbc.internal.DDLFormatterImpl;
import org.hibernate.engine.jdbc.spi.SqlStatementLogger;
/** /**
* Defines access to a JDBC Connection for use in Schema generation * Defines access to a JDBC Connection for use in Schema generation
@ -37,10 +39,13 @@ import org.hibernate.engine.jdbc.connections.spi.JdbcConnectionAccess;
*/ */
class JdbcConnectionContext { class JdbcConnectionContext {
private final JdbcConnectionAccess jdbcConnectionAccess; private final JdbcConnectionAccess jdbcConnectionAccess;
private final SqlStatementLogger sqlStatementLogger;
private Connection jdbcConnection; private Connection jdbcConnection;
JdbcConnectionContext(JdbcConnectionAccess jdbcConnectionAccess) { JdbcConnectionContext(JdbcConnectionAccess jdbcConnectionAccess, SqlStatementLogger sqlStatementLogger) {
this.jdbcConnectionAccess = jdbcConnectionAccess; this.jdbcConnectionAccess = jdbcConnectionAccess;
this.sqlStatementLogger = sqlStatementLogger;
} }
public Connection getJdbcConnection() { public Connection getJdbcConnection() {
@ -65,4 +70,8 @@ class JdbcConnectionContext {
} }
} }
} }
public void logSqlStatement(String sqlStatement) {
sqlStatementLogger.logStatement( sqlStatement, DDLFormatterImpl.INSTANCE );
}
} }

View File

@ -45,6 +45,8 @@ import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider;
import org.hibernate.engine.jdbc.connections.spi.JdbcConnectionAccess; import org.hibernate.engine.jdbc.connections.spi.JdbcConnectionAccess;
import org.hibernate.engine.jdbc.dialect.spi.DatabaseInfoDialectResolver; import org.hibernate.engine.jdbc.dialect.spi.DatabaseInfoDialectResolver;
import org.hibernate.engine.jdbc.dialect.spi.DialectResolver; import org.hibernate.engine.jdbc.dialect.spi.DialectResolver;
import org.hibernate.engine.jdbc.spi.JdbcServices;
import org.hibernate.engine.jdbc.spi.SqlStatementLogger;
import org.hibernate.internal.util.StringHelper; import org.hibernate.internal.util.StringHelper;
import org.hibernate.internal.util.config.ConfigurationHelper; import org.hibernate.internal.util.config.ConfigurationHelper;
import org.hibernate.jpa.AvailableSettings; import org.hibernate.jpa.AvailableSettings;
@ -116,6 +118,18 @@ public class JpaSchemaGenerator {
final List<GenerationTarget> targets = Arrays.asList( databaseTarget, scriptsTarget ); final List<GenerationTarget> targets = Arrays.asList( databaseTarget, scriptsTarget );
// See if native Hibernate schema generation has also been requested and warn the user if so...
final String hbm2ddl = hibernateConfiguration.getProperty( org.hibernate.cfg.AvailableSettings.HBM2DDL_AUTO );
if ( StringHelper.isNotEmpty( hbm2ddl ) ) {
log.warnf(
"Hibernate hbm2ddl-auto setting was specified [%s] in combination with JPA schema-generation; " +
"combination will likely cause trouble",
hbm2ddl
);
}
// finally, do the generation // finally, do the generation
try { try {
@ -237,6 +251,8 @@ public class JpaSchemaGenerator {
private static JdbcConnectionContext determineAppropriateJdbcConnectionContext( private static JdbcConnectionContext determineAppropriateJdbcConnectionContext(
Configuration hibernateConfiguration, Configuration hibernateConfiguration,
ServiceRegistry serviceRegistry) { ServiceRegistry serviceRegistry) {
final SqlStatementLogger sqlStatementLogger = serviceRegistry.getService( JdbcServices.class ).getSqlStatementLogger();
// see if a specific connection has been provided: // see if a specific connection has been provided:
final Connection providedConnection = (Connection) hibernateConfiguration.getProperties().get( final Connection providedConnection = (Connection) hibernateConfiguration.getProperties().get(
AvailableSettings.SCHEMA_GEN_CONNECTION AvailableSettings.SCHEMA_GEN_CONNECTION
@ -259,7 +275,8 @@ public class JpaSchemaGenerator {
public boolean supportsAggressiveRelease() { public boolean supportsAggressiveRelease() {
return false; return false;
} }
} },
sqlStatementLogger
); );
} }
@ -281,12 +298,13 @@ public class JpaSchemaGenerator {
public boolean supportsAggressiveRelease() { public boolean supportsAggressiveRelease() {
return connectionProvider.supportsAggressiveRelease(); return connectionProvider.supportsAggressiveRelease();
} }
} },
sqlStatementLogger
); );
} }
// otherwise, return a no-op impl // otherwise, return a no-op impl
return new JdbcConnectionContext( null ) { return new JdbcConnectionContext( null, sqlStatementLogger ) {
@Override @Override
public Connection getJdbcConnection() { public Connection getJdbcConnection() {
throw new PersistenceException( "No connection information supplied" ); throw new PersistenceException( "No connection information supplied" );
@ -393,13 +411,13 @@ public class JpaSchemaGenerator {
List<GenerationSource> dropSourceList, List<GenerationSource> dropSourceList,
List<GenerationTarget> targets) { List<GenerationTarget> targets) {
for ( GenerationTarget target : targets ) { for ( GenerationTarget target : targets ) {
for ( GenerationSource source : createSourceList ) {
target.acceptCreateCommands( source.getCommands() );
}
for ( GenerationSource source : dropSourceList ) { for ( GenerationSource source : dropSourceList ) {
target.acceptDropCommands( source.getCommands() ); target.acceptDropCommands( source.getCommands() );
} }
for ( GenerationSource source : createSourceList ) {
target.acceptCreateCommands( source.getCommands() );
}
} }
} }

View File

@ -322,19 +322,25 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage
} }
} }
@Override
public Query createQuery(String jpaqlString) { public Query createQuery(String jpaqlString) {
checkOpen();
try { try {
return applyProperties( new QueryImpl<Object>( getSession().createQuery( jpaqlString ), this ) ); return applyProperties( new QueryImpl<Object>( internalGetSession().createQuery( jpaqlString ), this ) );
} }
catch ( HibernateException he ) { catch ( HibernateException he ) {
throw convert( he ); throw convert( he );
} }
} }
protected abstract void checkOpen();
@Override
public <T> TypedQuery<T> createQuery(String jpaqlString, Class<T> resultClass) { public <T> TypedQuery<T> createQuery(String jpaqlString, Class<T> resultClass) {
checkOpen();
try { try {
// do the translation // do the translation
org.hibernate.Query hqlQuery = getSession().createQuery( jpaqlString ); org.hibernate.Query hqlQuery = internalGetSession().createQuery( jpaqlString );
resultClassChecking( resultClass, hqlQuery ); resultClassChecking( resultClass, hqlQuery );
@ -529,13 +535,14 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage
} }
} }
@Override
public <T> QueryImpl<T> createQuery( public <T> QueryImpl<T> createQuery(
String jpaqlString, String jpaqlString,
Class<T> resultClass, Class<T> resultClass,
Selection selection, Selection selection,
Options options) { Options options) {
try { try {
org.hibernate.Query hqlQuery = getSession().createQuery( jpaqlString ); org.hibernate.Query hqlQuery = internalGetSession().createQuery( jpaqlString );
if ( options.getValueHandlers() == null ) { if ( options.getValueHandlers() == null ) {
if ( options.getResultMetadataValidator() != null ) { if ( options.getResultMetadataValidator() != null ) {
@ -675,23 +682,29 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage
return criteriaCompiler; return criteriaCompiler;
} }
@Override
public <T> TypedQuery<T> createQuery(CriteriaQuery<T> criteriaQuery) { public <T> TypedQuery<T> createQuery(CriteriaQuery<T> criteriaQuery) {
checkOpen();
return (TypedQuery<T>) criteriaCompiler().compile( (CompilableCriteria) criteriaQuery ); return (TypedQuery<T>) criteriaCompiler().compile( (CompilableCriteria) criteriaQuery );
} }
@Override @Override
public Query createQuery(CriteriaUpdate criteriaUpdate) { public Query createQuery(CriteriaUpdate criteriaUpdate) {
checkOpen();
return criteriaCompiler().compile( (CompilableCriteria) criteriaUpdate ); return criteriaCompiler().compile( (CompilableCriteria) criteriaUpdate );
} }
@Override @Override
public Query createQuery(CriteriaDelete criteriaDelete) { public Query createQuery(CriteriaDelete criteriaDelete) {
checkOpen();
return criteriaCompiler().compile( (CompilableCriteria) criteriaDelete ); return criteriaCompiler().compile( (CompilableCriteria) criteriaDelete );
} }
@Override
public Query createNamedQuery(String name) { public Query createNamedQuery(String name) {
checkOpen();
try { try {
org.hibernate.Query namedQuery = getSession().getNamedQuery( name ); org.hibernate.Query namedQuery = internalGetSession().getNamedQuery( name );
try { try {
return new QueryImpl( namedQuery, this ); return new QueryImpl( namedQuery, this );
} }
@ -704,7 +717,9 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage
} }
} }
@Override
public <T> TypedQuery<T> createNamedQuery(String name, Class<T> resultClass) { public <T> TypedQuery<T> createNamedQuery(String name, Class<T> resultClass) {
checkOpen();
try { try {
/* /*
* Get the named query. * Get the named query.
@ -712,7 +727,7 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage
* or its associated result set mapping * or its associated result set mapping
* If the named query is a HQL query, use getReturnType() * If the named query is a HQL query, use getReturnType()
*/ */
org.hibernate.Query namedQuery = getSession().getNamedQuery( name ); org.hibernate.Query namedQuery = internalGetSession().getNamedQuery( name );
//TODO clean this up to avoid downcasting //TODO clean this up to avoid downcasting
final SessionFactoryImplementor factoryImplementor = entityManagerFactory.getSessionFactory(); final SessionFactoryImplementor factoryImplementor = entityManagerFactory.getSessionFactory();
final NamedSQLQueryDefinition queryDefinition = factoryImplementor.getNamedSQLQuery( name ); final NamedSQLQueryDefinition queryDefinition = factoryImplementor.getNamedSQLQuery( name );
@ -776,9 +791,11 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage
); );
} }
@Override
public Query createNativeQuery(String sqlString) { public Query createNativeQuery(String sqlString) {
checkOpen();
try { try {
SQLQuery q = getSession().createSQLQuery( sqlString ); SQLQuery q = internalGetSession().createSQLQuery( sqlString );
return new QueryImpl( q, this ); return new QueryImpl( q, this );
} }
catch ( HibernateException he ) { catch ( HibernateException he ) {
@ -786,9 +803,11 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage
} }
} }
@Override
public Query createNativeQuery(String sqlString, Class resultClass) { public Query createNativeQuery(String sqlString, Class resultClass) {
checkOpen();
try { try {
SQLQuery q = getSession().createSQLQuery( sqlString ); SQLQuery q = internalGetSession().createSQLQuery( sqlString );
q.addEntity( "alias1", resultClass.getName(), LockMode.READ ); q.addEntity( "alias1", resultClass.getName(), LockMode.READ );
return new QueryImpl( q, this ); return new QueryImpl( q, this );
} }
@ -797,9 +816,11 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage
} }
} }
@Override
public Query createNativeQuery(String sqlString, String resultSetMapping) { public Query createNativeQuery(String sqlString, String resultSetMapping) {
checkOpen();
try { try {
SQLQuery q = getSession().createSQLQuery( sqlString ); SQLQuery q = internalGetSession().createSQLQuery( sqlString );
q.setResultSetMapping( resultSetMapping ); q.setResultSetMapping( resultSetMapping );
return new QueryImpl( q, this ); return new QueryImpl( q, this );
} }
@ -810,13 +831,15 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage
@Override @Override
public StoredProcedureQuery createNamedStoredProcedureQuery(String name) { public StoredProcedureQuery createNamedStoredProcedureQuery(String name) {
checkOpen();
throw new NotYetImplementedException(); throw new NotYetImplementedException();
} }
@Override @Override
public StoredProcedureQuery createStoredProcedureQuery(String procedureName) { public StoredProcedureQuery createStoredProcedureQuery(String procedureName) {
checkOpen();
try { try {
ProcedureCall procedureCall = getSession().createStoredProcedureCall( procedureName ); ProcedureCall procedureCall = internalGetSession().createStoredProcedureCall( procedureName );
return new StoredProcedureQueryImpl( procedureCall, this ); return new StoredProcedureQueryImpl( procedureCall, this );
} }
catch ( HibernateException he ) { catch ( HibernateException he ) {
@ -826,8 +849,9 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage
@Override @Override
public StoredProcedureQuery createStoredProcedureQuery(String procedureName, Class... resultClasses) { public StoredProcedureQuery createStoredProcedureQuery(String procedureName, Class... resultClasses) {
checkOpen();
try { try {
ProcedureCall procedureCall = getSession().createStoredProcedureCall( procedureName, resultClasses ); ProcedureCall procedureCall = internalGetSession().createStoredProcedureCall( procedureName, resultClasses );
return new StoredProcedureQueryImpl( procedureCall, this ); return new StoredProcedureQueryImpl( procedureCall, this );
} }
catch ( HibernateException he ) { catch ( HibernateException he ) {
@ -837,13 +861,16 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage
@Override @Override
public StoredProcedureQuery createStoredProcedureQuery(String procedureName, String... resultSetMappings) { public StoredProcedureQuery createStoredProcedureQuery(String procedureName, String... resultSetMappings) {
checkOpen();
throw new NotYetImplementedException(); throw new NotYetImplementedException();
} }
@Override
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public <T> T getReference(Class<T> entityClass, Object primaryKey) { public <T> T getReference(Class<T> entityClass, Object primaryKey) {
checkOpen();
try { try {
return ( T ) getSession().load( entityClass, ( Serializable ) primaryKey ); return ( T ) internalGetSession().load( entityClass, ( Serializable ) primaryKey );
} }
catch ( MappingException e ) { catch ( MappingException e ) {
throw new IllegalArgumentException( e.getMessage(), e ); throw new IllegalArgumentException( e.getMessage(), e );
@ -859,35 +886,44 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage
} }
} }
@Override
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public <A> A find(Class<A> entityClass, Object primaryKey) { public <A> A find(Class<A> entityClass, Object primaryKey) {
checkOpen();
return find( entityClass, primaryKey, null, null ); return find( entityClass, primaryKey, null, null );
} }
@Override
public <T> T find(Class<T> entityClass, Object primaryKey, Map<String, Object> properties) { public <T> T find(Class<T> entityClass, Object primaryKey, Map<String, Object> properties) {
checkOpen();
return find( entityClass, primaryKey, null, properties ); return find( entityClass, primaryKey, null, properties );
} }
@Override
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public <A> A find(Class<A> entityClass, Object primaryKey, LockModeType lockModeType) { public <A> A find(Class<A> entityClass, Object primaryKey, LockModeType lockModeType) {
checkOpen();
return find( entityClass, primaryKey, lockModeType, null ); return find( entityClass, primaryKey, lockModeType, null );
} }
@Override
public <A> A find(Class<A> entityClass, Object primaryKey, LockModeType lockModeType, Map<String, Object> properties) { public <A> A find(Class<A> entityClass, Object primaryKey, LockModeType lockModeType, Map<String, Object> properties) {
CacheMode previousCacheMode = getSession().getCacheMode(); checkOpen();
Session session = internalGetSession();
CacheMode previousCacheMode = session.getCacheMode();
CacheMode cacheMode = determineAppropriateLocalCacheMode( properties ); CacheMode cacheMode = determineAppropriateLocalCacheMode( properties );
LockOptions lockOptions = null; LockOptions lockOptions = null;
try { try {
getSession().setCacheMode( cacheMode ); session.setCacheMode( cacheMode );
if ( lockModeType != null ) { if ( lockModeType != null ) {
lockOptions = getLockRequest( lockModeType, properties ); lockOptions = getLockRequest( lockModeType, properties );
return ( A ) getSession().get( return ( A ) session.get(
entityClass, ( Serializable ) primaryKey, entityClass, ( Serializable ) primaryKey,
lockOptions lockOptions
); );
} }
else { else {
return ( A ) getSession().get( entityClass, ( Serializable ) primaryKey ); return ( A ) session.get( entityClass, ( Serializable ) primaryKey );
} }
} }
catch ( EntityNotFoundException ignored ) { catch ( EntityNotFoundException ignored ) {
@ -921,7 +957,7 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage
throw convert( he, lockOptions ); throw convert( he, lockOptions );
} }
finally { finally {
getSession().setCacheMode( previousCacheMode ); session.setCacheMode( previousCacheMode );
} }
} }
@ -952,10 +988,12 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage
} }
} }
@Override
public void persist(Object entity) { public void persist(Object entity) {
checkOpen();
checkTransactionNeeded(); checkTransactionNeeded();
try { try {
getSession().persist( entity ); internalGetSession().persist( entity );
} }
catch ( MappingException e ) { catch ( MappingException e ) {
throw new IllegalArgumentException( e.getMessage() ); throw new IllegalArgumentException( e.getMessage() );
@ -965,11 +1003,13 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage
} }
} }
@Override
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public <A> A merge(A entity) { public <A> A merge(A entity) {
checkOpen();
checkTransactionNeeded(); checkTransactionNeeded();
try { try {
return ( A ) getSession().merge( entity ); return ( A ) internalGetSession().merge( entity );
} }
catch ( ObjectDeletedException sse ) { catch ( ObjectDeletedException sse ) {
throw new IllegalArgumentException( sse ); throw new IllegalArgumentException( sse );
@ -982,10 +1022,12 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage
} }
} }
@Override
public void remove(Object entity) { public void remove(Object entity) {
checkOpen();
checkTransactionNeeded(); checkTransactionNeeded();
try { try {
getSession().delete( entity ); internalGetSession().delete( entity );
} }
catch ( MappingException e ) { catch ( MappingException e ) {
throw new IllegalArgumentException( e.getMessage(), e ); throw new IllegalArgumentException( e.getMessage(), e );
@ -995,34 +1037,41 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage
} }
} }
@Override
public void refresh(Object entity) { public void refresh(Object entity) {
refresh( entity, null, null ); refresh( entity, null, null );
} }
@Override
public void refresh(Object entity, Map<String, Object> properties) { public void refresh(Object entity, Map<String, Object> properties) {
refresh( entity, null, properties ); refresh( entity, null, properties );
} }
@Override
public void refresh(Object entity, LockModeType lockModeType) { public void refresh(Object entity, LockModeType lockModeType) {
refresh( entity, lockModeType, null ); refresh( entity, lockModeType, null );
} }
@Override
public void refresh(Object entity, LockModeType lockModeType, Map<String, Object> properties) { public void refresh(Object entity, LockModeType lockModeType, Map<String, Object> properties) {
checkOpen();
checkTransactionNeeded(); checkTransactionNeeded();
CacheMode previousCacheMode = getSession().getCacheMode();
Session session = internalGetSession();
CacheMode previousCacheMode = session.getCacheMode();
CacheMode localCacheMode = determineAppropriateLocalCacheMode( properties ); CacheMode localCacheMode = determineAppropriateLocalCacheMode( properties );
LockOptions lockOptions = null; LockOptions lockOptions = null;
try { try {
getSession().setCacheMode( localCacheMode ); session.setCacheMode( localCacheMode );
if ( !getSession().contains( entity ) ) { if ( !session.contains( entity ) ) {
throw new IllegalArgumentException( "Entity not managed" ); throw new IllegalArgumentException( "Entity not managed" );
} }
if ( lockModeType != null ) { if ( lockModeType != null ) {
lockOptions = getLockRequest( lockModeType, properties ); lockOptions = getLockRequest( lockModeType, properties );
getSession().refresh( entity, lockOptions ); session.refresh( entity, lockOptions );
} }
else { else {
getSession().refresh( entity ); session.refresh( entity );
} }
} }
catch ( MappingException e ) { catch ( MappingException e ) {
@ -1032,18 +1081,21 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage
throw convert( he, lockOptions ); throw convert( he, lockOptions );
} }
finally { finally {
getSession().setCacheMode( previousCacheMode ); session.setCacheMode( previousCacheMode );
} }
} }
@Override
public boolean contains(Object entity) { public boolean contains(Object entity) {
checkOpen();
try { try {
if ( entity != null if ( entity != null
&& !( entity instanceof HibernateProxy ) && !( entity instanceof HibernateProxy )
&& getSession().getSessionFactory().getClassMetadata( entity.getClass() ) == null ) { && internalGetSession().getSessionFactory().getClassMetadata( entity.getClass() ) == null ) {
throw new IllegalArgumentException( "Not an entity:" + entity.getClass() ); throw new IllegalArgumentException( "Not an entity:" + entity.getClass() );
} }
return getSession().contains( entity ); return internalGetSession().contains( entity );
} }
catch ( MappingException e ) { catch ( MappingException e ) {
throw new IllegalArgumentException( e.getMessage(), e ); throw new IllegalArgumentException( e.getMessage(), e );
@ -1053,30 +1105,43 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage
} }
} }
@Override
public LockModeType getLockMode(Object entity) { public LockModeType getLockMode(Object entity) {
checkOpen();
if ( !contains( entity ) ) { if ( !contains( entity ) ) {
throw new IllegalArgumentException( "entity not in the persistence context" ); throw new IllegalArgumentException( "entity not in the persistence context" );
} }
return getLockModeType( getSession().getCurrentLockMode( entity ) ); return getLockModeType( internalGetSession().getCurrentLockMode( entity ) );
} }
@Override
public void setProperty(String s, Object o) { public void setProperty(String s, Object o) {
checkOpen();
if ( entityManagerSpecificProperties.contains( s ) ) { if ( entityManagerSpecificProperties.contains( s ) ) {
properties.put( s, o ); properties.put( s, o );
applyProperties(); applyProperties();
} else LOG.debugf("Trying to set a property which is not supported on entity manager level"); }
else {
LOG.debugf("Trying to set a property which is not supported on entity manager level");
}
} }
@Override
public Map<String, Object> getProperties() { public Map<String, Object> getProperties() {
return Collections.unmodifiableMap( properties ); return Collections.unmodifiableMap( properties );
} }
@Override
public void flush() { public void flush() {
checkOpen();
if ( !isTransactionInProgress() ) { if ( !isTransactionInProgress() ) {
throw new TransactionRequiredException( "no transaction is in progress" ); throw new TransactionRequiredException( "no transaction is in progress" );
} }
try { try {
getSession().flush(); internalGetSession().flush();
} }
catch ( RuntimeException e ) { catch ( RuntimeException e ) {
throw convert( e ); throw convert( e );
@ -1094,9 +1159,19 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage
* Return a Session (even if the entity manager is closed). * Return a Session (even if the entity manager is closed).
* *
* @return A session. * @return A session.
* @deprecated Deprecated in favor of {@link #getRawSession()}
*/ */
@Deprecated
protected abstract Session getRawSession(); protected abstract Session getRawSession();
/**
* Return a Session without any validation checks.
*
* @return A session.
*/
protected abstract Session internalGetSession();
@Override
public EntityTransaction getTransaction() { public EntityTransaction getTransaction() {
if ( transactionType == PersistenceUnitTransactionType.JTA ) { if ( transactionType == PersistenceUnitTransactionType.JTA ) {
throw new IllegalStateException( "A JTA EntityManager cannot use getTransaction()" ); throw new IllegalStateException( "A JTA EntityManager cannot use getTransaction()" );
@ -1104,58 +1179,63 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage
return tx; return tx;
} }
/** @Override
* {@inheritDoc}
*/
public EntityManagerFactoryImpl getEntityManagerFactory() { public EntityManagerFactoryImpl getEntityManagerFactory() {
checkOpen();
return internalGetEntityManagerFactory();
}
protected EntityManagerFactoryImpl internalGetEntityManagerFactory() {
return entityManagerFactory; return entityManagerFactory;
} }
/** @Override
* {@inheritDoc}
*/
public HibernateEntityManagerFactory getFactory() { public HibernateEntityManagerFactory getFactory() {
return entityManagerFactory; return entityManagerFactory;
} }
/** @Override
* {@inheritDoc}
*/
public CriteriaBuilder getCriteriaBuilder() { public CriteriaBuilder getCriteriaBuilder() {
checkOpen();
return getEntityManagerFactory().getCriteriaBuilder(); return getEntityManagerFactory().getCriteriaBuilder();
} }
/** @Override
* {@inheritDoc}
*/
public Metamodel getMetamodel() { public Metamodel getMetamodel() {
checkOpen();
return getEntityManagerFactory().getMetamodel(); return getEntityManagerFactory().getMetamodel();
} }
@Override
public void setFlushMode(FlushModeType flushModeType) { public void setFlushMode(FlushModeType flushModeType) {
checkOpen();
if ( flushModeType == FlushModeType.AUTO ) { if ( flushModeType == FlushModeType.AUTO ) {
getSession().setFlushMode( FlushMode.AUTO ); internalGetSession().setFlushMode( FlushMode.AUTO );
} }
else if ( flushModeType == FlushModeType.COMMIT ) { else if ( flushModeType == FlushModeType.COMMIT ) {
getSession().setFlushMode( FlushMode.COMMIT ); internalGetSession().setFlushMode( FlushMode.COMMIT );
} }
else { else {
throw new AssertionFailure( "Unknown FlushModeType: " + flushModeType ); throw new AssertionFailure( "Unknown FlushModeType: " + flushModeType );
} }
} }
@Override
public void clear() { public void clear() {
checkOpen();
try { try {
getSession().clear(); internalGetSession().clear();
} }
catch ( HibernateException he ) { catch ( HibernateException he ) {
throw convert( he ); throw convert( he );
} }
} }
@Override
public void detach(Object entity) { public void detach(Object entity) {
checkOpen();
try { try {
getSession().evict( entity ); internalGetSession().evict( entity );
} }
catch ( HibernateException he ) { catch ( HibernateException he ) {
throw convert( he ); throw convert( he );
@ -1168,8 +1248,11 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage
* If it returns null, do em.unwrap(Session.class).getFlushMode() to get the * If it returns null, do em.unwrap(Session.class).getFlushMode() to get the
* Hibernate flush mode * Hibernate flush mode
*/ */
@Override
public FlushModeType getFlushMode() { public FlushModeType getFlushMode() {
FlushMode mode = getSession().getFlushMode(); checkOpen();
FlushMode mode = internalGetSession().getFlushMode();
if ( mode == FlushMode.AUTO ) { if ( mode == FlushMode.AUTO ) {
return FlushModeType.AUTO; return FlushModeType.AUTO;
} }
@ -1187,6 +1270,8 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage
} }
public void lock(Object entity, LockModeType lockModeType, Map<String, Object> properties) { public void lock(Object entity, LockModeType lockModeType, Map<String, Object> properties) {
checkOpen();
LockOptions lockOptions = null; LockOptions lockOptions = null;
if ( !isTransactionInProgress() ) { if ( !isTransactionInProgress() ) {
throw new TransactionRequiredException( "no transaction is in progress" ); throw new TransactionRequiredException( "no transaction is in progress" );
@ -1197,7 +1282,7 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage
throw new IllegalArgumentException( "entity not in the persistence context" ); throw new IllegalArgumentException( "entity not in the persistence context" );
} }
lockOptions = getLockRequest( lockModeType, properties ); lockOptions = getLockRequest( lockModeType, properties );
getSession().buildLockRequest( lockOptions ).lock( entity ); internalGetSession().buildLockRequest( lockOptions ).lock( entity );
} }
catch ( HibernateException he ) { catch ( HibernateException he ) {
throw convert( he, lockOptions ); throw convert( he, lockOptions );
@ -1226,20 +1311,22 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage
} }
public boolean isTransactionInProgress() { public boolean isTransactionInProgress() {
return ( ( SessionImplementor ) getRawSession() ).isTransactionInProgress(); return ( ( SessionImplementor ) internalGetSession() ).isTransactionInProgress();
} }
private SessionFactoryImplementor sfi() { private SessionFactoryImplementor sfi() {
return (SessionFactoryImplementor) getRawSession().getSessionFactory(); return (SessionFactoryImplementor) internalGetSession().getSessionFactory();
} }
@Override @Override
public <T> T unwrap(Class<T> clazz) { public <T> T unwrap(Class<T> clazz) {
checkOpen();
if ( Session.class.isAssignableFrom( clazz ) ) { if ( Session.class.isAssignableFrom( clazz ) ) {
return ( T ) getSession(); return ( T ) internalGetSession();
} }
if ( SessionImplementor.class.isAssignableFrom( clazz ) ) { if ( SessionImplementor.class.isAssignableFrom( clazz ) ) {
return ( T ) getSession(); return ( T ) internalGetSession();
} }
if ( EntityManager.class.isAssignableFrom( clazz ) ) { if ( EntityManager.class.isAssignableFrom( clazz ) ) {
return ( T ) this; return ( T ) this;
@ -1275,7 +1362,9 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage
@Override @Override
public boolean isJoinedToTransaction() { public boolean isJoinedToTransaction() {
final SessionImplementor session = (SessionImplementor) getSession(); checkOpen();
final SessionImplementor session = (SessionImplementor) internalGetSession();
final TransactionCoordinator transactionCoordinator = session.getTransactionCoordinator(); final TransactionCoordinator transactionCoordinator = session.getTransactionCoordinator();
final TransactionImplementor transaction = transactionCoordinator.getTransaction(); final TransactionImplementor transaction = transactionCoordinator.getTransaction();
@ -1284,9 +1373,7 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage
@Override @Override
public void joinTransaction() { public void joinTransaction() {
if( !isOpen() ){ checkOpen();
throw new IllegalStateException( "EntityManager is closed" );
}
joinTransaction( true ); joinTransaction( true );
} }
@ -1298,7 +1385,7 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage
return; return;
} }
final SessionImplementor session = (SessionImplementor) getSession(); final SessionImplementor session = (SessionImplementor) internalGetSession();
final TransactionCoordinator transactionCoordinator = session.getTransactionCoordinator(); final TransactionCoordinator transactionCoordinator = session.getTransactionCoordinator();
final TransactionImplementor transaction = transactionCoordinator.getTransaction(); final TransactionImplementor transaction = transactionCoordinator.getTransaction();
@ -1350,7 +1437,8 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage
* returns the underlying session * returns the underlying session
*/ */
public Object getDelegate() { public Object getDelegate() {
return getSession(); checkOpen();
return internalGetSession();
} }
private void writeObject(ObjectOutputStream oos) throws IOException { private void writeObject(ObjectOutputStream oos) throws IOException {
@ -1362,9 +1450,7 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage
tx = new TransactionImpl( this ); tx = new TransactionImpl( this );
} }
/** @Override
* {@inheritDoc}
*/
public void handlePersistenceException(PersistenceException e) { public void handlePersistenceException(PersistenceException e) {
if ( e instanceof NoResultException ) { if ( e instanceof NoResultException ) {
return; return;
@ -1388,19 +1474,15 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage
} }
} }
/** @Override
* {@inheritDoc}
*/
public void throwPersistenceException(PersistenceException e) { public void throwPersistenceException(PersistenceException e) {
handlePersistenceException( e ); handlePersistenceException( e );
throw e; throw e;
} }
/** @Override
* {@inheritDoc}
*/
//FIXME should we remove all calls to this method and use convert(RuntimeException) ?
public RuntimeException convert(HibernateException e) { public RuntimeException convert(HibernateException e) {
//FIXME should we remove all calls to this method and use convert(RuntimeException) ?
return convert( e, null ); return convert( e, null );
} }
@ -1415,9 +1497,7 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage
return result; return result;
} }
/** @Override
* {@inheritDoc}
*/
public RuntimeException convert(HibernateException e, LockOptions lockOptions) { public RuntimeException convert(HibernateException e, LockOptions lockOptions) {
if ( e instanceof StaleStateException ) { if ( e instanceof StaleStateException ) {
PersistenceException converted = wrapStaleStateException( ( StaleStateException ) e ); PersistenceException converted = wrapStaleStateException( ( StaleStateException ) e );
@ -1484,16 +1564,12 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage
} }
} }
/** @Override
* {@inheritDoc}
*/
public void throwPersistenceException(HibernateException e) { public void throwPersistenceException(HibernateException e) {
throw convert( e ); throw convert( e );
} }
/** @Override
* {@inheritDoc}
*/
public PersistenceException wrapStaleStateException(StaleStateException e) { public PersistenceException wrapStaleStateException(StaleStateException e) {
PersistenceException pe; PersistenceException pe;
if ( e instanceof StaleObjectStateException ) { if ( e instanceof StaleObjectStateException ) {
@ -1501,7 +1577,7 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage
Serializable identifier = sose.getIdentifier(); Serializable identifier = sose.getIdentifier();
if ( identifier != null ) { if ( identifier != null ) {
try { try {
Object entity = getRawSession().load( sose.getEntityName(), identifier ); Object entity = internalGetSession().load( sose.getEntityName(), identifier );
if ( entity instanceof Serializable ) { if ( entity instanceof Serializable ) {
//avoid some user errors regarding boundary crossing //avoid some user errors regarding boundary crossing
pe = new OptimisticLockException( null, e, entity ); pe = new OptimisticLockException( null, e, entity );

View File

@ -23,64 +23,35 @@
*/ */
package org.hibernate.jpa.spi; package org.hibernate.jpa.spi;
import javax.persistence.CacheRetrieveMode;
import javax.persistence.CacheStoreMode;
import javax.persistence.FlushModeType; import javax.persistence.FlushModeType;
import javax.persistence.Parameter; import javax.persistence.Parameter;
import javax.persistence.TemporalType;
import javax.persistence.TransactionRequiredException; import javax.persistence.TransactionRequiredException;
import javax.persistence.TypedQuery; import javax.persistence.TypedQuery;
import java.util.Collection; import java.util.Calendar;
import java.util.HashMap; import java.util.Date;
import java.util.Map;
import java.util.Set; import java.util.Set;
import org.jboss.logging.Logger;
import org.hibernate.CacheMode;
import org.hibernate.FlushMode;
import org.hibernate.HibernateException; import org.hibernate.HibernateException;
import org.hibernate.LockMode;
import org.hibernate.TypeMismatchException; import org.hibernate.TypeMismatchException;
import org.hibernate.hql.internal.QueryExecutionRequestException; import org.hibernate.hql.internal.QueryExecutionRequestException;
import org.hibernate.jpa.AvailableSettings;
import org.hibernate.jpa.QueryHints; import org.hibernate.jpa.QueryHints;
import org.hibernate.jpa.internal.EntityManagerMessageLogger;
import org.hibernate.jpa.internal.util.CacheModeHelper;
import org.hibernate.jpa.internal.util.ConfigurationHelper;
import org.hibernate.jpa.internal.util.LockModeTypeHelper;
import static org.hibernate.jpa.QueryHints.HINT_CACHEABLE;
import static org.hibernate.jpa.QueryHints.HINT_CACHE_MODE;
import static org.hibernate.jpa.QueryHints.HINT_CACHE_REGION;
import static org.hibernate.jpa.QueryHints.HINT_COMMENT;
import static org.hibernate.jpa.QueryHints.HINT_FETCH_SIZE;
import static org.hibernate.jpa.QueryHints.HINT_FLUSH_MODE;
import static org.hibernate.jpa.QueryHints.HINT_READONLY;
import static org.hibernate.jpa.QueryHints.HINT_TIMEOUT;
import static org.hibernate.jpa.QueryHints.SPEC_HINT_TIMEOUT;
/** /**
* Intended as a base class providing convenience in implementing both {@link javax.persistence.Query} and * Base class for implementing both {@link javax.persistence.Query} and {@link javax.persistence.TypedQuery}, including
* {@link javax.persistence.TypedQuery}. * query references built from criteria queries.
* <p/> * <p/>
* IMPL NOTE : This issue, and the reason for this distinction, is that criteria and hl.sql queries share no * Not intended as base for {@link javax.persistence.StoredProcedureQuery}
* commonality currently in Hibernate internals.
* *
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public abstract class AbstractQueryImpl<X> implements TypedQuery<X> { public abstract class AbstractQueryImpl<X> extends BaseQueryImpl implements TypedQuery<X> {
private static final EntityManagerMessageLogger LOG = Logger.getMessageLogger(EntityManagerMessageLogger.class,
AbstractQueryImpl.class.getName());
private final HibernateEntityManagerImplementor entityManager;
public AbstractQueryImpl(HibernateEntityManagerImplementor entityManager) { public AbstractQueryImpl(HibernateEntityManagerImplementor entityManager) {
this.entityManager = entityManager; super( entityManager );
} }
protected HibernateEntityManagerImplementor getEntityManager() { protected HibernateEntityManagerImplementor getEntityManager() {
return entityManager; return entityManager();
} }
/** /**
@ -93,9 +64,14 @@ public abstract class AbstractQueryImpl<X> implements TypedQuery<X> {
@Override @Override
@SuppressWarnings({ "ThrowableInstanceNeverThrown" }) @SuppressWarnings({ "ThrowableInstanceNeverThrown" })
public int executeUpdate() { public int executeUpdate() {
checkOpen( true );
try { try {
if ( ! entityManager.isTransactionInProgress() ) { if ( ! entityManager().isTransactionInProgress() ) {
entityManager.throwPersistenceException( new TransactionRequiredException( "Executing an update/delete query" ) ); entityManager().throwPersistenceException(
new TransactionRequiredException(
"Executing an update/delete query"
)
);
return 0; return 0;
} }
return internalExecuteUpdate(); return internalExecuteUpdate();
@ -107,197 +83,27 @@ public abstract class AbstractQueryImpl<X> implements TypedQuery<X> {
throw new IllegalArgumentException(e); throw new IllegalArgumentException(e);
} }
catch ( HibernateException he) { catch ( HibernateException he) {
entityManager.throwPersistenceException( he ); entityManager().throwPersistenceException( he );
return 0; return 0;
} }
} }
private int maxResults = -1;
/**
* Apply the given max results value.
*
* @param maxResults The specified max results
*/
protected abstract void applyMaxResults(int maxResults);
@Override @Override
public TypedQuery<X> setMaxResults(int maxResult) { @SuppressWarnings("unchecked")
if ( maxResult < 0 ) { public AbstractQueryImpl<X> setMaxResults(int maxResults) {
throw new IllegalArgumentException( return (AbstractQueryImpl<X>) super.setMaxResults( maxResults );
"Negative value (" + maxResult + ") passed to setMaxResults"
);
}
this.maxResults = maxResult;
applyMaxResults( maxResult );
return this;
}
public int getSpecifiedMaxResults() {
return maxResults;
} }
@Override @Override
public int getMaxResults() { @SuppressWarnings("unchecked")
return maxResults == -1 public AbstractQueryImpl<X> setFirstResult(int firstResult) {
? Integer.MAX_VALUE // stupid spec... MAX_VALUE?? return (AbstractQueryImpl<X>) super.setFirstResult( firstResult );
: maxResults;
} }
private int firstResult;
/**
* Apply the given first-result value.
*
* @param firstResult The specified first-result value.
*/
protected abstract void applyFirstResult(int firstResult);
@Override
public TypedQuery<X> setFirstResult(int firstResult) {
if ( firstResult < 0 ) {
throw new IllegalArgumentException(
"Negative value (" + firstResult + ") passed to setFirstResult"
);
}
this.firstResult = firstResult;
applyFirstResult( firstResult );
return this;
}
@Override
public int getFirstResult() {
return firstResult;
}
private Map<String, Object> hints;
@Override
public Map<String, Object> getHints() {
return hints;
}
protected abstract void applyTimeout(int timeout);
protected abstract void applyLockTimeout(int timeout);
protected abstract void applyComment(String comment);
protected abstract void applyFetchSize(int fetchSize);
protected abstract void applyCacheable(boolean isCacheable);
protected abstract void applyCacheRegion(String regionName);
protected abstract void applyReadOnly(boolean isReadOnly);
protected abstract void applyCacheMode(CacheMode cacheMode);
protected abstract void applyFlushMode(FlushMode flushMode);
protected abstract boolean canApplyLockModes();
protected abstract void applyAliasSpecificLockMode(String alias, LockMode lockMode);
@Override @Override
@SuppressWarnings( {"deprecation"}) @SuppressWarnings( {"deprecation"})
public TypedQuery<X> setHint(String hintName, Object value) { public AbstractQueryImpl<X> setHint(String hintName, Object value) {
boolean skipped = false; super.setHint( hintName, value );
try {
if ( HINT_TIMEOUT.equals( hintName ) ) {
applyTimeout( ConfigurationHelper.getInteger( value ) );
}
else if ( SPEC_HINT_TIMEOUT.equals( hintName ) ) {
// convert milliseconds to seconds
int timeout = (int)Math.round(ConfigurationHelper.getInteger( value ).doubleValue() / 1000.0 );
applyTimeout( timeout );
}
else if ( AvailableSettings.LOCK_TIMEOUT.equals( hintName ) ) {
applyLockTimeout( ConfigurationHelper.getInteger( value ) );
}
else if ( HINT_COMMENT.equals( hintName ) ) {
applyComment( (String) value );
}
else if ( HINT_FETCH_SIZE.equals( hintName ) ) {
applyFetchSize( ConfigurationHelper.getInteger( value ) );
}
else if ( HINT_CACHEABLE.equals( hintName ) ) {
applyCacheable( ConfigurationHelper.getBoolean( value ) );
}
else if ( HINT_CACHE_REGION.equals( hintName ) ) {
applyCacheRegion( (String) value );
}
else if ( HINT_READONLY.equals( hintName ) ) {
applyReadOnly( ConfigurationHelper.getBoolean( value ) );
}
else if ( HINT_CACHE_MODE.equals( hintName ) ) {
applyCacheMode( ConfigurationHelper.getCacheMode( value ) );
}
else if ( HINT_FLUSH_MODE.equals( hintName ) ) {
applyFlushMode( ConfigurationHelper.getFlushMode( value ) );
}
else if ( AvailableSettings.SHARED_CACHE_RETRIEVE_MODE.equals( hintName ) ) {
final CacheRetrieveMode retrieveMode = (CacheRetrieveMode) value;
CacheStoreMode storeMode = hints != null
? (CacheStoreMode) hints.get( AvailableSettings.SHARED_CACHE_STORE_MODE )
: null;
if ( storeMode == null ) {
storeMode = (CacheStoreMode) entityManager.getProperties()
.get( AvailableSettings.SHARED_CACHE_STORE_MODE );
}
applyCacheMode(
CacheModeHelper.interpretCacheMode( storeMode, retrieveMode )
);
}
else if ( AvailableSettings.SHARED_CACHE_STORE_MODE.equals( hintName ) ) {
final CacheStoreMode storeMode = (CacheStoreMode) value;
CacheRetrieveMode retrieveMode = hints != null
? (CacheRetrieveMode) hints.get( AvailableSettings.SHARED_CACHE_RETRIEVE_MODE )
: null;
if ( retrieveMode == null ) {
retrieveMode = (CacheRetrieveMode) entityManager.getProperties()
.get( AvailableSettings.SHARED_CACHE_RETRIEVE_MODE );
}
applyCacheMode(
CacheModeHelper.interpretCacheMode( storeMode, retrieveMode )
);
}
else if ( hintName.startsWith( AvailableSettings.ALIAS_SPECIFIC_LOCK_MODE ) ) {
if ( ! canApplyLockModes() ) {
skipped = true;
}
else {
// extract the alias
final String alias = hintName.substring( AvailableSettings.ALIAS_SPECIFIC_LOCK_MODE.length() + 1 );
// determine the LockMode
try {
final LockMode lockMode = LockModeTypeHelper.interpretLockMode( value );
applyAliasSpecificLockMode( alias, lockMode );
}
catch ( Exception e ) {
LOG.unableToDetermineLockModeValue(hintName, value);
skipped = true;
}
}
}
else {
skipped = true;
LOG.ignoringUnrecognizedQueryHint(hintName);
}
}
catch ( ClassCastException e ) {
throw new IllegalArgumentException( "Value for hint" );
}
if ( !skipped ) {
if ( hints == null ) {
hints = new HashMap<String,Object>();
}
hints.put( hintName, value );
}
return this; return this;
} }
@ -306,171 +112,91 @@ public abstract class AbstractQueryImpl<X> implements TypedQuery<X> {
return QueryHints.getDefinedHints(); return QueryHints.getDefinedHints();
} }
@Override private javax.persistence.LockModeType jpaLockMode = javax.persistence.LockModeType.NONE;
public abstract TypedQuery<X> setLockMode(javax.persistence.LockModeType lockModeType);
@Override @Override
public abstract javax.persistence.LockModeType getLockMode(); @SuppressWarnings({ "unchecked" })
public TypedQuery<X> setLockMode(javax.persistence.LockModeType lockModeType) {
private FlushModeType jpaFlushMode; checkOpen( true );
if (! getEntityManager().isTransactionInProgress()) {
@Override throw new TransactionRequiredException( "no transaction is in progress" );
public TypedQuery<X> setFlushMode(FlushModeType jpaFlushMode) {
this.jpaFlushMode = jpaFlushMode;
// TODO : treat as hint?
if ( jpaFlushMode == FlushModeType.AUTO ) {
applyFlushMode( FlushMode.AUTO );
} }
else if ( jpaFlushMode == FlushModeType.COMMIT ) { if ( ! canApplyAliasSpecificLockModeHints() ) {
applyFlushMode( FlushMode.COMMIT ); throw new IllegalStateException( "Not a JPAQL/Criteria query" );
} }
this.jpaLockMode = lockModeType;
internalApplyLockMode( lockModeType );
return this; return this;
} }
@SuppressWarnings( {"UnusedDeclaration"}) protected abstract void internalApplyLockMode(javax.persistence.LockModeType lockModeType);
protected FlushModeType getSpecifiedFlushMode() {
return jpaFlushMode; @Override
public javax.persistence.LockModeType getLockMode() {
getEntityManager().checkOpen( false );
return jpaLockMode;
}
// convariant return handling ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@Override
@SuppressWarnings("unchecked")
public <T> AbstractQueryImpl<X> setParameter(Parameter<T> param, T value) {
return (AbstractQueryImpl<X>) super.setParameter( param, value );
} }
@Override @Override
public FlushModeType getFlushMode() { @SuppressWarnings("unchecked")
return jpaFlushMode != null public AbstractQueryImpl<X> setParameter(Parameter<Calendar> param, Calendar value, TemporalType temporalType) {
? jpaFlushMode return (AbstractQueryImpl<X>) super.setParameter( param, value, temporalType );
: entityManager.getFlushMode();
}
private Map parameterBindings;
@SuppressWarnings( {"unchecked"})
protected void registerParameterBinding(Parameter parameter, Object value) {
if ( parameter == null ) {
throw new IllegalArgumentException( "parameter cannot be null" );
}
validateParameterBinding( parameter, value );
if ( parameterBindings == null ) {
parameterBindings = new HashMap();
}
parameterBindings.put( parameter, value );
}
private void validateParameterBinding(Parameter parameter, Object value) {
if ( value == null || parameter.getParameterType() == null ) {
// nothing we can check
return;
}
if ( Collection.class.isInstance( value )
&& ! Collection.class.isAssignableFrom( parameter.getParameterType() ) ) {
// we have a collection passed in where we are expecting a non-collection.
// NOTE : this can happen in Hibernate's notion of "parameter list" binding
// NOTE2 : the case of a collection value and an expected collection (if that can even happen)
// will fall through to the main check.
validateCollectionValuedParameterMultiBinding( parameter, (Collection) value );
}
else if ( value.getClass().isArray() ) {
validateArrayValuedParameterBinding( parameter, value );
}
else {
if ( ! parameter.getParameterType().isInstance( value ) ) {
throw new IllegalArgumentException(
String.format(
"Parameter value [%s] did not match expected type [%s]",
value,
parameter.getParameterType().getName()
)
);
}
}
}
private void validateCollectionValuedParameterMultiBinding(Parameter parameter, Collection value) {
// validate the elements...
for ( Object element : value ) {
if ( ! parameter.getParameterType().isInstance( element ) ) {
throw new IllegalArgumentException(
String.format(
"Parameter value element [%s] did not match expected type [%s]",
element,
parameter.getParameterType().getName()
)
);
}
}
}
private void validateArrayValuedParameterBinding(Parameter parameter, Object value) {
if ( ! parameter.getParameterType().isArray() ) {
throw new IllegalArgumentException(
String.format(
"Encountered array-valued parameter binding, but was expecting [%s]",
parameter.getParameterType().getName()
)
);
}
if ( value.getClass().getComponentType().isPrimitive() ) {
// we have a primitive array. we validate that the actual array has the component type (type odf elements)
// we expect based on the component type of the parameter specification
if ( ! parameter.getParameterType().getComponentType().isAssignableFrom( value.getClass().getComponentType() ) ) {
throw new IllegalArgumentException(
String.format(
"Primitive array-valued parameter bind value type [%s] did not match expected type [%s]",
value.getClass().getComponentType().getName(),
parameter.getParameterType().getName()
)
);
}
}
else {
// we have an object array. Here we loop over the array and physically check each element against
// the type we expect based on the component type of the parameter specification
final Object[] array = (Object[]) value;
for ( Object element : array ) {
if ( ! parameter.getParameterType().getComponentType().isInstance( element ) ) {
throw new IllegalArgumentException(
String.format(
"Array-valued parameter value element [%s] did not match expected type [%s]",
element,
parameter.getParameterType().getName()
)
);
}
}
}
} }
@Override @Override
public boolean isBound(Parameter<?> param) { @SuppressWarnings("unchecked")
return parameterBindings != null && parameterBindings.containsKey( param ); public AbstractQueryImpl<X> setParameter(Parameter<Date> param, Date value, TemporalType temporalType) {
return (AbstractQueryImpl<X>) super.setParameter( param, value, temporalType );
} }
@Override @Override
@SuppressWarnings({ "unchecked" }) @SuppressWarnings("unchecked")
public <T> T getParameterValue(Parameter<T> param) { public AbstractQueryImpl<X> setParameter(String name, Object value) {
if ( parameterBindings == null ) { return (AbstractQueryImpl<X>) super.setParameter( name, value );
throw new IllegalStateException( "No parameters have been bound" );
}
try {
T value = (T) parameterBindings.get( param );
if ( value == null ) {
throw new IllegalStateException( "Parameter has not been bound" );
}
return value;
}
catch ( ClassCastException cce ) {
throw new IllegalStateException( "Encountered a parameter value type exception" );
}
} }
@Override @Override
public Object getParameterValue(String name) { @SuppressWarnings("unchecked")
return getParameterValue( getParameter( name ) ); public AbstractQueryImpl<X> setParameter(String name, Calendar value, TemporalType temporalType) {
return (AbstractQueryImpl<X>) super.setParameter( name, value, temporalType );
} }
@Override @Override
public Object getParameterValue(int position) { @SuppressWarnings("unchecked")
return getParameterValue( getParameter( position ) ); public AbstractQueryImpl<X> setParameter(String name, Date value, TemporalType temporalType) {
return (AbstractQueryImpl<X>) super.setParameter( name, value, temporalType );
}
@Override
@SuppressWarnings("unchecked")
public AbstractQueryImpl<X> setParameter(int position, Object value) {
return (AbstractQueryImpl<X>) super.setParameter( position, value );
}
@Override
@SuppressWarnings("unchecked")
public AbstractQueryImpl<X> setParameter(int position, Calendar value, TemporalType temporalType) {
return (AbstractQueryImpl<X>) super.setParameter( position, value, temporalType );
}
@Override
@SuppressWarnings("unchecked")
public AbstractQueryImpl<X> setParameter(int position, Date value, TemporalType temporalType) {
return (AbstractQueryImpl<X>) super.setParameter( position, value, temporalType );
}
@Override
@SuppressWarnings("unchecked")
public AbstractQueryImpl<X> setFlushMode(FlushModeType jpaFlushMode) {
return (AbstractQueryImpl<X>) super.setFlushMode( jpaFlushMode );
} }
} }

View File

@ -27,12 +27,14 @@ import javax.persistence.CacheRetrieveMode;
import javax.persistence.CacheStoreMode; import javax.persistence.CacheStoreMode;
import javax.persistence.FlushModeType; import javax.persistence.FlushModeType;
import javax.persistence.Parameter; import javax.persistence.Parameter;
import javax.persistence.ParameterMode;
import javax.persistence.Query; import javax.persistence.Query;
import javax.persistence.TemporalType; import javax.persistence.TemporalType;
import java.util.Calendar; import java.util.Calendar;
import java.util.Collection;
import java.util.Date; import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.HashSet;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
@ -40,7 +42,9 @@ import org.jboss.logging.Logger;
import org.hibernate.CacheMode; import org.hibernate.CacheMode;
import org.hibernate.FlushMode; import org.hibernate.FlushMode;
import org.hibernate.HibernateException;
import org.hibernate.LockMode; import org.hibernate.LockMode;
import org.hibernate.QueryParameterException;
import org.hibernate.jpa.AvailableSettings; import org.hibernate.jpa.AvailableSettings;
import org.hibernate.jpa.QueryHints; import org.hibernate.jpa.QueryHints;
import org.hibernate.jpa.internal.EntityManagerMessageLogger; import org.hibernate.jpa.internal.EntityManagerMessageLogger;
@ -59,9 +63,9 @@ import static org.hibernate.jpa.QueryHints.HINT_TIMEOUT;
import static org.hibernate.jpa.QueryHints.SPEC_HINT_TIMEOUT; import static org.hibernate.jpa.QueryHints.SPEC_HINT_TIMEOUT;
/** /**
* Intended as the base class for all {@link javax.persistence.Query} implementations, including {@link javax.persistence.TypedQuery} and * Intended as the base class for all {@link javax.persistence.Query} implementations, including
* {@link javax.persistence.StoredProcedureQuery}. Care should be taken that all changes here fit with all * {@link javax.persistence.TypedQuery} and {@link javax.persistence.StoredProcedureQuery}. Care should be taken
* those usages. * that all changes here fit with all those usages.
* *
* @author Steve Ebersole * @author Steve Ebersole
*/ */
@ -86,6 +90,10 @@ public abstract class BaseQueryImpl implements Query {
return entityManager; return entityManager;
} }
protected void checkOpen(boolean markForRollbackIfClosed) {
entityManager.checkOpen( markForRollbackIfClosed );
}
// Limits (first and max results) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Limits (first and max results) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -98,6 +106,8 @@ public abstract class BaseQueryImpl implements Query {
@Override @Override
public BaseQueryImpl setFirstResult(int firstResult) { public BaseQueryImpl setFirstResult(int firstResult) {
checkOpen( true );
if ( firstResult < 0 ) { if ( firstResult < 0 ) {
throw new IllegalArgumentException( throw new IllegalArgumentException(
"Negative value (" + firstResult + ") passed to setFirstResult" "Negative value (" + firstResult + ") passed to setFirstResult"
@ -110,6 +120,7 @@ public abstract class BaseQueryImpl implements Query {
@Override @Override
public int getFirstResult() { public int getFirstResult() {
checkOpen( false ); // technically should rollback
return firstResult; return firstResult;
} }
@ -122,6 +133,7 @@ public abstract class BaseQueryImpl implements Query {
@Override @Override
public BaseQueryImpl setMaxResults(int maxResult) { public BaseQueryImpl setMaxResults(int maxResult) {
checkOpen( true );
if ( maxResult < 0 ) { if ( maxResult < 0 ) {
throw new IllegalArgumentException( throw new IllegalArgumentException(
"Negative value (" + maxResult + ") passed to setMaxResults" "Negative value (" + maxResult + ") passed to setMaxResults"
@ -138,6 +150,7 @@ public abstract class BaseQueryImpl implements Query {
@Override @Override
public int getMaxResults() { public int getMaxResults() {
checkOpen( false ); // technically should rollback
return maxResults == -1 return maxResults == -1
? Integer.MAX_VALUE // stupid spec... MAX_VALUE?? ? Integer.MAX_VALUE // stupid spec... MAX_VALUE??
: maxResults; : maxResults;
@ -153,6 +166,7 @@ public abstract class BaseQueryImpl implements Query {
@Override @Override
public Map<String, Object> getHints() { public Map<String, Object> getHints() {
checkOpen( false ); // technically should rollback
return hints; return hints;
} }
@ -190,7 +204,7 @@ public abstract class BaseQueryImpl implements Query {
* *
* @return {@code true} if the hint was "applied" * @return {@code true} if the hint was "applied"
*/ */
protected abstract boolean applyFetchSize(int fetchSize); protected abstract boolean applyFetchSizeHint(int fetchSize);
/** /**
* Apply the cacheable (true/false) hint. * Apply the cacheable (true/false) hint.
@ -242,11 +256,11 @@ public abstract class BaseQueryImpl implements Query {
* *
* @return {@code true} indicates they can be applied, {@code false} otherwise. * @return {@code true} indicates they can be applied, {@code false} otherwise.
*/ */
protected abstract boolean canApplyLockModesHints(); protected abstract boolean canApplyAliasSpecificLockModeHints();
/** /**
* Apply the alias specific lock modes. Assumes {@link #canApplyLockModesHints()} has already been called and * Apply the alias specific lock modes. Assumes {@link #canApplyAliasSpecificLockModeHints()} has already been
* returned {@code true}. * called and returned {@code true}.
* *
* @param alias The alias to apply the 'lockMode' to. * @param alias The alias to apply the 'lockMode' to.
* @param lockMode The LockMode to apply. * @param lockMode The LockMode to apply.
@ -256,6 +270,7 @@ public abstract class BaseQueryImpl implements Query {
@Override @Override
@SuppressWarnings( {"deprecation"}) @SuppressWarnings( {"deprecation"})
public BaseQueryImpl setHint(String hintName, Object value) { public BaseQueryImpl setHint(String hintName, Object value) {
checkOpen( true );
boolean applied = false; boolean applied = false;
try { try {
if ( HINT_TIMEOUT.equals( hintName ) ) { if ( HINT_TIMEOUT.equals( hintName ) ) {
@ -273,7 +288,7 @@ public abstract class BaseQueryImpl implements Query {
applied = applyCommentHint( (String) value ); applied = applyCommentHint( (String) value );
} }
else if ( HINT_FETCH_SIZE.equals( hintName ) ) { else if ( HINT_FETCH_SIZE.equals( hintName ) ) {
applied = applyFetchSize( ConfigurationHelper.getInteger( value ) ); applied = applyFetchSizeHint( ConfigurationHelper.getInteger( value ) );
} }
else if ( HINT_CACHEABLE.equals( hintName ) ) { else if ( HINT_CACHEABLE.equals( hintName ) ) {
applied = applyCacheableHint( ConfigurationHelper.getBoolean( value ) ); applied = applyCacheableHint( ConfigurationHelper.getBoolean( value ) );
@ -315,7 +330,7 @@ public abstract class BaseQueryImpl implements Query {
); );
} }
else if ( hintName.startsWith( AvailableSettings.ALIAS_SPECIFIC_LOCK_MODE ) ) { else if ( hintName.startsWith( AvailableSettings.ALIAS_SPECIFIC_LOCK_MODE ) ) {
if ( canApplyLockModesHints() ) { if ( canApplyAliasSpecificLockModeHints() ) {
// extract the alias // extract the alias
final String alias = hintName.substring( AvailableSettings.ALIAS_SPECIFIC_LOCK_MODE.length() + 1 ); final String alias = hintName.substring( AvailableSettings.ALIAS_SPECIFIC_LOCK_MODE.length() + 1 );
// determine the LockMode // determine the LockMode
@ -360,6 +375,7 @@ public abstract class BaseQueryImpl implements Query {
@Override @Override
public BaseQueryImpl setFlushMode(FlushModeType jpaFlushMode) { public BaseQueryImpl setFlushMode(FlushModeType jpaFlushMode) {
checkOpen( true );
this.jpaFlushMode = jpaFlushMode; this.jpaFlushMode = jpaFlushMode;
// TODO : treat as hint? // TODO : treat as hint?
if ( jpaFlushMode == FlushModeType.AUTO ) { if ( jpaFlushMode == FlushModeType.AUTO ) {
@ -378,6 +394,7 @@ public abstract class BaseQueryImpl implements Query {
@Override @Override
public FlushModeType getFlushMode() { public FlushModeType getFlushMode() {
checkOpen( false );
return jpaFlushMode != null return jpaFlushMode != null
? jpaFlushMode ? jpaFlushMode
: entityManager.getFlushMode(); : entityManager.getFlushMode();
@ -386,27 +403,78 @@ public abstract class BaseQueryImpl implements Query {
// Parameters ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Parameters ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
private List<ParameterImplementor> parameters; private Set<ParameterRegistration<?>> parameterRegistrations;
protected <X> ParameterRegistration<X> findParameterRegistration(Parameter<X> parameter) {
if ( ParameterRegistration.class.isInstance( parameter ) ) {
return (ParameterRegistration<X>) parameter;
}
else {
if ( parameter.getName() != null ) {
return findParameterRegistration( parameter.getName() );
}
else if ( parameter.getPosition() != null ) {
return findParameterRegistration( parameter.getPosition() );
}
}
throw new IllegalArgumentException( "Unable to resolve incoming parameter [" + parameter + "] to registration" );
}
@SuppressWarnings("unchecked")
protected <X> ParameterRegistration<X> findParameterRegistration(String parameterName) {
return (ParameterRegistration<X>) getParameter( parameterName );
}
@SuppressWarnings("unchecked")
protected <X> ParameterRegistration<X> findParameterRegistration(int parameterPosition) {
if ( isJpaPositionalParameter( parameterPosition ) ) {
return findParameterRegistration( Integer.toString( parameterPosition ) );
}
else {
return (ParameterRegistration<X>) getParameter( parameterPosition );
}
}
protected abstract boolean isJpaPositionalParameter(int position);
/** /**
* Hibernate specific extension to the JPA {@link javax.persistence.Parameter} contract. * Hibernate specific extension to the JPA {@link javax.persistence.Parameter} contract.
*/ */
protected static interface ParameterImplementor<T> extends Parameter<T> { protected static interface ParameterRegistration<T> extends Parameter<T> {
/**
* Retrieves the parameter "mode" which describes how the parameter is defined in the actual database procedure
* definition (is it an INPUT parameter? An OUTPUT parameter? etc).
*
* @return The parameter mode.
*/
public ParameterMode getMode();
public boolean isBindable(); public boolean isBindable();
public ParameterValue getBoundValue(); public void bindValue(T value);
public void bindValue(T value, TemporalType specifiedTemporalType);
public ParameterBind<T> getBind();
} }
protected static class ParameterValue { protected static interface ParameterBind<T> {
private final Object value; public T getValue();
public TemporalType getSpecifiedTemporalType();
}
protected static class ParameterBindImpl<T> implements ParameterBind<T> {
private final T value;
private final TemporalType specifiedTemporalType; private final TemporalType specifiedTemporalType;
public ParameterValue(Object value, TemporalType specifiedTemporalType) { public ParameterBindImpl(T value, TemporalType specifiedTemporalType) {
this.value = value; this.value = value;
this.specifiedTemporalType = specifiedTemporalType; this.specifiedTemporalType = specifiedTemporalType;
} }
public Object getValue() { public T getValue() {
return value; return value;
} }
@ -415,131 +483,193 @@ public abstract class BaseQueryImpl implements Query {
} }
} }
private Map<ParameterImplementor<?>,ParameterValue> parameterBindingMap; private Set<ParameterRegistration<?>> parameterRegistrations() {
if ( parameterRegistrations == null ) {
private Map<ParameterImplementor<?>,ParameterValue> parameterBindingMap() { // todo : could se use an identity set here?
if ( parameterBindingMap == null ) { parameterRegistrations = new HashSet<ParameterRegistration<?>>();
parameterBindingMap = new HashMap<ParameterImplementor<?>, ParameterValue>();
} }
return parameterBindingMap; return parameterRegistrations;
} }
protected void registerParameter(ParameterImplementor parameter) { protected void registerParameter(ParameterRegistration parameter) {
if ( parameter == null ) { if ( parameter == null ) {
throw new IllegalArgumentException( "parameter cannot be null" ); throw new IllegalArgumentException( "parameter cannot be null" );
} }
if ( parameterBindingMap().containsKey( parameter ) ) { if ( parameterRegistrations().contains( parameter ) ) {
LOG.debug( "Parameter registered multiple times : " + parameter );
return; return;
} }
parameterBindingMap().put( parameter, null ); parameterRegistrations().add( parameter );
}
@SuppressWarnings("unchecked")
protected void registerParameterBinding(Parameter parameter, ParameterValue bindValue) {
validateParameterBinding( (ParameterImplementor) parameter, bindValue );
parameterBindingMap().put( (ParameterImplementor) parameter, bindValue );
}
protected void validateParameterBinding(ParameterImplementor parameter, ParameterValue bindValue) {
if ( parameter == null ) {
throw new IllegalArgumentException( "parameter cannot be null" );
}
if ( ! parameter.isBindable() ) {
throw new IllegalArgumentException( "Parameter [" + parameter + "] not valid for binding" );
}
if ( ! parameterBindingMap().containsKey( parameter ) ) {
throw new IllegalArgumentException( "Unknown parameter [" + parameter + "] specified for value binding" );
}
if ( isBound( parameter ) ) {
throw new IllegalArgumentException( "Parameter [" + parameter + "] already had bound value" );
}
validateParameterBindingTypes( parameter, bindValue );
}
protected abstract void validateParameterBindingTypes(ParameterImplementor parameter, ParameterValue bindValue);
protected ParameterValue makeBindValue(Object value) {
return new ParameterValue( value, null );
}
protected ParameterValue makeBindValue(Calendar value, TemporalType temporalType) {
return new ParameterValue( value, temporalType );
}
protected ParameterValue makeBindValue(Date value, TemporalType temporalType) {
return new ParameterValue( value, temporalType );
} }
@Override @Override
public <T> BaseQueryImpl setParameter(Parameter<T> param, T value) { public <T> BaseQueryImpl setParameter(Parameter<T> param, T value) {
registerParameterBinding( param, makeBindValue( value ) ); checkOpen( true );
try {
findParameterRegistration( param ).bindValue( value );
}
catch (QueryParameterException e) {
throw new IllegalArgumentException( e );
}
catch (HibernateException he) {
throw entityManager.convert( he );
}
return this; return this;
} }
@Override @Override
public BaseQueryImpl setParameter(Parameter<Calendar> param, Calendar value, TemporalType temporalType) { public BaseQueryImpl setParameter(Parameter<Calendar> param, Calendar value, TemporalType temporalType) {
registerParameterBinding( param, makeBindValue( value, temporalType ) ); checkOpen( true );
try {
findParameterRegistration( param ).bindValue( value, temporalType );
}
catch (QueryParameterException e) {
throw new IllegalArgumentException( e );
}
catch (HibernateException he) {
throw entityManager.convert( he );
}
return this; return this;
} }
@Override @Override
public BaseQueryImpl setParameter(Parameter<Date> param, Date value, TemporalType temporalType) { public BaseQueryImpl setParameter(Parameter<Date> param, Date value, TemporalType temporalType) {
registerParameterBinding( param, makeBindValue( value, temporalType ) ); checkOpen( true );
try {
findParameterRegistration( param ).bindValue( value, temporalType );
}
catch (QueryParameterException e) {
throw new IllegalArgumentException( e );
}
catch (HibernateException he) {
throw entityManager.convert( he );
}
return this; return this;
} }
@Override @Override
@SuppressWarnings("unchecked")
public BaseQueryImpl setParameter(String name, Object value) { public BaseQueryImpl setParameter(String name, Object value) {
registerParameterBinding( getParameter( name ), makeBindValue( value ) ); checkOpen( true );
try {
findParameterRegistration( name ).bindValue( value );
}
catch (QueryParameterException e) {
throw new IllegalArgumentException( e );
}
catch (HibernateException he) {
throw entityManager.convert( he );
}
return this; return this;
} }
@Override @Override
public BaseQueryImpl setParameter(String name, Calendar value, TemporalType temporalType) { public BaseQueryImpl setParameter(String name, Calendar value, TemporalType temporalType) {
registerParameterBinding( getParameter( name ), makeBindValue( value, temporalType ) ); checkOpen( true );
try {
findParameterRegistration( name ).bindValue( value, temporalType );
}
catch (QueryParameterException e) {
throw new IllegalArgumentException( e );
}
catch (HibernateException he) {
throw entityManager.convert( he );
}
return this; return this;
} }
@Override @Override
public BaseQueryImpl setParameter(String name, Date value, TemporalType temporalType) { public BaseQueryImpl setParameter(String name, Date value, TemporalType temporalType) {
registerParameterBinding( getParameter( name ), makeBindValue( value, temporalType ) ); checkOpen( true );
try {
findParameterRegistration( name ).bindValue( value, temporalType );
}
catch (QueryParameterException e) {
throw new IllegalArgumentException( e );
}
catch (HibernateException he) {
throw entityManager.convert( he );
}
return this; return this;
} }
@Override @Override
public BaseQueryImpl setParameter(int position, Object value) { public BaseQueryImpl setParameter(int position, Object value) {
registerParameterBinding( getParameter( position ), makeBindValue( value ) ); checkOpen( true );
try {
findParameterRegistration( position ).bindValue( value );
}
catch (QueryParameterException e) {
throw new IllegalArgumentException( e );
}
catch (HibernateException he) {
throw entityManager.convert( he );
}
return this; return this;
} }
@Override @Override
public BaseQueryImpl setParameter(int position, Calendar value, TemporalType temporalType) { public BaseQueryImpl setParameter(int position, Calendar value, TemporalType temporalType) {
registerParameterBinding( getParameter( position ), makeBindValue( value, temporalType ) ); checkOpen( true );
try {
findParameterRegistration( position ).bindValue( value, temporalType );
}
catch (QueryParameterException e) {
throw new IllegalArgumentException( e );
}
catch (HibernateException he) {
throw entityManager.convert( he );
}
return this; return this;
} }
@Override @Override
public BaseQueryImpl setParameter(int position, Date value, TemporalType temporalType) { public BaseQueryImpl setParameter(int position, Date value, TemporalType temporalType) {
registerParameterBinding( getParameter( position ), makeBindValue( value, temporalType ) ); checkOpen( true );
try {
findParameterRegistration( position ).bindValue( value, temporalType );
}
catch (QueryParameterException e) {
throw new IllegalArgumentException( e );
}
catch (HibernateException he) {
throw entityManager.convert( he );
}
return this; return this;
} }
@Override @Override
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public Set getParameters() { public Set getParameters() {
return parameterBindingMap().keySet(); checkOpen( false );
return parameterRegistrations();
} }
@Override @Override
public Parameter<?> getParameter(String name) { public Parameter<?> getParameter(String name) {
if ( parameterBindingMap() != null ) { checkOpen( false );
for ( ParameterImplementor<?> param : parameterBindingMap.keySet() ) { if ( parameterRegistrations != null ) {
for ( ParameterRegistration<?> param : parameterRegistrations ) {
if ( name.equals( param.getName() ) ) { if ( name.equals( param.getName() ) ) {
return param; return param;
} }
@ -551,13 +681,36 @@ public abstract class BaseQueryImpl implements Query {
@Override @Override
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public <T> Parameter<T> getParameter(String name, Class<T> type) { public <T> Parameter<T> getParameter(String name, Class<T> type) {
return (Parameter<T>) getParameter( name ); checkOpen( false );
Parameter param = getParameter( name );
if ( param.getParameterType() != null ) {
// we were able to determine the expected type during analysis, so validate it here
if ( ! param.getParameterType().isAssignableFrom( type ) ) {
throw new IllegalArgumentException(
String.format(
"Parameter type [%s] is not assignment compatible with requested type [%s] for parameter named [%s]",
param.getParameterType().getName(),
type.getName(),
name
)
);
}
}
return (Parameter<T>) param;
} }
@Override @Override
public Parameter<?> getParameter(int position) { public Parameter<?> getParameter(int position) {
if ( parameterBindingMap() != null ) { if ( isJpaPositionalParameter( position ) ) {
for ( ParameterImplementor<?> param : parameterBindingMap.keySet() ) { return getParameter( Integer.toString( position ) );
}
checkOpen( false );
if ( parameterRegistrations != null ) {
for ( ParameterRegistration<?> param : parameterRegistrations ) {
if ( param.getPosition() == null ) {
continue;
}
if ( position == param.getPosition() ) { if ( position == param.getPosition() ) {
return param; return param;
} }
@ -569,22 +722,46 @@ public abstract class BaseQueryImpl implements Query {
@Override @Override
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public <T> Parameter<T> getParameter(int position, Class<T> type) { public <T> Parameter<T> getParameter(int position, Class<T> type) {
return (Parameter<T>) getParameter( position ); checkOpen( false );
Parameter param = getParameter( position );
if ( param.getParameterType() != null ) {
// we were able to determine the expected type during analysis, so validate it here
if ( ! param.getParameterType().isAssignableFrom( type ) ) {
throw new IllegalArgumentException(
String.format(
"Parameter type [%s] is not assignment compatible with requested type [%s] for parameter at position [%s]",
param.getParameterType().getName(),
type.getName(),
position
)
);
}
}
return (Parameter<T>) param;
} }
@Override @Override
public boolean isBound(Parameter<?> param) { public boolean isBound(Parameter<?> param) {
return parameterBindingMap() != null checkOpen( false );
&& parameterBindingMap.get( (ParameterImplementor) param ) != null; final ParameterRegistration registration = findParameterRegistration( param );
return registration != null && registration.isBindable() && registration.getBind() != null;
} }
@Override @Override
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public <T> T getParameterValue(Parameter<T> param) { public <T> T getParameterValue(Parameter<T> param) {
if ( parameterBindingMap != null ) { checkOpen( false );
final ParameterValue boundValue = parameterBindingMap.get( (ParameterImplementor) param );
if ( boundValue != null ) { final ParameterRegistration<T> registration = findParameterRegistration( param );
return (T) boundValue.getValue(); if ( registration != null ) {
if ( ! registration.isBindable() ) {
throw new IllegalArgumentException( "Passed parameter [" + param + "] is not bindable" );
}
final ParameterBind<T> bind = registration.getBind();
if ( bind != null ) {
return bind.getValue();
} }
} }
throw new IllegalStateException( "Parameter [" + param + "] has not yet been bound" ); throw new IllegalStateException( "Parameter [" + param + "] has not yet been bound" );
@ -592,11 +769,153 @@ public abstract class BaseQueryImpl implements Query {
@Override @Override
public Object getParameterValue(String name) { public Object getParameterValue(String name) {
checkOpen( false );
return getParameterValue( getParameter( name ) ); return getParameterValue( getParameter( name ) );
} }
@Override @Override
public Object getParameterValue(int position) { public Object getParameterValue(int position) {
checkOpen( false );
return getParameterValue( getParameter( position ) ); return getParameterValue( getParameter( position ) );
} }
protected static void validateBinding(Class parameterType, Object bind, TemporalType temporalType) {
if ( bind == null || parameterType == null ) {
// nothing we can check
return;
}
if ( Collection.class.isInstance( bind ) && ! Collection.class.isAssignableFrom( parameterType ) ) {
// we have a collection passed in where we are expecting a non-collection.
// NOTE : this can happen in Hibernate's notion of "parameter list" binding
// NOTE2 : the case of a collection value and an expected collection (if that can even happen)
// will fall through to the main check.
validateCollectionValuedParameterBinding( parameterType, (Collection) bind, temporalType );
}
else if ( bind.getClass().isArray() ) {
validateArrayValuedParameterBinding( parameterType, bind, temporalType );
}
else {
if ( ! isValidBindValue( parameterType, bind, temporalType ) ) {
throw new IllegalArgumentException(
String.format(
"Parameter value [%s] did not match expected type [%s (%s)]",
bind,
parameterType.getName(),
extractName( temporalType )
)
);
}
}
}
private static String extractName(TemporalType temporalType) {
return temporalType == null ? "n/a" : temporalType.name();
}
private static void validateCollectionValuedParameterBinding(
Class parameterType,
Collection value,
TemporalType temporalType) {
// validate the elements...
for ( Object element : value ) {
if ( ! isValidBindValue( parameterType, element, temporalType ) ) {
throw new IllegalArgumentException(
String.format(
"Parameter value element [%s] did not match expected type [%s (%s)]",
element,
parameterType.getName(),
extractName( temporalType )
)
);
}
}
}
private static void validateArrayValuedParameterBinding(
Class parameterType,
Object value,
TemporalType temporalType) {
if ( ! parameterType.isArray() ) {
throw new IllegalArgumentException(
String.format(
"Encountered array-valued parameter binding, but was expecting [%s (%s)]",
parameterType.getName(),
extractName( temporalType )
)
);
}
if ( value.getClass().getComponentType().isPrimitive() ) {
// we have a primitive array. we validate that the actual array has the component type (type of elements)
// we expect based on the component type of the parameter specification
if ( ! parameterType.getComponentType().isAssignableFrom( value.getClass().getComponentType() ) ) {
throw new IllegalArgumentException(
String.format(
"Primitive array-valued parameter bind value type [%s] did not match expected type [%s (%s)]",
value.getClass().getComponentType().getName(),
parameterType.getName(),
extractName( temporalType )
)
);
}
}
else {
// we have an object array. Here we loop over the array and physically check each element against
// the type we expect based on the component type of the parameter specification
final Object[] array = (Object[]) value;
for ( Object element : array ) {
if ( ! isValidBindValue( parameterType.getComponentType(), element, temporalType ) ) {
throw new IllegalArgumentException(
String.format(
"Array-valued parameter value element [%s] did not match expected type [%s (%s)]",
element,
parameterType.getName(),
extractName( temporalType )
)
);
}
}
}
}
private static boolean isValidBindValue(Class expectedType, Object value, TemporalType temporalType) {
if ( expectedType.isInstance( value ) ) {
return true;
}
if ( temporalType != null ) {
final boolean parameterDeclarationIsTemporal = Date.class.isAssignableFrom( expectedType )
|| Calendar.class.isAssignableFrom( expectedType );
final boolean bindIsTemporal = Date.class.isInstance( value )
|| Calendar.class.isInstance( value );
if ( parameterDeclarationIsTemporal && bindIsTemporal ) {
return true;
}
}
return false;
}
} }

View File

@ -52,6 +52,19 @@ public interface HibernateEntityManagerImplementor extends HibernateEntityManage
*/ */
public HibernateEntityManagerFactory getFactory(); public HibernateEntityManagerFactory getFactory();
/**
* Used to ensure the EntityManager is open, throwing IllegalStateException if it is closed.
*
* Depending on the value of {@code markForRollbackIfClosed}, may also rollback any enlisted-in transaction. This
* distinction is made across various sections of the spec. Most failed checks should rollback. Section
* 3.10.7 (per 2.1 spec) lists cases related to calls on related query objects that should not rollback.
*
* @param markForRollbackIfClosed If the EM is closed, should the transaction (if one) be marked for rollback?
*
* @throws IllegalStateException Thrown if the EM is closed
*/
public void checkOpen(boolean markForRollbackIfClosed) throws IllegalStateException;
/** /**
* Provides access to whether a transaction is currently in progress. * Provides access to whether a transaction is currently in progress.
* *

View File

@ -23,11 +23,14 @@
*/ */
package org.hibernate.jpa.test.query; package org.hibernate.jpa.test.query;
import java.sql.Timestamp;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Date; import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List; import java.util.List;
import javax.persistence.EntityManager; import javax.persistence.EntityManager;
import javax.persistence.Parameter;
import javax.persistence.Query; import javax.persistence.Query;
import javax.persistence.TemporalType; import javax.persistence.TemporalType;
import javax.persistence.Tuple; import javax.persistence.Tuple;
@ -357,6 +360,24 @@ public class QueryTest extends BaseEntityManagerFunctionalTestCase {
em.close(); em.close();
} }
@Test
public void testTemporalTypeBinding() {
EntityManager em = getOrCreateEntityManager();
em.getTransaction().begin();
Query query = em.createQuery( "select w from " + Wallet.class.getName() + " w where w.marketEntrance = :me" );
Parameter parameter = query.getParameter( "me", Date.class );
assertEquals( parameter.getParameterType(), Date.class );
query.setParameter( "me", new Date() );
query.setParameter( "me", new Date(), TemporalType.DATE );
query.setParameter( "me", new GregorianCalendar(), TemporalType.DATE );
em.getTransaction().commit();
em.close();
}
@Test @Test
public void testPositionalParameterForms() throws Exception { public void testPositionalParameterForms() throws Exception {
EntityManager em = getOrCreateEntityManager(); EntityManager em = getOrCreateEntityManager();
@ -404,12 +425,11 @@ public class QueryTest extends BaseEntityManagerFunctionalTestCase {
em.flush(); em.flush();
try {
Query query = em.createQuery( "select w from Wallet w where w.brand = ?1 and w.model = ?3" ); Query query = em.createQuery( "select w from Wallet w where w.brand = ?1 and w.model = ?3" );
query.setParameter( 1, "Lacoste" ); query.setParameter( 1, "Lacoste" );
try {
query.setParameter( 2, "Expensive" ); query.setParameter( 2, "Expensive" );
query.getResultList(); fail( "Should fail due to a user error in parameters" );
fail("The query should fail due to a user error in parameters");
} }
catch ( IllegalArgumentException e ) { catch ( IllegalArgumentException e ) {
//success //success

View File

@ -30,7 +30,7 @@ sourceSets {
} }
// Generate JPA2 static metamodel for default revision entities // Generate JPA2 static metamodel for default revision entities
task generateJpaMetamodelClasses(type: Compile) { task generateJpaMetamodelClasses(type: JavaCompile) {
classpath = compileJava.classpath + configurations.hibernateJpaModelGenTool classpath = compileJava.classpath + configurations.hibernateJpaModelGenTool
source = sourceSets.main.originalJavaSrcDirs source = sourceSets.main.originalJavaSrcDirs
destinationDir = file( "${buildDir}/tmp/apt" ) destinationDir = file( "${buildDir}/tmp/apt" )
@ -47,6 +47,7 @@ task generateJpaMetamodelClasses(type: Compile) {
} }
} }
compileJava.dependsOn generateJpaMetamodelClasses compileJava.dependsOn generateJpaMetamodelClasses
generateSources.dependsOn generateJpaMetamodelClasses
jar { jar {
manifest { manifest {

View File

@ -72,6 +72,25 @@ public interface AuditReader {
Number revision) throws IllegalArgumentException, Number revision) throws IllegalArgumentException,
NotAuditedException, IllegalStateException; NotAuditedException, IllegalStateException;
/**
* Find an entity by primary key at the given revision with the specified entityName,
* possibly including deleted entities in the search.
* @param cls Class of the entity.
* @param entityName Name of the entity (if can't be guessed basing on the {@code cls}).
* @param primaryKey Primary key of the entity.
* @param revision Revision in which to get the entity.
* @param includeDeletions Whether to include deleted entities in the search.
* @return The found entity instance at the given revision (its properties may be partially filled
* if not all properties are audited) or null, if an entity with that id didn't exist at that
* revision.
* @throws IllegalArgumentException If cls or primaryKey is null or revision is less or equal to 0.
* @throws NotAuditedException When entities of the given class are not audited.
* @throws IllegalStateException If the associated entity manager is closed.
*/
<T> T find(Class<T> cls, String entityName, Object primaryKey,
Number revision, boolean includeDeletions) throws IllegalArgumentException,
NotAuditedException, IllegalStateException;
/** /**
* Get a list of revision numbers, at which an entity was modified. * Get a list of revision numbers, at which an entity was modified.
* @param cls Class of the entity. * @param cls Class of the entity.

View File

@ -23,6 +23,7 @@
*/ */
package org.hibernate.envers.entities; package org.hibernate.envers.entities;
import org.hibernate.envers.RevisionType;
import org.hibernate.envers.configuration.AuditConfiguration; import org.hibernate.envers.configuration.AuditConfiguration;
import org.hibernate.envers.entities.mapper.id.IdMapper; import org.hibernate.envers.entities.mapper.id.IdMapper;
import org.hibernate.envers.entities.mapper.relation.lazy.ToOneDelegateSessionImplementor; import org.hibernate.envers.entities.mapper.relation.lazy.ToOneDelegateSessionImplementor;
@ -77,7 +78,7 @@ public class EntityInstantiator {
// Fixes HHH-4751 issue (@IdClass with @ManyToOne relation mapping inside) // Fixes HHH-4751 issue (@IdClass with @ManyToOne relation mapping inside)
// Note that identifiers are always audited // Note that identifiers are always audited
// Replace identifier proxies if do not point to audit tables // Replace identifier proxies if do not point to audit tables
replaceNonAuditIdProxies(originalId, revision); replaceNonAuditIdProxies(versionsEntity, revision);
Object primaryKey = idMapper.mapToIdFromMap(originalId); Object primaryKey = idMapper.mapToIdFromMap(originalId);
@ -116,7 +117,8 @@ public class EntityInstantiator {
} }
@SuppressWarnings({"unchecked"}) @SuppressWarnings({"unchecked"})
private void replaceNonAuditIdProxies(Map originalId, Number revision) { private void replaceNonAuditIdProxies(Map versionsEntity, Number revision) {
final Map originalId = (Map) versionsEntity.get( verCfg.getAuditEntCfg().getOriginalIdPropName() );
for (Object key : originalId.keySet()) { for (Object key : originalId.keySet()) {
Object value = originalId.get(key); Object value = originalId.get(key);
if (value instanceof HibernateProxy) { if (value instanceof HibernateProxy) {
@ -133,7 +135,10 @@ public class EntityInstantiator {
catch ( ClassNotFoundException e ) { catch ( ClassNotFoundException e ) {
throw new AuditException( e ); throw new AuditException( e );
} }
final ToOneDelegateSessionImplementor delegate = new ToOneDelegateSessionImplementor(versionsReader, entityClass, entityId, revision, verCfg); final ToOneDelegateSessionImplementor delegate = new ToOneDelegateSessionImplementor(
versionsReader, entityClass, entityId, revision,
RevisionType.DEL.equals( versionsEntity.get( verCfg.getAuditEntCfg().getRevisionTypePropName() ) ),
verCfg);
originalId.put(key, originalId.put(key,
versionsReader.getSessionImplementor().getFactory().getEntityPersister(entityName).createProxy(entityId, delegate)); versionsReader.getSessionImplementor().getFactory().getEntityPersister(entityName).createProxy(entityId, delegate));
} }

View File

@ -15,10 +15,12 @@ public class ToOneEntityLoader {
* Immediately loads historical entity or its current state when excluded from audit process. * Immediately loads historical entity or its current state when excluded from audit process.
*/ */
public static Object loadImmediate(AuditReaderImplementor versionsReader, Class<?> entityClass, String entityName, public static Object loadImmediate(AuditReaderImplementor versionsReader, Class<?> entityClass, String entityName,
Object entityId, Number revision, AuditConfiguration verCfg) { Object entityId, Number revision, boolean removed, AuditConfiguration verCfg) {
if ( verCfg.getEntCfg().getNotVersionEntityConfiguration( entityName ) == null ) { if ( verCfg.getEntCfg().getNotVersionEntityConfiguration( entityName ) == null ) {
// Audited relation, look up entity with Envers. // Audited relation, look up entity with Envers.
return versionsReader.find( entityClass, entityName, entityId, revision ); // When user traverses removed entities graph, do not restrict revision type of referencing objects
// to ADD or MOD (DEL possible). See HHH-5845.
return versionsReader.find( entityClass, entityName, entityId, revision, removed);
} }
else { else {
// Not audited relation, look up entity with Hibernate. // Not audited relation, look up entity with Hibernate.
@ -30,11 +32,11 @@ public class ToOneEntityLoader {
* Creates proxy of referenced *-to-one entity. * Creates proxy of referenced *-to-one entity.
*/ */
public static Object createProxy(AuditReaderImplementor versionsReader, Class<?> entityClass, String entityName, public static Object createProxy(AuditReaderImplementor versionsReader, Class<?> entityClass, String entityName,
Object entityId, Number revision, AuditConfiguration verCfg) { Object entityId, Number revision, boolean removed, AuditConfiguration verCfg) {
EntityPersister persister = versionsReader.getSessionImplementor().getFactory().getEntityPersister( entityName ); EntityPersister persister = versionsReader.getSessionImplementor().getFactory().getEntityPersister( entityName );
return persister.createProxy( return persister.createProxy(
(Serializable) entityId, (Serializable) entityId,
new ToOneDelegateSessionImplementor( versionsReader, entityClass, entityId, revision, verCfg ) new ToOneDelegateSessionImplementor( versionsReader, entityClass, entityId, revision, removed, verCfg )
); );
} }
@ -43,11 +45,11 @@ public class ToOneEntityLoader {
* allowed (e.g. @Proxy(lazy=false), final class). * allowed (e.g. @Proxy(lazy=false), final class).
*/ */
public static Object createProxyOrLoadImmediate(AuditReaderImplementor versionsReader, Class<?> entityClass, String entityName, public static Object createProxyOrLoadImmediate(AuditReaderImplementor versionsReader, Class<?> entityClass, String entityName,
Object entityId, Number revision, AuditConfiguration verCfg) { Object entityId, Number revision, boolean removed, AuditConfiguration verCfg) {
EntityPersister persister = versionsReader.getSessionImplementor().getFactory().getEntityPersister( entityName ); EntityPersister persister = versionsReader.getSessionImplementor().getFactory().getEntityPersister( entityName );
if ( persister.hasProxy() ) { if ( persister.hasProxy() ) {
return createProxy( versionsReader, entityClass, entityName, entityId, revision, verCfg ); return createProxy( versionsReader, entityClass, entityName, entityId, revision, removed, verCfg );
} }
return loadImmediate( versionsReader, entityClass, entityName, entityId, revision, verCfg ); return loadImmediate( versionsReader, entityClass, entityName, entityId, revision, removed, verCfg );
} }
} }

View File

@ -28,6 +28,7 @@ import java.util.HashMap;
import java.util.Map; import java.util.Map;
import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.envers.RevisionType;
import org.hibernate.envers.configuration.AuditConfiguration; import org.hibernate.envers.configuration.AuditConfiguration;
import org.hibernate.envers.entities.PropertyData; import org.hibernate.envers.entities.PropertyData;
import org.hibernate.envers.entities.mapper.id.IdMapper; import org.hibernate.envers.entities.mapper.id.IdMapper;
@ -99,7 +100,7 @@ public class ToOneIdMapper extends AbstractToOneMapper {
EntityInfo referencedEntity = getEntityInfo(verCfg, referencedEntityName); EntityInfo referencedEntity = getEntityInfo(verCfg, referencedEntityName);
value = ToOneEntityLoader.createProxyOrLoadImmediate( value = ToOneEntityLoader.createProxyOrLoadImmediate(
versionsReader, referencedEntity.getEntityClass(), referencedEntityName, versionsReader, referencedEntity.getEntityClass(), referencedEntityName,
entityId, revision, verCfg entityId, revision, RevisionType.DEL.equals( data.get( verCfg.getAuditEntCfg().getRevisionTypePropName() ) ), verCfg
); );
} }
} }

View File

@ -42,20 +42,22 @@ public class ToOneDelegateSessionImplementor extends AbstractDelegateSessionImpl
private final Class<?> entityClass; private final Class<?> entityClass;
private final Object entityId; private final Object entityId;
private final Number revision; private final Number revision;
private final boolean removed;
private final AuditConfiguration verCfg; private final AuditConfiguration verCfg;
public ToOneDelegateSessionImplementor(AuditReaderImplementor versionsReader, public ToOneDelegateSessionImplementor(AuditReaderImplementor versionsReader,
Class<?> entityClass, Object entityId, Number revision, Class<?> entityClass, Object entityId, Number revision, boolean removed,
AuditConfiguration verCfg) { AuditConfiguration verCfg) {
super(versionsReader.getSessionImplementor()); super(versionsReader.getSessionImplementor());
this.versionsReader = versionsReader; this.versionsReader = versionsReader;
this.entityClass = entityClass; this.entityClass = entityClass;
this.entityId = entityId; this.entityId = entityId;
this.revision = revision; this.revision = revision;
this.removed = removed;
this.verCfg = verCfg; this.verCfg = verCfg;
} }
public Object doImmediateLoad(String entityName) throws HibernateException { public Object doImmediateLoad(String entityName) throws HibernateException {
return ToOneEntityLoader.loadImmediate( versionsReader, entityClass, entityName, entityId, revision, verCfg ); return ToOneEntityLoader.loadImmediate( versionsReader, entityClass, entityName, entityId, revision, removed, verCfg );
} }
} }

View File

@ -49,7 +49,7 @@ public class AuditQueryCreator {
/** /**
* Creates a query, which will return entities satisfying some conditions (specified later), * Creates a query, which will return entities satisfying some conditions (specified later),
* at a given revision. * at a given revision. Deleted entities are not included.
* @param c Class of the entities for which to query. * @param c Class of the entities for which to query.
* @param revision Revision number at which to execute the query. * @param revision Revision number at which to execute the query.
* @return A query for entities at a given revision, to which conditions can be added and which * @return A query for entities at a given revision, to which conditions can be added and which
@ -60,12 +60,12 @@ public class AuditQueryCreator {
checkNotNull(revision, "Entity revision"); checkNotNull(revision, "Entity revision");
checkPositive(revision, "Entity revision"); checkPositive(revision, "Entity revision");
c = getTargetClassIfProxied(c); c = getTargetClassIfProxied(c);
return new EntitiesAtRevisionQuery(auditCfg, auditReaderImplementor, c, revision); return new EntitiesAtRevisionQuery(auditCfg, auditReaderImplementor, c, revision, false);
} }
/** /**
* Creates a query, which will return entities satisfying some conditions (specified later), * Creates a query, which will return entities satisfying some conditions (specified later),
* at a given revision and a given entityName. * at a given revision and a given entityName. Deleted entities are not included.
* @param c Class of the entities for which to query. * @param c Class of the entities for which to query.
* @param entityName Name of the entity (if can't be guessed basing on the {@code c}). * @param entityName Name of the entity (if can't be guessed basing on the {@code c}).
* @param revision Revision number at which to execute the query. * @param revision Revision number at which to execute the query.
@ -74,10 +74,26 @@ public class AuditQueryCreator {
* projection is added. * projection is added.
*/ */
public AuditQuery forEntitiesAtRevision(Class<?> c, String entityName, Number revision) { public AuditQuery forEntitiesAtRevision(Class<?> c, String entityName, Number revision) {
return forEntitiesAtRevision(c, entityName, revision, false);
}
/**
* Creates a query, which will return entities satisfying some conditions (specified later),
* at a given revision and a given entityName. Deleted entities may be optionally
* included.
* @param c Class of the entities for which to query.
* @param entityName Name of the entity (if can't be guessed basing on the {@code c}).
* @param revision Revision number at which to execute the query.
* @param includeDeletions Whether to include deleted entities in the search.
* @return A query for entities at a given revision, to which conditions can be added and which
* can then be executed. The result of the query will be a list of entities (beans), unless a
* projection is added.
*/
public AuditQuery forEntitiesAtRevision(Class<?> c, String entityName, Number revision, boolean includeDeletions) {
checkNotNull(revision, "Entity revision"); checkNotNull(revision, "Entity revision");
checkPositive(revision, "Entity revision"); checkPositive(revision, "Entity revision");
c = getTargetClassIfProxied(c); c = getTargetClassIfProxied(c);
return new EntitiesAtRevisionQuery(auditCfg, auditReaderImplementor, c, entityName, revision); return new EntitiesAtRevisionQuery(auditCfg, auditReaderImplementor, c, entityName, revision, includeDeletions);
} }
/** /**

View File

@ -45,18 +45,22 @@ import static org.hibernate.envers.entities.mapper.relation.query.QueryConstants
*/ */
public class EntitiesAtRevisionQuery extends AbstractAuditQuery { public class EntitiesAtRevisionQuery extends AbstractAuditQuery {
private final Number revision; private final Number revision;
private final boolean includeDeletions;
public EntitiesAtRevisionQuery(AuditConfiguration verCfg, public EntitiesAtRevisionQuery(AuditConfiguration verCfg,
AuditReaderImplementor versionsReader, Class<?> cls, AuditReaderImplementor versionsReader, Class<?> cls,
Number revision) { Number revision, boolean includeDeletions) {
super(verCfg, versionsReader, cls); super(verCfg, versionsReader, cls);
this.revision = revision; this.revision = revision;
this.includeDeletions = includeDeletions;
} }
public EntitiesAtRevisionQuery(AuditConfiguration verCfg, public EntitiesAtRevisionQuery(AuditConfiguration verCfg,
AuditReaderImplementor versionsReader, Class<?> cls, String entityName, Number revision) { AuditReaderImplementor versionsReader, Class<?> cls,
String entityName, Number revision, boolean includeDeletions) {
super(verCfg, versionsReader, cls, entityName); super(verCfg, versionsReader, cls, entityName);
this.revision = revision; this.revision = revision;
this.includeDeletions = includeDeletions;
} }
@SuppressWarnings({"unchecked"}) @SuppressWarnings({"unchecked"})
@ -91,8 +95,10 @@ public class EntitiesAtRevisionQuery extends AbstractAuditQuery {
verEntCfg.getRevisionEndFieldName(), true, referencedIdData, verEntCfg.getRevisionEndFieldName(), true, referencedIdData,
revisionPropertyPath, originalIdPropertyName, REFERENCED_ENTITY_ALIAS, REFERENCED_ENTITY_ALIAS_DEF_AUD_STR); revisionPropertyPath, originalIdPropertyName, REFERENCED_ENTITY_ALIAS, REFERENCED_ENTITY_ALIAS_DEF_AUD_STR);
if (!includeDeletions) {
// e.revision_type != DEL // e.revision_type != DEL
qb.getRootParameters().addWhereWithParam(verEntCfg.getRevisionTypePropName(), "<>", RevisionType.DEL); qb.getRootParameters().addWhereWithParam(verEntCfg.getRevisionTypePropName(), "<>", RevisionType.DEL);
}
// all specified conditions // all specified conditions
for (AuditCriterion criterion : criterions) { for (AuditCriterion criterion : criterions) {

View File

@ -96,8 +96,14 @@ public class AuditReaderImpl implements AuditReaderImplementor {
return this.find(cls, cls.getName(), primaryKey, revision); return this.find(cls, cls.getName(), primaryKey, revision);
} }
public <T> T find(Class<T> cls, String entityName, Object primaryKey, Number revision)
throws IllegalArgumentException, NotAuditedException, IllegalStateException {
return this.find(cls, entityName, primaryKey, revision, false);
}
@SuppressWarnings({"unchecked"}) @SuppressWarnings({"unchecked"})
public <T> T find(Class<T> cls, String entityName, Object primaryKey, Number revision) throws public <T> T find(Class<T> cls, String entityName, Object primaryKey, Number revision,
boolean includeDeletions) throws
IllegalArgumentException, NotAuditedException, IllegalStateException { IllegalArgumentException, NotAuditedException, IllegalStateException {
cls = getTargetClassIfProxied(cls); cls = getTargetClassIfProxied(cls);
checkNotNull(cls, "Entity class"); checkNotNull(cls, "Entity class");
@ -118,7 +124,7 @@ public class AuditReaderImpl implements AuditReaderImplementor {
Object result; Object result;
try { try {
// The result is put into the cache by the entity instantiator called from the query // The result is put into the cache by the entity instantiator called from the query
result = createQuery().forEntitiesAtRevision(cls, entityName, revision) result = createQuery().forEntitiesAtRevision(cls, entityName, revision, includeDeletions)
.add(AuditEntity.id().eq(primaryKey)).getSingleResult(); .add(AuditEntity.id().eq(primaryKey)).getSingleResult();
} catch (NoResultException e) { } catch (NoResultException e) {
result = null; result = null;

View File

@ -0,0 +1,83 @@
package org.hibernate.envers.test.integration.proxy;
import org.hibernate.Hibernate;
import org.hibernate.envers.RevisionType;
import org.hibernate.envers.query.AuditEntity;
import org.hibernate.envers.query.AuditQuery;
import org.hibernate.envers.test.BaseEnversJPAFunctionalTestCase;
import org.hibernate.envers.test.Priority;
import org.hibernate.envers.test.entities.onetomany.SetRefEdEntity;
import org.hibernate.envers.test.entities.onetomany.SetRefIngEntity;
import org.hibernate.envers.test.tools.TestTools;
import org.hibernate.testing.FailureExpected;
import org.hibernate.testing.TestForIssue;
import org.junit.Assert;
import org.junit.Test;
import java.util.List;
import java.util.Map;
import javax.persistence.EntityManager;
@TestForIssue(jiraKey = "HHH-5845")
public class RemovedObjectQueryTest extends BaseEnversJPAFunctionalTestCase {
@Override
@SuppressWarnings("unchecked")
protected void addConfigOptions(Map options) {
options.put("org.hibernate.envers.store_data_at_delete", "true");
}
@Override
protected Class<?>[] getAnnotatedClasses() {
return new Class<?>[] { SetRefEdEntity.class, SetRefIngEntity.class };
}
@Test
@Priority(10)
public void initData() {
EntityManager em = getEntityManager();
SetRefEdEntity refEdEntity = new SetRefEdEntity(1, "Demo Data");
SetRefIngEntity refIngEntity = new SetRefIngEntity(2, "Example Data", refEdEntity);
em.getTransaction().begin();
em.persist(refEdEntity);
em.persist(refIngEntity);
em.getTransaction().commit();
em.getTransaction().begin();
refIngEntity = em.find(SetRefIngEntity.class, 2);
em.remove(refIngEntity);
em.remove(refEdEntity);
em.getTransaction().commit();
}
@Test
public void testFindDeletedReference() {
AuditQuery query = getAuditReader().createQuery().forRevisionsOfEntity(SetRefIngEntity.class, false, true)
.add(AuditEntity.revisionType().eq(RevisionType.DEL));
List queryResult = (List) query.getResultList();
Object[] objArray = (Object[]) queryResult.get(0);
SetRefIngEntity refIngEntity = (SetRefIngEntity) objArray[0];
Assert.assertEquals("Example Data", refIngEntity.getData());
Hibernate.initialize(refIngEntity.getReference());
Assert.assertEquals("Demo Data", refIngEntity.getReference().getData());
}
@FailureExpected(jiraKey = "HHH-5845") // TODO: doesn't work until collection queries are fixed
@Test
public void testFindDeletedReferring() {
AuditQuery query = getAuditReader().createQuery().forRevisionsOfEntity(SetRefEdEntity.class, false, true)
.add(AuditEntity.revisionType().eq(RevisionType.DEL));
List queryResult = (List) query.getResultList();
Object[] objArray = (Object[]) queryResult.get(0);
SetRefEdEntity refEdEntity = (SetRefEdEntity) objArray[0];
Assert.assertEquals("Demo Data", refEdEntity.getData());
Hibernate.initialize(refEdEntity.getReffering());
Assert.assertEquals(TestTools.makeSet(new SetRefIngEntity(2, "Example Data")), refEdEntity.getReffering());
}
}

View File

@ -1,7 +1,7 @@
dependencies { dependencies {
compile( project( ':hibernate-core' ) ) compile( project( ':hibernate-core' ) )
compile( project( ':hibernate-entitymanager' ) ) compile( project( ':hibernate-entitymanager' ) )
compile( "org.osgi:org.osgi.core:4.2.0" ) compile( "org.osgi:org.osgi.core:4.3.0" )
} }
jar { jar {

View File

@ -23,7 +23,8 @@
*/ */
package org.hibernate.osgi; package org.hibernate.osgi;
import java.util.Properties; import java.util.Dictionary;
import java.util.Hashtable;
import javax.persistence.spi.PersistenceProvider; import javax.persistence.spi.PersistenceProvider;
@ -72,7 +73,7 @@ public class HibernateBundleActivator implements BundleActivator {
osgiJtaPlatform = new OsgiJtaPlatform( context ); osgiJtaPlatform = new OsgiJtaPlatform( context );
Properties properties = new Properties(); Dictionary properties = new Hashtable();
// In order to support existing persistence.xml files, register // In order to support existing persistence.xml files, register
// using the legacy provider name. // using the legacy provider name.
properties.put( "javax.persistence.provider", HibernatePersistenceProvider.class.getName() ); properties.put( "javax.persistence.provider", HibernatePersistenceProvider.class.getName() );
@ -80,7 +81,7 @@ public class HibernateBundleActivator implements BundleActivator {
new OsgiPersistenceProviderService( osgiClassLoader, osgiJtaPlatform ), properties ); new OsgiPersistenceProviderService( osgiClassLoader, osgiJtaPlatform ), properties );
context.registerService( SessionFactory.class.getName(), context.registerService( SessionFactory.class.getName(),
new OsgiSessionFactoryService( osgiClassLoader, osgiJtaPlatform ), new Properties()); new OsgiSessionFactoryService( osgiClassLoader, osgiJtaPlatform ), new Hashtable());
} }
@Override @Override

View File

@ -0,0 +1,106 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* JBoss, Home of Professional Open Source
* Copyright 2013 Red Hat Inc. and/or its affiliates and other contributors
* as indicated by the @authors tag. All rights reserved.
* See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* 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, v. 2.1.
* This program is distributed in the hope that it will be useful, but WITHOUT A
* 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,
* v.2.1 along with this distribution; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
package org.hibernate.osgi;
import java.io.InputStream;
import java.util.Collection;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.jpa.boot.archive.spi.ArchiveContext;
import org.hibernate.jpa.boot.archive.spi.ArchiveDescriptor;
import org.hibernate.jpa.boot.archive.spi.ArchiveEntry;
import org.hibernate.jpa.boot.spi.InputStreamAccess;
import org.hibernate.jpa.boot.spi.NamedInputStream;
import org.jboss.logging.Logger;
import org.osgi.framework.Bundle;
import org.osgi.framework.wiring.BundleWiring;
/**
* @author Brett Meyer
* @author Tim Ward
*/
public class OsgiArchiveDescriptor implements ArchiveDescriptor {
private static final CoreMessageLogger LOG = Logger.getMessageLogger( CoreMessageLogger.class,
OsgiArchiveDescriptor.class.getName() );
private BundleWiring bundleWiring;
private Bundle persistenceBundle;
public OsgiArchiveDescriptor(Bundle persistenceBundle) {
this.persistenceBundle = persistenceBundle;
bundleWiring = (BundleWiring) persistenceBundle.adapt( BundleWiring.class );
}
@Override
public void visitArchive(ArchiveContext context) {
Collection<String> resources = bundleWiring.listResources( "/", "*", BundleWiring.LISTRESOURCES_RECURSE );
for ( final String resource : resources ) {
try {
final InputStream inputStream = persistenceBundle.getResource( resource ).openStream();
// TODO: Is using resource as the names correct?
final InputStreamAccess inputStreamAccess = new InputStreamAccess() {
@Override
public String getStreamName() {
return resource;
}
@Override
public InputStream accessInputStream() {
return inputStream;
}
@Override
public NamedInputStream asNamedInputStream() {
return new NamedInputStream( resource, inputStream );
}
};
final ArchiveEntry entry = new ArchiveEntry() {
@Override
public String getName() {
return resource;
}
@Override
public String getNameWithinArchive() {
return resource;
}
@Override
public InputStreamAccess getStreamAccess() {
return inputStreamAccess;
}
};
context.obtainArchiveEntryHandler( entry ).handleEntry( entry, context );
}
catch ( Exception e ) {
LOG.unableToLoadScannedClassOrResource( e );
}
}
}
}

View File

@ -0,0 +1,49 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* JBoss, Home of Professional Open Source
* Copyright 2013 Red Hat Inc. and/or its affiliates and other contributors
* as indicated by the @authors tag. All rights reserved.
* See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* 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, v. 2.1.
* This program is distributed in the hope that it will be useful, but WITHOUT A
* 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,
* v.2.1 along with this distribution; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
package org.hibernate.osgi;
import java.net.URL;
import org.hibernate.jpa.boot.archive.internal.StandardArchiveDescriptorFactory;
import org.hibernate.jpa.boot.archive.spi.ArchiveDescriptor;
import org.osgi.framework.Bundle;
/**
* @author Brett Meyer
* @author Tim Ward
*/
public class OsgiArchiveDescriptorFactory extends StandardArchiveDescriptorFactory {
private Bundle persistenceBundle;
public OsgiArchiveDescriptorFactory(Bundle persistenceBundle) {
this.persistenceBundle = persistenceBundle;
}
@Override
public ArchiveDescriptor buildArchiveDescriptor(URL url, String entry) {
final String protocol = url.getProtocol();
if ( "bundle".equals( protocol ) ) {
return new OsgiArchiveDescriptor( persistenceBundle );
}
return super.buildArchiveDescriptor( url, entry );
}
}

View File

@ -32,6 +32,7 @@ import javax.persistence.spi.PersistenceUnitInfo;
import org.hibernate.cfg.AvailableSettings; import org.hibernate.cfg.AvailableSettings;
import org.hibernate.jpa.HibernatePersistenceProvider; import org.hibernate.jpa.HibernatePersistenceProvider;
import org.osgi.framework.Bundle; import org.osgi.framework.Bundle;
import org.osgi.framework.BundleReference;
/** /**
* @author Brett Meyer * @author Brett Meyer
@ -62,6 +63,9 @@ public class OsgiPersistenceProvider extends HibernatePersistenceProvider {
properties = new HashMap(); properties = new HashMap();
} }
properties.put( AvailableSettings.JTA_PLATFORM, osgiJtaPlatform ); properties.put( AvailableSettings.JTA_PLATFORM, osgiJtaPlatform );
// TODO: This needs tested.
properties.put( org.hibernate.ejb.AvailableSettings.SCANNER,
new OsgiScanner( requestingBundle ) );
osgiClassLoader.addBundle( requestingBundle ); osgiClassLoader.addBundle( requestingBundle );
@ -74,6 +78,9 @@ public class OsgiPersistenceProvider extends HibernatePersistenceProvider {
properties = new HashMap(); properties = new HashMap();
} }
properties.put( AvailableSettings.JTA_PLATFORM, osgiJtaPlatform ); properties.put( AvailableSettings.JTA_PLATFORM, osgiJtaPlatform );
// OSGi ClassLoaders must implement BundleReference
properties.put( org.hibernate.ejb.AvailableSettings.SCANNER,
new OsgiScanner( ( (BundleReference) info.getClassLoader() ).getBundle() ) );
osgiClassLoader.addClassLoader( info.getClassLoader() ); osgiClassLoader.addClassLoader( info.getClassLoader() );

View File

@ -0,0 +1,38 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* JBoss, Home of Professional Open Source
* Copyright 2013 Red Hat Inc. and/or its affiliates and other contributors
* as indicated by the @authors tag. All rights reserved.
* See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* 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, v. 2.1.
* This program is distributed in the hope that it will be useful, but WITHOUT A
* 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,
* v.2.1 along with this distribution; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
package org.hibernate.osgi;
import org.hibernate.jpa.boot.scan.spi.AbstractScannerImpl;
import org.osgi.framework.Bundle;
/**
* OSGi-specific implementation of the Scanner contract. Scans the persistence
* unit Bundle for classes and resources.
*
* @author Brett Meyer
* @author Tim Ward
*/
public class OsgiScanner extends AbstractScannerImpl {
public OsgiScanner(Bundle persistenceBundle) {
super( new OsgiArchiveDescriptorFactory( persistenceBundle ) );
}
}

View File

@ -57,7 +57,7 @@ ext {
infinispan: "org.infinispan:infinispan-core:${infinispanVersion}", infinispan: "org.infinispan:infinispan-core:${infinispanVersion}",
// javax // javax
jpa: 'org.hibernate.javax.persistence:hibernate-jpa-2.1-api:1.0.0.Draft-14', jpa: 'org.hibernate.javax.persistence:hibernate-jpa-2.1-api:1.0.0.Draft-16',
jta: 'org.jboss.spec.javax.transaction:jboss-transaction-api_1.2_spec:1.0.0.Alpha1', jta: 'org.jboss.spec.javax.transaction:jboss-transaction-api_1.2_spec:1.0.0.Alpha1',
validation: 'javax.validation:validation-api:1.1.0.CR3', validation: 'javax.validation:validation-api:1.1.0.CR3',
jacc: 'org.jboss.spec.javax.security.jacc:jboss-jacc-api_1.4_spec:1.0.2.Final', jacc: 'org.jboss.spec.javax.security.jacc:jboss-jacc-api_1.4_spec:1.0.2.Final',

View File

@ -0,0 +1,565 @@
/*
* 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
*/
/* Javadoc style sheet */
/*
Overall document style
*/
body {
/*
background-color:#ffffff;
color:#353833;
font-family:Arial, Helvetica, sans-serif;
font-size:76%;
margin:0;
*/
background: #FFFFFF url(images/bkg_gradient.gif) repeat-x;
margin:0 auto;
font-family:'Lucida Grande', Geneva, Verdana, Arial, sans-serif;
font-size:12px;
padding:0 2em;
color:#333;
}
a:link, a:visited {
text-decoration:none;
color:#4c6b87;
}
a:hover, a:focus {
text-decoration:none;
color:#BCAE79;
}
a:active {
text-decoration:none;
color:#4c6b87;
}
a[name] {
color:#353833;
}
a[name]:hover {
text-decoration:none;
color:#353833;
}
pre {
font-size:1.3em;
}
h1 {
background: url(images/h1_hdr.png) no-repeat;
line-height:1.2em;
color:#586464;
font-size:2em;
padding:1.5em;
margin-top: 0;
text-align:left;
}
/*
h1 {
font-size:1.8em;
}
*/
h2 {
color:#586464;
font-size:1.5em;
}
h3 {
font-size:1.4em;
}
h4 {
font-size:1.3em;
}
h5 {
font-size:1.2em;
}
h6 {
font-size:1.1em;
}
ul {
list-style-type:disc;
}
code, tt {
font-size:1.2em;
}
dt code {
font-size:1.2em;
}
table tr td dt code {
font-size:1.2em;
vertical-align:top;
}
sup {
font-size:.6em;
}
/*
Document title and Copyright styles
*/
.clear {
clear:both;
height:0px;
overflow:hidden;
}
.aboutLanguage {
float:right;
padding:0px 21px;
font-size:.8em;
z-index:200;
margin-top:-7px;
}
.legalCopy {
margin-left:.5em;
}
.bar a, .bar a:link, .bar a:visited, .bar a:active {
color:#FFFFFF;
text-decoration:none;
}
.bar a:hover, .bar a:focus {
color:#BCAE79;
}
.tab {
background-color:#0066FF;
/* background-image:url(resources/titlebar.gif); */
background-image:url(images/bkgheader.png);
background-position:left top;
background-repeat:no-repeat;
color:#ffffff;
padding:8px;
width:5em;
font-weight:bold;
}
/*
Navigation bar styles
*/
.bar {
/* background-image:url(resources/background.gif);*/
background-image:url(images/bkgheader.png);
background-repeat:repeat-x;
color:#FFFFFF;
padding:.8em .5em .4em .8em;
height:auto;/*height:1.8em;*/
font-size:1em;
margin:0;
}
.topNav {
/* background-image:url(resources/background.gif);*/
background-image:url(images/bkgheader.png);
background-repeat:repeat-x;
color:#FFFFFF;
float:left;
padding:0;
width:100%;
clear:right;
height:2.8em;
padding-top:10px;
overflow:hidden;
}
.bottomNav {
margin-top:10px;
/* background-image:url(resources/background.gif);*/
background-image:url(images/bkgheader.png);
background-repeat:repeat-x;
color:#FFFFFF;
float:left;
padding:0;
width:100%;
clear:right;
height:2.8em;
padding-top:10px;
overflow:hidden;
}
.subNav {
background-color:#dee3e9;
border-bottom:1px solid #9eadc0;
float:left;
width:100%;
overflow:hidden;
}
.subNav div {
clear:left;
float:left;
padding:0 0 5px 6px;
}
ul.navList, ul.subNavList {
float:left;
margin:0 25px 0 0;
padding:0;
}
ul.navList li{
list-style:none;
float:left;
padding:3px 6px;
}
ul.subNavList li{
list-style:none;
float:left;
font-size:90%;
}
.topNav a:link, .topNav a:active, .topNav a:visited, .bottomNav a:link, .bottomNav a:active, .bottomNav a:visited {
color:#FFFFFF;
text-decoration:none;
}
.topNav a:hover, .bottomNav a:hover {
text-decoration:none;
color:#BCAE79;
}
.navBarCell1Rev {
background-image:url(resources/tab.gif);
background-color:#a88834;
color:#FFFFFF;
margin: auto 5px;
border:1px solid #c9aa44;
}
/*
Page header and footer styles
*/
.header, .footer {
clear:both;
margin:0 20px;
padding:5px 0 0 0;
}
.indexHeader {
margin:10px;
position:relative;
}
.indexHeader h1 {
font-size:1.3em;
}
.title {
color:#2c4557;
margin:10px 0;
}
.subTitle {
margin:5px 0 0 0;
}
.header ul {
margin:0 0 25px 0;
padding:0;
}
.footer ul {
margin:20px 0 5px 0;
}
.header ul li, .footer ul li {
list-style:none;
font-size:1.2em;
}
/*
Heading styles
*/
div.details ul.blockList ul.blockList ul.blockList li.blockList h4, div.details ul.blockList ul.blockList ul.blockListLast li.blockList h4 {
background-color:#dee3e9;
border-top:1px solid #9eadc0;
border-bottom:1px solid #9eadc0;
margin:0 0 6px -8px;
padding:2px 5px;
}
ul.blockList ul.blockList ul.blockList li.blockList h3 {
background-color:#dee3e9;
border-top:1px solid #9eadc0;
border-bottom:1px solid #9eadc0;
margin:0 0 6px -8px;
padding:2px 5px;
}
ul.blockList ul.blockList li.blockList h3 {
padding:0;
margin:15px 0;
}
ul.blockList li.blockList h2 {
padding:0px 0 20px 0;
}
/*
Page layout container styles
*/
.contentContainer, .sourceContainer, .classUseContainer, .serializedFormContainer, .constantValuesContainer {
clear:both;
padding:10px 20px;
position:relative;
}
.indexContainer {
margin:10px;
position:relative;
font-size:1.0em;
}
.indexContainer h2 {
font-size:1.1em;
padding:0 0 3px 0;
}
.indexContainer ul {
margin:0;
padding:0;
}
.indexContainer ul li {
list-style:none;
}
.contentContainer .description dl dt, .contentContainer .details dl dt, .serializedFormContainer dl dt {
font-size:1.1em;
font-weight:bold;
margin:10px 0 0 0;
color:#4E4E4E;
}
.contentContainer .description dl dd, .contentContainer .details dl dd, .serializedFormContainer dl dd {
margin:10px 0 10px 20px;
}
.serializedFormContainer dl.nameValue dt {
margin-left:1px;
font-size:1.1em;
display:inline;
font-weight:bold;
}
.serializedFormContainer dl.nameValue dd {
margin:0 0 0 1px;
font-size:1.1em;
display:inline;
}
/*
List styles
*/
ul.horizontal li {
display:inline;
font-size:0.9em;
}
ul.inheritance {
margin:0;
padding:0;
}
ul.inheritance li {
display:inline;
list-style:none;
}
ul.inheritance li ul.inheritance {
margin-left:15px;
padding-left:15px;
padding-top:1px;
}
ul.blockList, ul.blockListLast {
margin:10px 0 10px 0;
padding:0;
}
ul.blockList li.blockList, ul.blockListLast li.blockList {
list-style:none;
margin-bottom:25px;
}
ul.blockList ul.blockList li.blockList, ul.blockList ul.blockListLast li.blockList {
padding:0px 20px 5px 10px;
border:1px solid #9eadc0;
background-color:#f9f9f9;
}
ul.blockList ul.blockList ul.blockList li.blockList, ul.blockList ul.blockList ul.blockListLast li.blockList {
padding:0 0 5px 8px;
background-color:#ffffff;
border:1px solid #9eadc0;
border-top:none;
}
ul.blockList ul.blockList ul.blockList ul.blockList li.blockList {
margin-left:0;
padding-left:0;
padding-bottom:15px;
border:none;
border-bottom:1px solid #9eadc0;
}
ul.blockList ul.blockList ul.blockList ul.blockList li.blockListLast {
list-style:none;
border-bottom:none;
padding-bottom:0;
}
table tr td dl, table tr td dl dt, table tr td dl dd {
margin-top:0;
margin-bottom:1px;
}
/*
Table styles
*/
.contentContainer table, .classUseContainer table, .constantValuesContainer table {
border-bottom:1px solid #9eadc0;
width:100%;
}
.contentContainer ul li table, .classUseContainer ul li table, .constantValuesContainer ul li table {
width:100%;
}
.contentContainer .description table, .contentContainer .details table {
border-bottom:none;
}
.contentContainer ul li table th.colOne, .contentContainer ul li table th.colFirst, .contentContainer ul li table th.colLast, .classUseContainer ul li table th, .constantValuesContainer ul li table th, .contentContainer ul li table td.colOne, .contentContainer ul li table td.colFirst, .contentContainer ul li table td.colLast, .classUseContainer ul li table td, .constantValuesContainer ul li table td{
vertical-align:top;
padding-right:20px;
}
.contentContainer ul li table th.colLast, .classUseContainer ul li table th.colLast,.constantValuesContainer ul li table th.colLast,
.contentContainer ul li table td.colLast, .classUseContainer ul li table td.colLast,.constantValuesContainer ul li table td.colLast,
.contentContainer ul li table th.colOne, .classUseContainer ul li table th.colOne,
.contentContainer ul li table td.colOne, .classUseContainer ul li table td.colOne {
padding-right:3px;
}
.overviewSummary caption, .packageSummary caption, .contentContainer ul.blockList li.blockList caption, .summary caption, .classUseContainer caption, .constantValuesContainer caption {
position:relative;
text-align:left;
background-repeat:no-repeat;
color:#FFFFFF;
font-weight:bold;
clear:none;
overflow:hidden;
padding:0px;
margin:0px;
}
caption a:link, caption a:hover, caption a:active, caption a:visited {
color:#FFFFFF;
}
.overviewSummary caption span, .packageSummary caption span, .contentContainer ul.blockList li.blockList caption span, .summary caption span, .classUseContainer caption span, .constantValuesContainer caption span {
white-space:nowrap;
padding-top:8px;
padding-left:8px;
display:block;
float:left;
background-image:url(resources/titlebar.gif);
height:18px;
}
.overviewSummary .tabEnd, .packageSummary .tabEnd, .contentContainer ul.blockList li.blockList .tabEnd, .summary .tabEnd, .classUseContainer .tabEnd, .constantValuesContainer .tabEnd {
width:10px;
background-image:url(resources/titlebar_end.gif);
background-repeat:no-repeat;
background-position:top right;
position:relative;
float:left;
}
ul.blockList ul.blockList li.blockList table {
margin:0 0 12px 0px;
width:100%;
}
.tableSubHeadingColor {
background-color: #EEEEFF;
}
.altColor {
background-color:#eeeeef;
}
.rowColor {
background-color:#ffffff;
}
.overviewSummary td, .packageSummary td, .contentContainer ul.blockList li.blockList td, .summary td, .classUseContainer td, .constantValuesContainer td {
text-align:left;
padding:3px 3px 3px 7px;
}
th.colFirst, th.colLast, th.colOne, .constantValuesContainer th {
background:#dee3e9;
border-top:1px solid #9eadc0;
border-bottom:1px solid #9eadc0;
text-align:left;
padding:3px 3px 3px 7px;
}
td.colOne a:link, td.colOne a:active, td.colOne a:visited, td.colOne a:hover, td.colFirst a:link, td.colFirst a:active, td.colFirst a:visited, td.colFirst a:hover, td.colLast a:link, td.colLast a:active, td.colLast a:visited, td.colLast a:hover, .constantValuesContainer td a:link, .constantValuesContainer td a:active, .constantValuesContainer td a:visited, .constantValuesContainer td a:hover {
font-weight:bold;
}
td.colFirst, th.colFirst {
border-left:1px solid #9eadc0;
white-space:nowrap;
}
td.colLast, th.colLast {
border-right:1px solid #9eadc0;
}
td.colOne, th.colOne {
border-right:1px solid #9eadc0;
border-left:1px solid #9eadc0;
}
table.overviewSummary {
padding:0px;
margin-left:0px;
}
table.overviewSummary td.colFirst, table.overviewSummary th.colFirst,
table.overviewSummary td.colOne, table.overviewSummary th.colOne {
width:25%;
vertical-align:middle;
}
table.packageSummary td.colFirst, table.overviewSummary th.colFirst {
width:25%;
vertical-align:middle;
}
/*
Content styles
*/
.description pre {
margin-top:0;
}
.deprecatedContent {
margin:0;
padding:10px 0;
}
.docSummary {
padding:0;
}
/*
Formatting effect styles
*/
.sourceLineNo {
color:green;
padding:0 30px 0 0;
}
h1.hidden {
visibility:hidden;
overflow:hidden;
font-size:.9em;
}
.block {
display:block;
margin:3px 0 0 0;
}
.strong {
font-weight:bold;
}
table.overviewSummary td.colFirst, table.overviewSummary th.colFirst, table.overviewSummary td.colOne, table.overviewSummary
th.colOne {
width: 5%;
}
table.overviewSummary td.colFirst code {
float: right;
}
table.overviewSummary .block {
padding-left: 3em;
}
table.overviewSummary .block .block {
padding-left: 0em;
}
table.overviewSummary, table.packageSummary {
border-collapse: collapse;
}
table.overviewSummary td, table.packageSummary td {
border: 1px solid #9EADC0;
}
td.colOne a:link, td.colOne a:active, td.colOne a:visited, td.colOne a:hover, td.colFirst a:link, td.colFirst a:active,
td.colFirst a:visited, td.colFirst a:hover, td.colLast a:link, td.colLast a:active, td.colLast a:visited, td.colLast a:hover {
font-weight: normal;
}
td.colOne strong a:link, td.colOne strong a:active, td.colOne strong a:visited, td.colOne strong a:hover, td.colFirst strong
a:link, td.colFirst strong a:active, td.colFirst strong a:visited, td.colFirst strong a:hover, td.colLast strong a:link,
td.colLast strong a:active, td.colLast strong a:visited, td.colLast strong a:hover {
font-weight: bold;
}

View File

@ -0,0 +1,474 @@
/* Javadoc style sheet */
/*
Overall document style
*/
body {
background-color:#ffffff;
color:#353833;
font-family:Arial, Helvetica, sans-serif;
font-size:76%;
margin:0;
}
a:link, a:visited {
text-decoration:none;
color:#4c6b87;
}
a:hover, a:focus {
text-decoration:none;
color:#bb7a2a;
}
a:active {
text-decoration:none;
color:#4c6b87;
}
a[name] {
color:#353833;
}
a[name]:hover {
text-decoration:none;
color:#353833;
}
pre {
font-size:1.3em;
}
h1 {
font-size:1.8em;
}
h2 {
font-size:1.5em;
}
h3 {
font-size:1.4em;
}
h4 {
font-size:1.3em;
}
h5 {
font-size:1.2em;
}
h6 {
font-size:1.1em;
}
ul {
list-style-type:disc;
}
code, tt {
font-size:1.2em;
}
dt code {
font-size:1.2em;
}
table tr td dt code {
font-size:1.2em;
vertical-align:top;
}
sup {
font-size:.6em;
}
/*
Document title and Copyright styles
*/
.clear {
clear:both;
height:0px;
overflow:hidden;
}
.aboutLanguage {
float:right;
padding:0px 21px;
font-size:.8em;
z-index:200;
margin-top:-7px;
}
.legalCopy {
margin-left:.5em;
}
.bar a, .bar a:link, .bar a:visited, .bar a:active {
color:#FFFFFF;
text-decoration:none;
}
.bar a:hover, .bar a:focus {
color:#bb7a2a;
}
.tab {
background-color:#0066FF;
background-image:url(resources/titlebar.gif);
background-position:left top;
background-repeat:no-repeat;
color:#ffffff;
padding:8px;
width:5em;
font-weight:bold;
}
/*
Navigation bar styles
*/
.bar {
background-image:url(resources/background.gif);
background-repeat:repeat-x;
color:#FFFFFF;
padding:.8em .5em .4em .8em;
height:auto;/*height:1.8em;*/
font-size:1em;
margin:0;
}
.topNav {
background-image:url(resources/background.gif);
background-repeat:repeat-x;
color:#FFFFFF;
float:left;
padding:0;
width:100%;
clear:right;
height:2.8em;
padding-top:10px;
overflow:hidden;
}
.bottomNav {
margin-top:10px;
background-image:url(resources/background.gif);
background-repeat:repeat-x;
color:#FFFFFF;
float:left;
padding:0;
width:100%;
clear:right;
height:2.8em;
padding-top:10px;
overflow:hidden;
}
.subNav {
background-color:#dee3e9;
border-bottom:1px solid #9eadc0;
float:left;
width:100%;
overflow:hidden;
}
.subNav div {
clear:left;
float:left;
padding:0 0 5px 6px;
}
ul.navList, ul.subNavList {
float:left;
margin:0 25px 0 0;
padding:0;
}
ul.navList li{
list-style:none;
float:left;
padding:3px 6px;
}
ul.subNavList li{
list-style:none;
float:left;
font-size:90%;
}
.topNav a:link, .topNav a:active, .topNav a:visited, .bottomNav a:link, .bottomNav a:active, .bottomNav a:visited {
color:#FFFFFF;
text-decoration:none;
}
.topNav a:hover, .bottomNav a:hover {
text-decoration:none;
color:#bb7a2a;
}
.navBarCell1Rev {
background-image:url(resources/tab.gif);
background-color:#a88834;
color:#FFFFFF;
margin: auto 5px;
border:1px solid #c9aa44;
}
/*
Page header and footer styles
*/
.header, .footer {
clear:both;
margin:0 20px;
padding:5px 0 0 0;
}
.indexHeader {
margin:10px;
position:relative;
}
.indexHeader h1 {
font-size:1.3em;
}
.title {
color:#2c4557;
margin:10px 0;
}
.subTitle {
margin:5px 0 0 0;
}
.header ul {
margin:0 0 25px 0;
padding:0;
}
.footer ul {
margin:20px 0 5px 0;
}
.header ul li, .footer ul li {
list-style:none;
font-size:1.2em;
}
/*
Heading styles
*/
div.details ul.blockList ul.blockList ul.blockList li.blockList h4, div.details ul.blockList ul.blockList ul.blockListLast li.blockList h4 {
background-color:#dee3e9;
border-top:1px solid #9eadc0;
border-bottom:1px solid #9eadc0;
margin:0 0 6px -8px;
padding:2px 5px;
}
ul.blockList ul.blockList ul.blockList li.blockList h3 {
background-color:#dee3e9;
border-top:1px solid #9eadc0;
border-bottom:1px solid #9eadc0;
margin:0 0 6px -8px;
padding:2px 5px;
}
ul.blockList ul.blockList li.blockList h3 {
padding:0;
margin:15px 0;
}
ul.blockList li.blockList h2 {
padding:0px 0 20px 0;
}
/*
Page layout container styles
*/
.contentContainer, .sourceContainer, .classUseContainer, .serializedFormContainer, .constantValuesContainer {
clear:both;
padding:10px 20px;
position:relative;
}
.indexContainer {
margin:10px;
position:relative;
font-size:1.0em;
}
.indexContainer h2 {
font-size:1.1em;
padding:0 0 3px 0;
}
.indexContainer ul {
margin:0;
padding:0;
}
.indexContainer ul li {
list-style:none;
}
.contentContainer .description dl dt, .contentContainer .details dl dt, .serializedFormContainer dl dt {
font-size:1.1em;
font-weight:bold;
margin:10px 0 0 0;
color:#4E4E4E;
}
.contentContainer .description dl dd, .contentContainer .details dl dd, .serializedFormContainer dl dd {
margin:10px 0 10px 20px;
}
.serializedFormContainer dl.nameValue dt {
margin-left:1px;
font-size:1.1em;
display:inline;
font-weight:bold;
}
.serializedFormContainer dl.nameValue dd {
margin:0 0 0 1px;
font-size:1.1em;
display:inline;
}
/*
List styles
*/
ul.horizontal li {
display:inline;
font-size:0.9em;
}
ul.inheritance {
margin:0;
padding:0;
}
ul.inheritance li {
display:inline;
list-style:none;
}
ul.inheritance li ul.inheritance {
margin-left:15px;
padding-left:15px;
padding-top:1px;
}
ul.blockList, ul.blockListLast {
margin:10px 0 10px 0;
padding:0;
}
ul.blockList li.blockList, ul.blockListLast li.blockList {
list-style:none;
margin-bottom:25px;
}
ul.blockList ul.blockList li.blockList, ul.blockList ul.blockListLast li.blockList {
padding:0px 20px 5px 10px;
border:1px solid #9eadc0;
background-color:#f9f9f9;
}
ul.blockList ul.blockList ul.blockList li.blockList, ul.blockList ul.blockList ul.blockListLast li.blockList {
padding:0 0 5px 8px;
background-color:#ffffff;
border:1px solid #9eadc0;
border-top:none;
}
ul.blockList ul.blockList ul.blockList ul.blockList li.blockList {
margin-left:0;
padding-left:0;
padding-bottom:15px;
border:none;
border-bottom:1px solid #9eadc0;
}
ul.blockList ul.blockList ul.blockList ul.blockList li.blockListLast {
list-style:none;
border-bottom:none;
padding-bottom:0;
}
table tr td dl, table tr td dl dt, table tr td dl dd {
margin-top:0;
margin-bottom:1px;
}
/*
Table styles
*/
.contentContainer table, .classUseContainer table, .constantValuesContainer table {
border-bottom:1px solid #9eadc0;
width:100%;
}
.contentContainer ul li table, .classUseContainer ul li table, .constantValuesContainer ul li table {
width:100%;
}
.contentContainer .description table, .contentContainer .details table {
border-bottom:none;
}
.contentContainer ul li table th.colOne, .contentContainer ul li table th.colFirst, .contentContainer ul li table th.colLast, .classUseContainer ul li table th, .constantValuesContainer ul li table th, .contentContainer ul li table td.colOne, .contentContainer ul li table td.colFirst, .contentContainer ul li table td.colLast, .classUseContainer ul li table td, .constantValuesContainer ul li table td{
vertical-align:top;
padding-right:20px;
}
.contentContainer ul li table th.colLast, .classUseContainer ul li table th.colLast,.constantValuesContainer ul li table th.colLast,
.contentContainer ul li table td.colLast, .classUseContainer ul li table td.colLast,.constantValuesContainer ul li table td.colLast,
.contentContainer ul li table th.colOne, .classUseContainer ul li table th.colOne,
.contentContainer ul li table td.colOne, .classUseContainer ul li table td.colOne {
padding-right:3px;
}
.overviewSummary caption, .packageSummary caption, .contentContainer ul.blockList li.blockList caption, .summary caption, .classUseContainer caption, .constantValuesContainer caption {
position:relative;
text-align:left;
background-repeat:no-repeat;
color:#FFFFFF;
font-weight:bold;
clear:none;
overflow:hidden;
padding:0px;
margin:0px;
}
caption a:link, caption a:hover, caption a:active, caption a:visited {
color:#FFFFFF;
}
.overviewSummary caption span, .packageSummary caption span, .contentContainer ul.blockList li.blockList caption span, .summary caption span, .classUseContainer caption span, .constantValuesContainer caption span {
white-space:nowrap;
padding-top:8px;
padding-left:8px;
display:block;
float:left;
background-image:url(resources/titlebar.gif);
height:18px;
}
.overviewSummary .tabEnd, .packageSummary .tabEnd, .contentContainer ul.blockList li.blockList .tabEnd, .summary .tabEnd, .classUseContainer .tabEnd, .constantValuesContainer .tabEnd {
width:10px;
background-image:url(resources/titlebar_end.gif);
background-repeat:no-repeat;
background-position:top right;
position:relative;
float:left;
}
ul.blockList ul.blockList li.blockList table {
margin:0 0 12px 0px;
width:100%;
}
.tableSubHeadingColor {
background-color: #EEEEFF;
}
.altColor {
background-color:#eeeeef;
}
.rowColor {
background-color:#ffffff;
}
.overviewSummary td, .packageSummary td, .contentContainer ul.blockList li.blockList td, .summary td, .classUseContainer td, .constantValuesContainer td {
text-align:left;
padding:3px 3px 3px 7px;
}
th.colFirst, th.colLast, th.colOne, .constantValuesContainer th {
background:#dee3e9;
border-top:1px solid #9eadc0;
border-bottom:1px solid #9eadc0;
text-align:left;
padding:3px 3px 3px 7px;
}
td.colOne a:link, td.colOne a:active, td.colOne a:visited, td.colOne a:hover, td.colFirst a:link, td.colFirst a:active, td.colFirst a:visited, td.colFirst a:hover, td.colLast a:link, td.colLast a:active, td.colLast a:visited, td.colLast a:hover, .constantValuesContainer td a:link, .constantValuesContainer td a:active, .constantValuesContainer td a:visited, .constantValuesContainer td a:hover {
font-weight:bold;
}
td.colFirst, th.colFirst {
border-left:1px solid #9eadc0;
white-space:nowrap;
}
td.colLast, th.colLast {
border-right:1px solid #9eadc0;
}
td.colOne, th.colOne {
border-right:1px solid #9eadc0;
border-left:1px solid #9eadc0;
}
table.overviewSummary {
padding:0px;
margin-left:0px;
}
table.overviewSummary td.colFirst, table.overviewSummary th.colFirst,
table.overviewSummary td.colOne, table.overviewSummary th.colOne {
width:25%;
vertical-align:middle;
}
table.packageSummary td.colFirst, table.overviewSummary th.colFirst {
width:25%;
vertical-align:middle;
}
/*
Content styles
*/
.description pre {
margin-top:0;
}
.deprecatedContent {
margin:0;
padding:10px 0;
}
.docSummary {
padding:0;
}
/*
Formatting effect styles
*/
.sourceLineNo {
color:green;
padding:0 30px 0 0;
}
h1.hidden {
visibility:hidden;
overflow:hidden;
font-size:.9em;
}
.block {
display:block;
margin:3px 0 0 0;
}
.strong {
font-weight:bold;
}