merge master
This commit is contained in:
commit
0e62ff4856
|
@ -326,6 +326,19 @@
|
||||||
Name of column used for storing ordinal of the change in sets of embeddable elements.
|
Name of column used for storing ordinal of the change in sets of embeddable elements.
|
||||||
</entry>
|
</entry>
|
||||||
</row>
|
</row>
|
||||||
|
<row>
|
||||||
|
<entry>
|
||||||
|
<property>org.hibernate.envers.allow_identifier_reuse</property>
|
||||||
|
</entry>
|
||||||
|
<entry>
|
||||||
|
false
|
||||||
|
</entry>
|
||||||
|
<entry>
|
||||||
|
Guarantees proper validity audit strategy behavior when application reuses identifiers
|
||||||
|
of deleted entities. Exactly one row with <literal>null</literal> end date exists
|
||||||
|
for each identifier.
|
||||||
|
</entry>
|
||||||
|
</row>
|
||||||
</tbody>
|
</tbody>
|
||||||
</tgroup>
|
</tgroup>
|
||||||
</table>
|
</table>
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
<bundle start-level="30">mvn:org.apache.aries.transaction/org.apache.aries.transaction.manager/1.0.1</bundle>
|
<bundle start-level="30">mvn:org.apache.aries.transaction/org.apache.aries.transaction.manager/1.0.1</bundle>
|
||||||
|
|
||||||
<!-- JPA -->
|
<!-- JPA -->
|
||||||
<bundle start-level="30">mvn:org.hibernate.javax.persistence/hibernate-jpa-2.1-api/1.0.0-SNAPSHOT</bundle>
|
<bundle start-level="30">mvn:org.hibernate.javax.persistence/hibernate-jpa-2.1-api/1.0.0.Final</bundle>
|
||||||
<!-- No container currently supports JPA 2.1. Clone and build Aries JPA from the following fork (upgrades to
|
<!-- No container currently supports JPA 2.1. Clone and build Aries JPA from the following fork (upgrades to
|
||||||
JPA 2.1). Aries should be upgrading as soon as the spec is out.
|
JPA 2.1). Aries should be upgrading as soon as the spec is out.
|
||||||
https://github.com/brmeyer/aries/tree/jpa21 -->
|
https://github.com/brmeyer/aries/tree/jpa21 -->
|
||||||
|
@ -46,7 +46,6 @@
|
||||||
|
|
||||||
<!-- These do not natively support OSGi, so using 3rd party bundles. -->
|
<!-- These do not natively support OSGi, so using 3rd party bundles. -->
|
||||||
<bundle>mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.antlr/2.7.7_5</bundle>
|
<bundle>mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.antlr/2.7.7_5</bundle>
|
||||||
<bundle>wrap:mvn:org.javassist/javassist/3.18.0-GA</bundle>
|
|
||||||
<bundle>mvn:org.apache.servicemix.specs/org.apache.servicemix.specs.jsr303-api-1.0.0/2.2.0</bundle>
|
<bundle>mvn:org.apache.servicemix.specs/org.apache.servicemix.specs.jsr303-api-1.0.0/2.2.0</bundle>
|
||||||
<bundle>mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.ant/1.8.2_2</bundle>
|
<bundle>mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.ant/1.8.2_2</bundle>
|
||||||
<bundle>mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.dom4j/1.6.1_5</bundle>
|
<bundle>mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.dom4j/1.6.1_5</bundle>
|
||||||
|
@ -55,8 +54,9 @@
|
||||||
<bundle>wrap:mvn:org.jboss/jandex/1.1.0.Alpha1</bundle>
|
<bundle>wrap:mvn:org.jboss/jandex/1.1.0.Alpha1</bundle>
|
||||||
|
|
||||||
<bundle>wrap:mvn:org.hibernate.common/hibernate-commons-annotations/4.0.2.Final</bundle>
|
<bundle>wrap:mvn:org.hibernate.common/hibernate-commons-annotations/4.0.2.Final</bundle>
|
||||||
<bundle>mvn:com.fasterxml/classmate/0.8.0</bundle>
|
<bundle>mvn:com.fasterxml/classmate/0.5.4</bundle>
|
||||||
<bundle>mvn:org.jboss.logging/jboss-logging/3.1.1.GA</bundle>
|
<bundle>mvn:org.jboss.logging/jboss-logging/3.1.0.GA</bundle>
|
||||||
|
<bundle>mvn:org.javassist/javassist/3.18.0-GA</bundle>
|
||||||
|
|
||||||
<bundle>mvn:org.hibernate/hibernate-core/5.0.0-SNAPSHOT</bundle>
|
<bundle>mvn:org.hibernate/hibernate-core/5.0.0-SNAPSHOT</bundle>
|
||||||
<bundle>mvn:org.hibernate/hibernate-entitymanager/5.0.0-SNAPSHOT</bundle>
|
<bundle>mvn:org.hibernate/hibernate-entitymanager/5.0.0-SNAPSHOT</bundle>
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.hibernate.javax.persistence</groupId>
|
<groupId>org.hibernate.javax.persistence</groupId>
|
||||||
<artifactId>hibernate-jpa-2.1-api</artifactId>
|
<artifactId>hibernate-jpa-2.1-api</artifactId>
|
||||||
<version>1.0.0-SNAPSHOT</version>
|
<version>1.0.0.Final</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.osgi</groupId>
|
<groupId>org.osgi</groupId>
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
<bundle start-level="30">mvn:org.apache.geronimo.specs/geronimo-jta_1.1_spec/1.1.1</bundle>
|
<bundle start-level="30">mvn:org.apache.geronimo.specs/geronimo-jta_1.1_spec/1.1.1</bundle>
|
||||||
|
|
||||||
<!-- JPA -->
|
<!-- JPA -->
|
||||||
<bundle start-level="30">mvn:org.hibernate.javax.persistence/hibernate-jpa-2.1-api/1.0.0-SNAPSHOT</bundle>
|
<bundle start-level="30">mvn:org.hibernate.javax.persistence/hibernate-jpa-2.1-api/1.0.0.Final</bundle>
|
||||||
|
|
||||||
<!-- Taken from Karaf-Tutorial -->
|
<!-- Taken from Karaf-Tutorial -->
|
||||||
<bundle>mvn:commons-collections/commons-collections/3.2.1</bundle>
|
<bundle>mvn:commons-collections/commons-collections/3.2.1</bundle>
|
||||||
|
@ -21,7 +21,6 @@
|
||||||
|
|
||||||
<!-- These do not natively support OSGi, so using 3rd party bundles. -->
|
<!-- These do not natively support OSGi, so using 3rd party bundles. -->
|
||||||
<bundle>mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.antlr/2.7.7_5</bundle>
|
<bundle>mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.antlr/2.7.7_5</bundle>
|
||||||
<bundle>wrap:mvn:org.javassist/javassist/3.18.0-GA</bundle>
|
|
||||||
<bundle>mvn:org.apache.servicemix.specs/org.apache.servicemix.specs.jsr303-api-1.0.0/2.2.0</bundle>
|
<bundle>mvn:org.apache.servicemix.specs/org.apache.servicemix.specs.jsr303-api-1.0.0/2.2.0</bundle>
|
||||||
<bundle>mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.ant/1.8.2_2</bundle>
|
<bundle>mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.ant/1.8.2_2</bundle>
|
||||||
<bundle>mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.dom4j/1.6.1_5</bundle>
|
<bundle>mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.dom4j/1.6.1_5</bundle>
|
||||||
|
@ -30,8 +29,9 @@
|
||||||
<bundle>wrap:mvn:org.hibernate.common/hibernate-commons-annotations/4.0.2.Final</bundle>
|
<bundle>wrap:mvn:org.hibernate.common/hibernate-commons-annotations/4.0.2.Final</bundle>
|
||||||
<bundle>wrap:mvn:org.jboss/jandex/1.1.0.Alpha1</bundle>
|
<bundle>wrap:mvn:org.jboss/jandex/1.1.0.Alpha1</bundle>
|
||||||
|
|
||||||
<bundle>mvn:com.fasterxml/classmate/0.8.0</bundle>
|
<bundle>mvn:com.fasterxml/classmate/0.5.4</bundle>
|
||||||
<bundle>mvn:org.jboss.logging/jboss-logging/3.1.1.GA</bundle>
|
<bundle>mvn:org.jboss.logging/jboss-logging/3.1.0.GA</bundle>
|
||||||
|
<bundle>mvn:org.javassist/javassist/3.18.0-GA</bundle>
|
||||||
|
|
||||||
<bundle>mvn:org.hibernate/hibernate-core/5.0.0-SNAPSHOT</bundle>
|
<bundle>mvn:org.hibernate/hibernate-core/5.0.0-SNAPSHOT</bundle>
|
||||||
<bundle>mvn:org.hibernate/hibernate-entitymanager/5.0.0-SNAPSHOT</bundle>
|
<bundle>mvn:org.hibernate/hibernate-entitymanager/5.0.0-SNAPSHOT</bundle>
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.hibernate.javax.persistence</groupId>
|
<groupId>org.hibernate.javax.persistence</groupId>
|
||||||
<artifactId>hibernate-jpa-2.1-api</artifactId>
|
<artifactId>hibernate-jpa-2.1-api</artifactId>
|
||||||
<version>1.0.0-SNAPSHOT</version>
|
<version>1.0.0.Final</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.osgi</groupId>
|
<groupId>org.osgi</groupId>
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
<bundle start-level="30">mvn:org.apache.geronimo.specs/geronimo-jta_1.1_spec/1.1.1</bundle>
|
<bundle start-level="30">mvn:org.apache.geronimo.specs/geronimo-jta_1.1_spec/1.1.1</bundle>
|
||||||
|
|
||||||
<!-- JPA -->
|
<!-- JPA -->
|
||||||
<bundle start-level="30">mvn:org.hibernate.javax.persistence/hibernate-jpa-2.1-api/1.0.0-SNAPSHOT</bundle>
|
<bundle start-level="30">mvn:org.hibernate.javax.persistence/hibernate-jpa-2.1-api/1.0.0.Final</bundle>
|
||||||
|
|
||||||
<!-- Taken from Karaf-Tutorial -->
|
<!-- Taken from Karaf-Tutorial -->
|
||||||
<bundle>mvn:commons-collections/commons-collections/3.2.1</bundle>
|
<bundle>mvn:commons-collections/commons-collections/3.2.1</bundle>
|
||||||
|
@ -21,7 +21,6 @@
|
||||||
|
|
||||||
<!-- These do not natively support OSGi, so using 3rd party bundles. -->
|
<!-- These do not natively support OSGi, so using 3rd party bundles. -->
|
||||||
<bundle>mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.antlr/2.7.7_5</bundle>
|
<bundle>mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.antlr/2.7.7_5</bundle>
|
||||||
<bundle>wrap:mvn:org.javassist/javassist/3.18.0-GA</bundle>
|
|
||||||
<bundle>mvn:org.apache.servicemix.specs/org.apache.servicemix.specs.jsr303-api-1.0.0/2.2.0</bundle>
|
<bundle>mvn:org.apache.servicemix.specs/org.apache.servicemix.specs.jsr303-api-1.0.0/2.2.0</bundle>
|
||||||
<bundle>mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.ant/1.8.2_2</bundle>
|
<bundle>mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.ant/1.8.2_2</bundle>
|
||||||
<bundle>mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.dom4j/1.6.1_5</bundle>
|
<bundle>mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.dom4j/1.6.1_5</bundle>
|
||||||
|
@ -36,8 +35,9 @@
|
||||||
<!-- Optional. Needed to test ehcache 2lc. -->
|
<!-- Optional. Needed to test ehcache 2lc. -->
|
||||||
<!-- <bundle>wrap:mvn:net.sf.ehcache/ehcache-core/2.4.3</bundle> -->
|
<!-- <bundle>wrap:mvn:net.sf.ehcache/ehcache-core/2.4.3</bundle> -->
|
||||||
|
|
||||||
<bundle>mvn:com.fasterxml/classmate/0.8.0</bundle>
|
<bundle>mvn:com.fasterxml/classmate/0.5.4</bundle>
|
||||||
<bundle>mvn:org.jboss.logging/jboss-logging/3.1.1.GA</bundle>
|
<bundle>mvn:org.jboss.logging/jboss-logging/3.1.0.GA</bundle>
|
||||||
|
<bundle>mvn:org.javassist/javassist/3.18.0-GA</bundle>
|
||||||
|
|
||||||
<!-- JACC is optional. -->
|
<!-- JACC is optional. -->
|
||||||
<!--<bundle>mvn:javax.servlet/javax.servlet-api/3.0.1</bundle>
|
<!--<bundle>mvn:javax.servlet/javax.servlet-api/3.0.1</bundle>
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.hibernate.javax.persistence</groupId>
|
<groupId>org.hibernate.javax.persistence</groupId>
|
||||||
<artifactId>hibernate-jpa-2.1-api</artifactId>
|
<artifactId>hibernate-jpa-2.1-api</artifactId>
|
||||||
<version>1.0.0-SNAPSHOT</version>
|
<version>1.0.0.Final</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.osgi</groupId>
|
<groupId>org.osgi</groupId>
|
||||||
|
|
|
@ -29,6 +29,9 @@ dependencies {
|
||||||
// for test runtime
|
// for test runtime
|
||||||
transitive = true
|
transitive = true
|
||||||
}
|
}
|
||||||
|
// for testing stored procedure support
|
||||||
|
testCompile( libraries.derby )
|
||||||
|
|
||||||
|
|
||||||
testRuntime( 'jaxen:jaxen:1.1' )
|
testRuntime( 'jaxen:jaxen:1.1' )
|
||||||
testRuntime( libraries.javassist )
|
testRuntime( libraries.javassist )
|
||||||
|
|
|
@ -1092,9 +1092,17 @@ public class Configuration implements Serializable {
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Foreign keys must be created *after* unique keys for numerous DBs. See HH-8390.
|
||||||
|
iter = getTableMappings();
|
||||||
|
while ( iter.hasNext() ) {
|
||||||
|
Table table = (Table) iter.next();
|
||||||
|
if ( table.isPhysicalTable() ) {
|
||||||
|
|
||||||
if ( dialect.hasAlterTable() ) {
|
if ( dialect.hasAlterTable() ) {
|
||||||
subIter = table.getForeignKeyIterator();
|
Iterator subIter = table.getForeignKeyIterator();
|
||||||
while ( subIter.hasNext() ) {
|
while ( subIter.hasNext() ) {
|
||||||
ForeignKey fk = (ForeignKey) subIter.next();
|
ForeignKey fk = (ForeignKey) subIter.next();
|
||||||
if ( fk.isPhysicalConstraint() ) {
|
if ( fk.isPhysicalConstraint() ) {
|
||||||
|
@ -1232,6 +1240,33 @@ public class Configuration implements Serializable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Iterator subIter = table.getIndexIterator();
|
||||||
|
while ( subIter.hasNext() ) {
|
||||||
|
final Index index = (Index) subIter.next();
|
||||||
|
// Skip if index already exists
|
||||||
|
if ( tableInfo != null && StringHelper.isNotEmpty( index.getName() ) ) {
|
||||||
|
final IndexMetadata meta = tableInfo.getIndexMetadata( index.getName() );
|
||||||
|
if ( meta != null ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
scripts.add( new SchemaUpdateScript( index.sqlCreateString( dialect, mapping, tableCatalog,
|
||||||
|
tableSchema ), false ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Foreign keys must be created *after* unique keys for numerous DBs. See HH-8390.
|
||||||
|
iter = getTableMappings();
|
||||||
|
while ( iter.hasNext() ) {
|
||||||
|
Table table = (Table) iter.next();
|
||||||
|
String tableSchema = ( table.getSchema() == null ) ? defaultSchema : table.getSchema();
|
||||||
|
String tableCatalog = ( table.getCatalog() == null ) ? defaultCatalog : table.getCatalog();
|
||||||
|
if ( table.isPhysicalTable() ) {
|
||||||
|
|
||||||
|
TableMetadata tableInfo = databaseMetadata.getTableMetadata( table.getName(), tableSchema,
|
||||||
|
tableCatalog, table.isQuoted() );
|
||||||
|
|
||||||
if ( dialect.hasAlterTable() ) {
|
if ( dialect.hasAlterTable() ) {
|
||||||
Iterator subIter = table.getForeignKeyIterator();
|
Iterator subIter = table.getForeignKeyIterator();
|
||||||
while ( subIter.hasNext() ) {
|
while ( subIter.hasNext() ) {
|
||||||
|
@ -1247,20 +1282,6 @@ public class Configuration implements Serializable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Iterator subIter = table.getIndexIterator();
|
|
||||||
while ( subIter.hasNext() ) {
|
|
||||||
final Index index = (Index) subIter.next();
|
|
||||||
// Skip if index already exists
|
|
||||||
if ( tableInfo != null && StringHelper.isNotEmpty( index.getName() ) ) {
|
|
||||||
final IndexMetadata meta = tableInfo.getIndexMetadata( index.getName() );
|
|
||||||
if ( meta != null ) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
scripts.add( new SchemaUpdateScript( index.sqlCreateString( dialect, mapping, tableCatalog,
|
|
||||||
tableSchema ), false ) );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -173,7 +173,8 @@ public class NamedProcedureCallDefinition {
|
||||||
: ParameterStrategy.POSITIONAL;
|
: ParameterStrategy.POSITIONAL;
|
||||||
parameterDefinitions = new ParameterDefinition[ parameters.length ];
|
parameterDefinitions = new ParameterDefinition[ parameters.length ];
|
||||||
for ( int i = 0; i < parameters.length; i++ ) {
|
for ( int i = 0; i < parameters.length; i++ ) {
|
||||||
parameterDefinitions[i] = new ParameterDefinition( i, parameters[i] );
|
// i+1 for the position because the apis say the numbers are 1-based, not zero
|
||||||
|
parameterDefinitions[i] = new ParameterDefinition( i+1, parameters[i] );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,8 @@ import java.sql.Types;
|
||||||
|
|
||||||
import org.hibernate.MappingException;
|
import org.hibernate.MappingException;
|
||||||
import org.hibernate.dialect.function.VarArgsSQLFunction;
|
import org.hibernate.dialect.function.VarArgsSQLFunction;
|
||||||
|
import org.hibernate.dialect.unique.InformixUniqueDelegate;
|
||||||
|
import org.hibernate.dialect.unique.UniqueDelegate;
|
||||||
import org.hibernate.exception.spi.TemplatedViolatedConstraintNameExtracter;
|
import org.hibernate.exception.spi.TemplatedViolatedConstraintNameExtracter;
|
||||||
import org.hibernate.exception.spi.ViolatedConstraintNameExtracter;
|
import org.hibernate.exception.spi.ViolatedConstraintNameExtracter;
|
||||||
import org.hibernate.internal.util.JdbcExceptionHelper;
|
import org.hibernate.internal.util.JdbcExceptionHelper;
|
||||||
|
@ -43,6 +45,8 @@ import org.hibernate.type.StandardBasicTypes;
|
||||||
*/
|
*/
|
||||||
public class InformixDialect extends Dialect {
|
public class InformixDialect extends Dialect {
|
||||||
|
|
||||||
|
private final UniqueDelegate uniqueDelegate;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates new <code>InformixDialect</code> instance. Sets up the JDBC /
|
* Creates new <code>InformixDialect</code> instance. Sets up the JDBC /
|
||||||
* Informix type mappings.
|
* Informix type mappings.
|
||||||
|
@ -77,6 +81,8 @@ public class InformixDialect extends Dialect {
|
||||||
registerColumnType( Types.VARCHAR, 32739, "lvarchar($l)" );
|
registerColumnType( Types.VARCHAR, 32739, "lvarchar($l)" );
|
||||||
|
|
||||||
registerFunction( "concat", new VarArgsSQLFunction( StandardBasicTypes.STRING, "(", "||", ")" ) );
|
registerFunction( "concat", new VarArgsSQLFunction( StandardBasicTypes.STRING, "(", "||", ")" ) );
|
||||||
|
|
||||||
|
uniqueDelegate = new InformixUniqueDelegate( this );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -286,4 +292,9 @@ public class InformixDialect extends Dialect {
|
||||||
public String getCreateTemporaryTablePostfix() {
|
public String getCreateTemporaryTablePostfix() {
|
||||||
return "with no log";
|
return "with no log";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public UniqueDelegate getUniqueDelegate() {
|
||||||
|
return uniqueDelegate;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,62 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* JBoss, Home of Professional Open Source
|
||||||
|
* Copyright 2012 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.dialect.unique;
|
||||||
|
|
||||||
|
import org.hibernate.dialect.Dialect;
|
||||||
|
import org.hibernate.metamodel.relational.UniqueKey;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Informix requires the constraint name to come last on the alter table.
|
||||||
|
*
|
||||||
|
* @author Brett Meyer
|
||||||
|
*/
|
||||||
|
public class InformixUniqueDelegate extends DefaultUniqueDelegate {
|
||||||
|
|
||||||
|
public InformixUniqueDelegate( Dialect dialect ) {
|
||||||
|
super( dialect );
|
||||||
|
}
|
||||||
|
|
||||||
|
// legacy model ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getAlterTableToAddUniqueKeyCommand(
|
||||||
|
org.hibernate.mapping.UniqueKey uniqueKey,
|
||||||
|
String defaultCatalog,
|
||||||
|
String defaultSchema) {
|
||||||
|
// Do this here, rather than allowing UniqueKey/Constraint to do it.
|
||||||
|
// We need full, simplified control over whether or not it happens.
|
||||||
|
final String tableName = uniqueKey.getTable().getQualifiedName( dialect, defaultCatalog, defaultSchema );
|
||||||
|
final String constraintName = dialect.quote( uniqueKey.getName() );
|
||||||
|
return "alter table " + tableName + " add constraint " + uniqueConstraintSql( uniqueKey ) + " constraint " + constraintName;
|
||||||
|
}
|
||||||
|
|
||||||
|
// new model ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getAlterTableToAddUniqueKeyCommand(UniqueKey uniqueKey) {
|
||||||
|
// Do this here, rather than allowing UniqueKey/Constraint to do it.
|
||||||
|
// We need full, simplified control over whether or not it happens.
|
||||||
|
final String tableName = uniqueKey.getTable().getQualifiedName( dialect );
|
||||||
|
final String constraintName = dialect.quote( uniqueKey.getName() );
|
||||||
|
|
||||||
|
return "alter table " + tableName + " add constraint " + uniqueConstraintSql( uniqueKey ) + " constraint " + constraintName;
|
||||||
|
}
|
||||||
|
}
|
|
@ -55,7 +55,7 @@ public class NaturalIdXrefDelegate {
|
||||||
private static final Logger LOG = Logger.getLogger( NaturalIdXrefDelegate.class );
|
private static final Logger LOG = Logger.getLogger( NaturalIdXrefDelegate.class );
|
||||||
|
|
||||||
private final StatefulPersistenceContext persistenceContext;
|
private final StatefulPersistenceContext persistenceContext;
|
||||||
private final Map<EntityPersister, NaturalIdResolutionCache> naturalIdResolutionCacheMap = new ConcurrentHashMap<EntityPersister, NaturalIdResolutionCache>();
|
private final ConcurrentHashMap<EntityPersister, NaturalIdResolutionCache> naturalIdResolutionCacheMap = new ConcurrentHashMap<EntityPersister, NaturalIdResolutionCache>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a NaturalIdXrefDelegate
|
* Constructs a NaturalIdXrefDelegate
|
||||||
|
@ -92,7 +92,10 @@ public class NaturalIdXrefDelegate {
|
||||||
NaturalIdResolutionCache entityNaturalIdResolutionCache = naturalIdResolutionCacheMap.get( persister );
|
NaturalIdResolutionCache entityNaturalIdResolutionCache = naturalIdResolutionCacheMap.get( persister );
|
||||||
if ( entityNaturalIdResolutionCache == null ) {
|
if ( entityNaturalIdResolutionCache == null ) {
|
||||||
entityNaturalIdResolutionCache = new NaturalIdResolutionCache( persister );
|
entityNaturalIdResolutionCache = new NaturalIdResolutionCache( persister );
|
||||||
naturalIdResolutionCacheMap.put( persister, entityNaturalIdResolutionCache );
|
NaturalIdResolutionCache previousInstance = naturalIdResolutionCacheMap.putIfAbsent( persister, entityNaturalIdResolutionCache );
|
||||||
|
if ( previousInstance != null ) {
|
||||||
|
entityNaturalIdResolutionCache = previousInstance;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return entityNaturalIdResolutionCache.cache( pk, naturalIdValues );
|
return entityNaturalIdResolutionCache.cache( pk, naturalIdValues );
|
||||||
}
|
}
|
||||||
|
@ -279,7 +282,10 @@ public class NaturalIdXrefDelegate {
|
||||||
|
|
||||||
if ( entityNaturalIdResolutionCache == null ) {
|
if ( entityNaturalIdResolutionCache == null ) {
|
||||||
entityNaturalIdResolutionCache = new NaturalIdResolutionCache( persister );
|
entityNaturalIdResolutionCache = new NaturalIdResolutionCache( persister );
|
||||||
naturalIdResolutionCacheMap.put( persister, entityNaturalIdResolutionCache );
|
NaturalIdResolutionCache existingCache = naturalIdResolutionCacheMap.putIfAbsent( persister, entityNaturalIdResolutionCache );
|
||||||
|
if ( existingCache != null ) {
|
||||||
|
entityNaturalIdResolutionCache = existingCache;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
entityNaturalIdResolutionCache.pkToNaturalIdMap.put( pk, cachedNaturalId );
|
entityNaturalIdResolutionCache.pkToNaturalIdMap.put( pk, cachedNaturalId );
|
||||||
|
|
|
@ -37,6 +37,7 @@ import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
|
import java.util.concurrent.ConcurrentMap;
|
||||||
|
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
|
|
||||||
|
@ -109,7 +110,7 @@ public class StatefulPersistenceContext implements PersistenceContext {
|
||||||
// private Map<Object,EntityEntry> entityEntries;
|
// private Map<Object,EntityEntry> entityEntries;
|
||||||
|
|
||||||
// Entity proxies, by EntityKey
|
// Entity proxies, by EntityKey
|
||||||
private Map<EntityKey, Object> proxiesByKey;
|
private ConcurrentMap<EntityKey, Object> proxiesByKey;
|
||||||
|
|
||||||
// Snapshots of current database state for entities
|
// Snapshots of current database state for entities
|
||||||
// that have *not* been loaded
|
// that have *not* been loaded
|
||||||
|
@ -563,9 +564,7 @@ public class StatefulPersistenceContext implements PersistenceContext {
|
||||||
final EntityPersister persister = session.getFactory().getEntityPersister( li.getEntityName() );
|
final EntityPersister persister = session.getFactory().getEntityPersister( li.getEntityName() );
|
||||||
final EntityKey key = session.generateEntityKey( li.getIdentifier(), persister );
|
final EntityKey key = session.generateEntityKey( li.getIdentifier(), persister );
|
||||||
// any earlier proxy takes precedence
|
// any earlier proxy takes precedence
|
||||||
if ( !proxiesByKey.containsKey( key ) ) {
|
proxiesByKey.putIfAbsent( key, proxy );
|
||||||
proxiesByKey.put( key, proxy );
|
|
||||||
}
|
|
||||||
proxy.getHibernateLazyInitializer().setSession( session );
|
proxy.getHibernateLazyInitializer().setSession( session );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -71,6 +71,7 @@ public class DriverManagerConnectionProviderImpl
|
||||||
private int poolSize;
|
private int poolSize;
|
||||||
private boolean autocommit;
|
private boolean autocommit;
|
||||||
|
|
||||||
|
//Access guarded by synchronization on the pool instance
|
||||||
private final ArrayList<Connection> pool = new ArrayList<Connection>();
|
private final ArrayList<Connection> pool = new ArrayList<Connection>();
|
||||||
private final AtomicInteger checkedOut = new AtomicInteger();
|
private final AtomicInteger checkedOut = new AtomicInteger();
|
||||||
|
|
||||||
|
@ -170,6 +171,7 @@ public class DriverManagerConnectionProviderImpl
|
||||||
public void stop() {
|
public void stop() {
|
||||||
LOG.cleaningUpConnectionPool( url );
|
LOG.cleaningUpConnectionPool( url );
|
||||||
|
|
||||||
|
synchronized ( pool ) {
|
||||||
for ( Connection connection : pool ) {
|
for ( Connection connection : pool ) {
|
||||||
try {
|
try {
|
||||||
connection.close();
|
connection.close();
|
||||||
|
@ -179,6 +181,7 @@ public class DriverManagerConnectionProviderImpl
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pool.clear();
|
pool.clear();
|
||||||
|
}
|
||||||
stopped = true;
|
stopped = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -152,7 +152,7 @@ public class HiLoOptimizer extends AbstractOptimizer {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IntegralDataTypeHolder getLastSourceValue() {
|
public synchronized IntegralDataTypeHolder getLastSourceValue() {
|
||||||
return noTenantGenerationState().lastSourceValue;
|
return noTenantGenerationState().lastSourceValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -168,7 +168,7 @@ public class HiLoOptimizer extends AbstractOptimizer {
|
||||||
*
|
*
|
||||||
* @return Value for property 'lastValue'.
|
* @return Value for property 'lastValue'.
|
||||||
*/
|
*/
|
||||||
public IntegralDataTypeHolder getLastValue() {
|
public synchronized IntegralDataTypeHolder getLastValue() {
|
||||||
return noTenantGenerationState().value.copy().decrement();
|
return noTenantGenerationState().value.copy().decrement();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -179,7 +179,7 @@ public class HiLoOptimizer extends AbstractOptimizer {
|
||||||
*
|
*
|
||||||
* @return Value for property 'upperLimit'.
|
* @return Value for property 'upperLimit'.
|
||||||
*/
|
*/
|
||||||
public IntegralDataTypeHolder getHiValue() {
|
public synchronized IntegralDataTypeHolder getHiValue() {
|
||||||
return noTenantGenerationState().upperLimit;
|
return noTenantGenerationState().upperLimit;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -125,7 +125,7 @@ public class LegacyHiLoAlgorithmOptimizer extends AbstractOptimizer {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IntegralDataTypeHolder getLastSourceValue() {
|
public synchronized IntegralDataTypeHolder getLastSourceValue() {
|
||||||
return noTenantGenerationState().lastSourceValue.copy();
|
return noTenantGenerationState().lastSourceValue.copy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -142,7 +142,7 @@ public class LegacyHiLoAlgorithmOptimizer extends AbstractOptimizer {
|
||||||
* @return Value for property 'lastValue'.
|
* @return Value for property 'lastValue'.
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings( {"UnusedDeclaration"})
|
@SuppressWarnings( {"UnusedDeclaration"})
|
||||||
public IntegralDataTypeHolder getLastValue() {
|
public synchronized IntegralDataTypeHolder getLastValue() {
|
||||||
return noTenantGenerationState().value;
|
return noTenantGenerationState().value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,7 +53,8 @@ public final class StringHelper {
|
||||||
public static int lastIndexOfLetter(String string) {
|
public static int lastIndexOfLetter(String string) {
|
||||||
for ( int i=0; i<string.length(); i++ ) {
|
for ( int i=0; i<string.length(); i++ ) {
|
||||||
char character = string.charAt(i);
|
char character = string.charAt(i);
|
||||||
if ( !Character.isLetter(character) /*&& !('_'==character)*/ ) return i-1;
|
// Include "_". See HHH-8073
|
||||||
|
if ( !Character.isLetter(character) && !('_'==character) ) return i-1;
|
||||||
}
|
}
|
||||||
return string.length()-1;
|
return string.length()-1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -594,6 +594,17 @@ public class CustomLoader extends Loader {
|
||||||
rowProcessor.columnProcessors[i].performDiscovery( metadata, types, aliases );
|
rowProcessor.columnProcessors[i].performDiscovery( metadata, types, aliases );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
validateAliases( aliases );
|
||||||
|
|
||||||
|
resultTypes = ArrayHelper.toTypeArray( types );
|
||||||
|
transformerAliases = ArrayHelper.toStringArray( aliases );
|
||||||
|
}
|
||||||
|
catch ( SQLException e ) {
|
||||||
|
throw new HibernateException( "Exception while trying to autodiscover types.", e );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void validateAliases(List<String> aliases) {
|
||||||
// lets make sure we did not end up with duplicate aliases. this can occur when the user supplied query
|
// lets make sure we did not end up with duplicate aliases. this can occur when the user supplied query
|
||||||
// did not rename same-named columns. e.g.:
|
// did not rename same-named columns. e.g.:
|
||||||
// select u.username, u2.username from t_user u, t_user u2 ...
|
// select u.username, u2.username from t_user u, t_user u2 ...
|
||||||
|
@ -603,6 +614,7 @@ public class CustomLoader extends Loader {
|
||||||
// troublesome condition, so lets throw an error. See HHH-5992
|
// troublesome condition, so lets throw an error. See HHH-5992
|
||||||
final HashSet<String> aliasesSet = new HashSet<String>();
|
final HashSet<String> aliasesSet = new HashSet<String>();
|
||||||
for ( String alias : aliases ) {
|
for ( String alias : aliases ) {
|
||||||
|
validateAlias( alias );
|
||||||
boolean alreadyExisted = !aliasesSet.add( alias );
|
boolean alreadyExisted = !aliasesSet.add( alias );
|
||||||
if ( alreadyExisted ) {
|
if ( alreadyExisted ) {
|
||||||
throw new NonUniqueDiscoveredSqlAliasException(
|
throw new NonUniqueDiscoveredSqlAliasException(
|
||||||
|
@ -611,13 +623,9 @@ public class CustomLoader extends Loader {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
resultTypes = ArrayHelper.toTypeArray( types );
|
protected void validateAlias(String alias) {
|
||||||
transformerAliases = ArrayHelper.toStringArray( aliases );
|
|
||||||
}
|
|
||||||
catch ( SQLException e ) {
|
|
||||||
throw new HibernateException( "Exception while trying to autodiscover types.", e );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class Metadata {
|
private static class Metadata {
|
||||||
|
|
|
@ -111,7 +111,7 @@ public class Column implements Selectable, Serializable, Cloneable {
|
||||||
@Override
|
@Override
|
||||||
public String getAlias(Dialect dialect) {
|
public String getAlias(Dialect dialect) {
|
||||||
final int lastLetter = StringHelper.lastIndexOfLetter( name );
|
final int lastLetter = StringHelper.lastIndexOfLetter( name );
|
||||||
String suffix = Integer.toString(uniqueInteger) + '_';
|
final String suffix = Integer.toString(uniqueInteger) + '_';
|
||||||
|
|
||||||
String alias = name;
|
String alias = name;
|
||||||
if ( lastLetter == -1 ) {
|
if ( lastLetter == -1 ) {
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013, Red Hat Inc. or third-party contributors as
|
||||||
|
* indicated by the @author tags or express copyright attribution
|
||||||
|
* statements applied by the authors. All third-party contributions are
|
||||||
|
* distributed under license by Red Hat Inc.
|
||||||
|
*
|
||||||
|
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||||
|
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||||
|
* Lesser General Public License, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||||
|
* for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this distribution; if not, write to:
|
||||||
|
* Free Software Foundation, Inc.
|
||||||
|
* 51 Franklin Street, Fifth Floor
|
||||||
|
* Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
package org.hibernate.procedure;
|
||||||
|
|
||||||
|
import org.hibernate.HibernateException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public class NoSuchParameterException extends HibernateException {
|
||||||
|
public NoSuchParameterException(String message) {
|
||||||
|
super( message );
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013, Red Hat Inc. or third-party contributors as
|
||||||
|
* indicated by the @author tags or express copyright attribution
|
||||||
|
* statements applied by the authors. All third-party contributions are
|
||||||
|
* distributed under license by Red Hat Inc.
|
||||||
|
*
|
||||||
|
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||||
|
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||||
|
* Lesser General Public License, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||||
|
* for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this distribution; if not, write to:
|
||||||
|
* Free Software Foundation, Inc.
|
||||||
|
* 51 Franklin Street, Fifth Floor
|
||||||
|
* Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
package org.hibernate.procedure;
|
||||||
|
|
||||||
|
import org.hibernate.HibernateException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public class ParameterStrategyException extends HibernateException {
|
||||||
|
public ParameterStrategyException(String message) {
|
||||||
|
super( message );
|
||||||
|
}
|
||||||
|
}
|
|
@ -82,6 +82,9 @@ public interface ProcedureCall extends BasicQueryContract, SynchronizeableQuery
|
||||||
* @param position The parameter position
|
* @param position The parameter position
|
||||||
*
|
*
|
||||||
* @return The parameter registration memento
|
* @return The parameter registration memento
|
||||||
|
*
|
||||||
|
* @throws ParameterStrategyException If the ProcedureCall is defined using named parameters
|
||||||
|
* @throws NoSuchParameterException If no parameter with that position exists
|
||||||
*/
|
*/
|
||||||
public ParameterRegistration getParameterRegistration(int position);
|
public ParameterRegistration getParameterRegistration(int position);
|
||||||
|
|
||||||
|
@ -122,6 +125,9 @@ public interface ProcedureCall extends BasicQueryContract, SynchronizeableQuery
|
||||||
* @param name The parameter name
|
* @param name The parameter name
|
||||||
*
|
*
|
||||||
* @return The parameter registration memento
|
* @return The parameter registration memento
|
||||||
|
*
|
||||||
|
* @throws ParameterStrategyException If the ProcedureCall is defined using positional parameters
|
||||||
|
* @throws NoSuchParameterException If no parameter with that name exists
|
||||||
*/
|
*/
|
||||||
public ParameterRegistration getParameterRegistration(String name);
|
public ParameterRegistration getParameterRegistration(String name);
|
||||||
|
|
||||||
|
@ -134,13 +140,14 @@ public interface ProcedureCall extends BasicQueryContract, SynchronizeableQuery
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves access to outputs of this procedure call. Can be called multiple times, returning the same
|
* Retrieves access to outputs of this procedure call. Can be called multiple times, returning the same
|
||||||
* Output instance each time.
|
* ProcedureResult instance each time.
|
||||||
* <p/>
|
* <p/>
|
||||||
* Note that the procedure will not actually be executed until the outputs are actually accessed.
|
* If the procedure call has not actually be executed yet, it will be executed and then the ProcedureResult
|
||||||
|
* will be returned.
|
||||||
*
|
*
|
||||||
* @return The outputs representation
|
* @return The ProcedureResult representation
|
||||||
*/
|
*/
|
||||||
public ProcedureResult getResult();
|
public ProcedureOutputs getResult();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extract the disconnected representation of this call. Used in HEM to allow redefining a named query
|
* Extract the disconnected representation of this call. Used in HEM to allow redefining a named query
|
||||||
|
|
|
@ -29,7 +29,7 @@ import org.hibernate.Session;
|
||||||
import org.hibernate.engine.spi.SessionImplementor;
|
import org.hibernate.engine.spi.SessionImplementor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a "memento" of a ProcedureCall
|
* Represents a "memento" (disconnected, externalizable form) of a ProcedureCall
|
||||||
*
|
*
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -23,20 +23,20 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.procedure;
|
package org.hibernate.procedure;
|
||||||
|
|
||||||
import org.hibernate.result.Result;
|
import org.hibernate.result.Outputs;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specialization of the {@link Result} contract providing access to the stored procedure's registered
|
* Specialization of the {@link org.hibernate.result.Outputs} contract providing access to the stored procedure's registered
|
||||||
* output parameters.
|
* output parameters.
|
||||||
*
|
*
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public interface ProcedureResult extends Result {
|
public interface ProcedureOutputs extends Outputs {
|
||||||
/**
|
/**
|
||||||
* Retrieve the value of an OUTPUT parameter by the parameter's registration memento.
|
* Retrieve the value of an OUTPUT parameter by the parameter's registration memento.
|
||||||
* <p/>
|
* <p/>
|
||||||
* Should NOT be called for parameters registered as REF_CURSOR. REF_CURSOR parameters should be
|
* Should NOT be called for parameters registered as REF_CURSOR. REF_CURSOR parameters should be
|
||||||
* accessed via the returns (see {@link #getNextReturn}
|
* accessed via the returns (see {@link #getNextOutput}
|
||||||
*
|
*
|
||||||
* @param parameterRegistration The parameter's registration memento.
|
* @param parameterRegistration The parameter's registration memento.
|
||||||
*
|
*
|
||||||
|
@ -53,6 +53,9 @@ public interface ProcedureResult extends Result {
|
||||||
*
|
*
|
||||||
* @return The output value.
|
* @return The output value.
|
||||||
*
|
*
|
||||||
|
* @throws ParameterStrategyException If the ProcedureCall is defined using positional parameters
|
||||||
|
* @throws NoSuchParameterException If no parameter with that name exists
|
||||||
|
*
|
||||||
* @see ProcedureCall#registerParameter(String, Class, javax.persistence.ParameterMode)
|
* @see ProcedureCall#registerParameter(String, Class, javax.persistence.ParameterMode)
|
||||||
*/
|
*/
|
||||||
public Object getOutputParameterValue(String name);
|
public Object getOutputParameterValue(String name);
|
||||||
|
@ -64,6 +67,9 @@ public interface ProcedureResult extends Result {
|
||||||
*
|
*
|
||||||
* @return The output value.
|
* @return The output value.
|
||||||
*
|
*
|
||||||
|
* @throws ParameterStrategyException If the ProcedureCall is defined using named parameters
|
||||||
|
* @throws NoSuchParameterException If no parameter with that position exists
|
||||||
|
*
|
||||||
* @see ProcedureCall#registerParameter(int, Class, javax.persistence.ParameterMode)
|
* @see ProcedureCall#registerParameter(int, Class, javax.persistence.ParameterMode)
|
||||||
*/
|
*/
|
||||||
public Object getOutputParameterValue(int position);
|
public Object getOutputParameterValue(int position);
|
|
@ -50,10 +50,12 @@ import org.hibernate.internal.util.StringHelper;
|
||||||
import org.hibernate.internal.util.collections.CollectionHelper;
|
import org.hibernate.internal.util.collections.CollectionHelper;
|
||||||
import org.hibernate.persister.entity.EntityPersister;
|
import org.hibernate.persister.entity.EntityPersister;
|
||||||
import org.hibernate.procedure.NamedParametersNotSupportedException;
|
import org.hibernate.procedure.NamedParametersNotSupportedException;
|
||||||
|
import org.hibernate.procedure.NoSuchParameterException;
|
||||||
import org.hibernate.procedure.ParameterRegistration;
|
import org.hibernate.procedure.ParameterRegistration;
|
||||||
|
import org.hibernate.procedure.ParameterStrategyException;
|
||||||
import org.hibernate.procedure.ProcedureCall;
|
import org.hibernate.procedure.ProcedureCall;
|
||||||
import org.hibernate.procedure.ProcedureCallMemento;
|
import org.hibernate.procedure.ProcedureCallMemento;
|
||||||
import org.hibernate.procedure.ProcedureResult;
|
import org.hibernate.procedure.ProcedureOutputs;
|
||||||
import org.hibernate.result.spi.ResultContext;
|
import org.hibernate.result.spi.ResultContext;
|
||||||
import org.hibernate.type.Type;
|
import org.hibernate.type.Type;
|
||||||
|
|
||||||
|
@ -75,7 +77,7 @@ public class ProcedureCallImpl extends AbstractBasicQueryContractImpl implements
|
||||||
|
|
||||||
private Set<String> synchronizedQuerySpaces;
|
private Set<String> synchronizedQuerySpaces;
|
||||||
|
|
||||||
private ProcedureResultImpl outputs;
|
private ProcedureOutputsImpl outputs;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The no-returns form.
|
* The no-returns form.
|
||||||
|
@ -321,21 +323,22 @@ public class ProcedureCallImpl extends AbstractBasicQueryContractImpl implements
|
||||||
@Override
|
@Override
|
||||||
public ParameterRegistrationImplementor getParameterRegistration(int position) {
|
public ParameterRegistrationImplementor getParameterRegistration(int position) {
|
||||||
if ( parameterStrategy != ParameterStrategy.POSITIONAL ) {
|
if ( parameterStrategy != ParameterStrategy.POSITIONAL ) {
|
||||||
throw new IllegalArgumentException( "Positions were not used to register parameters with this stored procedure call" );
|
throw new ParameterStrategyException(
|
||||||
|
"Attempt to access positional parameter [" + position + "] but ProcedureCall using named parameters"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
try {
|
for ( ParameterRegistrationImplementor parameter : registeredParameters ) {
|
||||||
return registeredParameters.get( position );
|
if ( position == parameter.getPosition() ) {
|
||||||
|
return parameter;
|
||||||
}
|
}
|
||||||
catch ( Exception e ) {
|
|
||||||
throw new QueryException( "Could not locate parameter registered using that position [" + position + "]" );
|
|
||||||
}
|
}
|
||||||
|
throw new NoSuchParameterException( "Could not locate parameter registered using that position [" + position + "]" );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public <T> ParameterRegistration<T> registerParameter(String name, Class<T> type, ParameterMode mode) {
|
public <T> ParameterRegistration<T> registerParameter(String name, Class<T> type, ParameterMode mode) {
|
||||||
final NamedParameterRegistration parameterRegistration
|
final NamedParameterRegistration parameterRegistration = new NamedParameterRegistration( this, name, mode, type );
|
||||||
= new NamedParameterRegistration( this, name, mode, type );
|
|
||||||
registerParameter( parameterRegistration );
|
registerParameter( parameterRegistration );
|
||||||
return parameterRegistration;
|
return parameterRegistration;
|
||||||
}
|
}
|
||||||
|
@ -350,14 +353,14 @@ public class ProcedureCallImpl extends AbstractBasicQueryContractImpl implements
|
||||||
@Override
|
@Override
|
||||||
public ParameterRegistrationImplementor getParameterRegistration(String name) {
|
public ParameterRegistrationImplementor getParameterRegistration(String name) {
|
||||||
if ( parameterStrategy != ParameterStrategy.NAMED ) {
|
if ( parameterStrategy != ParameterStrategy.NAMED ) {
|
||||||
throw new IllegalArgumentException( "Names were not used to register parameters with this stored procedure call" );
|
throw new ParameterStrategyException( "Names were not used to register parameters with this stored procedure call" );
|
||||||
}
|
}
|
||||||
for ( ParameterRegistrationImplementor parameter : registeredParameters ) {
|
for ( ParameterRegistrationImplementor parameter : registeredParameters ) {
|
||||||
if ( name.equals( parameter.getName() ) ) {
|
if ( name.equals( parameter.getName() ) ) {
|
||||||
return parameter;
|
return parameter;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
throw new IllegalArgumentException( "Could not locate parameter registered under that name [" + name + "]" );
|
throw new NoSuchParameterException( "Could not locate parameter registered under that name [" + name + "]" );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -367,7 +370,7 @@ public class ProcedureCallImpl extends AbstractBasicQueryContractImpl implements
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ProcedureResult getResult() {
|
public ProcedureOutputs getResult() {
|
||||||
if ( outputs == null ) {
|
if ( outputs == null ) {
|
||||||
outputs = buildOutputs();
|
outputs = buildOutputs();
|
||||||
}
|
}
|
||||||
|
@ -375,7 +378,7 @@ public class ProcedureCallImpl extends AbstractBasicQueryContractImpl implements
|
||||||
return outputs;
|
return outputs;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ProcedureResultImpl buildOutputs() {
|
private ProcedureOutputsImpl buildOutputs() {
|
||||||
// todo : going to need a very specialized Loader for this.
|
// todo : going to need a very specialized Loader for this.
|
||||||
// or, might be a good time to look at splitting Loader up into:
|
// or, might be a good time to look at splitting Loader up into:
|
||||||
// 1) building statement objects
|
// 1) building statement objects
|
||||||
|
@ -385,6 +388,11 @@ public class ProcedureCallImpl extends AbstractBasicQueryContractImpl implements
|
||||||
// for now assume there are no resultClasses nor mappings defined..
|
// for now assume there are no resultClasses nor mappings defined..
|
||||||
// TOTAL PROOF-OF-CONCEPT!!!!!!
|
// TOTAL PROOF-OF-CONCEPT!!!!!!
|
||||||
|
|
||||||
|
// todo : how to identify calls which should be in the form `{? = call procName...}` ??? (note leading param marker)
|
||||||
|
// more than likely this will need to be a method on the native API. I can see this as a trigger to
|
||||||
|
// both: (1) add the `? = ` part and also (2) register a REFCURSOR parameter for DBs (Oracle, PGSQL) that
|
||||||
|
// need it.
|
||||||
|
|
||||||
final StringBuilder buffer = new StringBuilder().append( "{call " )
|
final StringBuilder buffer = new StringBuilder().append( "{call " )
|
||||||
.append( procedureName )
|
.append( procedureName )
|
||||||
.append( "(" );
|
.append( "(" );
|
||||||
|
@ -414,7 +422,7 @@ public class ProcedureCallImpl extends AbstractBasicQueryContractImpl implements
|
||||||
i += parameter.getSqlTypes().length;
|
i += parameter.getSqlTypes().length;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new ProcedureResultImpl( this, statement );
|
return new ProcedureOutputsImpl( this, statement );
|
||||||
}
|
}
|
||||||
catch (SQLException e) {
|
catch (SQLException e) {
|
||||||
throw getSession().getFactory().getSQLExceptionHelper().convert(
|
throw getSession().getFactory().getSQLExceptionHelper().convert(
|
||||||
|
|
|
@ -25,28 +25,26 @@ package org.hibernate.procedure.internal;
|
||||||
|
|
||||||
import java.sql.CallableStatement;
|
import java.sql.CallableStatement;
|
||||||
import java.sql.ResultSet;
|
import java.sql.ResultSet;
|
||||||
import java.sql.SQLException;
|
|
||||||
|
|
||||||
import org.hibernate.JDBCException;
|
|
||||||
import org.hibernate.engine.jdbc.cursor.spi.RefCursorSupport;
|
import org.hibernate.engine.jdbc.cursor.spi.RefCursorSupport;
|
||||||
import org.hibernate.procedure.ParameterRegistration;
|
import org.hibernate.procedure.ParameterRegistration;
|
||||||
import org.hibernate.procedure.ProcedureResult;
|
import org.hibernate.procedure.ProcedureOutputs;
|
||||||
import org.hibernate.result.Return;
|
import org.hibernate.result.Output;
|
||||||
import org.hibernate.result.internal.ResultImpl;
|
import org.hibernate.result.internal.OutputsImpl;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implementation of ProcedureResult. Defines centralized access to all of the results of a procedure call.
|
* Implementation of ProcedureResult. Defines centralized access to all of the results of a procedure call.
|
||||||
*
|
*
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public class ProcedureResultImpl extends ResultImpl implements ProcedureResult {
|
public class ProcedureOutputsImpl extends OutputsImpl implements ProcedureOutputs {
|
||||||
private final ProcedureCallImpl procedureCall;
|
private final ProcedureCallImpl procedureCall;
|
||||||
private final CallableStatement callableStatement;
|
private final CallableStatement callableStatement;
|
||||||
|
|
||||||
private final ParameterRegistrationImplementor[] refCursorParameters;
|
private final ParameterRegistrationImplementor[] refCursorParameters;
|
||||||
private int refCursorParamIndex;
|
private int refCursorParamIndex;
|
||||||
|
|
||||||
ProcedureResultImpl(ProcedureCallImpl procedureCall, CallableStatement callableStatement) {
|
ProcedureOutputsImpl(ProcedureCallImpl procedureCall, CallableStatement callableStatement) {
|
||||||
super( procedureCall, callableStatement );
|
super( procedureCall, callableStatement );
|
||||||
this.procedureCall = procedureCall;
|
this.procedureCall = procedureCall;
|
||||||
this.callableStatement = callableStatement;
|
this.callableStatement = callableStatement;
|
||||||
|
@ -70,48 +68,45 @@ public class ProcedureResultImpl extends ResultImpl implements ProcedureResult {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected CurrentReturnDescriptor buildCurrentReturnDescriptor(boolean isResultSet, int updateCount) {
|
protected CurrentReturnState buildCurrentReturnState(boolean isResultSet, int updateCount) {
|
||||||
return new ProcedureCurrentReturnDescriptor( isResultSet, updateCount, refCursorParamIndex );
|
return new ProcedureCurrentReturnState( isResultSet, updateCount, refCursorParamIndex );
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean hasMoreReturns(CurrentReturnDescriptor descriptor) {
|
protected class ProcedureCurrentReturnState extends CurrentReturnState {
|
||||||
return super.hasMoreReturns( descriptor )
|
private final int refCursorParamIndex;
|
||||||
|| ( (ProcedureCurrentReturnDescriptor) descriptor ).refCursorParamIndex < refCursorParameters.length;
|
|
||||||
|
private ProcedureCurrentReturnState(boolean isResultSet, int updateCount, int refCursorParamIndex) {
|
||||||
|
super( isResultSet, updateCount );
|
||||||
|
this.refCursorParamIndex = refCursorParamIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Return buildExtendedReturn(CurrentReturnDescriptor returnDescriptor) {
|
public boolean indicatesMoreOutputs() {
|
||||||
this.refCursorParamIndex++;
|
return super.indicatesMoreOutputs()
|
||||||
final int refCursorParamIndex = ( (ProcedureCurrentReturnDescriptor) returnDescriptor ).refCursorParamIndex;
|
|| ProcedureOutputsImpl.this.refCursorParamIndex < ProcedureOutputsImpl.this.refCursorParameters.length;
|
||||||
final ParameterRegistrationImplementor refCursorParam = refCursorParameters[refCursorParamIndex];
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean hasExtendedReturns() {
|
||||||
|
return refCursorParamIndex < refCursorParameters.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Output buildExtendedReturn() {
|
||||||
|
ProcedureOutputsImpl.this.refCursorParamIndex++;
|
||||||
|
final ParameterRegistrationImplementor refCursorParam = ProcedureOutputsImpl.this.refCursorParameters[refCursorParamIndex];
|
||||||
ResultSet resultSet;
|
ResultSet resultSet;
|
||||||
if ( refCursorParam.getName() != null ) {
|
if ( refCursorParam.getName() != null ) {
|
||||||
resultSet = procedureCall.getSession().getFactory().getServiceRegistry()
|
resultSet = ProcedureOutputsImpl.this.procedureCall.getSession().getFactory().getServiceRegistry()
|
||||||
.getService( RefCursorSupport.class )
|
.getService( RefCursorSupport.class )
|
||||||
.getResultSet( callableStatement, refCursorParam.getName() );
|
.getResultSet( ProcedureOutputsImpl.this.callableStatement, refCursorParam.getName() );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
resultSet = procedureCall.getSession().getFactory().getServiceRegistry()
|
resultSet = ProcedureOutputsImpl.this.procedureCall.getSession().getFactory().getServiceRegistry()
|
||||||
.getService( RefCursorSupport.class )
|
.getService( RefCursorSupport.class )
|
||||||
.getResultSet( callableStatement, refCursorParam.getPosition() );
|
.getResultSet( ProcedureOutputsImpl.this.callableStatement, refCursorParam.getPosition() );
|
||||||
}
|
}
|
||||||
return new ResultSetReturn( this, resultSet );
|
return buildResultSetOutput( extractResults( resultSet ) );
|
||||||
}
|
|
||||||
|
|
||||||
protected JDBCException convert(SQLException e, String message) {
|
|
||||||
return procedureCall.getSession().getFactory().getSQLExceptionHelper().convert(
|
|
||||||
e,
|
|
||||||
message,
|
|
||||||
procedureCall.getProcedureName()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected static class ProcedureCurrentReturnDescriptor extends CurrentReturnDescriptor {
|
|
||||||
private final int refCursorParamIndex;
|
|
||||||
|
|
||||||
private ProcedureCurrentReturnDescriptor(boolean isResultSet, int updateCount, int refCursorParamIndex) {
|
|
||||||
super( isResultSet, updateCount );
|
|
||||||
this.refCursorParamIndex = refCursorParamIndex;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,4 +32,8 @@ public class NoMoreReturnsException extends HibernateException {
|
||||||
public NoMoreReturnsException(String message) {
|
public NoMoreReturnsException(String message) {
|
||||||
super( message );
|
super( message );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public NoMoreReturnsException() {
|
||||||
|
super( "Results have been exhausted" );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,18 +24,18 @@
|
||||||
package org.hibernate.result;
|
package org.hibernate.result;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Common contract for individual return objects which can be either results ({@link ResultSetReturn}) or update
|
* Common contract for individual return objects which can be either results ({@link ResultSetOutput}) or update
|
||||||
* counts ({@link UpdateCountReturn}).
|
* counts ({@link UpdateCountOutput}).
|
||||||
*
|
*
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public interface Return {
|
public interface Output {
|
||||||
/**
|
/**
|
||||||
* Determine if this return is a result (castable to {@link ResultSetReturn}). The alternative is that it is
|
* Determine if this return is a result (castable to {@link ResultSetOutput}). The alternative is that it is
|
||||||
* an update count (castable to {@link UpdateCountReturn}).
|
* an update count (castable to {@link UpdateCountOutput}).
|
||||||
*
|
*
|
||||||
* @return {@code true} indicates that {@code this} can be safely cast to {@link ResultSetReturn}), other wise
|
* @return {@code true} indicates that {@code this} can be safely cast to {@link ResultSetOutput}), other wise
|
||||||
* it can be cast to {@link UpdateCountReturn}.
|
* it can be cast to {@link UpdateCountOutput}.
|
||||||
*/
|
*/
|
||||||
public boolean isResultSet();
|
public boolean isResultSet();
|
||||||
}
|
}
|
|
@ -24,27 +24,32 @@
|
||||||
package org.hibernate.result;
|
package org.hibernate.result;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents the result of executing a JDBC statement accounting for mixing of result sets and update counts hiding the
|
* Represents the outputs of executing a JDBC statement accounting for mixing of result sets and update counts
|
||||||
* complexity (IMO) of how this is exposed in the JDBC API.
|
* hiding the complexity (IMO) of how this is exposed in the JDBC API.
|
||||||
*
|
* <p/>
|
||||||
* A result is made up of group of {@link Return} objects, each representing a single result set or update count.
|
* The outputs are exposed as a group of {@link Output} objects, each representing a single result set or update count.
|
||||||
* Conceptually, Result presents those Returns as an iterator.
|
* Conceptually, Result presents those Returns as an iterator.
|
||||||
*
|
*
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public interface Result {
|
public interface Outputs {
|
||||||
/**
|
/**
|
||||||
* Are there any more returns associated with this result?
|
* Retrieve the current Output object.
|
||||||
*
|
*
|
||||||
* @return {@code true} means there are more returns available via {@link #getNextReturn()}; {@code false}
|
* @return The current Output object. Can be {@code null}
|
||||||
* indicates that calling {@link #getNextReturn()} will certainly result in an exception.
|
|
||||||
*/
|
*/
|
||||||
public boolean hasMoreReturns();
|
public Output getCurrent();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve the next return.
|
* Go to the next Output object (if any), returning an indication of whether there was another (aka, will
|
||||||
|
* the next call to {@link #getCurrent()} return {@code null}?
|
||||||
*
|
*
|
||||||
* @return The next return.
|
* @return {@code true} if the next call to {@link #getCurrent()} will return a non-{@code null} value.
|
||||||
*/
|
*/
|
||||||
public Return getNextReturn() throws NoMoreReturnsException;
|
public boolean goToNext();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Eagerly release any resources held by this Outputs.
|
||||||
|
*/
|
||||||
|
public void release();
|
||||||
}
|
}
|
|
@ -30,7 +30,7 @@ import java.util.List;
|
||||||
*
|
*
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public interface ResultSetReturn extends Return {
|
public interface ResultSetOutput extends Output {
|
||||||
/**
|
/**
|
||||||
* Consume the underlying {@link java.sql.ResultSet} and return the resulting List.
|
* Consume the underlying {@link java.sql.ResultSet} and return the resulting List.
|
||||||
*
|
*
|
|
@ -28,7 +28,7 @@ package org.hibernate.result;
|
||||||
*
|
*
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public interface UpdateCountReturn extends Return {
|
public interface UpdateCountOutput extends Output {
|
||||||
/**
|
/**
|
||||||
* Retrieve the associated update count
|
* Retrieve the associated update count
|
||||||
*
|
*
|
|
@ -0,0 +1,321 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013, Red Hat Inc. or third-party contributors as
|
||||||
|
* indicated by the @author tags or express copyright attribution
|
||||||
|
* statements applied by the authors. All third-party contributions are
|
||||||
|
* distributed under license by Red Hat Inc.
|
||||||
|
*
|
||||||
|
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||||
|
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||||
|
* Lesser General Public License, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||||
|
* for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this distribution; if not, write to:
|
||||||
|
* Free Software Foundation, Inc.
|
||||||
|
* 51 Franklin Street, Fifth Floor
|
||||||
|
* Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
package org.hibernate.result.internal;
|
||||||
|
|
||||||
|
import java.sql.PreparedStatement;
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.jboss.logging.Logger;
|
||||||
|
|
||||||
|
import org.hibernate.JDBCException;
|
||||||
|
import org.hibernate.engine.spi.QueryParameters;
|
||||||
|
import org.hibernate.engine.spi.SessionImplementor;
|
||||||
|
import org.hibernate.internal.CoreLogging;
|
||||||
|
import org.hibernate.loader.custom.CustomLoader;
|
||||||
|
import org.hibernate.loader.custom.CustomQuery;
|
||||||
|
import org.hibernate.loader.custom.sql.SQLQueryReturnProcessor;
|
||||||
|
import org.hibernate.loader.spi.AfterLoadAction;
|
||||||
|
import org.hibernate.result.NoMoreReturnsException;
|
||||||
|
import org.hibernate.result.Outputs;
|
||||||
|
import org.hibernate.result.Output;
|
||||||
|
import org.hibernate.result.spi.ResultContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public class OutputsImpl implements Outputs {
|
||||||
|
private static final Logger log = CoreLogging.logger( OutputsImpl.class );
|
||||||
|
|
||||||
|
private final ResultContext context;
|
||||||
|
private final PreparedStatement jdbcStatement;
|
||||||
|
private final CustomLoaderExtension loader;
|
||||||
|
|
||||||
|
private CurrentReturnState currentReturnState;
|
||||||
|
|
||||||
|
public OutputsImpl(ResultContext context, PreparedStatement jdbcStatement) {
|
||||||
|
this.context = context;
|
||||||
|
this.jdbcStatement = jdbcStatement;
|
||||||
|
|
||||||
|
// For now... but see the LoadPlan work; eventually this should just be a ResultSetProcessor.
|
||||||
|
this.loader = buildSpecializedCustomLoader( context );
|
||||||
|
|
||||||
|
try {
|
||||||
|
final boolean isResultSet = jdbcStatement.execute();
|
||||||
|
currentReturnState = buildCurrentReturnState( isResultSet );
|
||||||
|
}
|
||||||
|
catch (SQLException e) {
|
||||||
|
throw convert( e, "Error calling CallableStatement.getMoreResults" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private CurrentReturnState buildCurrentReturnState(boolean isResultSet) {
|
||||||
|
int updateCount = -1;
|
||||||
|
if ( ! isResultSet ) {
|
||||||
|
try {
|
||||||
|
updateCount = jdbcStatement.getUpdateCount();
|
||||||
|
}
|
||||||
|
catch (SQLException e) {
|
||||||
|
throw convert( e, "Error calling CallableStatement.getUpdateCount" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return buildCurrentReturnState( isResultSet, updateCount );
|
||||||
|
}
|
||||||
|
|
||||||
|
protected CurrentReturnState buildCurrentReturnState(boolean isResultSet, int updateCount) {
|
||||||
|
return new CurrentReturnState( isResultSet, updateCount );
|
||||||
|
}
|
||||||
|
|
||||||
|
protected JDBCException convert(SQLException e, String message) {
|
||||||
|
return context.getSession().getFactory().getSQLExceptionHelper().convert(
|
||||||
|
e,
|
||||||
|
message,
|
||||||
|
context.getSql()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Output getCurrent() {
|
||||||
|
if ( currentReturnState == null ) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return currentReturnState.getOutput();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean goToNext() {
|
||||||
|
if ( currentReturnState == null ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( currentReturnState.indicatesMoreOutputs() )
|
||||||
|
// prepare the next return state
|
||||||
|
try {
|
||||||
|
final boolean isResultSet = jdbcStatement.getMoreResults();
|
||||||
|
currentReturnState = buildCurrentReturnState( isResultSet );
|
||||||
|
}
|
||||||
|
catch (SQLException e) {
|
||||||
|
throw convert( e, "Error calling CallableStatement.getMoreResults" );
|
||||||
|
}
|
||||||
|
|
||||||
|
// and return
|
||||||
|
return currentReturnState != null && currentReturnState.indicatesMoreOutputs();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void release() {
|
||||||
|
try {
|
||||||
|
jdbcStatement.close();
|
||||||
|
}
|
||||||
|
catch (SQLException e) {
|
||||||
|
log.debug( "Unable to close PreparedStatement", e );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private List extractCurrentResults() {
|
||||||
|
try {
|
||||||
|
return extractResults( jdbcStatement.getResultSet() );
|
||||||
|
}
|
||||||
|
catch (SQLException e) {
|
||||||
|
throw convert( e, "Error calling CallableStatement.getResultSet" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected List extractResults(ResultSet resultSet) {
|
||||||
|
try {
|
||||||
|
return loader.processResultSet( resultSet );
|
||||||
|
}
|
||||||
|
catch (SQLException e) {
|
||||||
|
throw convert( e, "Error extracting results from CallableStatement" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encapsulates the information needed to interpret the current return within a result
|
||||||
|
*/
|
||||||
|
protected class CurrentReturnState {
|
||||||
|
private final boolean isResultSet;
|
||||||
|
private final int updateCount;
|
||||||
|
|
||||||
|
private Output rtn;
|
||||||
|
|
||||||
|
protected CurrentReturnState(boolean isResultSet, int updateCount) {
|
||||||
|
this.isResultSet = isResultSet;
|
||||||
|
this.updateCount = updateCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean indicatesMoreOutputs() {
|
||||||
|
return isResultSet() || getUpdateCount() >= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isResultSet() {
|
||||||
|
return isResultSet;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getUpdateCount() {
|
||||||
|
return updateCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Output getOutput() {
|
||||||
|
if ( rtn == null ) {
|
||||||
|
rtn = buildOutput();
|
||||||
|
}
|
||||||
|
return rtn;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Output buildOutput() {
|
||||||
|
if ( log.isDebugEnabled() ) {
|
||||||
|
log.debugf(
|
||||||
|
"Building Return [isResultSet=%s, updateCount=%s, extendedReturn=%s",
|
||||||
|
isResultSet(),
|
||||||
|
getUpdateCount(),
|
||||||
|
hasExtendedReturns()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
// todo : temporary for tck testing...
|
||||||
|
System.out.println(
|
||||||
|
String.format(
|
||||||
|
"Building Return [isResultSet=%s, updateCount=%s, extendedReturn=%s",
|
||||||
|
isResultSet(),
|
||||||
|
getUpdateCount(),
|
||||||
|
hasExtendedReturns()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
if ( isResultSet() ) {
|
||||||
|
return buildResultSetOutput( extractCurrentResults() );
|
||||||
|
}
|
||||||
|
else if ( getUpdateCount() >= 0 ) {
|
||||||
|
return buildUpdateCountOutput( updateCount );
|
||||||
|
}
|
||||||
|
else if ( hasExtendedReturns() ) {
|
||||||
|
return buildExtendedReturn();
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new NoMoreReturnsException();
|
||||||
|
}
|
||||||
|
|
||||||
|
// hooks for stored procedure (out param) processing ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
protected Output buildResultSetOutput(List list) {
|
||||||
|
return new ResultSetOutputImpl( list );
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Output buildUpdateCountOutput(int updateCount) {
|
||||||
|
return new UpdateCountOutputImpl( updateCount );
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean hasExtendedReturns() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Output buildExtendedReturn() {
|
||||||
|
throw new IllegalStateException( "State does not define extended returns" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
// Hooks into Hibernate's Loader hierarchy for ResultSet -> Object mapping
|
||||||
|
|
||||||
|
private static CustomLoaderExtension buildSpecializedCustomLoader(final ResultContext context) {
|
||||||
|
// might be better to just manually construct the Return(s).. SQLQueryReturnProcessor does a lot of
|
||||||
|
// work that is really unnecessary here.
|
||||||
|
final SQLQueryReturnProcessor processor = new SQLQueryReturnProcessor(
|
||||||
|
context.getQueryReturns(),
|
||||||
|
context.getSession().getFactory()
|
||||||
|
);
|
||||||
|
processor.process();
|
||||||
|
final List<org.hibernate.loader.custom.Return> customReturns = processor.generateCustomReturns( false );
|
||||||
|
|
||||||
|
CustomQuery customQuery = new CustomQuery() {
|
||||||
|
@Override
|
||||||
|
public String getSQL() {
|
||||||
|
return context.getSql();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<String> getQuerySpaces() {
|
||||||
|
return context.getSynchronizedQuerySpaces();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map getNamedParameterBindPoints() {
|
||||||
|
// no named parameters in terms of embedded in the SQL string
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<org.hibernate.loader.custom.Return> getCustomQueryReturns() {
|
||||||
|
return customReturns;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return new CustomLoaderExtension(
|
||||||
|
customQuery,
|
||||||
|
context.getQueryParameters(),
|
||||||
|
context.getSession()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class CustomLoaderExtension extends CustomLoader {
|
||||||
|
private QueryParameters queryParameters;
|
||||||
|
private SessionImplementor session;
|
||||||
|
|
||||||
|
private boolean needsDiscovery = true;
|
||||||
|
|
||||||
|
public CustomLoaderExtension(
|
||||||
|
CustomQuery customQuery,
|
||||||
|
QueryParameters queryParameters,
|
||||||
|
SessionImplementor session) {
|
||||||
|
super( customQuery, session.getFactory() );
|
||||||
|
this.queryParameters = queryParameters;
|
||||||
|
this.session = session;
|
||||||
|
}
|
||||||
|
|
||||||
|
// todo : this would be a great way to add locking to stored procedure support (at least where returning entities).
|
||||||
|
|
||||||
|
public List processResultSet(ResultSet resultSet) throws SQLException {
|
||||||
|
if ( needsDiscovery ) {
|
||||||
|
super.autoDiscoverTypes( resultSet );
|
||||||
|
// todo : EntityAliases discovery
|
||||||
|
needsDiscovery = false;
|
||||||
|
}
|
||||||
|
return super.processResultSet(
|
||||||
|
resultSet,
|
||||||
|
queryParameters,
|
||||||
|
session,
|
||||||
|
true,
|
||||||
|
null,
|
||||||
|
Integer.MAX_VALUE,
|
||||||
|
Collections.<AfterLoadAction>emptyList()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,293 +0,0 @@
|
||||||
/*
|
|
||||||
* Hibernate, Relational Persistence for Idiomatic Java
|
|
||||||
*
|
|
||||||
* Copyright (c) 2013, Red Hat Inc. or third-party contributors as
|
|
||||||
* indicated by the @author tags or express copyright attribution
|
|
||||||
* statements applied by the authors. All third-party contributions are
|
|
||||||
* distributed under license by Red Hat Inc.
|
|
||||||
*
|
|
||||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
|
||||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
|
||||||
* Lesser General Public License, as published by the Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
||||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
|
||||||
* for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
|
||||||
* along with this distribution; if not, write to:
|
|
||||||
* Free Software Foundation, Inc.
|
|
||||||
* 51 Franklin Street, Fifth Floor
|
|
||||||
* Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
package org.hibernate.result.internal;
|
|
||||||
|
|
||||||
import java.sql.PreparedStatement;
|
|
||||||
import java.sql.ResultSet;
|
|
||||||
import java.sql.SQLException;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import org.hibernate.JDBCException;
|
|
||||||
import org.hibernate.engine.spi.QueryParameters;
|
|
||||||
import org.hibernate.engine.spi.SessionImplementor;
|
|
||||||
import org.hibernate.loader.custom.CustomLoader;
|
|
||||||
import org.hibernate.loader.custom.CustomQuery;
|
|
||||||
import org.hibernate.loader.custom.sql.SQLQueryReturnProcessor;
|
|
||||||
import org.hibernate.loader.spi.AfterLoadAction;
|
|
||||||
import org.hibernate.result.NoMoreReturnsException;
|
|
||||||
import org.hibernate.result.Result;
|
|
||||||
import org.hibernate.result.Return;
|
|
||||||
import org.hibernate.result.spi.ResultContext;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Steve Ebersole
|
|
||||||
*/
|
|
||||||
public class ResultImpl implements Result {
|
|
||||||
private final ResultContext context;
|
|
||||||
private final PreparedStatement jdbcStatement;
|
|
||||||
private final CustomLoaderExtension loader;
|
|
||||||
|
|
||||||
private CurrentReturnDescriptor currentReturnDescriptor;
|
|
||||||
|
|
||||||
private boolean executed = false;
|
|
||||||
|
|
||||||
public ResultImpl(ResultContext context, PreparedStatement jdbcStatement) {
|
|
||||||
this.context = context;
|
|
||||||
this.jdbcStatement = jdbcStatement;
|
|
||||||
|
|
||||||
// For now...
|
|
||||||
this.loader = buildSpecializedCustomLoader( context );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean hasMoreReturns() {
|
|
||||||
if ( currentReturnDescriptor == null ) {
|
|
||||||
final boolean isResultSet;
|
|
||||||
|
|
||||||
if ( executed ) {
|
|
||||||
try {
|
|
||||||
isResultSet = jdbcStatement.getMoreResults();
|
|
||||||
}
|
|
||||||
catch (SQLException e) {
|
|
||||||
throw convert( e, "Error calling CallableStatement.getMoreResults" );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
try {
|
|
||||||
isResultSet = jdbcStatement.execute();
|
|
||||||
}
|
|
||||||
catch (SQLException e) {
|
|
||||||
throw convert( e, "Error calling CallableStatement.execute" );
|
|
||||||
}
|
|
||||||
executed = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
int updateCount = -1;
|
|
||||||
if ( ! isResultSet ) {
|
|
||||||
try {
|
|
||||||
updateCount = jdbcStatement.getUpdateCount();
|
|
||||||
}
|
|
||||||
catch (SQLException e) {
|
|
||||||
throw convert( e, "Error calling CallableStatement.getUpdateCount" );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
currentReturnDescriptor = buildCurrentReturnDescriptor( isResultSet, updateCount );
|
|
||||||
}
|
|
||||||
|
|
||||||
return hasMoreReturns( currentReturnDescriptor );
|
|
||||||
}
|
|
||||||
|
|
||||||
protected CurrentReturnDescriptor buildCurrentReturnDescriptor(boolean isResultSet, int updateCount) {
|
|
||||||
return new CurrentReturnDescriptor( isResultSet, updateCount );
|
|
||||||
}
|
|
||||||
|
|
||||||
protected boolean hasMoreReturns(CurrentReturnDescriptor descriptor) {
|
|
||||||
return descriptor.isResultSet
|
|
||||||
|| descriptor.updateCount >= 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Return getNextReturn() {
|
|
||||||
if ( currentReturnDescriptor == null ) {
|
|
||||||
if ( executed ) {
|
|
||||||
throw new IllegalStateException( "Unexpected condition" );
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
throw new IllegalStateException( "hasMoreReturns() not called before getNextReturn()" );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( ! hasMoreReturns( currentReturnDescriptor ) ) {
|
|
||||||
throw new NoMoreReturnsException( "Results have been exhausted" );
|
|
||||||
}
|
|
||||||
|
|
||||||
CurrentReturnDescriptor copyReturnDescriptor = currentReturnDescriptor;
|
|
||||||
currentReturnDescriptor = null;
|
|
||||||
|
|
||||||
if ( copyReturnDescriptor.isResultSet ) {
|
|
||||||
try {
|
|
||||||
return new ResultSetReturn( this, jdbcStatement.getResultSet() );
|
|
||||||
}
|
|
||||||
catch (SQLException e) {
|
|
||||||
throw convert( e, "Error calling CallableStatement.getResultSet" );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if ( copyReturnDescriptor.updateCount >= 0 ) {
|
|
||||||
return new UpdateCountReturn( this, copyReturnDescriptor.updateCount );
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return buildExtendedReturn( copyReturnDescriptor );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Return buildExtendedReturn(CurrentReturnDescriptor copyReturnDescriptor) {
|
|
||||||
throw new NoMoreReturnsException( "Results have been exhausted" );
|
|
||||||
}
|
|
||||||
|
|
||||||
protected JDBCException convert(SQLException e, String message) {
|
|
||||||
return context.getSession().getFactory().getSQLExceptionHelper().convert(
|
|
||||||
e,
|
|
||||||
message,
|
|
||||||
context.getSql()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected static class CurrentReturnDescriptor {
|
|
||||||
private final boolean isResultSet;
|
|
||||||
private final int updateCount;
|
|
||||||
|
|
||||||
protected CurrentReturnDescriptor(boolean isResultSet, int updateCount) {
|
|
||||||
this.isResultSet = isResultSet;
|
|
||||||
this.updateCount = updateCount;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected static class ResultSetReturn implements org.hibernate.result.ResultSetReturn {
|
|
||||||
private final ResultImpl storedProcedureOutputs;
|
|
||||||
private final ResultSet resultSet;
|
|
||||||
|
|
||||||
public ResultSetReturn(ResultImpl storedProcedureOutputs, ResultSet resultSet) {
|
|
||||||
this.storedProcedureOutputs = storedProcedureOutputs;
|
|
||||||
this.resultSet = resultSet;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isResultSet() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public List getResultList() {
|
|
||||||
try {
|
|
||||||
return storedProcedureOutputs.loader.processResultSet( resultSet );
|
|
||||||
}
|
|
||||||
catch (SQLException e) {
|
|
||||||
throw storedProcedureOutputs.convert( e, "Error calling ResultSet.next" );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object getSingleResult() {
|
|
||||||
List results = getResultList();
|
|
||||||
if ( results == null || results.isEmpty() ) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return results.get( 0 );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected static class UpdateCountReturn implements org.hibernate.result.UpdateCountReturn {
|
|
||||||
private final ResultImpl result;
|
|
||||||
private final int updateCount;
|
|
||||||
|
|
||||||
public UpdateCountReturn(ResultImpl result, int updateCount) {
|
|
||||||
this.result = result;
|
|
||||||
this.updateCount = updateCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getUpdateCount() {
|
|
||||||
return updateCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isResultSet() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static CustomLoaderExtension buildSpecializedCustomLoader(final ResultContext context) {
|
|
||||||
final SQLQueryReturnProcessor processor = new SQLQueryReturnProcessor(
|
|
||||||
context.getQueryReturns(),
|
|
||||||
context.getSession().getFactory()
|
|
||||||
);
|
|
||||||
processor.process();
|
|
||||||
final List<org.hibernate.loader.custom.Return> customReturns = processor.generateCustomReturns( false );
|
|
||||||
|
|
||||||
CustomQuery customQuery = new CustomQuery() {
|
|
||||||
@Override
|
|
||||||
public String getSQL() {
|
|
||||||
return context.getSql();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Set<String> getQuerySpaces() {
|
|
||||||
return context.getSynchronizedQuerySpaces();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Map getNamedParameterBindPoints() {
|
|
||||||
// no named parameters in terms of embedded in the SQL string
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<org.hibernate.loader.custom.Return> getCustomQueryReturns() {
|
|
||||||
return customReturns;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return new CustomLoaderExtension(
|
|
||||||
customQuery,
|
|
||||||
context.getQueryParameters(),
|
|
||||||
context.getSession()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class CustomLoaderExtension extends CustomLoader {
|
|
||||||
private QueryParameters queryParameters;
|
|
||||||
private SessionImplementor session;
|
|
||||||
|
|
||||||
public CustomLoaderExtension(
|
|
||||||
CustomQuery customQuery,
|
|
||||||
QueryParameters queryParameters,
|
|
||||||
SessionImplementor session) {
|
|
||||||
super( customQuery, session.getFactory() );
|
|
||||||
this.queryParameters = queryParameters;
|
|
||||||
this.session = session;
|
|
||||||
}
|
|
||||||
|
|
||||||
// todo : this would be a great way to add locking to stored procedure support (at least where returning entities).
|
|
||||||
|
|
||||||
public List processResultSet(ResultSet resultSet) throws SQLException {
|
|
||||||
super.autoDiscoverTypes( resultSet );
|
|
||||||
return super.processResultSet(
|
|
||||||
resultSet,
|
|
||||||
queryParameters,
|
|
||||||
session,
|
|
||||||
true,
|
|
||||||
null,
|
|
||||||
Integer.MAX_VALUE,
|
|
||||||
Collections.<AfterLoadAction>emptyList()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,63 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013, Red Hat Inc. or third-party contributors as
|
||||||
|
* indicated by the @author tags or express copyright attribution
|
||||||
|
* statements applied by the authors. All third-party contributions are
|
||||||
|
* distributed under license by Red Hat Inc.
|
||||||
|
*
|
||||||
|
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||||
|
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||||
|
* Lesser General Public License, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||||
|
* for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this distribution; if not, write to:
|
||||||
|
* Free Software Foundation, Inc.
|
||||||
|
* 51 Franklin Street, Fifth Floor
|
||||||
|
* Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
package org.hibernate.result.internal;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.hibernate.result.ResultSetOutput;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of ResultSetOutput
|
||||||
|
*
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
class ResultSetOutputImpl implements ResultSetOutput {
|
||||||
|
private final List results;
|
||||||
|
|
||||||
|
public ResultSetOutputImpl(List results) {
|
||||||
|
this.results = results;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isResultSet() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public List getResultList() {
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object getSingleResult() {
|
||||||
|
final List results = getResultList();
|
||||||
|
if ( results == null || results.isEmpty() ) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return results.get( 0 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,49 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013, Red Hat Inc. or third-party contributors as
|
||||||
|
* indicated by the @author tags or express copyright attribution
|
||||||
|
* statements applied by the authors. All third-party contributions are
|
||||||
|
* distributed under license by Red Hat Inc.
|
||||||
|
*
|
||||||
|
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||||
|
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||||
|
* Lesser General Public License, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||||
|
* for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this distribution; if not, write to:
|
||||||
|
* Free Software Foundation, Inc.
|
||||||
|
* 51 Franklin Street, Fifth Floor
|
||||||
|
* Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
package org.hibernate.result.internal;
|
||||||
|
|
||||||
|
import org.hibernate.result.UpdateCountOutput;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of UpdateCountOutput
|
||||||
|
*
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
class UpdateCountOutputImpl implements UpdateCountOutput {
|
||||||
|
private final int updateCount;
|
||||||
|
|
||||||
|
public UpdateCountOutputImpl(int updateCount) {
|
||||||
|
this.updateCount = updateCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getUpdateCount() {
|
||||||
|
return updateCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isResultSet() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
|
@ -38,6 +38,7 @@ import org.hibernate.testing.junit4.BaseCoreFunctionalTestMethod;
|
||||||
import org.hibernate.testing.junit4.BaseUnitTestCase;
|
import org.hibernate.testing.junit4.BaseUnitTestCase;
|
||||||
import org.hibernate.type.SerializationException;
|
import org.hibernate.type.SerializationException;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
import static org.junit.Assert.assertSame;
|
import static org.junit.Assert.assertSame;
|
||||||
import static org.junit.Assert.fail;
|
import static org.junit.Assert.fail;
|
||||||
|
|
||||||
|
@ -66,7 +67,11 @@ public class SessionFactorySerializationTest extends BaseCoreFunctionalTestMetho
|
||||||
|
|
||||||
SessionFactory factory2 = (SessionFactory) SerializationHelper.clone( factory );
|
SessionFactory factory2 = (SessionFactory) SerializationHelper.clone( factory );
|
||||||
assertSame( factory, factory2 );
|
assertSame( factory, factory2 );
|
||||||
|
|
||||||
|
SessionFactoryRegistry.INSTANCE.removeSessionFactory( "some-other-uuid", NAME, false, null );
|
||||||
factory.close();
|
factory.close();
|
||||||
|
|
||||||
|
assertFalse( SessionFactoryRegistry.INSTANCE.hasRegistrations() );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -82,17 +87,20 @@ public class SessionFactorySerializationTest extends BaseCoreFunctionalTestMetho
|
||||||
StringRefAddr refAddr = (StringRefAddr) reference.get( "uuid" );
|
StringRefAddr refAddr = (StringRefAddr) reference.get( "uuid" );
|
||||||
String uuid = (String) refAddr.getContent();
|
String uuid = (String) refAddr.getContent();
|
||||||
// deregister under this uuid...
|
// deregister under this uuid...
|
||||||
SessionFactoryRegistry.INSTANCE.removeSessionFactory( uuid, NAME, false, null );
|
SessionFactoryRegistry.INSTANCE.removeSessionFactory( uuid, null, false, null );
|
||||||
// and then register under a different uuid...
|
// and then register under a different uuid...
|
||||||
SessionFactoryRegistry.INSTANCE.addSessionFactory( "some-other-uuid", NAME, false, factory, null );
|
SessionFactoryRegistry.INSTANCE.addSessionFactory( "some-other-uuid", null, false, factory, null );
|
||||||
|
|
||||||
try {
|
try {
|
||||||
SerializationHelper.clone( factory );
|
SerializationHelper.clone( factory );
|
||||||
fail( "Expecting an error" );
|
fail( "Expecting an error" );
|
||||||
}
|
}
|
||||||
catch ( SerializationException expected ) {
|
catch ( SerializationException expected ) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SessionFactoryRegistry.INSTANCE.removeSessionFactory( "some-other-uuid", null, false, null );
|
||||||
factory.close();
|
factory.close();
|
||||||
|
|
||||||
|
assertFalse( SessionFactoryRegistry.INSTANCE.hasRegistrations() );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,12 +56,11 @@ public class EmbeddableIntegratorTest extends BaseUnitTestCase {
|
||||||
*/
|
*/
|
||||||
@Test(expected = GenericJDBCException.class)
|
@Test(expected = GenericJDBCException.class)
|
||||||
public void testWithoutIntegrator() {
|
public void testWithoutIntegrator() {
|
||||||
|
|
||||||
ServiceRegistry reg = new StandardServiceRegistryBuilder( new BootstrapServiceRegistryImpl() ).build();
|
ServiceRegistry reg = new StandardServiceRegistryBuilder( new BootstrapServiceRegistryImpl() ).build();
|
||||||
|
|
||||||
SessionFactory sf = new Configuration().addAnnotatedClass( Investor.class )
|
SessionFactory sf = new Configuration().addAnnotatedClass( Investor.class )
|
||||||
.setProperty( "hibernate.hbm2ddl.auto", "create-drop" ).buildSessionFactory( reg );
|
.setProperty( "hibernate.hbm2ddl.auto", "create-drop" ).buildSessionFactory( reg );
|
||||||
|
|
||||||
|
try {
|
||||||
Session sess = sf.openSession();
|
Session sess = sf.openSession();
|
||||||
Investor myInv = getInvestor();
|
Investor myInv = getInvestor();
|
||||||
myInv.setId( 1L );
|
myInv.setId( 1L );
|
||||||
|
@ -74,18 +73,22 @@ public class EmbeddableIntegratorTest extends BaseUnitTestCase {
|
||||||
assertEquals( new BigDecimal( "100" ), inv.getInvestments().get( 0 ).getAmount().getAmount() );
|
assertEquals( new BigDecimal( "100" ), inv.getInvestments().get( 0 ).getAmount().getAmount() );
|
||||||
|
|
||||||
sess.close();
|
sess.close();
|
||||||
|
}
|
||||||
|
finally {
|
||||||
sf.close();
|
sf.close();
|
||||||
StandardServiceRegistryBuilder.destroy( reg );
|
StandardServiceRegistryBuilder.destroy( reg );
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testWithIntegrator() {
|
public void testWithIntegrator() {
|
||||||
StandardServiceRegistry reg = new StandardServiceRegistryBuilder( new BootstrapServiceRegistryBuilder().with(
|
StandardServiceRegistry reg = new StandardServiceRegistryBuilder(
|
||||||
new InvestorIntegrator() ).build() ).build();
|
new BootstrapServiceRegistryBuilder().with( new InvestorIntegrator() ).build()
|
||||||
|
).build();
|
||||||
SessionFactory sf = new Configuration().addAnnotatedClass( Investor.class )
|
SessionFactory sf = new Configuration().addAnnotatedClass( Investor.class )
|
||||||
.setProperty( "hibernate.hbm2ddl.auto", "create-drop" ).buildSessionFactory( reg );
|
.setProperty( "hibernate.hbm2ddl.auto", "create-drop" ).buildSessionFactory( reg );
|
||||||
|
|
||||||
|
try {
|
||||||
Session sess = sf.openSession();
|
Session sess = sf.openSession();
|
||||||
Investor myInv = getInvestor();
|
Investor myInv = getInvestor();
|
||||||
myInv.setId( 2L );
|
myInv.setId( 2L );
|
||||||
|
@ -98,9 +101,12 @@ public class EmbeddableIntegratorTest extends BaseUnitTestCase {
|
||||||
assertEquals( new BigDecimal( "100" ), inv.getInvestments().get( 0 ).getAmount().getAmount() );
|
assertEquals( new BigDecimal( "100" ), inv.getInvestments().get( 0 ).getAmount().getAmount() );
|
||||||
|
|
||||||
sess.close();
|
sess.close();
|
||||||
|
}
|
||||||
|
finally {
|
||||||
sf.close();
|
sf.close();
|
||||||
StandardServiceRegistryBuilder.destroy( reg );
|
StandardServiceRegistryBuilder.destroy( reg );
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private Investor getInvestor() {
|
private Investor getInvestor() {
|
||||||
Investor i = new Investor();
|
Investor i = new Investor();
|
||||||
|
|
|
@ -70,6 +70,9 @@ public class OrmVersion1SupportedTest extends BaseCoreFunctionalTestCase {
|
||||||
s.close();
|
s.close();
|
||||||
|
|
||||||
assertEquals( "HHH00196 should not be called", 0, BytemanHelper.getAndResetInvocationCount() );
|
assertEquals( "HHH00196 should not be called", 0, BytemanHelper.getAndResetInvocationCount() );
|
||||||
|
|
||||||
|
// which means we also need to close it manually
|
||||||
|
releaseSessionFactory();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -25,7 +25,6 @@ package org.hibernate.test.cfg.cache;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import org.hibernate.SessionFactory;
|
|
||||||
import org.hibernate.cfg.Configuration;
|
import org.hibernate.cfg.Configuration;
|
||||||
import org.hibernate.testing.FailureExpectedWithNewMetamodel;
|
import org.hibernate.testing.FailureExpectedWithNewMetamodel;
|
||||||
import org.hibernate.testing.junit4.BaseUnitTestCase;
|
import org.hibernate.testing.junit4.BaseUnitTestCase;
|
||||||
|
@ -44,7 +43,8 @@ public class CacheConfigurationTest extends BaseUnitTestCase {
|
||||||
if(isMetadataUsed()){
|
if(isMetadataUsed()){
|
||||||
throw new IllegalStateException( "what should we do here " );
|
throw new IllegalStateException( "what should we do here " );
|
||||||
}
|
}
|
||||||
|
// we only care if the SF builds successfully.
|
||||||
Configuration cfg = new Configuration().configure(CFG_XML);
|
Configuration cfg = new Configuration().configure(CFG_XML);
|
||||||
SessionFactory sessionFactory = cfg.buildSessionFactory();
|
cfg.buildSessionFactory().close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,14 +37,15 @@ import org.hibernate.dialect.Dialect;
|
||||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
import org.hibernate.internal.CriteriaImpl;
|
import org.hibernate.internal.CriteriaImpl;
|
||||||
import org.hibernate.loader.criteria.CriteriaQueryTranslator;
|
import org.hibernate.loader.criteria.CriteriaQueryTranslator;
|
||||||
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
|
||||||
|
import org.hibernate.testing.junit4.BaseUnitTestCase;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public class CriterionTest extends BaseCoreFunctionalTestCase {
|
public class CriterionTest extends BaseUnitTestCase {
|
||||||
@Test
|
@Test
|
||||||
public void testIlikeRendering() {
|
public void testIlikeRendering() {
|
||||||
SessionFactory sf = new Configuration()
|
SessionFactory sf = new Configuration()
|
||||||
|
@ -52,6 +53,7 @@ public class CriterionTest extends BaseCoreFunctionalTestCase {
|
||||||
.setProperty( AvailableSettings.DIALECT, IlikeSupportingDialect.class.getName() )
|
.setProperty( AvailableSettings.DIALECT, IlikeSupportingDialect.class.getName() )
|
||||||
.setProperty( Environment.HBM2DDL_AUTO, "create-drop" )
|
.setProperty( Environment.HBM2DDL_AUTO, "create-drop" )
|
||||||
.buildSessionFactory();
|
.buildSessionFactory();
|
||||||
|
try {
|
||||||
final Criteria criteria = sf.openSession().createCriteria( IrrelevantEntity.class );
|
final Criteria criteria = sf.openSession().createCriteria( IrrelevantEntity.class );
|
||||||
final CriteriaQueryTranslator translator = new CriteriaQueryTranslator(
|
final CriteriaQueryTranslator translator = new CriteriaQueryTranslator(
|
||||||
(SessionFactoryImplementor) sf,
|
(SessionFactoryImplementor) sf,
|
||||||
|
@ -63,6 +65,10 @@ public class CriterionTest extends BaseCoreFunctionalTestCase {
|
||||||
final String ilikeExpressionSqlFragment = ilikeExpression.toSqlString( criteria, translator );
|
final String ilikeExpressionSqlFragment = ilikeExpression.toSqlString( criteria, translator );
|
||||||
assertEquals( "a.name insensitiveLike ?", ilikeExpressionSqlFragment );
|
assertEquals( "a.name insensitiveLike ?", ilikeExpressionSqlFragment );
|
||||||
}
|
}
|
||||||
|
finally {
|
||||||
|
sf.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testIlikeMimicing() {
|
public void testIlikeMimicing() {
|
||||||
|
@ -71,6 +77,7 @@ public class CriterionTest extends BaseCoreFunctionalTestCase {
|
||||||
.setProperty( AvailableSettings.DIALECT, NonIlikeSupportingDialect.class.getName() )
|
.setProperty( AvailableSettings.DIALECT, NonIlikeSupportingDialect.class.getName() )
|
||||||
.setProperty( Environment.HBM2DDL_AUTO, "create-drop" )
|
.setProperty( Environment.HBM2DDL_AUTO, "create-drop" )
|
||||||
.buildSessionFactory();
|
.buildSessionFactory();
|
||||||
|
try {
|
||||||
final Criteria criteria = sf.openSession().createCriteria( IrrelevantEntity.class );
|
final Criteria criteria = sf.openSession().createCriteria( IrrelevantEntity.class );
|
||||||
final CriteriaQueryTranslator translator = new CriteriaQueryTranslator(
|
final CriteriaQueryTranslator translator = new CriteriaQueryTranslator(
|
||||||
(SessionFactoryImplementor) sf,
|
(SessionFactoryImplementor) sf,
|
||||||
|
@ -82,6 +89,10 @@ public class CriterionTest extends BaseCoreFunctionalTestCase {
|
||||||
final String ilikeExpressionSqlFragment = ilikeExpression.toSqlString( criteria, translator );
|
final String ilikeExpressionSqlFragment = ilikeExpression.toSqlString( criteria, translator );
|
||||||
assertEquals( "lowLowLow(a.name) like ?", ilikeExpressionSqlFragment );
|
assertEquals( "lowLowLow(a.name) like ?", ilikeExpressionSqlFragment );
|
||||||
}
|
}
|
||||||
|
finally {
|
||||||
|
sf.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static class IlikeSupportingDialect extends Dialect {
|
public static class IlikeSupportingDialect extends Dialect {
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -21,15 +21,19 @@
|
||||||
package org.hibernate.test.mapping;
|
package org.hibernate.test.mapping;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertNotNull;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
import static org.junit.Assert.fail;
|
||||||
|
|
||||||
|
import org.hibernate.HibernateException;
|
||||||
|
import org.hibernate.Session;
|
||||||
import org.hibernate.mapping.Table;
|
import org.hibernate.mapping.Table;
|
||||||
import org.hibernate.metamodel.spi.relational.TableSpecification;
|
import org.hibernate.metamodel.spi.relational.TableSpecification;
|
||||||
import org.hibernate.test.util.SchemaUtil;
|
import org.hibernate.test.util.SchemaUtil;
|
||||||
import org.hibernate.testing.TestForIssue;
|
import org.hibernate.testing.TestForIssue;
|
||||||
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
||||||
|
|
||||||
import static org.junit.Assert.assertTrue;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Column aliases utilize {@link Table#getUniqueInteger()} for naming. The
|
* Column aliases utilize {@link Table#getUniqueInteger()} for naming. The
|
||||||
* unique integer used to be statically generated by the Table class, meaning
|
* unique integer used to be statically generated by the Table class, meaning
|
||||||
|
@ -41,18 +45,64 @@ import static org.junit.Assert.assertTrue;
|
||||||
*
|
*
|
||||||
* @author Brett Meyer
|
* @author Brett Meyer
|
||||||
*/
|
*/
|
||||||
@TestForIssue( jiraKey = "HHH-2448" )
|
|
||||||
public class AliasTest extends BaseCoreFunctionalTestCase {
|
public class AliasTest extends BaseCoreFunctionalTestCase {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Column aliases utilize {@link Table#getUniqueInteger()} for naming. The unique integer used to be statically
|
||||||
|
* generated by the Table class, meaning it was dependent on mapping order. HHH-2448 made the alias names
|
||||||
|
* deterministic by having Configuration determine the unique integers on its second pass over the Tables tree map.
|
||||||
|
* AliasTest and {@link MappingReorderedAliasTest} ensure that the unique integers are the same, regardless of
|
||||||
|
* mapping ordering.
|
||||||
|
*/
|
||||||
@Test
|
@Test
|
||||||
|
@TestForIssue( jiraKey = "HHH-2448" )
|
||||||
public void testAliasOrdering() {
|
public void testAliasOrdering() {
|
||||||
TableSpecification table1 = SchemaUtil.getTable( "Table1", metadata() );
|
TableSpecification table1 = SchemaUtil.getTable( "Table1", metadata() );
|
||||||
TableSpecification table2 = SchemaUtil.getTable( "Table2", metadata() );
|
TableSpecification table2 = SchemaUtil.getTable( "Table2", metadata() );
|
||||||
assertTrue( table1.getTableNumber() < table2.getTableNumber() );
|
assertTrue( table1.getTableNumber() < table2.getTableNumber() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestForIssue( jiraKey = "HHH-8371" )
|
||||||
|
public final void testUnderscoreInColumnName() throws Throwable {
|
||||||
|
final Session s = openSession();
|
||||||
|
s.getTransaction().begin();
|
||||||
|
|
||||||
|
UserEntity user = new UserEntity();
|
||||||
|
user.setName( "foo" );
|
||||||
|
s.persist(user);
|
||||||
|
final ConfEntity conf = new ConfEntity();
|
||||||
|
conf.setConfKey("counter");
|
||||||
|
conf.setConfValue("3");
|
||||||
|
final UserConfEntity uc = new UserConfEntity();
|
||||||
|
uc.setUser(user);
|
||||||
|
uc.setConf(conf);
|
||||||
|
conf.getUserConf().add(uc);
|
||||||
|
s.persist(conf);
|
||||||
|
|
||||||
|
s.getTransaction().commit();
|
||||||
|
s.clear();
|
||||||
|
|
||||||
|
s.getTransaction().begin();
|
||||||
|
user = (UserEntity) s.get(UserEntity.class, user.getId());
|
||||||
|
|
||||||
|
try {
|
||||||
|
s.flush();
|
||||||
|
}
|
||||||
|
catch ( HibernateException e ) {
|
||||||
|
// original issue from HHH-8371
|
||||||
|
fail( "The explicit column name's underscore(s) were not considered during alias creation." );
|
||||||
|
}
|
||||||
|
|
||||||
|
assertNotNull( user );
|
||||||
|
assertEquals( user.getName(), "foo" );
|
||||||
|
|
||||||
|
s.getTransaction().commit();
|
||||||
|
s.close();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Class<?>[] getAnnotatedClasses() {
|
protected Class<?>[] getAnnotatedClasses() {
|
||||||
return new Class<?>[] { Table1.class, Table2.class };
|
return new Class<?>[] { Table1.class, Table2.class, ConfEntity.class, UserConfEntity.class, UserEntity.class };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,54 @@
|
||||||
|
package org.hibernate.test.mapping;
|
||||||
|
|
||||||
|
import static javax.persistence.CascadeType.ALL;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import javax.persistence.Column;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.FetchType;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.IdClass;
|
||||||
|
import javax.persistence.OneToMany;
|
||||||
|
import javax.persistence.Table;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@Table(name = "CONF")
|
||||||
|
@IdClass(ConfId.class)
|
||||||
|
public class ConfEntity implements Serializable{
|
||||||
|
|
||||||
|
private static final long serialVersionUID = -5089484717715507169L;
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@Column(name = "confKey")
|
||||||
|
private String confKey;
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@Column(name = "confValue")
|
||||||
|
private String confValue;
|
||||||
|
|
||||||
|
@OneToMany(mappedBy="conf", cascade = ALL, orphanRemoval = true, fetch = FetchType.LAZY)
|
||||||
|
private Set<UserConfEntity> userConf = new HashSet<UserConfEntity>();
|
||||||
|
|
||||||
|
public String getConfKey() {
|
||||||
|
return confKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setConfKey(String confKey) {
|
||||||
|
this.confKey = confKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getConfValue() {
|
||||||
|
return confValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setConfValue(String confValue) {
|
||||||
|
this.confValue = confValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<UserConfEntity> getUserConf() {
|
||||||
|
return userConf;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,67 @@
|
||||||
|
package org.hibernate.test.mapping;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
public class ConfId implements Serializable{
|
||||||
|
|
||||||
|
private static final long serialVersionUID = -6722022851594514199L;
|
||||||
|
|
||||||
|
private String confKey;
|
||||||
|
|
||||||
|
private String confValue;
|
||||||
|
|
||||||
|
public ConfId(){
|
||||||
|
}
|
||||||
|
|
||||||
|
public ConfId(String confKey, String confValue) {
|
||||||
|
this.confKey = confKey;
|
||||||
|
this.confValue = confValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getConfKey() {
|
||||||
|
return confKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setConfKey(String confKey) {
|
||||||
|
this.confKey = confKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getConfValue() {
|
||||||
|
return confValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setConfValue(String confValue) {
|
||||||
|
this.confValue = confValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
final int prime = 31;
|
||||||
|
int result = 1;
|
||||||
|
result = prime * result + ((confKey == null) ? 0 : confKey.hashCode());
|
||||||
|
result = prime * result + ((confValue == null) ? 0 : confValue.hashCode());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (this == obj)
|
||||||
|
return true;
|
||||||
|
if (obj == null)
|
||||||
|
return false;
|
||||||
|
if (getClass() != obj.getClass())
|
||||||
|
return false;
|
||||||
|
ConfId other = (ConfId) obj;
|
||||||
|
if (confKey == null) {
|
||||||
|
if (other.confKey != null)
|
||||||
|
return false;
|
||||||
|
} else if (!confKey.equals(other.confKey))
|
||||||
|
return false;
|
||||||
|
else if (confValue == null) {
|
||||||
|
if (other.confValue != null)
|
||||||
|
return false;
|
||||||
|
} else if (!confValue.equals(other.confValue))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
|
@ -27,6 +27,6 @@ public class MappingReorderedAliasTest extends AliasTest {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Class<?>[] getAnnotatedClasses() {
|
protected Class<?>[] getAnnotatedClasses() {
|
||||||
return new Class<?>[] { Table2.class, Table1.class };
|
return new Class<?>[] { Table2.class, Table1.class, ConfEntity.class, UserConfEntity.class, UserEntity.class };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,48 @@
|
||||||
|
package org.hibernate.test.mapping;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.IdClass;
|
||||||
|
import javax.persistence.JoinColumn;
|
||||||
|
import javax.persistence.JoinColumns;
|
||||||
|
import javax.persistence.ManyToOne;
|
||||||
|
import javax.persistence.Table;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@Table(name = "USER_CONFS")
|
||||||
|
@IdClass(UserConfId.class)
|
||||||
|
public class UserConfEntity implements Serializable{
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 9153314908821604322L;
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@ManyToOne
|
||||||
|
@JoinColumn(name="user_id")
|
||||||
|
private UserEntity user;
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@ManyToOne
|
||||||
|
@JoinColumns({
|
||||||
|
@JoinColumn(name="cnf_key", referencedColumnName="confKey"),
|
||||||
|
@JoinColumn(name="cnf_value", referencedColumnName="confValue")})
|
||||||
|
private ConfEntity conf;
|
||||||
|
|
||||||
|
public ConfEntity getConf() {
|
||||||
|
return conf;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setConf(ConfEntity conf) {
|
||||||
|
this.conf = conf;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public UserEntity getUser() {
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUser(UserEntity user) {
|
||||||
|
this.user = user;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,70 @@
|
||||||
|
package org.hibernate.test.mapping;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public class UserConfId implements Serializable{
|
||||||
|
|
||||||
|
private static final long serialVersionUID = -161134972658451944L;
|
||||||
|
|
||||||
|
private Long user;
|
||||||
|
|
||||||
|
private ConfId conf;
|
||||||
|
|
||||||
|
public UserConfId(){
|
||||||
|
}
|
||||||
|
|
||||||
|
public UserConfId(Long user, ConfId conf) {
|
||||||
|
this.user = user;
|
||||||
|
this.conf = conf;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getUser() {
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUser(Long user) {
|
||||||
|
this.user = user;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public ConfId getConf() {
|
||||||
|
return conf;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setConf(ConfId conf) {
|
||||||
|
this.conf = conf;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
final int prime = 31;
|
||||||
|
int result = 1;
|
||||||
|
result = prime * result + ((conf == null) ? 0 : conf.hashCode());
|
||||||
|
result = prime * result + ((user == null) ? 0 : user.hashCode());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (this == obj)
|
||||||
|
return true;
|
||||||
|
if (obj == null)
|
||||||
|
return false;
|
||||||
|
if (getClass() != obj.getClass())
|
||||||
|
return false;
|
||||||
|
UserConfId other = (UserConfId) obj;
|
||||||
|
if (conf == null) {
|
||||||
|
if (other.conf != null)
|
||||||
|
return false;
|
||||||
|
} else if (!conf.equals(other.conf))
|
||||||
|
return false;
|
||||||
|
if (user == null) {
|
||||||
|
if (other.user != null)
|
||||||
|
return false;
|
||||||
|
} else if (!user.equals(other.user))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,58 @@
|
||||||
|
package org.hibernate.test.mapping;
|
||||||
|
|
||||||
|
import static javax.persistence.CascadeType.ALL;
|
||||||
|
import static javax.persistence.FetchType.EAGER;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import javax.persistence.Column;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.GeneratedValue;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.OneToMany;
|
||||||
|
import javax.persistence.OrderColumn;
|
||||||
|
import javax.persistence.Table;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@Table(name = "USER")
|
||||||
|
public class UserEntity implements Serializable{
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@GeneratedValue
|
||||||
|
@Column(name = "user_id")
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@OrderColumn(name = "cnf_order")
|
||||||
|
@OneToMany(mappedBy="user", fetch = EAGER, cascade = ALL, orphanRemoval = true)
|
||||||
|
private Set<UserConfEntity> confs = new HashSet<UserConfEntity>();
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<UserConfEntity> getConfs() {
|
||||||
|
return confs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setConfs(Set<UserConfEntity> confs) {
|
||||||
|
this.confs = confs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
}
|
|
@ -30,24 +30,20 @@ import org.junit.Test;
|
||||||
|
|
||||||
import org.hibernate.JDBCException;
|
import org.hibernate.JDBCException;
|
||||||
import org.hibernate.Session;
|
import org.hibernate.Session;
|
||||||
import org.hibernate.cfg.Configuration;
|
|
||||||
import org.hibernate.dialect.Dialect;
|
import org.hibernate.dialect.Dialect;
|
||||||
import org.hibernate.dialect.H2Dialect;
|
import org.hibernate.dialect.H2Dialect;
|
||||||
import org.hibernate.engine.spi.Mapping;
|
|
||||||
import org.hibernate.mapping.AuxiliaryDatabaseObject;
|
|
||||||
import org.hibernate.metamodel.spi.MetadataImplementor;
|
import org.hibernate.metamodel.spi.MetadataImplementor;
|
||||||
import org.hibernate.metamodel.spi.relational.Database;
|
import org.hibernate.metamodel.spi.relational.Database;
|
||||||
import org.hibernate.procedure.ProcedureCall;
|
import org.hibernate.procedure.ProcedureCall;
|
||||||
import org.hibernate.procedure.ProcedureResult;
|
import org.hibernate.procedure.ProcedureOutputs;
|
||||||
import org.hibernate.result.ResultSetReturn;
|
import org.hibernate.result.ResultSetOutput;
|
||||||
import org.hibernate.result.Return;
|
import org.hibernate.result.Output;
|
||||||
import org.hibernate.testing.RequiresDialect;
|
import org.hibernate.testing.RequiresDialect;
|
||||||
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
||||||
import org.hibernate.testing.junit4.ExtraAssertions;
|
|
||||||
|
|
||||||
|
import static org.hibernate.testing.junit4.ExtraAssertions.assertTyping;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertNotNull;
|
import static org.junit.Assert.assertNotNull;
|
||||||
import static org.junit.Assert.assertTrue;
|
|
||||||
import static org.junit.Assert.fail;
|
import static org.junit.Assert.fail;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -305,13 +301,11 @@ public class StoredProcedureTest extends BaseCoreFunctionalTestCase {
|
||||||
Session session = openSession();
|
Session session = openSession();
|
||||||
session.beginTransaction();
|
session.beginTransaction();
|
||||||
|
|
||||||
ProcedureCall query = session.createStoredProcedureCall( "user");
|
ProcedureCall procedureCall = session.createStoredProcedureCall( "user");
|
||||||
ProcedureResult procedureResult = query.getResult();
|
ProcedureOutputs procedureOutputs = procedureCall.getResult();
|
||||||
assertTrue( "Checking ProcedureResult has more returns", procedureResult.hasMoreReturns() );
|
Output currentOutput = procedureOutputs.getCurrent();
|
||||||
Return nextReturn = procedureResult.getNextReturn();
|
assertNotNull( currentOutput );
|
||||||
assertNotNull( nextReturn );
|
ResultSetOutput resultSetReturn = assertTyping( ResultSetOutput.class, currentOutput );
|
||||||
ExtraAssertions.assertClassAssignability( ResultSetReturn.class, nextReturn.getClass() );
|
|
||||||
ResultSetReturn resultSetReturn = (ResultSetReturn) nextReturn;
|
|
||||||
String name = (String) resultSetReturn.getSingleResult();
|
String name = (String) resultSetReturn.getSingleResult();
|
||||||
assertEquals( "SA", name );
|
assertEquals( "SA", name );
|
||||||
|
|
||||||
|
@ -325,14 +319,12 @@ public class StoredProcedureTest extends BaseCoreFunctionalTestCase {
|
||||||
session.beginTransaction();
|
session.beginTransaction();
|
||||||
|
|
||||||
ProcedureCall query = session.createStoredProcedureCall( "findOneUser" );
|
ProcedureCall query = session.createStoredProcedureCall( "findOneUser" );
|
||||||
ProcedureResult procedureResult = query.getResult();
|
ProcedureOutputs procedureResult = query.getResult();
|
||||||
assertTrue( "Checking ProcedureResult has more returns", procedureResult.hasMoreReturns() );
|
Output currentOutput = procedureResult.getCurrent();
|
||||||
Return nextReturn = procedureResult.getNextReturn();
|
assertNotNull( currentOutput );
|
||||||
assertNotNull( nextReturn );
|
ResultSetOutput resultSetReturn = assertTyping( ResultSetOutput.class, currentOutput );
|
||||||
ExtraAssertions.assertClassAssignability( ResultSetReturn.class, nextReturn.getClass() );
|
|
||||||
ResultSetReturn resultSetReturn = (ResultSetReturn) nextReturn;
|
|
||||||
Object result = resultSetReturn.getSingleResult();
|
Object result = resultSetReturn.getSingleResult();
|
||||||
ExtraAssertions.assertTyping( Object[].class, result );
|
assertTyping( Object[].class, result );
|
||||||
String name = (String) ( (Object[]) result )[1];
|
String name = (String) ( (Object[]) result )[1];
|
||||||
assertEquals( "Steve", name );
|
assertEquals( "Steve", name );
|
||||||
|
|
||||||
|
@ -346,17 +338,15 @@ public class StoredProcedureTest extends BaseCoreFunctionalTestCase {
|
||||||
session.beginTransaction();
|
session.beginTransaction();
|
||||||
|
|
||||||
ProcedureCall query = session.createStoredProcedureCall( "findUsers" );
|
ProcedureCall query = session.createStoredProcedureCall( "findUsers" );
|
||||||
ProcedureResult procedureResult = query.getResult();
|
ProcedureOutputs procedureResult = query.getResult();
|
||||||
assertTrue( "Checking ProcedureResult has more returns", procedureResult.hasMoreReturns() );
|
Output currentOutput = procedureResult.getCurrent();
|
||||||
Return nextReturn = procedureResult.getNextReturn();
|
assertNotNull( currentOutput );
|
||||||
assertNotNull( nextReturn );
|
ResultSetOutput resultSetReturn = assertTyping( ResultSetOutput.class, currentOutput );
|
||||||
ExtraAssertions.assertClassAssignability( ResultSetReturn.class, nextReturn.getClass() );
|
|
||||||
ResultSetReturn resultSetReturn = (ResultSetReturn) nextReturn;
|
|
||||||
List results = resultSetReturn.getResultList();
|
List results = resultSetReturn.getResultList();
|
||||||
assertEquals( 3, results.size() );
|
assertEquals( 3, results.size() );
|
||||||
|
|
||||||
for ( Object result : results ) {
|
for ( Object result : results ) {
|
||||||
ExtraAssertions.assertTyping( Object[].class, result );
|
assertTyping( Object[].class, result );
|
||||||
Integer id = (Integer) ( (Object[]) result )[0];
|
Integer id = (Integer) ( (Object[]) result )[0];
|
||||||
String name = (String) ( (Object[]) result )[1];
|
String name = (String) ( (Object[]) result )[1];
|
||||||
if ( id.equals( 1 ) ) {
|
if ( id.equals( 1 ) ) {
|
||||||
|
@ -385,16 +375,14 @@ public class StoredProcedureTest extends BaseCoreFunctionalTestCase {
|
||||||
ProcedureCall query = session.createStoredProcedureCall( "findUserRange" );
|
ProcedureCall query = session.createStoredProcedureCall( "findUserRange" );
|
||||||
query.registerParameter( "start", Integer.class, ParameterMode.IN ).bindValue( 1 );
|
query.registerParameter( "start", Integer.class, ParameterMode.IN ).bindValue( 1 );
|
||||||
query.registerParameter( "end", Integer.class, ParameterMode.IN ).bindValue( 2 );
|
query.registerParameter( "end", Integer.class, ParameterMode.IN ).bindValue( 2 );
|
||||||
ProcedureResult procedureResult = query.getResult();
|
ProcedureOutputs procedureResult = query.getResult();
|
||||||
assertTrue( "Checking ProcedureResult has more returns", procedureResult.hasMoreReturns() );
|
Output currentOutput = procedureResult.getCurrent();
|
||||||
Return nextReturn = procedureResult.getNextReturn();
|
assertNotNull( currentOutput );
|
||||||
assertNotNull( nextReturn );
|
ResultSetOutput resultSetReturn = assertTyping( ResultSetOutput.class, currentOutput );
|
||||||
ExtraAssertions.assertClassAssignability( ResultSetReturn.class, nextReturn.getClass() );
|
|
||||||
ResultSetReturn resultSetReturn = (ResultSetReturn) nextReturn;
|
|
||||||
List results = resultSetReturn.getResultList();
|
List results = resultSetReturn.getResultList();
|
||||||
assertEquals( 1, results.size() );
|
assertEquals( 1, results.size() );
|
||||||
Object result = results.get( 0 );
|
Object result = results.get( 0 );
|
||||||
ExtraAssertions.assertTyping( Object[].class, result );
|
assertTyping( Object[].class, result );
|
||||||
Integer id = (Integer) ( (Object[]) result )[0];
|
Integer id = (Integer) ( (Object[]) result )[0];
|
||||||
String name = (String) ( (Object[]) result )[1];
|
String name = (String) ( (Object[]) result )[1];
|
||||||
assertEquals( 1, (int) id );
|
assertEquals( 1, (int) id );
|
||||||
|
@ -412,16 +400,14 @@ public class StoredProcedureTest extends BaseCoreFunctionalTestCase {
|
||||||
ProcedureCall query = session.createStoredProcedureCall( "findUserRange" );
|
ProcedureCall query = session.createStoredProcedureCall( "findUserRange" );
|
||||||
query.registerParameter( 1, Integer.class, ParameterMode.IN ).bindValue( 1 );
|
query.registerParameter( 1, Integer.class, ParameterMode.IN ).bindValue( 1 );
|
||||||
query.registerParameter( 2, Integer.class, ParameterMode.IN ).bindValue( 2 );
|
query.registerParameter( 2, Integer.class, ParameterMode.IN ).bindValue( 2 );
|
||||||
ProcedureResult procedureResult = query.getResult();
|
ProcedureOutputs procedureResult = query.getResult();
|
||||||
assertTrue( "Checking ProcedureResult has more returns", procedureResult.hasMoreReturns() );
|
Output currentOutput = procedureResult.getCurrent();
|
||||||
Return nextReturn = procedureResult.getNextReturn();
|
assertNotNull( currentOutput );
|
||||||
assertNotNull( nextReturn );
|
ResultSetOutput resultSetReturn = assertTyping( ResultSetOutput.class, currentOutput );
|
||||||
ExtraAssertions.assertClassAssignability( ResultSetReturn.class, nextReturn.getClass() );
|
|
||||||
ResultSetReturn resultSetReturn = (ResultSetReturn) nextReturn;
|
|
||||||
List results = resultSetReturn.getResultList();
|
List results = resultSetReturn.getResultList();
|
||||||
assertEquals( 1, results.size() );
|
assertEquals( 1, results.size() );
|
||||||
Object result = results.get( 0 );
|
Object result = results.get( 0 );
|
||||||
ExtraAssertions.assertTyping( Object[].class, result );
|
assertTyping( Object[].class, result );
|
||||||
Integer id = (Integer) ( (Object[]) result )[0];
|
Integer id = (Integer) ( (Object[]) result )[0];
|
||||||
String name = (String) ( (Object[]) result )[1];
|
String name = (String) ( (Object[]) result )[1];
|
||||||
assertEquals( 1, (int) id );
|
assertEquals( 1, (int) id );
|
||||||
|
@ -443,9 +429,8 @@ public class StoredProcedureTest extends BaseCoreFunctionalTestCase {
|
||||||
ProcedureCall query = session.createStoredProcedureCall( "findUserRange" );
|
ProcedureCall query = session.createStoredProcedureCall( "findUserRange" );
|
||||||
query.registerParameter( 1, Integer.class, ParameterMode.IN );
|
query.registerParameter( 1, Integer.class, ParameterMode.IN );
|
||||||
query.registerParameter( 2, Integer.class, ParameterMode.IN ).bindValue( 2 );
|
query.registerParameter( 2, Integer.class, ParameterMode.IN ).bindValue( 2 );
|
||||||
ProcedureResult procedureResult = query.getResult();
|
|
||||||
try {
|
try {
|
||||||
procedureResult.hasMoreReturns();
|
query.getResult();
|
||||||
fail( "Expecting failure due to missing parameter bind" );
|
fail( "Expecting failure due to missing parameter bind" );
|
||||||
}
|
}
|
||||||
catch (JDBCException expected) {
|
catch (JDBCException expected) {
|
||||||
|
@ -456,9 +441,8 @@ public class StoredProcedureTest extends BaseCoreFunctionalTestCase {
|
||||||
ProcedureCall query = session.createStoredProcedureCall( "findUserRange" );
|
ProcedureCall query = session.createStoredProcedureCall( "findUserRange" );
|
||||||
query.registerParameter( "start", Integer.class, ParameterMode.IN );
|
query.registerParameter( "start", Integer.class, ParameterMode.IN );
|
||||||
query.registerParameter( "end", Integer.class, ParameterMode.IN ).bindValue( 2 );
|
query.registerParameter( "end", Integer.class, ParameterMode.IN ).bindValue( 2 );
|
||||||
ProcedureResult procedureResult = query.getResult();
|
|
||||||
try {
|
try {
|
||||||
procedureResult.hasMoreReturns();
|
query.getResult();
|
||||||
fail( "Expecting failure due to missing parameter bind" );
|
fail( "Expecting failure due to missing parameter bind" );
|
||||||
}
|
}
|
||||||
catch (JDBCException expected) {
|
catch (JDBCException expected) {
|
||||||
|
|
|
@ -34,6 +34,7 @@ import org.hibernate.Session;
|
||||||
import org.hibernate.SessionFactory;
|
import org.hibernate.SessionFactory;
|
||||||
import org.hibernate.Transaction;
|
import org.hibernate.Transaction;
|
||||||
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
|
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
|
||||||
|
import org.hibernate.cfg.AvailableSettings;
|
||||||
import org.hibernate.cfg.Configuration;
|
import org.hibernate.cfg.Configuration;
|
||||||
import org.hibernate.cfg.Environment;
|
import org.hibernate.cfg.Environment;
|
||||||
import org.hibernate.engine.FetchStyle;
|
import org.hibernate.engine.FetchStyle;
|
||||||
|
@ -58,56 +59,59 @@ public class StatsTest extends BaseCoreFunctionalTestCase {
|
||||||
public String[] getMappings() {
|
public String[] getMappings() {
|
||||||
return new String[] { "stats/Continent.hbm.xml" };
|
return new String[] { "stats/Continent.hbm.xml" };
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void configure(Configuration cfg) {
|
protected void initialize(){
|
||||||
super.configure( cfg );
|
super.initialize();
|
||||||
cfg.setProperty( Environment.GENERATE_STATISTICS, "true" );
|
getTestConfiguration().getProperties().setProperty( Environment.GENERATE_STATISTICS, "true" );
|
||||||
|
getTestConfiguration().getProperties().setProperty( AvailableSettings.HBM2DDL_AUTO, "create");
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void prepareStandardServiceRegistryBuilder(StandardServiceRegistryBuilder serviceRegistryBuilder) {
|
protected boolean createSchema() {
|
||||||
serviceRegistryBuilder.applySetting( Environment.GENERATE_STATISTICS, "true" );
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@SuppressWarnings( {"UnusedAssignment"})
|
@SuppressWarnings( {"UnusedAssignment"})
|
||||||
public void testCollectionFetchVsLoad() throws Exception {
|
public void testCollectionFetchVsLoad() throws Exception {
|
||||||
Statistics stats = sessionFactory().getStatistics();
|
SessionFactory sf =sessionFactory();
|
||||||
stats.clear();
|
|
||||||
|
|
||||||
Session s = openSession();
|
Session s = sf.openSession();
|
||||||
Transaction tx = s.beginTransaction();
|
Transaction tx = s.beginTransaction();
|
||||||
Continent europe = fillDb(s);
|
Continent europe = fillDb(s);
|
||||||
tx.commit();
|
tx.commit();
|
||||||
s.clear();
|
s.close();
|
||||||
|
|
||||||
|
s = sf.openSession();
|
||||||
tx = s.beginTransaction();
|
tx = s.beginTransaction();
|
||||||
assertEquals(0, stats.getCollectionLoadCount() );
|
assertEquals(0, sf.getStatistics().getCollectionLoadCount() );
|
||||||
assertEquals(0, stats.getCollectionFetchCount() );
|
assertEquals(0, sf.getStatistics().getCollectionFetchCount() );
|
||||||
Continent europe2 = (Continent) s.get( Continent.class, europe.getId() );
|
Continent europe2 = (Continent) s.get( Continent.class, europe.getId() );
|
||||||
assertEquals("Lazy true: no collection should be loaded", 0, stats.getCollectionLoadCount() );
|
assertEquals("Lazy true: no collection should be loaded", 0, sf.getStatistics().getCollectionLoadCount() );
|
||||||
assertEquals( 0, stats.getCollectionFetchCount() );
|
assertEquals( 0, sf.getStatistics().getCollectionFetchCount() );
|
||||||
europe2.getCountries().size();
|
europe2.getCountries().size();
|
||||||
assertEquals( 1, stats.getCollectionLoadCount() );
|
assertEquals( 1, sf.getStatistics().getCollectionLoadCount() );
|
||||||
assertEquals("Explicit fetch of the collection state", 1, stats.getCollectionFetchCount() );
|
assertEquals("Explicit fetch of the collection state", 1, sf.getStatistics().getCollectionFetchCount() );
|
||||||
tx.commit();
|
tx.commit();
|
||||||
s.close();
|
s.close();
|
||||||
|
|
||||||
s = openSession();
|
sf.getStatistics().clear();
|
||||||
|
|
||||||
|
s = sf.openSession();
|
||||||
tx = s.beginTransaction();
|
tx = s.beginTransaction();
|
||||||
stats.clear();
|
|
||||||
europe = fillDb(s);
|
europe = fillDb(s);
|
||||||
tx.commit();
|
tx.commit();
|
||||||
s.clear();
|
s.clear();
|
||||||
tx = s.beginTransaction();
|
tx = s.beginTransaction();
|
||||||
assertEquals( 0, stats.getCollectionLoadCount() );
|
assertEquals( 0, sf.getStatistics().getCollectionLoadCount() );
|
||||||
assertEquals( 0, stats.getCollectionFetchCount() );
|
assertEquals( 0, sf.getStatistics().getCollectionFetchCount() );
|
||||||
europe2 = (Continent) s.createQuery(
|
europe2 = (Continent) s.createQuery(
|
||||||
"from " + Continent.class.getName() + " a join fetch a.countries where a.id = " + europe.getId()
|
"from " + Continent.class.getName() + " a join fetch a.countries where a.id = " + europe.getId()
|
||||||
).uniqueResult();
|
).uniqueResult();
|
||||||
assertEquals( 1, stats.getCollectionLoadCount() );
|
assertEquals( 1, sf.getStatistics().getCollectionLoadCount() );
|
||||||
assertEquals( "collection should be loaded in the same query as its parent", 0, stats.getCollectionFetchCount() );
|
assertEquals( "collection should be loaded in the same query as its parent", 0, sf.getStatistics().getCollectionFetchCount() );
|
||||||
tx.commit();
|
tx.commit();
|
||||||
s.close();
|
s.close();
|
||||||
|
|
||||||
|
@ -115,21 +119,23 @@ public class StatsTest extends BaseCoreFunctionalTestCase {
|
||||||
PluralAttributeBinding coll = SchemaUtil.getCollection( Continent.class, "countries", metadata() );
|
PluralAttributeBinding coll = SchemaUtil.getCollection( Continent.class, "countries", metadata() );
|
||||||
coll.setFetchStyle( FetchStyle.JOIN );
|
coll.setFetchStyle( FetchStyle.JOIN );
|
||||||
coll.setFetchTiming( FetchTiming.IMMEDIATE );
|
coll.setFetchTiming( FetchTiming.IMMEDIATE );
|
||||||
SessionFactory sf = metadata().getSessionFactoryBuilder().build();
|
sf = metadata().getSessionFactoryBuilder().build();
|
||||||
stats = sf.getStatistics();
|
Statistics stats = sf.getStatistics();
|
||||||
stats.clear();
|
stats.clear();
|
||||||
stats.setStatisticsEnabled(true);
|
stats.setStatisticsEnabled(true);
|
||||||
s = sf.openSession();
|
s = sf.openSession();
|
||||||
tx = s.beginTransaction();
|
tx = s.beginTransaction();
|
||||||
europe = fillDb(s);
|
europe = fillDb(s);
|
||||||
tx.commit();
|
tx.commit();
|
||||||
s.clear();
|
s.close();
|
||||||
|
|
||||||
|
s = sf.openSession();
|
||||||
tx = s.beginTransaction();
|
tx = s.beginTransaction();
|
||||||
assertEquals( 0, stats.getCollectionLoadCount() );
|
assertEquals( 0, sf.getStatistics().getCollectionLoadCount() );
|
||||||
assertEquals( 0, stats.getCollectionFetchCount() );
|
assertEquals( 0, sf.getStatistics().getCollectionFetchCount() );
|
||||||
europe2 = (Continent) s.get( Continent.class, europe.getId() );
|
europe2 = (Continent) s.get( Continent.class, europe.getId() );
|
||||||
assertEquals( 1, stats.getCollectionLoadCount() );
|
assertEquals( 1, sf.getStatistics().getCollectionLoadCount() );
|
||||||
assertEquals( "Should do direct load, not indirect second load when lazy false and JOIN", 0, stats.getCollectionFetchCount() );
|
assertEquals( "Should do direct load, not indirect second load when lazy false and JOIN", 0, sf.getStatistics().getCollectionFetchCount() );
|
||||||
tx.commit();
|
tx.commit();
|
||||||
s.close();
|
s.close();
|
||||||
sf.close();
|
sf.close();
|
||||||
|
@ -146,42 +152,45 @@ public class StatsTest extends BaseCoreFunctionalTestCase {
|
||||||
tx = s.beginTransaction();
|
tx = s.beginTransaction();
|
||||||
europe = fillDb(s);
|
europe = fillDb(s);
|
||||||
tx.commit();
|
tx.commit();
|
||||||
s.clear();
|
s.close();
|
||||||
|
|
||||||
|
s = sf.openSession();
|
||||||
tx = s.beginTransaction();
|
tx = s.beginTransaction();
|
||||||
assertEquals( 0, stats.getCollectionLoadCount() );
|
assertEquals( 0, sf.getStatistics().getCollectionLoadCount() );
|
||||||
assertEquals( 0, stats.getCollectionFetchCount() );
|
assertEquals( 0, sf.getStatistics().getCollectionFetchCount() );
|
||||||
europe2 = (Continent) s.get( Continent.class, europe.getId() );
|
europe2 = (Continent) s.get( Continent.class, europe.getId() );
|
||||||
assertEquals( 1, stats.getCollectionLoadCount() );
|
assertEquals( 1, sf.getStatistics().getCollectionLoadCount() );
|
||||||
assertEquals( "Should do explicit collection load, not part of the first one", 1, stats.getCollectionFetchCount() );
|
assertEquals( "Should do explicit collection load, not part of the first one", 1, sf.getStatistics().getCollectionFetchCount() );
|
||||||
for ( Object o : europe2.getCountries() ) {
|
for ( Object o : europe2.getCountries() ) {
|
||||||
s.delete( o );
|
s.delete( o );
|
||||||
}
|
}
|
||||||
cleanDb( s );
|
cleanDb( s );
|
||||||
tx.commit();
|
tx.commit();
|
||||||
s.close();
|
s.close();
|
||||||
|
|
||||||
|
sf.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testQueryStatGathering() {
|
public void testQueryStatGathering() {
|
||||||
Statistics stats = sessionFactory().getStatistics();
|
SessionFactory sf = sessionFactory();
|
||||||
stats.clear();
|
|
||||||
|
|
||||||
Session s = openSession();
|
Session s = sf.openSession();
|
||||||
Transaction tx = s.beginTransaction();
|
Transaction tx = s.beginTransaction();
|
||||||
fillDb(s);
|
fillDb(s);
|
||||||
tx.commit();
|
tx.commit();
|
||||||
s.close();
|
s.close();
|
||||||
|
|
||||||
s = openSession();
|
s = sf.openSession();
|
||||||
tx = s.beginTransaction();
|
tx = s.beginTransaction();
|
||||||
final String continents = "from Continent";
|
final String continents = "from Continent";
|
||||||
int results = s.createQuery( continents ).list().size();
|
int results = s.createQuery( continents ).list().size();
|
||||||
QueryStatistics continentStats = stats.getQueryStatistics( continents );
|
QueryStatistics continentStats = sf.getStatistics().getQueryStatistics( continents );
|
||||||
assertNotNull( "stats were null", continentStats );
|
assertNotNull( "stats were null", continentStats );
|
||||||
assertEquals( "unexpected execution count", 1, continentStats.getExecutionCount() );
|
assertEquals( "unexpected execution count", 1, continentStats.getExecutionCount() );
|
||||||
assertEquals( "unexpected row count", results, continentStats.getExecutionRowCount() );
|
assertEquals( "unexpected row count", results, continentStats.getExecutionRowCount() );
|
||||||
long maxTime = continentStats.getExecutionMaxTime();
|
long maxTime = continentStats.getExecutionMaxTime();
|
||||||
assertEquals( maxTime, stats.getQueryExecutionMaxTime() );
|
assertEquals( maxTime, sf.getStatistics().getQueryExecutionMaxTime() );
|
||||||
// assertEquals( continents, stats.getQueryExecutionMaxTimeQueryString() );
|
// assertEquals( continents, stats.getQueryExecutionMaxTimeQueryString() );
|
||||||
|
|
||||||
Iterator itr = s.createQuery( continents ).iterate();
|
Iterator itr = s.createQuery( continents ).iterate();
|
||||||
|
@ -206,44 +215,47 @@ public class StatsTest extends BaseCoreFunctionalTestCase {
|
||||||
|
|
||||||
// explicitly check that statistics for "split queries" get collected
|
// explicitly check that statistics for "split queries" get collected
|
||||||
// under the original query
|
// under the original query
|
||||||
stats.clear();
|
sf.getStatistics().clear();
|
||||||
s = openSession();
|
|
||||||
|
s = sf.openSession();
|
||||||
tx = s.beginTransaction();
|
tx = s.beginTransaction();
|
||||||
final String localities = "from Locality";
|
final String localities = "from Locality";
|
||||||
results = s.createQuery( localities ).list().size();
|
results = s.createQuery( localities ).list().size();
|
||||||
QueryStatistics localityStats = stats.getQueryStatistics( localities );
|
QueryStatistics localityStats = sf.getStatistics().getQueryStatistics( localities );
|
||||||
assertNotNull( "stats were null", localityStats );
|
assertNotNull( "stats were null", localityStats );
|
||||||
// ...one for each split query
|
// ...one for each split query
|
||||||
assertEquals( "unexpected execution count", 2, localityStats.getExecutionCount() );
|
assertEquals( "unexpected execution count", 2, localityStats.getExecutionCount() );
|
||||||
assertEquals( "unexpected row count", results, localityStats.getExecutionRowCount() );
|
assertEquals( "unexpected row count", results, localityStats.getExecutionRowCount() );
|
||||||
maxTime = localityStats.getExecutionMaxTime();
|
maxTime = localityStats.getExecutionMaxTime();
|
||||||
assertEquals( maxTime, stats.getQueryExecutionMaxTime() );
|
assertEquals( maxTime, sf.getStatistics().getQueryExecutionMaxTime() );
|
||||||
// assertEquals( localities, stats.getQueryExecutionMaxTimeQueryString() );
|
// assertEquals( localities, stats.getQueryExecutionMaxTimeQueryString() );
|
||||||
tx.commit();
|
tx.commit();
|
||||||
s.close();
|
s.close();
|
||||||
assertFalse( s.isOpen() );
|
assertFalse( s.isOpen() );
|
||||||
|
|
||||||
// native sql queries
|
// native sql queries
|
||||||
stats.clear();
|
sf.getStatistics().clear();
|
||||||
s = openSession();
|
|
||||||
|
s = sf.openSession();
|
||||||
tx = s.beginTransaction();
|
tx = s.beginTransaction();
|
||||||
final String sql = "select id, name from Country";
|
final String sql = "select id, name from Country";
|
||||||
results = s.createSQLQuery( sql ).addEntity( Country.class ).list().size();
|
results = s.createSQLQuery( sql ).addEntity( Country.class ).list().size();
|
||||||
QueryStatistics sqlStats = stats.getQueryStatistics( sql );
|
QueryStatistics sqlStats = sf.getStatistics().getQueryStatistics( sql );
|
||||||
assertNotNull( "sql stats were null", sqlStats );
|
assertNotNull( "sql stats were null", sqlStats );
|
||||||
assertEquals( "unexpected execution count", 1, sqlStats.getExecutionCount() );
|
assertEquals( "unexpected execution count", 1, sqlStats.getExecutionCount() );
|
||||||
assertEquals( "unexpected row count", results, sqlStats.getExecutionRowCount() );
|
assertEquals( "unexpected row count", results, sqlStats.getExecutionRowCount() );
|
||||||
maxTime = sqlStats.getExecutionMaxTime();
|
maxTime = sqlStats.getExecutionMaxTime();
|
||||||
assertEquals( maxTime, stats.getQueryExecutionMaxTime() );
|
assertEquals( maxTime, sf.getStatistics().getQueryExecutionMaxTime() );
|
||||||
// assertEquals( sql, stats.getQueryExecutionMaxTimeQueryString() );
|
// assertEquals( sql, stats.getQueryExecutionMaxTimeQueryString() );
|
||||||
tx.commit();
|
tx.commit();
|
||||||
s.close();
|
s.close();
|
||||||
|
|
||||||
s = openSession();
|
s = sf.openSession();
|
||||||
tx = s.beginTransaction();
|
tx = s.beginTransaction();
|
||||||
cleanDb( s );
|
cleanDb( s );
|
||||||
tx.commit();
|
tx.commit();
|
||||||
s.close();
|
s.close();
|
||||||
|
sf.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
private Continent fillDb(Session s) {
|
private Continent fillDb(Session s) {
|
||||||
|
|
|
@ -22,6 +22,9 @@ dependencies {
|
||||||
testRuntime( libraries.validator )
|
testRuntime( libraries.validator )
|
||||||
testRuntime( "org.jboss.spec.javax.ejb:jboss-ejb-api_3.2_spec:1.0.0.Alpha2" )
|
testRuntime( "org.jboss.spec.javax.ejb:jboss-ejb-api_3.2_spec:1.0.0.Alpha2" )
|
||||||
// testRuntime( "org.glassfish.web:el-impl:2.1.2-b04" )
|
// testRuntime( "org.glassfish.web:el-impl:2.1.2-b04" )
|
||||||
|
|
||||||
|
// for testing stored procedure support
|
||||||
|
testCompile( libraries.derby )
|
||||||
}
|
}
|
||||||
|
|
||||||
def pomName() {
|
def pomName() {
|
||||||
|
|
|
@ -24,7 +24,6 @@
|
||||||
package org.hibernate.jpa.event.internal.jpa;
|
package org.hibernate.jpa.event.internal.jpa;
|
||||||
|
|
||||||
import javax.persistence.PersistenceException;
|
import javax.persistence.PersistenceException;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
import org.hibernate.jpa.event.spi.jpa.ListenerFactory;
|
import org.hibernate.jpa.event.spi.jpa.ListenerFactory;
|
||||||
|
@ -36,7 +35,8 @@ import org.hibernate.jpa.event.spi.jpa.ListenerFactory;
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public class StandardListenerFactory implements ListenerFactory {
|
public class StandardListenerFactory implements ListenerFactory {
|
||||||
private Map listenerInstances = new ConcurrentHashMap();
|
|
||||||
|
private final ConcurrentHashMap listenerInstances = new ConcurrentHashMap();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
|
@ -52,7 +52,10 @@ public class StandardListenerFactory implements ListenerFactory {
|
||||||
e
|
e
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
listenerInstances.put( listenerClass, listenerInstance );
|
Object existing = listenerInstances.putIfAbsent( listenerClass, listenerInstance );
|
||||||
|
if ( existing != null ) {
|
||||||
|
listenerInstance = existing;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return (T) listenerInstance;
|
return (T) listenerInstance;
|
||||||
}
|
}
|
||||||
|
|
|
@ -269,6 +269,8 @@ public class EntityManagerFactoryImpl implements HibernateEntityManagerFactory {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public EntityManager createEntityManager(SynchronizationType synchronizationType, Map map) {
|
public EntityManager createEntityManager(SynchronizationType synchronizationType, Map map) {
|
||||||
|
validateNotClosed();
|
||||||
|
|
||||||
//TODO support discardOnClose, persistencecontexttype?, interceptor,
|
//TODO support discardOnClose, persistencecontexttype?, interceptor,
|
||||||
return new EntityManagerImpl(
|
return new EntityManagerImpl(
|
||||||
this,
|
this,
|
||||||
|
@ -282,42 +284,49 @@ public class EntityManagerFactoryImpl implements HibernateEntityManagerFactory {
|
||||||
}
|
}
|
||||||
|
|
||||||
public CriteriaBuilder getCriteriaBuilder() {
|
public CriteriaBuilder getCriteriaBuilder() {
|
||||||
|
validateNotClosed();
|
||||||
return criteriaBuilder;
|
return criteriaBuilder;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Metamodel getMetamodel() {
|
public Metamodel getMetamodel() {
|
||||||
|
validateNotClosed();
|
||||||
return metamodel;
|
return metamodel;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void close() {
|
public void close() {
|
||||||
|
// The spec says so, that's why :(
|
||||||
|
validateNotClosed();
|
||||||
|
|
||||||
sessionFactory.close();
|
sessionFactory.close();
|
||||||
EntityManagerFactoryRegistry.INSTANCE.removeEntityManagerFactory(entityManagerFactoryName, this);
|
EntityManagerFactoryRegistry.INSTANCE.removeEntityManagerFactory(entityManagerFactoryName, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<String, Object> getProperties() {
|
public Map<String, Object> getProperties() {
|
||||||
|
validateNotClosed();
|
||||||
return properties;
|
return properties;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Cache getCache() {
|
public Cache getCache() {
|
||||||
|
validateNotClosed();
|
||||||
|
|
||||||
// TODO : cache the cache reference?
|
// TODO : cache the cache reference?
|
||||||
if ( ! isOpen() ) {
|
|
||||||
throw new IllegalStateException("EntityManagerFactory is closed");
|
|
||||||
}
|
|
||||||
return new JPACache( sessionFactory );
|
return new JPACache( sessionFactory );
|
||||||
}
|
}
|
||||||
|
|
||||||
public PersistenceUnitUtil getPersistenceUnitUtil() {
|
protected void validateNotClosed() {
|
||||||
if ( ! isOpen() ) {
|
if ( ! isOpen() ) {
|
||||||
throw new IllegalStateException("EntityManagerFactory is closed");
|
throw new IllegalStateException( "EntityManagerFactory is closed" );
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public PersistenceUnitUtil getPersistenceUnitUtil() {
|
||||||
|
validateNotClosed();
|
||||||
return util;
|
return util;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addNamedQuery(String name, Query query) {
|
public void addNamedQuery(String name, Query query) {
|
||||||
if ( ! isOpen() ) {
|
validateNotClosed();
|
||||||
throw new IllegalStateException( "EntityManagerFactory is closed" );
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( StoredProcedureQueryImpl.class.isInstance( query ) ) {
|
if ( StoredProcedureQueryImpl.class.isInstance( query ) ) {
|
||||||
final ProcedureCall procedureCall = ( (StoredProcedureQueryImpl) query ).getHibernateProcedureCall();
|
final ProcedureCall procedureCall = ( (StoredProcedureQueryImpl) query ).getHibernateProcedureCall();
|
||||||
|
|
|
@ -197,7 +197,7 @@ public class EntityManagerImpl extends AbstractEntityManagerImpl implements Sess
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public <T> EntityGraph<T> getEntityGraph(String graphName) {
|
public EntityGraph<?> getEntityGraph(String graphName) {
|
||||||
checkOpen();
|
checkOpen();
|
||||||
final EntityGraphImpl named = getEntityManagerFactory().findEntityGraphByName( graphName );
|
final EntityGraphImpl named = getEntityManagerFactory().findEntityGraphByName( graphName );
|
||||||
if ( named == null ) {
|
if ( named == null ) {
|
||||||
|
|
|
@ -23,13 +23,10 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.jpa.internal;
|
package org.hibernate.jpa.internal;
|
||||||
|
|
||||||
import javax.persistence.NoResultException;
|
import static javax.persistence.TemporalType.DATE;
|
||||||
import javax.persistence.NonUniqueResultException;
|
import static javax.persistence.TemporalType.TIME;
|
||||||
import javax.persistence.ParameterMode;
|
import static javax.persistence.TemporalType.TIMESTAMP;
|
||||||
import javax.persistence.PersistenceException;
|
|
||||||
import javax.persistence.Query;
|
|
||||||
import javax.persistence.TemporalType;
|
|
||||||
import javax.persistence.TypedQuery;
|
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
@ -39,7 +36,13 @@ import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.jboss.logging.Logger;
|
import javax.persistence.NoResultException;
|
||||||
|
import javax.persistence.NonUniqueResultException;
|
||||||
|
import javax.persistence.ParameterMode;
|
||||||
|
import javax.persistence.PersistenceException;
|
||||||
|
import javax.persistence.Query;
|
||||||
|
import javax.persistence.TemporalType;
|
||||||
|
import javax.persistence.TypedQuery;
|
||||||
|
|
||||||
import org.hibernate.CacheMode;
|
import org.hibernate.CacheMode;
|
||||||
import org.hibernate.FlushMode;
|
import org.hibernate.FlushMode;
|
||||||
|
@ -59,10 +62,8 @@ import org.hibernate.jpa.internal.util.LockModeTypeHelper;
|
||||||
import org.hibernate.jpa.spi.AbstractEntityManagerImpl;
|
import org.hibernate.jpa.spi.AbstractEntityManagerImpl;
|
||||||
import org.hibernate.jpa.spi.AbstractQueryImpl;
|
import org.hibernate.jpa.spi.AbstractQueryImpl;
|
||||||
import org.hibernate.type.CompositeCustomType;
|
import org.hibernate.type.CompositeCustomType;
|
||||||
|
import org.hibernate.type.Type;
|
||||||
import static javax.persistence.TemporalType.DATE;
|
import org.jboss.logging.Logger;
|
||||||
import static javax.persistence.TemporalType.TIME;
|
|
||||||
import static javax.persistence.TemporalType.TIMESTAMP;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Hibernate implementation of both the {@link Query} and {@link TypedQuery} contracts.
|
* Hibernate implementation of both the {@link Query} and {@link TypedQuery} contracts.
|
||||||
|
@ -103,7 +104,7 @@ public class QueryImpl<X> extends AbstractQueryImpl<X> implements TypedQuery<X>,
|
||||||
for ( String name : (Set<String>) parameterMetadata.getNamedParameterNames() ) {
|
for ( String name : (Set<String>) parameterMetadata.getNamedParameterNames() ) {
|
||||||
final NamedParameterDescriptor descriptor = parameterMetadata.getNamedParameterDescriptor( name );
|
final NamedParameterDescriptor descriptor = parameterMetadata.getNamedParameterDescriptor( name );
|
||||||
Class javaType = namedParameterTypeRedefinition.get( name );
|
Class javaType = namedParameterTypeRedefinition.get( name );
|
||||||
if ( javaType != null && mightNeedRedefinition( javaType, descriptor.getExpectedType().getClass() ) ) {
|
if ( javaType != null && mightNeedRedefinition( javaType, descriptor.getExpectedType() ) ) {
|
||||||
descriptor.resetExpectedType(
|
descriptor.resetExpectedType(
|
||||||
sfi().getTypeResolver().heuristicType( javaType.getName() )
|
sfi().getTypeResolver().heuristicType( javaType.getName() )
|
||||||
);
|
);
|
||||||
|
@ -136,10 +137,13 @@ public class QueryImpl<X> extends AbstractQueryImpl<X> implements TypedQuery<X>,
|
||||||
return (SessionFactoryImplementor) getEntityManager().getFactory().getSessionFactory();
|
return (SessionFactoryImplementor) getEntityManager().getFactory().getSessionFactory();
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean mightNeedRedefinition(Class javaType, Class expectedType) {
|
private boolean mightNeedRedefinition(Class javaType, Type expectedType) {
|
||||||
// only redefine dates/times/timestamps that are not wrapped in a CompositeCustomType
|
// only redefine dates/times/timestamps that are not wrapped in a CompositeCustomType
|
||||||
|
if ( expectedType == null )
|
||||||
|
return java.util.Date.class.isAssignableFrom( javaType );
|
||||||
|
else
|
||||||
return java.util.Date.class.isAssignableFrom( javaType )
|
return java.util.Date.class.isAssignableFrom( javaType )
|
||||||
&& !CompositeCustomType.class.isAssignableFrom( expectedType );
|
&& !CompositeCustomType.class.isAssignableFrom( expectedType.getClass() );
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class ParameterRegistrationImpl<T> implements ParameterRegistration<T> {
|
private static class ParameterRegistrationImpl<T> implements ParameterRegistration<T> {
|
||||||
|
|
|
@ -25,11 +25,15 @@ package org.hibernate.jpa.internal;
|
||||||
|
|
||||||
import javax.persistence.FlushModeType;
|
import javax.persistence.FlushModeType;
|
||||||
import javax.persistence.LockModeType;
|
import javax.persistence.LockModeType;
|
||||||
|
import javax.persistence.NoResultException;
|
||||||
|
import javax.persistence.NonUniqueResultException;
|
||||||
import javax.persistence.Parameter;
|
import javax.persistence.Parameter;
|
||||||
import javax.persistence.ParameterMode;
|
import javax.persistence.ParameterMode;
|
||||||
|
import javax.persistence.PersistenceException;
|
||||||
import javax.persistence.Query;
|
import javax.persistence.Query;
|
||||||
import javax.persistence.StoredProcedureQuery;
|
import javax.persistence.StoredProcedureQuery;
|
||||||
import javax.persistence.TemporalType;
|
import javax.persistence.TemporalType;
|
||||||
|
import javax.persistence.TransactionRequiredException;
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -37,11 +41,15 @@ import java.util.List;
|
||||||
import org.hibernate.CacheMode;
|
import org.hibernate.CacheMode;
|
||||||
import org.hibernate.FlushMode;
|
import org.hibernate.FlushMode;
|
||||||
import org.hibernate.LockMode;
|
import org.hibernate.LockMode;
|
||||||
|
import org.hibernate.procedure.NoSuchParameterException;
|
||||||
|
import org.hibernate.procedure.ParameterStrategyException;
|
||||||
import org.hibernate.procedure.ProcedureCall;
|
import org.hibernate.procedure.ProcedureCall;
|
||||||
import org.hibernate.procedure.ProcedureResult;
|
import org.hibernate.procedure.ProcedureCallMemento;
|
||||||
import org.hibernate.result.ResultSetReturn;
|
import org.hibernate.procedure.ProcedureOutputs;
|
||||||
import org.hibernate.result.Return;
|
import org.hibernate.result.NoMoreReturnsException;
|
||||||
import org.hibernate.result.UpdateCountReturn;
|
import org.hibernate.result.ResultSetOutput;
|
||||||
|
import org.hibernate.result.Output;
|
||||||
|
import org.hibernate.result.UpdateCountOutput;
|
||||||
import org.hibernate.jpa.spi.BaseQueryImpl;
|
import org.hibernate.jpa.spi.BaseQueryImpl;
|
||||||
import org.hibernate.jpa.spi.HibernateEntityManagerImplementor;
|
import org.hibernate.jpa.spi.HibernateEntityManagerImplementor;
|
||||||
|
|
||||||
|
@ -50,13 +58,28 @@ import org.hibernate.jpa.spi.HibernateEntityManagerImplementor;
|
||||||
*/
|
*/
|
||||||
public class StoredProcedureQueryImpl extends BaseQueryImpl implements StoredProcedureQuery {
|
public class StoredProcedureQueryImpl extends BaseQueryImpl implements StoredProcedureQuery {
|
||||||
private final ProcedureCall procedureCall;
|
private final ProcedureCall procedureCall;
|
||||||
private ProcedureResult procedureResult;
|
private ProcedureOutputs procedureResult;
|
||||||
|
|
||||||
public StoredProcedureQueryImpl(ProcedureCall procedureCall, HibernateEntityManagerImplementor entityManager) {
|
public StoredProcedureQueryImpl(ProcedureCall procedureCall, HibernateEntityManagerImplementor entityManager) {
|
||||||
super( entityManager );
|
super( entityManager );
|
||||||
this.procedureCall = procedureCall;
|
this.procedureCall = procedureCall;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This form is used to build a StoredProcedureQueryImpl from a memento (usually from a NamedStoredProcedureQuery).
|
||||||
|
*
|
||||||
|
* @param memento The memento
|
||||||
|
* @param entityManager The EntityManager
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public StoredProcedureQueryImpl(ProcedureCallMemento memento, HibernateEntityManagerImplementor entityManager) {
|
||||||
|
super( entityManager );
|
||||||
|
this.procedureCall = memento.makeProcedureCall( entityManager.getSession() );
|
||||||
|
for ( org.hibernate.procedure.ParameterRegistration nativeParamReg : procedureCall.getRegisteredParameters() ) {
|
||||||
|
registerParameter( new ParameterRegistrationImpl( nativeParamReg ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean applyTimeoutHint(int timeout) {
|
protected boolean applyTimeoutHint(int timeout) {
|
||||||
procedureCall.setTimeout( timeout );
|
procedureCall.setTimeout( timeout );
|
||||||
|
@ -178,81 +201,162 @@ public class StoredProcedureQueryImpl extends BaseQueryImpl implements StoredPro
|
||||||
|
|
||||||
// outputs ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
// outputs ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
private ProcedureResult outputs() {
|
@Override
|
||||||
|
public boolean execute() {
|
||||||
|
try {
|
||||||
|
final Output rtn = outputs().getCurrent();
|
||||||
|
return rtn != null && ResultSetOutput.class.isInstance( rtn );
|
||||||
|
}
|
||||||
|
catch (NoMoreReturnsException e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected ProcedureOutputs outputs() {
|
||||||
if ( procedureResult == null ) {
|
if ( procedureResult == null ) {
|
||||||
procedureResult = procedureCall.getResult();
|
procedureResult = procedureCall.getResult();
|
||||||
}
|
}
|
||||||
return procedureResult;
|
return procedureResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int executeUpdate() {
|
||||||
|
if ( ! entityManager().isTransactionInProgress() ) {
|
||||||
|
throw new TransactionRequiredException( "javax.persistence.Query.executeUpdate requires active transaction" );
|
||||||
|
}
|
||||||
|
|
||||||
|
// the expectation is that there is just one Output, of type UpdateCountOutput
|
||||||
|
try {
|
||||||
|
execute();
|
||||||
|
return getUpdateCount();
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
outputs().release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object getOutputParameterValue(int position) {
|
public Object getOutputParameterValue(int position) {
|
||||||
|
try {
|
||||||
return outputs().getOutputParameterValue( position );
|
return outputs().getOutputParameterValue( position );
|
||||||
}
|
}
|
||||||
|
catch (ParameterStrategyException e) {
|
||||||
|
throw new IllegalArgumentException( "Invalid mix of named and positional parameters", e );
|
||||||
|
}
|
||||||
|
catch (NoSuchParameterException e) {
|
||||||
|
throw new IllegalArgumentException( e.getMessage(), e );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object getOutputParameterValue(String parameterName) {
|
public Object getOutputParameterValue(String parameterName) {
|
||||||
|
try {
|
||||||
return outputs().getOutputParameterValue( parameterName );
|
return outputs().getOutputParameterValue( parameterName );
|
||||||
}
|
}
|
||||||
|
catch (ParameterStrategyException e) {
|
||||||
@Override
|
throw new IllegalArgumentException( "Invalid mix of named and positional parameters", e );
|
||||||
public boolean execute() {
|
}
|
||||||
return outputs().hasMoreReturns();
|
catch (NoSuchParameterException e) {
|
||||||
|
throw new IllegalArgumentException( e.getMessage(), e );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public int executeUpdate() {
|
|
||||||
return getUpdateCount();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean hasMoreResults() {
|
public boolean hasMoreResults() {
|
||||||
return outputs().hasMoreReturns();
|
return outputs().goToNext() && ResultSetOutput.class.isInstance( outputs().getCurrent() );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getUpdateCount() {
|
public int getUpdateCount() {
|
||||||
final Return nextReturn = outputs().getNextReturn();
|
try {
|
||||||
if ( nextReturn.isResultSet() ) {
|
final Output rtn = outputs().getCurrent();
|
||||||
|
if ( rtn == null ) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
else if ( UpdateCountOutput.class.isInstance( rtn ) ) {
|
||||||
|
return ( (UpdateCountOutput) rtn ).getUpdateCount();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (NoMoreReturnsException e) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return ( (UpdateCountReturn) nextReturn ).getUpdateCount();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List getResultList() {
|
public List getResultList() {
|
||||||
final Return nextReturn = outputs().getNextReturn();
|
try {
|
||||||
if ( ! nextReturn.isResultSet() ) {
|
final Output rtn = outputs().getCurrent();
|
||||||
return null; // todo : what should be thrown/returned here?
|
if ( ! ResultSetOutput.class.isInstance( rtn ) ) {
|
||||||
|
throw new IllegalStateException( "Current CallableStatement ou was not a ResultSet, but getResultList was called" );
|
||||||
|
}
|
||||||
|
|
||||||
|
return ( (ResultSetOutput) rtn ).getResultList();
|
||||||
|
}
|
||||||
|
catch (NoMoreReturnsException e) {
|
||||||
|
// todo : the spec is completely silent on these type of edge-case scenarios.
|
||||||
|
// Essentially here we'd have a case where there are no more results (ResultSets nor updateCount) but
|
||||||
|
// getResultList was called.
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
return ( (ResultSetReturn) nextReturn ).getResultList();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object getSingleResult() {
|
public Object getSingleResult() {
|
||||||
final Return nextReturn = outputs().getNextReturn();
|
final List resultList = getResultList();
|
||||||
if ( ! nextReturn.isResultSet() ) {
|
if ( resultList == null || resultList.isEmpty() ) {
|
||||||
return null; // todo : what should be thrown/returned here?
|
throw new NoResultException(
|
||||||
|
String.format(
|
||||||
|
"Call to stored procedure [%s] returned no results",
|
||||||
|
procedureCall.getProcedureName()
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
return ( (ResultSetReturn) nextReturn ).getSingleResult();
|
else if ( resultList.size() > 1 ) {
|
||||||
|
throw new NonUniqueResultException(
|
||||||
|
String.format(
|
||||||
|
"Call to stored procedure [%s] returned multiple results",
|
||||||
|
procedureCall.getProcedureName()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return resultList.get( 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
public <T> T unwrap(Class<T> cls) {
|
public <T> T unwrap(Class<T> cls) {
|
||||||
return null;
|
if ( ProcedureCall.class.isAssignableFrom( cls ) ) {
|
||||||
|
return (T) procedureCall;
|
||||||
|
}
|
||||||
|
else if ( ProcedureOutputs.class.isAssignableFrom( cls ) ) {
|
||||||
|
return (T) outputs();
|
||||||
|
}
|
||||||
|
else if ( BaseQueryImpl.class.isAssignableFrom( cls ) ) {
|
||||||
|
return (T) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
throw new PersistenceException(
|
||||||
// ugh ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
String.format(
|
||||||
|
"Unsure how to unwrap %s impl [%s] as requested type [%s]",
|
||||||
|
StoredProcedureQuery.class.getSimpleName(),
|
||||||
|
this.getClass().getName(),
|
||||||
|
cls.getName()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Query setLockMode(LockModeType lockMode) {
|
public Query setLockMode(LockModeType lockMode) {
|
||||||
return null;
|
throw new IllegalStateException( "javax.persistence.Query.setLockMode not valid on javax.persistence.StoredProcedureQuery" );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public LockModeType getLockMode() {
|
public LockModeType getLockMode() {
|
||||||
return null;
|
throw new IllegalStateException( "javax.persistence.Query.getLockMode not valid on javax.persistence.StoredProcedureQuery" );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,7 @@ import java.sql.Connection;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
|
|
||||||
import org.hibernate.engine.jdbc.connections.spi.JdbcConnectionAccess;
|
import org.hibernate.engine.jdbc.connections.spi.JdbcConnectionAccess;
|
||||||
|
import org.jboss.logging.Logger;
|
||||||
|
|
||||||
import org.hibernate.engine.jdbc.internal.DDLFormatterImpl;
|
import org.hibernate.engine.jdbc.internal.DDLFormatterImpl;
|
||||||
import org.hibernate.engine.jdbc.spi.SqlStatementLogger;
|
import org.hibernate.engine.jdbc.spi.SqlStatementLogger;
|
||||||
|
@ -38,6 +39,8 @@ import org.hibernate.engine.jdbc.spi.SqlStatementLogger;
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
class JdbcConnectionContext {
|
class JdbcConnectionContext {
|
||||||
|
private static final Logger log = Logger.getLogger( JdbcConnectionContext.class );
|
||||||
|
|
||||||
private final JdbcConnectionAccess jdbcConnectionAccess;
|
private final JdbcConnectionAccess jdbcConnectionAccess;
|
||||||
private final SqlStatementLogger sqlStatementLogger;
|
private final SqlStatementLogger sqlStatementLogger;
|
||||||
|
|
||||||
|
@ -62,6 +65,15 @@ class JdbcConnectionContext {
|
||||||
|
|
||||||
public void release() {
|
public void release() {
|
||||||
if ( jdbcConnection != null ) {
|
if ( jdbcConnection != null ) {
|
||||||
|
try {
|
||||||
|
if ( ! jdbcConnection.getAutoCommit() ) {
|
||||||
|
jdbcConnection.commit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (SQLException e) {
|
||||||
|
log.debug( "Unable to commit JDBC transaction used for JPA schema export; may or may not be a problem" );
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
jdbcConnectionAccess.releaseConnection( jdbcConnection );
|
jdbcConnectionAccess.releaseConnection( jdbcConnection );
|
||||||
}
|
}
|
||||||
|
|
|
@ -838,8 +838,7 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage
|
||||||
if ( memento == null ) {
|
if ( memento == null ) {
|
||||||
throw new IllegalArgumentException( "No @NamedStoredProcedureQuery was found with that name : " + name );
|
throw new IllegalArgumentException( "No @NamedStoredProcedureQuery was found with that name : " + name );
|
||||||
}
|
}
|
||||||
final ProcedureCall procedureCall = memento.makeProcedureCall( internalGetSession() );
|
final StoredProcedureQueryImpl jpaImpl = new StoredProcedureQueryImpl( memento, this );
|
||||||
final StoredProcedureQueryImpl jpaImpl = new StoredProcedureQueryImpl( procedureCall, this );
|
|
||||||
// apply hints
|
// apply hints
|
||||||
if ( memento.getHintsMap() != null ) {
|
if ( memento.getHintsMap() != null ) {
|
||||||
for ( Map.Entry<String,Object> hintEntry : memento.getHintsMap().entrySet() ) {
|
for ( Map.Entry<String,Object> hintEntry : memento.getHintsMap().entrySet() ) {
|
||||||
|
|
|
@ -51,6 +51,8 @@ import org.hibernate.jpa.internal.EntityManagerMessageLogger;
|
||||||
import org.hibernate.jpa.internal.util.CacheModeHelper;
|
import org.hibernate.jpa.internal.util.CacheModeHelper;
|
||||||
import org.hibernate.jpa.internal.util.ConfigurationHelper;
|
import org.hibernate.jpa.internal.util.ConfigurationHelper;
|
||||||
import org.hibernate.jpa.internal.util.LockModeTypeHelper;
|
import org.hibernate.jpa.internal.util.LockModeTypeHelper;
|
||||||
|
import org.hibernate.procedure.NoSuchParameterException;
|
||||||
|
import org.hibernate.procedure.ParameterStrategyException;
|
||||||
|
|
||||||
import static org.hibernate.jpa.QueryHints.HINT_CACHEABLE;
|
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_MODE;
|
||||||
|
@ -439,7 +441,8 @@ public abstract class BaseQueryImpl implements Query {
|
||||||
protected abstract boolean isJpaPositionalParameter(int position);
|
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. Used here to track
|
||||||
|
* information known about the parameter.
|
||||||
*/
|
*/
|
||||||
protected static interface ParameterRegistration<T> extends Parameter<T> {
|
protected static interface ParameterRegistration<T> extends Parameter<T> {
|
||||||
/**
|
/**
|
||||||
|
@ -450,6 +453,12 @@ public abstract class BaseQueryImpl implements Query {
|
||||||
*/
|
*/
|
||||||
public ParameterMode getMode();
|
public ParameterMode getMode();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Can we bind (set) values on this parameter? Generally this is {@code true}, but would not be in the case
|
||||||
|
* of parameters with OUT or REF_CURSOR mode.
|
||||||
|
*
|
||||||
|
* @return Whether the parameter is bindable (can set be called).
|
||||||
|
*/
|
||||||
public boolean isBindable();
|
public boolean isBindable();
|
||||||
|
|
||||||
public void bindValue(T value);
|
public void bindValue(T value);
|
||||||
|
@ -459,6 +468,11 @@ public abstract class BaseQueryImpl implements Query {
|
||||||
public ParameterBind<T> getBind();
|
public ParameterBind<T> getBind();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents the value currently bound to a particular parameter.
|
||||||
|
*
|
||||||
|
* @param <T>
|
||||||
|
*/
|
||||||
protected static interface ParameterBind<T> {
|
protected static interface ParameterBind<T> {
|
||||||
public T getValue();
|
public T getValue();
|
||||||
|
|
||||||
|
@ -648,6 +662,12 @@ public abstract class BaseQueryImpl implements Query {
|
||||||
try {
|
try {
|
||||||
findParameterRegistration( position ).bindValue( value, temporalType );
|
findParameterRegistration( position ).bindValue( value, temporalType );
|
||||||
}
|
}
|
||||||
|
catch (ParameterStrategyException e) {
|
||||||
|
throw new IllegalArgumentException( "Invalid mix of named and positional parameters", e );
|
||||||
|
}
|
||||||
|
catch (NoSuchParameterException e) {
|
||||||
|
throw new IllegalArgumentException( e.getMessage(), e );
|
||||||
|
}
|
||||||
catch (QueryParameterException e) {
|
catch (QueryParameterException e) {
|
||||||
throw new IllegalArgumentException( e );
|
throw new IllegalArgumentException( e );
|
||||||
}
|
}
|
||||||
|
@ -755,18 +775,22 @@ public abstract class BaseQueryImpl implements Query {
|
||||||
checkOpen( false );
|
checkOpen( false );
|
||||||
|
|
||||||
final ParameterRegistration<T> registration = findParameterRegistration( param );
|
final ParameterRegistration<T> registration = findParameterRegistration( param );
|
||||||
if ( registration != null ) {
|
if ( registration == null ) {
|
||||||
|
throw new IllegalArgumentException( "Passed parameter [" + param + "] is not a (registered) parameter of this query" );
|
||||||
|
}
|
||||||
|
|
||||||
if ( ! registration.isBindable() ) {
|
if ( ! registration.isBindable() ) {
|
||||||
throw new IllegalArgumentException( "Passed parameter [" + param + "] is not bindable" );
|
throw new IllegalStateException( "Passed parameter [" + param + "] is not bindable" );
|
||||||
}
|
}
|
||||||
|
|
||||||
final ParameterBind<T> bind = registration.getBind();
|
final ParameterBind<T> bind = registration.getBind();
|
||||||
if ( bind != null ) {
|
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" );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return bind.getValue();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object getParameterValue(String name) {
|
public Object getParameterValue(String name) {
|
||||||
checkOpen( false );
|
checkOpen( false );
|
||||||
|
|
|
@ -32,6 +32,7 @@ import java.util.List;
|
||||||
|
|
||||||
import javax.persistence.EntityManager;
|
import javax.persistence.EntityManager;
|
||||||
import javax.persistence.TypedQuery;
|
import javax.persistence.TypedQuery;
|
||||||
|
import javax.persistence.criteria.CriteriaBuilder;
|
||||||
import javax.persistence.criteria.CriteriaQuery;
|
import javax.persistence.criteria.CriteriaQuery;
|
||||||
import javax.persistence.criteria.ParameterExpression;
|
import javax.persistence.criteria.ParameterExpression;
|
||||||
import javax.persistence.criteria.Predicate;
|
import javax.persistence.criteria.Predicate;
|
||||||
|
@ -103,4 +104,26 @@ public class BasicCriteriaUsageTest extends BaseEntityManagerFunctionalTestCase
|
||||||
em.getTransaction().commit();
|
em.getTransaction().commit();
|
||||||
em.close();
|
em.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestForIssue(jiraKey = "HHH-8373")
|
||||||
|
public void testFunctionCriteria() {
|
||||||
|
Wall wall = new Wall();
|
||||||
|
wall.setColor( "yellow" );
|
||||||
|
EntityManager em = getOrCreateEntityManager();
|
||||||
|
em.getTransaction().begin();
|
||||||
|
em.persist( wall );
|
||||||
|
|
||||||
|
CriteriaBuilder cb = em.getCriteriaBuilder();
|
||||||
|
CriteriaQuery<Wall> query = cb.createQuery( Wall.class );
|
||||||
|
Root<Wall> root = query.from( Wall.class );
|
||||||
|
|
||||||
|
query.select( root ).where( cb.equal( root.get( "color" ), cb.lower( cb.literal( "YELLOW" ) ) ) );
|
||||||
|
|
||||||
|
Wall resultItem = em.createQuery( query ).getSingleResult();
|
||||||
|
assertNotNull( resultItem );
|
||||||
|
|
||||||
|
em.getTransaction().commit();
|
||||||
|
em.close();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -91,7 +91,7 @@ public class BasicEntityGraphTests extends BaseEntityManagerFunctionalTestCase {
|
||||||
|
|
||||||
em.getEntityManagerFactory().addNamedEntityGraph( "immutable", graphRoot );
|
em.getEntityManagerFactory().addNamedEntityGraph( "immutable", graphRoot );
|
||||||
|
|
||||||
graphRoot = em.getEntityGraph( "immutable" );
|
graphRoot = (EntityGraph<Entity1>) em.getEntityGraph( "immutable" );
|
||||||
|
|
||||||
assertEquals( "immutable", graphRoot.getName() );
|
assertEquals( "immutable", graphRoot.getName() );
|
||||||
assertEquals( 2, graphRoot.getAttributeNodes().size() );
|
assertEquals( 2, graphRoot.getAttributeNodes().size() );
|
||||||
|
|
|
@ -52,13 +52,13 @@ public abstract class AbstractStoredProcedureTest extends BaseEntityManagerFunct
|
||||||
list = m2.getParameterDeclarations();
|
list = m2.getParameterDeclarations();
|
||||||
|
|
||||||
memento = list.get( 0 );
|
memento = list.get( 0 );
|
||||||
assertEquals( Integer.valueOf( 0 ), memento.getPosition() );
|
assertEquals( Integer.valueOf( 1 ), memento.getPosition() );
|
||||||
assertEquals( javax.persistence.ParameterMode.INOUT, memento.getMode() );
|
assertEquals( javax.persistence.ParameterMode.INOUT, memento.getMode() );
|
||||||
assertEquals( StringType.INSTANCE, memento.getHibernateType() );
|
assertEquals( StringType.INSTANCE, memento.getHibernateType() );
|
||||||
assertEquals( String.class, memento.getType() );
|
assertEquals( String.class, memento.getType() );
|
||||||
|
|
||||||
memento = list.get( 1 );
|
memento = list.get( 1 );
|
||||||
assertEquals( Integer.valueOf( 1 ), memento.getPosition() );
|
assertEquals( Integer.valueOf( 2 ), memento.getPosition() );
|
||||||
assertEquals( javax.persistence.ParameterMode.INOUT, memento.getMode() );
|
assertEquals( javax.persistence.ParameterMode.INOUT, memento.getMode() );
|
||||||
assertEquals( LongType.INSTANCE, memento.getHibernateType() );
|
assertEquals( LongType.INSTANCE, memento.getHibernateType() );
|
||||||
assertEquals( Long.class, memento.getType() );
|
assertEquals( Long.class, memento.getType() );
|
||||||
|
|
|
@ -0,0 +1,467 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013, Red Hat Inc. or third-party contributors as
|
||||||
|
* indicated by the @author tags or express copyright attribution
|
||||||
|
* statements applied by the authors. All third-party contributions are
|
||||||
|
* distributed under license by Red Hat Inc.
|
||||||
|
*
|
||||||
|
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||||
|
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||||
|
* Lesser General Public License, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||||
|
* for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this distribution; if not, write to:
|
||||||
|
* Free Software Foundation, Inc.
|
||||||
|
* 51 Franklin Street, Fifth Floor
|
||||||
|
* Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
package org.hibernate.jpa.test.procedure;
|
||||||
|
|
||||||
|
import javax.persistence.EntityManager;
|
||||||
|
import javax.persistence.StoredProcedureQuery;
|
||||||
|
import java.sql.Connection;
|
||||||
|
import java.sql.DriverManager;
|
||||||
|
import java.sql.PreparedStatement;
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.sql.Statement;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.hibernate.dialect.DerbyTenSevenDialect;
|
||||||
|
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
|
import org.hibernate.jpa.AvailableSettings;
|
||||||
|
import org.hibernate.jpa.HibernateEntityManagerFactory;
|
||||||
|
import org.hibernate.jpa.boot.spi.Bootstrap;
|
||||||
|
import org.hibernate.jpa.boot.spi.PersistenceUnitDescriptor;
|
||||||
|
import org.hibernate.jpa.internal.EntityManagerFactoryImpl;
|
||||||
|
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
|
||||||
|
|
||||||
|
import org.junit.After;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import org.hibernate.testing.FailureExpected;
|
||||||
|
import org.hibernate.testing.junit4.BaseUnitTestCase;
|
||||||
|
|
||||||
|
import static org.hibernate.testing.junit4.ExtraAssertions.assertTyping;
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
import static org.junit.Assert.fail;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests various JPA usage scenarios for performing stored procedures. Inspired by the awesomely well-done JPA TCK
|
||||||
|
*
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public class JpaTckUsageTest extends BaseUnitTestCase {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMultipleGetUpdateCountCalls() {
|
||||||
|
EntityManager em = entityManagerFactory.createEntityManager();
|
||||||
|
em.getTransaction().begin();
|
||||||
|
|
||||||
|
try {
|
||||||
|
StoredProcedureQuery query = em.createStoredProcedureQuery( "findOneUser" );
|
||||||
|
// this is what the TCK attempts to do, don't shoot the messenger...
|
||||||
|
query.getUpdateCount();
|
||||||
|
// yep, twice
|
||||||
|
query.getUpdateCount();
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
em.getTransaction().commit();
|
||||||
|
em.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testBasicScalarResults() {
|
||||||
|
EntityManager em = entityManagerFactory.createEntityManager();
|
||||||
|
em.getTransaction().begin();
|
||||||
|
|
||||||
|
try {
|
||||||
|
StoredProcedureQuery query = em.createStoredProcedureQuery( "findOneUser" );
|
||||||
|
boolean isResult = query.execute();
|
||||||
|
assertTrue( isResult );
|
||||||
|
int updateCount = query.getUpdateCount();
|
||||||
|
|
||||||
|
boolean results = false;
|
||||||
|
do {
|
||||||
|
List list = query.getResultList();
|
||||||
|
assertEquals( 1, list.size() );
|
||||||
|
|
||||||
|
results = query.hasMoreResults();
|
||||||
|
// and it only sets the updateCount once lol
|
||||||
|
} while ( results || updateCount != -1);
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
em.getTransaction().commit();
|
||||||
|
em.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@FailureExpected( jiraKey = "HHH-8416", message = "JPA TCK challenge" )
|
||||||
|
public void testHasMoreResultsHandlingTckChallenge() {
|
||||||
|
EntityManager em = entityManagerFactory.createEntityManager();
|
||||||
|
em.getTransaction().begin();
|
||||||
|
|
||||||
|
try {
|
||||||
|
StoredProcedureQuery query = em.createStoredProcedureQuery( "findOneUser", User.class );
|
||||||
|
assertTrue( query.execute() );
|
||||||
|
assertTrue( query.hasMoreResults() );
|
||||||
|
query.getResultList();
|
||||||
|
assertFalse( query.hasMoreResults() );
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
em.getTransaction().commit();
|
||||||
|
em.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testHasMoreResultsHandling() {
|
||||||
|
EntityManager em = entityManagerFactory.createEntityManager();
|
||||||
|
em.getTransaction().begin();
|
||||||
|
|
||||||
|
try {
|
||||||
|
StoredProcedureQuery query = em.createStoredProcedureQuery( "findOneUser", User.class );
|
||||||
|
assertTrue( query.execute() );
|
||||||
|
query.getResultList();
|
||||||
|
assertFalse( query.hasMoreResults() );
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
em.getTransaction().commit();
|
||||||
|
em.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testResultClassHandling() {
|
||||||
|
EntityManager em = entityManagerFactory.createEntityManager();
|
||||||
|
em.getTransaction().begin();
|
||||||
|
|
||||||
|
try {
|
||||||
|
StoredProcedureQuery query = em.createStoredProcedureQuery( "findOneUser", User.class );
|
||||||
|
boolean isResult = query.execute();
|
||||||
|
assertTrue( isResult );
|
||||||
|
int updateCount = query.getUpdateCount();
|
||||||
|
|
||||||
|
boolean results = false;
|
||||||
|
do {
|
||||||
|
List list = query.getResultList();
|
||||||
|
assertEquals( 1, list.size() );
|
||||||
|
assertTyping( User.class, list.get( 0 ) );
|
||||||
|
|
||||||
|
results = query.hasMoreResults();
|
||||||
|
// and it only sets the updateCount once lol
|
||||||
|
} while ( results || updateCount != -1);
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
em.getTransaction().commit();
|
||||||
|
em.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSettingInParamDefinedOnNamedStoredProcedureQuery() {
|
||||||
|
EntityManager em = entityManagerFactory.createEntityManager();
|
||||||
|
em.getTransaction().begin();
|
||||||
|
try {
|
||||||
|
StoredProcedureQuery query = em.createNamedStoredProcedureQuery( "positional-param" );
|
||||||
|
query.setParameter( 1, 1 );
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
em.getTransaction().commit();
|
||||||
|
em.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSettingNonExistingParams() {
|
||||||
|
EntityManager em = entityManagerFactory.createEntityManager();
|
||||||
|
em.getTransaction().begin();
|
||||||
|
|
||||||
|
try {
|
||||||
|
// non-existing positional param
|
||||||
|
try {
|
||||||
|
StoredProcedureQuery query = em.createNamedStoredProcedureQuery( "positional-param" );
|
||||||
|
query.setParameter( 99, 1 );
|
||||||
|
fail( "Expecting an exception" );
|
||||||
|
}
|
||||||
|
catch (IllegalArgumentException expected) {
|
||||||
|
// this is the expected condition
|
||||||
|
}
|
||||||
|
|
||||||
|
// non-existing named param
|
||||||
|
try {
|
||||||
|
StoredProcedureQuery query = em.createNamedStoredProcedureQuery( "positional-param" );
|
||||||
|
query.setParameter( "does-not-exist", 1 );
|
||||||
|
fail( "Expecting an exception" );
|
||||||
|
}
|
||||||
|
catch (IllegalArgumentException expected) {
|
||||||
|
// this is the expected condition
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
em.getTransaction().commit();
|
||||||
|
em.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@FailureExpected( jiraKey = "HHH-8395", message = "Out of the frying pan into the fire: https://issues.apache.org/jira/browse/DERBY-211" )
|
||||||
|
public void testExecuteUpdate() {
|
||||||
|
EntityManager em = entityManagerFactory.createEntityManager();
|
||||||
|
em.getTransaction().begin();
|
||||||
|
|
||||||
|
try {
|
||||||
|
StoredProcedureQuery query = em.createStoredProcedureQuery( "deleteAllUsers" );
|
||||||
|
int count = query.executeUpdate();
|
||||||
|
// this fails because the Derby EmbeddedDriver is returning zero here rather than the actual updateCount :(
|
||||||
|
// https://issues.apache.org/jira/browse/DERBY-211
|
||||||
|
assertEquals( 1, count );
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
em.getTransaction().commit();
|
||||||
|
em.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testParameterRegistration() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// todo : look at ways to allow "Auxiliary DB Objects" to the db via EMF bootstrapping.
|
||||||
|
|
||||||
|
// public static final String findOneUser_CREATE_CMD = "CREATE ALIAS findOneUser AS $$\n" +
|
||||||
|
// "import org.h2.tools.SimpleResultSet;\n" +
|
||||||
|
// "import java.sql.*;\n" +
|
||||||
|
// "@CODE\n" +
|
||||||
|
// "ResultSet findOneUser() {\n" +
|
||||||
|
// " SimpleResultSet rs = new SimpleResultSet();\n" +
|
||||||
|
// " rs.addColumn(\"ID\", Types.INTEGER, 10, 0);\n" +
|
||||||
|
// " rs.addColumn(\"NAME\", Types.VARCHAR, 255, 0);\n" +
|
||||||
|
// " rs.addRow(1, \"Steve\");\n" +
|
||||||
|
// " return rs;\n" +
|
||||||
|
// "}\n" +
|
||||||
|
// "$$";
|
||||||
|
// public static final String findOneUser_DROP_CMD = "DROP ALIAS findOneUser IF EXISTS";
|
||||||
|
//
|
||||||
|
// public static final String deleteAllUsers_CREATE_CMD = "CREATE ALIAS deleteAllUsers AS $$\n" +
|
||||||
|
// "@CODE\n" +
|
||||||
|
// "int deleteAllUsers() {\n" +
|
||||||
|
// " return 156;" +
|
||||||
|
// "}\n" +
|
||||||
|
// "$$";
|
||||||
|
// public static final String deleteAllUsers_DROP_CMD = "DROP ALIAS deleteAllUsers IF EXISTS";
|
||||||
|
|
||||||
|
HibernateEntityManagerFactory entityManagerFactory;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void startUp() {
|
||||||
|
// create the EMF
|
||||||
|
entityManagerFactory = (EntityManagerFactoryImpl) Bootstrap.getEntityManagerFactoryBuilder(
|
||||||
|
buildPersistenceUnitDescriptor(),
|
||||||
|
buildSettingsMap()
|
||||||
|
).build();
|
||||||
|
|
||||||
|
// create the procedures
|
||||||
|
createTestUser( entityManagerFactory );
|
||||||
|
createProcedures( entityManagerFactory );
|
||||||
|
}
|
||||||
|
|
||||||
|
private PersistenceUnitDescriptor buildPersistenceUnitDescriptor() {
|
||||||
|
return new BaseEntityManagerFunctionalTestCase.TestingPersistenceUnitDescriptorImpl( getClass().getSimpleName() );
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
private Map buildSettingsMap() {
|
||||||
|
Map settings = new HashMap();
|
||||||
|
|
||||||
|
settings.put( AvailableSettings.LOADED_CLASSES, Collections.singletonList( User.class ) );
|
||||||
|
|
||||||
|
settings.put( org.hibernate.cfg.AvailableSettings.DIALECT, DerbyTenSevenDialect.class );
|
||||||
|
settings.put( org.hibernate.cfg.AvailableSettings.DRIVER, org.apache.derby.jdbc.EmbeddedDriver.class.getName() );
|
||||||
|
// settings.put( org.hibernate.cfg.AvailableSettings.URL, "jdbc:derby:/tmp/hibernate-orm-testing;create=true" );
|
||||||
|
settings.put( org.hibernate.cfg.AvailableSettings.URL, "jdbc:derby:memory:hibernate-orm-testing;create=true" );
|
||||||
|
settings.put( org.hibernate.cfg.AvailableSettings.USER, "" );
|
||||||
|
|
||||||
|
settings.put( org.hibernate.cfg.AvailableSettings.HBM2DDL_AUTO, "create-drop" );
|
||||||
|
settings.put( org.hibernate.cfg.AvailableSettings.USE_NEW_ID_GENERATOR_MAPPINGS, "true" );
|
||||||
|
settings.put( org.hibernate.cfg.AvailableSettings.DIALECT, DerbyTenSevenDialect.class.getName() );
|
||||||
|
return settings;
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void tearDown() {
|
||||||
|
if ( entityManagerFactory == null ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
deleteTestUser( entityManagerFactory );
|
||||||
|
dropProcedures( entityManagerFactory );
|
||||||
|
|
||||||
|
entityManagerFactory.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createProcedures(HibernateEntityManagerFactory emf) {
|
||||||
|
final SessionFactoryImplementor sf = emf.unwrap( SessionFactoryImplementor.class );
|
||||||
|
final Connection conn;
|
||||||
|
try {
|
||||||
|
conn = sf.getConnectionProvider().getConnection();
|
||||||
|
conn.setAutoCommit( false );
|
||||||
|
|
||||||
|
try {
|
||||||
|
Statement statement = conn.createStatement();
|
||||||
|
|
||||||
|
// drop them, just to be sure
|
||||||
|
try {
|
||||||
|
dropProcedures( statement );
|
||||||
|
}
|
||||||
|
catch (SQLException ignore) {
|
||||||
|
}
|
||||||
|
|
||||||
|
createProcedureFindOneUser( statement );
|
||||||
|
createProcedureDeleteAllUsers( statement );
|
||||||
|
try {
|
||||||
|
statement.close();
|
||||||
|
}
|
||||||
|
catch (SQLException ignore) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
try {
|
||||||
|
conn.commit();
|
||||||
|
}
|
||||||
|
catch (SQLException e) {
|
||||||
|
System.out.println( "Unable to commit transaction after creating creating procedures");
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
sf.getConnectionProvider().closeConnection( conn );
|
||||||
|
}
|
||||||
|
catch (SQLException ignore) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (SQLException e) {
|
||||||
|
throw new RuntimeException( "Unable to create stored procedures", e );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void dropProcedures(Statement statement) throws SQLException {
|
||||||
|
statement.execute( "DROP PROCEDURE findOneUser" );
|
||||||
|
statement.execute( "DROP PROCEDURE deleteAllUsers" );
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createProcedureFindOneUser(Statement statement) throws SQLException {
|
||||||
|
statement.execute(
|
||||||
|
"CREATE PROCEDURE findOneUser() " +
|
||||||
|
"language java " +
|
||||||
|
"dynamic result sets 1 " +
|
||||||
|
"external name 'org.hibernate.jpa.test.procedure.JpaTckUsageTest.findOneUser' " +
|
||||||
|
"parameter style java"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createProcedureDeleteAllUsers(Statement statement) throws SQLException {
|
||||||
|
statement.execute(
|
||||||
|
"CREATE PROCEDURE deleteAllUsers() " +
|
||||||
|
"language java " +
|
||||||
|
"external name 'org.hibernate.jpa.test.procedure.JpaTckUsageTest.deleteAllUsers' " +
|
||||||
|
"parameter style java"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void findOneUser(ResultSet[] results) throws SQLException {
|
||||||
|
Connection conn = DriverManager.getConnection( "jdbc:default:connection" );
|
||||||
|
PreparedStatement ps = conn.prepareStatement( "select id, name from t_user where name=?" );
|
||||||
|
ps.setString( 1, "steve" );
|
||||||
|
results[0] = ps.executeQuery();
|
||||||
|
conn.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void findUserIds(ResultSet[] results) throws SQLException {
|
||||||
|
Connection conn = DriverManager.getConnection( "jdbc:default:connection" );
|
||||||
|
PreparedStatement ps = conn.prepareStatement( "select id from t_user" );
|
||||||
|
results[0] = ps.executeQuery();
|
||||||
|
conn.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void deleteAllUsers() throws SQLException {
|
||||||
|
// afaict the only way to return update counts here is to actually perform some DML
|
||||||
|
Connection conn = DriverManager.getConnection( "jdbc:default:connection" );
|
||||||
|
System.out.println( "Preparing delete all" );
|
||||||
|
PreparedStatement ps = conn.prepareStatement( "delete from t_user" );
|
||||||
|
System.out.println( "Executing delete all" );
|
||||||
|
int count = ps.executeUpdate();
|
||||||
|
System.out.println( "Count : " + count );
|
||||||
|
System.out.println( "Closing resources" );
|
||||||
|
ps.close();
|
||||||
|
conn.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createTestUser(HibernateEntityManagerFactory entityManagerFactory) {
|
||||||
|
EntityManager em = entityManagerFactory.createEntityManager();
|
||||||
|
em.getTransaction().begin();
|
||||||
|
|
||||||
|
em.persist( new User( 1, "steve" ) );
|
||||||
|
em.getTransaction().commit();
|
||||||
|
em.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void deleteTestUser(HibernateEntityManagerFactory entityManagerFactory) {
|
||||||
|
EntityManager em = entityManagerFactory.createEntityManager();
|
||||||
|
em.getTransaction().begin();
|
||||||
|
em.createQuery( "delete from User" ).executeUpdate();
|
||||||
|
em.getTransaction().commit();
|
||||||
|
em.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void dropProcedures(HibernateEntityManagerFactory emf) {
|
||||||
|
|
||||||
|
final SessionFactoryImplementor sf = emf.unwrap( SessionFactoryImplementor.class );
|
||||||
|
final Connection conn;
|
||||||
|
try {
|
||||||
|
conn = sf.getConnectionProvider().getConnection();
|
||||||
|
conn.setAutoCommit( false );
|
||||||
|
|
||||||
|
try {
|
||||||
|
Statement statement = conn.createStatement();
|
||||||
|
dropProcedures( statement );
|
||||||
|
try {
|
||||||
|
statement.close();
|
||||||
|
}
|
||||||
|
catch (SQLException ignore) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
try {
|
||||||
|
conn.commit();
|
||||||
|
}
|
||||||
|
catch (SQLException e) {
|
||||||
|
System.out.println( "Unable to commit transaction after creating dropping procedures");
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
sf.getConnectionProvider().closeConnection( conn );
|
||||||
|
}
|
||||||
|
catch (SQLException ignore) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (SQLException e) {
|
||||||
|
throw new RuntimeException( "Unable to drop stored procedures", e );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -9,6 +9,7 @@ import javax.persistence.NamedStoredProcedureQuery;
|
||||||
import javax.persistence.ParameterMode;
|
import javax.persistence.ParameterMode;
|
||||||
import javax.persistence.SqlResultSetMapping;
|
import javax.persistence.SqlResultSetMapping;
|
||||||
import javax.persistence.StoredProcedureParameter;
|
import javax.persistence.StoredProcedureParameter;
|
||||||
|
import javax.persistence.Table;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Strong Liu <stliu@hibernate.org>
|
* @author Strong Liu <stliu@hibernate.org>
|
||||||
|
@ -43,6 +44,13 @@ import javax.persistence.StoredProcedureParameter;
|
||||||
},
|
},
|
||||||
resultSetMappings = { "srms" }
|
resultSetMappings = { "srms" }
|
||||||
|
|
||||||
|
),
|
||||||
|
@NamedStoredProcedureQuery(
|
||||||
|
name = "positional-param",
|
||||||
|
procedureName = "positionalParameterTesting",
|
||||||
|
parameters = {
|
||||||
|
@StoredProcedureParameter( mode = ParameterMode.IN, type = Integer.class )
|
||||||
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -54,11 +62,20 @@ import javax.persistence.StoredProcedureParameter;
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@Table( name = "T_USER" )
|
||||||
public class User {
|
public class User {
|
||||||
@Id
|
@Id
|
||||||
private int id;
|
private int id;
|
||||||
private String name;
|
private String name;
|
||||||
|
|
||||||
|
public User() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public User(int id, String name) {
|
||||||
|
this.id = id;
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
public int getId() {
|
public int getId() {
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
# 51 Franklin Street, Fifth Floor
|
# 51 Franklin Street, Fifth Floor
|
||||||
# Boston, MA 02110-1301 USA
|
# Boston, MA 02110-1301 USA
|
||||||
#
|
#
|
||||||
|
|
||||||
hibernate.dialect org.hibernate.dialect.H2Dialect
|
hibernate.dialect org.hibernate.dialect.H2Dialect
|
||||||
hibernate.connection.driver_class org.h2.Driver
|
hibernate.connection.driver_class org.h2.Driver
|
||||||
hibernate.connection.url jdbc:h2:mem:db1;DB_CLOSE_DELAY=-1;MVCC=TRUE;LOCK_TIMEOUT=10000
|
hibernate.connection.url jdbc:h2:mem:db1;DB_CLOSE_DELAY=-1;MVCC=TRUE;LOCK_TIMEOUT=10000
|
||||||
|
|
|
@ -125,4 +125,10 @@ public interface EnversSettings {
|
||||||
* Name of column used for storing ordinal of the change in sets of embeddable elements. Defaults to {@literal SETORDINAL}.
|
* Name of column used for storing ordinal of the change in sets of embeddable elements. Defaults to {@literal SETORDINAL}.
|
||||||
*/
|
*/
|
||||||
public static final String EMBEDDABLE_SET_ORDINAL_FIELD_NAME = "org.hibernate.envers.embeddable_set_ordinal_field_name";
|
public static final String EMBEDDABLE_SET_ORDINAL_FIELD_NAME = "org.hibernate.envers.embeddable_set_ordinal_field_name";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Guarantees proper validity audit strategy behavior when application reuses identifiers of deleted entities.
|
||||||
|
* Exactly one row with {@code null} end date exists for each identifier.
|
||||||
|
*/
|
||||||
|
public static final String ALLOW_IDENTIFIER_REUSE = "org.hibernate.envers.allow_identifier_reuse";
|
||||||
}
|
}
|
||||||
|
|
|
@ -75,6 +75,9 @@ public class GlobalConfiguration {
|
||||||
// Use revision entity with native id generator
|
// Use revision entity with native id generator
|
||||||
private final boolean useRevisionEntityWithNativeId;
|
private final boolean useRevisionEntityWithNativeId;
|
||||||
|
|
||||||
|
// Support reused identifiers of previously deleted entities
|
||||||
|
private final boolean allowIdentifierReuse;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Which operator to use in correlated subqueries (when we want a property to be equal to the result of
|
Which operator to use in correlated subqueries (when we want a property to be equal to the result of
|
||||||
a correlated subquery, for example: e.p <operator> (select max(e2.p) where e2.p2 = e.p2 ...).
|
a correlated subquery, for example: e.p <operator> (select max(e2.p) where e2.p2 = e.p2 ...).
|
||||||
|
@ -131,6 +134,10 @@ public class GlobalConfiguration {
|
||||||
else {
|
else {
|
||||||
revisionListenerClass = null;
|
revisionListenerClass = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
allowIdentifierReuse = ConfigurationHelper.getBoolean(
|
||||||
|
EnversSettings.ALLOW_IDENTIFIER_REUSE, properties, false
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isGenerateRevisionsForCollections() {
|
public boolean isGenerateRevisionsForCollections() {
|
||||||
|
@ -184,4 +191,8 @@ public class GlobalConfiguration {
|
||||||
public boolean isUseRevisionEntityWithNativeId() {
|
public boolean isUseRevisionEntityWithNativeId() {
|
||||||
return useRevisionEntityWithNativeId;
|
return useRevisionEntityWithNativeId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isAllowIdentifierReuse() {
|
||||||
|
return allowIdentifierReuse;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,7 +73,7 @@ public final class OneAuditEntityQueryGenerator extends AbstractRelationQueryGen
|
||||||
final QueryBuilder validQuery = commonPart.deepCopy();
|
final QueryBuilder validQuery = commonPart.deepCopy();
|
||||||
final QueryBuilder removedQuery = commonPart.deepCopy();
|
final QueryBuilder removedQuery = commonPart.deepCopy();
|
||||||
createValidDataRestrictions(
|
createValidDataRestrictions(
|
||||||
globalCfg, auditStrategy, referencedIdData, validQuery, validQuery.getRootParameters(), true
|
globalCfg, auditStrategy, referencedIdData, validQuery, validQuery.getRootParameters()
|
||||||
);
|
);
|
||||||
createValidAndRemovedDataRestrictions( globalCfg, auditStrategy, referencedIdData, removedQuery );
|
createValidAndRemovedDataRestrictions( globalCfg, auditStrategy, referencedIdData, removedQuery );
|
||||||
|
|
||||||
|
@ -99,8 +99,7 @@ public final class OneAuditEntityQueryGenerator extends AbstractRelationQueryGen
|
||||||
*/
|
*/
|
||||||
private void createValidDataRestrictions(
|
private void createValidDataRestrictions(
|
||||||
GlobalConfiguration globalCfg, AuditStrategy auditStrategy,
|
GlobalConfiguration globalCfg, AuditStrategy auditStrategy,
|
||||||
MiddleIdData referencedIdData, QueryBuilder qb, Parameters rootParameters,
|
MiddleIdData referencedIdData, QueryBuilder qb, Parameters rootParameters) {
|
||||||
boolean inclusive) {
|
|
||||||
final String revisionPropertyPath = verEntCfg.getRevisionNumberPath();
|
final String revisionPropertyPath = verEntCfg.getRevisionNumberPath();
|
||||||
// (selecting e entities at revision :revision)
|
// (selecting e entities at revision :revision)
|
||||||
// --> based on auditStrategy (see above)
|
// --> based on auditStrategy (see above)
|
||||||
|
@ -108,7 +107,7 @@ public final class OneAuditEntityQueryGenerator extends AbstractRelationQueryGen
|
||||||
globalCfg, qb, rootParameters, revisionPropertyPath,
|
globalCfg, qb, rootParameters, revisionPropertyPath,
|
||||||
verEntCfg.getRevisionEndFieldName(), true, referencedIdData, revisionPropertyPath,
|
verEntCfg.getRevisionEndFieldName(), true, referencedIdData, revisionPropertyPath,
|
||||||
verEntCfg.getOriginalIdPropName(), REFERENCED_ENTITY_ALIAS, REFERENCED_ENTITY_ALIAS_DEF_AUD_STR,
|
verEntCfg.getOriginalIdPropName(), REFERENCED_ENTITY_ALIAS, REFERENCED_ENTITY_ALIAS_DEF_AUD_STR,
|
||||||
inclusive
|
true
|
||||||
);
|
);
|
||||||
// e.revision_type != DEL
|
// e.revision_type != DEL
|
||||||
rootParameters.addWhereWithNamedParam( getRevisionTypePath(), false, "!=", DEL_REVISION_TYPE_PARAMETER );
|
rootParameters.addWhereWithNamedParam( getRevisionTypePath(), false, "!=", DEL_REVISION_TYPE_PARAMETER );
|
||||||
|
@ -126,7 +125,7 @@ public final class OneAuditEntityQueryGenerator extends AbstractRelationQueryGen
|
||||||
// Restrictions to match all rows deleted at exactly given revision.
|
// Restrictions to match all rows deleted at exactly given revision.
|
||||||
final Parameters removed = disjoint.addSubParameters( "and" );
|
final Parameters removed = disjoint.addSubParameters( "and" );
|
||||||
// Excluding current revision, because we need to match data valid at the previous one.
|
// Excluding current revision, because we need to match data valid at the previous one.
|
||||||
createValidDataRestrictions( globalCfg, auditStrategy, referencedIdData, remQb, valid, false );
|
createValidDataRestrictions( globalCfg, auditStrategy, referencedIdData, remQb, valid );
|
||||||
// e.revision = :revision
|
// e.revision = :revision
|
||||||
removed.addWhereWithNamedParam( verEntCfg.getRevisionNumberPath(), false, "=", REVISION_PARAMETER );
|
removed.addWhereWithNamedParam( verEntCfg.getRevisionNumberPath(), false, "=", REVISION_PARAMETER );
|
||||||
// e.revision_type = DEL
|
// e.revision_type = DEL
|
||||||
|
|
|
@ -180,7 +180,7 @@ public final class ThreeEntityQueryGenerator extends AbstractRelationQueryGenera
|
||||||
originalIdPropertyName,
|
originalIdPropertyName,
|
||||||
REFERENCED_ENTITY_ALIAS,
|
REFERENCED_ENTITY_ALIAS,
|
||||||
REFERENCED_ENTITY_ALIAS_DEF_AUD_STR,
|
REFERENCED_ENTITY_ALIAS_DEF_AUD_STR,
|
||||||
inclusive
|
true
|
||||||
);
|
);
|
||||||
// (selecting f entities at revision :revision)
|
// (selecting f entities at revision :revision)
|
||||||
// --> based on auditStrategy (see above)
|
// --> based on auditStrategy (see above)
|
||||||
|
@ -188,15 +188,15 @@ public final class ThreeEntityQueryGenerator extends AbstractRelationQueryGenera
|
||||||
globalCfg,
|
globalCfg,
|
||||||
qb,
|
qb,
|
||||||
rootParameters,
|
rootParameters,
|
||||||
REFERENCED_ENTITY_ALIAS + "." + revisionPropertyPath,
|
INDEX_ENTITY_ALIAS + "." + revisionPropertyPath,
|
||||||
REFERENCED_ENTITY_ALIAS + "." + verEntCfg.getRevisionEndFieldName(),
|
INDEX_ENTITY_ALIAS + "." + verEntCfg.getRevisionEndFieldName(),
|
||||||
false,
|
false,
|
||||||
referencedIdData,
|
referencedIdData,
|
||||||
revisionPropertyPath,
|
revisionPropertyPath,
|
||||||
originalIdPropertyName,
|
originalIdPropertyName,
|
||||||
INDEX_ENTITY_ALIAS,
|
INDEX_ENTITY_ALIAS,
|
||||||
INDEX_ENTITY_ALIAS_DEF_AUD_STR,
|
INDEX_ENTITY_ALIAS_DEF_AUD_STR,
|
||||||
inclusive
|
true
|
||||||
);
|
);
|
||||||
// (with ee association at revision :revision)
|
// (with ee association at revision :revision)
|
||||||
// --> based on auditStrategy (see above)
|
// --> based on auditStrategy (see above)
|
||||||
|
|
|
@ -152,7 +152,7 @@ public final class TwoEntityQueryGenerator extends AbstractRelationQueryGenerato
|
||||||
originalIdPropertyName,
|
originalIdPropertyName,
|
||||||
REFERENCED_ENTITY_ALIAS,
|
REFERENCED_ENTITY_ALIAS,
|
||||||
REFERENCED_ENTITY_ALIAS_DEF_AUD_STR,
|
REFERENCED_ENTITY_ALIAS_DEF_AUD_STR,
|
||||||
inclusive
|
true
|
||||||
);
|
);
|
||||||
// (with ee association at revision :revision)
|
// (with ee association at revision :revision)
|
||||||
// --> based on auditStrategy (see above)
|
// --> based on auditStrategy (see above)
|
||||||
|
|
|
@ -98,8 +98,15 @@ public class ValidityAuditStrategy implements AuditStrategy {
|
||||||
session.save( auditedEntityName, data );
|
session.save( auditedEntityName, data );
|
||||||
sessionCacheCleaner.scheduleAuditDataRemoval( session, data );
|
sessionCacheCleaner.scheduleAuditDataRemoval( session, data );
|
||||||
|
|
||||||
// Update the end date of the previous row if this operation is expected to have a previous row
|
// Update the end date of the previous row.
|
||||||
if ( getRevisionType( auditCfg, data ) != RevisionType.ADD ) {
|
//
|
||||||
|
// When application reuses identifiers of previously removed entities:
|
||||||
|
// The UPDATE statement will no-op if an entity with a given identifier has been
|
||||||
|
// inserted for the first time. But in case a deleted primary key value was
|
||||||
|
// reused, this guarantees correct strategy behavior: exactly one row with
|
||||||
|
// null end date exists for each identifier.
|
||||||
|
final boolean reuseEntityIdentifier = auditCfg.getGlobalCfg().isAllowIdentifierReuse();
|
||||||
|
if ( reuseEntityIdentifier || getRevisionType( auditCfg, data ) != RevisionType.ADD ) {
|
||||||
final Queryable productionEntityQueryable = getQueryable( entityName, sessionImplementor );
|
final Queryable productionEntityQueryable = getQueryable( entityName, sessionImplementor );
|
||||||
final Queryable rootProductionEntityQueryable = getQueryable(
|
final Queryable rootProductionEntityQueryable = getQueryable(
|
||||||
productionEntityQueryable.getRootEntityName(),
|
productionEntityQueryable.getRootEntityName(),
|
||||||
|
@ -238,7 +245,7 @@ public class ValidityAuditStrategy implements AuditStrategy {
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
if ( rowCount != 1 ) {
|
if ( rowCount != 1 && ( !reuseEntityIdentifier || ( getRevisionType( auditCfg, data ) != RevisionType.ADD ) ) ) {
|
||||||
throw new RuntimeException(
|
throw new RuntimeException(
|
||||||
"Cannot update previous revision for entity " + auditedEntityName + " and id " + id
|
"Cannot update previous revision for entity " + auditedEntityName + " and id " + id
|
||||||
);
|
);
|
||||||
|
|
|
@ -58,9 +58,9 @@ public class CollectionRefIngEntity implements Serializable {
|
||||||
this.reference = reference;
|
this.reference = reference;
|
||||||
}
|
}
|
||||||
|
|
||||||
public CollectionRefIngEntity(String data, CollectionRefEdEntity reference) {
|
public CollectionRefIngEntity(Integer id, String data) {
|
||||||
|
this.id = id;
|
||||||
this.data = data;
|
this.data = data;
|
||||||
this.reference = reference;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Integer getId() {
|
public Integer getId() {
|
||||||
|
|
|
@ -106,7 +106,6 @@ public class NotOwnedBidirectional extends BaseEnversJPAFunctionalTestCase {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testHistoryOfPersonalContact() {
|
public void testHistoryOfPersonalContact() {
|
||||||
System.out.println( getAuditReader().find( PersonalContact.class, pc_id, 1 ).getAddresses() );
|
|
||||||
assert getAuditReader().find( PersonalContact.class, pc_id, 1 ).getAddresses().equals(
|
assert getAuditReader().find( PersonalContact.class, pc_id, 1 ).getAddresses().equals(
|
||||||
TestTools.makeSet( new Address( a1_id, "a1" ) )
|
TestTools.makeSet( new Address( a1_id, "a1" ) )
|
||||||
);
|
);
|
||||||
|
|
|
@ -106,7 +106,6 @@ public class NotOwnedBidirectional extends BaseEnversJPAFunctionalTestCase {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testHistoryOfPersonalContact() {
|
public void testHistoryOfPersonalContact() {
|
||||||
System.out.println( getAuditReader().find( PersonalContact.class, pc_id, 1 ).getAddresses() );
|
|
||||||
assert getAuditReader().find( PersonalContact.class, pc_id, 1 ).getAddresses().equals(
|
assert getAuditReader().find( PersonalContact.class, pc_id, 1 ).getAddresses().equals(
|
||||||
TestTools.makeSet( new Address( a1_id, "a1" ) )
|
TestTools.makeSet( new Address( a1_id, "a1" ) )
|
||||||
);
|
);
|
||||||
|
|
|
@ -156,10 +156,10 @@ public class BasicList extends BaseEnversJPAFunctionalTestCase {
|
||||||
ListOwnedEntity rev5 = getAuditReader().find( ListOwnedEntity.class, ed1_id, 5 );
|
ListOwnedEntity rev5 = getAuditReader().find( ListOwnedEntity.class, ed1_id, 5 );
|
||||||
|
|
||||||
assert rev1.getReferencing().equals( Collections.EMPTY_LIST );
|
assert rev1.getReferencing().equals( Collections.EMPTY_LIST );
|
||||||
assert TestTools.checkList( rev2.getReferencing(), ing1, ing2 );
|
assert TestTools.checkCollection( rev2.getReferencing(), ing1, ing2 );
|
||||||
assert TestTools.checkList( rev3.getReferencing(), ing1, ing2 );
|
assert TestTools.checkCollection( rev3.getReferencing(), ing1, ing2 );
|
||||||
assert TestTools.checkList( rev4.getReferencing(), ing2 );
|
assert TestTools.checkCollection( rev4.getReferencing(), ing2 );
|
||||||
assert TestTools.checkList( rev5.getReferencing(), ing2 );
|
assert TestTools.checkCollection( rev5.getReferencing(), ing2 );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -174,10 +174,10 @@ public class BasicList extends BaseEnversJPAFunctionalTestCase {
|
||||||
ListOwnedEntity rev5 = getAuditReader().find( ListOwnedEntity.class, ed2_id, 5 );
|
ListOwnedEntity rev5 = getAuditReader().find( ListOwnedEntity.class, ed2_id, 5 );
|
||||||
|
|
||||||
assert rev1.getReferencing().equals( Collections.EMPTY_LIST );
|
assert rev1.getReferencing().equals( Collections.EMPTY_LIST );
|
||||||
assert TestTools.checkList( rev2.getReferencing(), ing2 );
|
assert TestTools.checkCollection( rev2.getReferencing(), ing2 );
|
||||||
assert TestTools.checkList( rev3.getReferencing(), ing1, ing2 );
|
assert TestTools.checkCollection( rev3.getReferencing(), ing1, ing2 );
|
||||||
assert TestTools.checkList( rev4.getReferencing(), ing1, ing2 );
|
assert TestTools.checkCollection( rev4.getReferencing(), ing1, ing2 );
|
||||||
assert TestTools.checkList( rev5.getReferencing(), ing2 );
|
assert TestTools.checkCollection( rev5.getReferencing(), ing2 );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -192,9 +192,9 @@ public class BasicList extends BaseEnversJPAFunctionalTestCase {
|
||||||
ListOwningEntity rev5 = getAuditReader().find( ListOwningEntity.class, ing1_id, 5 );
|
ListOwningEntity rev5 = getAuditReader().find( ListOwningEntity.class, ing1_id, 5 );
|
||||||
|
|
||||||
assert rev1.getReferences().equals( Collections.EMPTY_LIST );
|
assert rev1.getReferences().equals( Collections.EMPTY_LIST );
|
||||||
assert TestTools.checkList( rev2.getReferences(), ed1 );
|
assert TestTools.checkCollection( rev2.getReferences(), ed1 );
|
||||||
assert TestTools.checkList( rev3.getReferences(), ed1, ed2 );
|
assert TestTools.checkCollection( rev3.getReferences(), ed1, ed2 );
|
||||||
assert TestTools.checkList( rev4.getReferences(), ed2 );
|
assert TestTools.checkCollection( rev4.getReferences(), ed2 );
|
||||||
assert rev5.getReferences().equals( Collections.EMPTY_LIST );
|
assert rev5.getReferences().equals( Collections.EMPTY_LIST );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -210,9 +210,9 @@ public class BasicList extends BaseEnversJPAFunctionalTestCase {
|
||||||
ListOwningEntity rev5 = getAuditReader().find( ListOwningEntity.class, ing2_id, 5 );
|
ListOwningEntity rev5 = getAuditReader().find( ListOwningEntity.class, ing2_id, 5 );
|
||||||
|
|
||||||
assert rev1.getReferences().equals( Collections.EMPTY_LIST );
|
assert rev1.getReferences().equals( Collections.EMPTY_LIST );
|
||||||
assert TestTools.checkList( rev2.getReferences(), ed1, ed2 );
|
assert TestTools.checkCollection( rev2.getReferences(), ed1, ed2 );
|
||||||
assert TestTools.checkList( rev3.getReferences(), ed1, ed2 );
|
assert TestTools.checkCollection( rev3.getReferences(), ed1, ed2 );
|
||||||
assert TestTools.checkList( rev4.getReferences(), ed1, ed2 );
|
assert TestTools.checkCollection( rev4.getReferences(), ed1, ed2 );
|
||||||
assert TestTools.checkList( rev5.getReferences(), ed1, ed2 );
|
assert TestTools.checkCollection( rev5.getReferences(), ed1, ed2 );
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -150,16 +150,16 @@ public class BasicWhereJoinTable extends BaseEnversJPAFunctionalTestCase {
|
||||||
WhereJoinTableEntity rev4 = getAuditReader().find( WhereJoinTableEntity.class, wjte1_id, 4 );
|
WhereJoinTableEntity rev4 = getAuditReader().find( WhereJoinTableEntity.class, wjte1_id, 4 );
|
||||||
|
|
||||||
// Checking 1st list
|
// Checking 1st list
|
||||||
assert TestTools.checkList( rev1.getReferences1() );
|
assert TestTools.checkCollection( rev1.getReferences1() );
|
||||||
assert TestTools.checkList( rev2.getReferences1(), ite1_1 );
|
assert TestTools.checkCollection( rev2.getReferences1(), ite1_1 );
|
||||||
assert TestTools.checkList( rev3.getReferences1(), ite1_1 );
|
assert TestTools.checkCollection( rev3.getReferences1(), ite1_1 );
|
||||||
assert TestTools.checkList( rev4.getReferences1() );
|
assert TestTools.checkCollection( rev4.getReferences1() );
|
||||||
|
|
||||||
// Checking 2nd list
|
// Checking 2nd list
|
||||||
assert TestTools.checkList( rev1.getReferences2() );
|
assert TestTools.checkCollection( rev1.getReferences2() );
|
||||||
assert TestTools.checkList( rev2.getReferences2(), ite2_1 );
|
assert TestTools.checkCollection( rev2.getReferences2(), ite2_1 );
|
||||||
assert TestTools.checkList( rev3.getReferences2(), ite2_1 );
|
assert TestTools.checkCollection( rev3.getReferences2(), ite2_1 );
|
||||||
assert TestTools.checkList( rev4.getReferences2(), ite2_1 );
|
assert TestTools.checkCollection( rev4.getReferences2(), ite2_1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -174,15 +174,15 @@ public class BasicWhereJoinTable extends BaseEnversJPAFunctionalTestCase {
|
||||||
WhereJoinTableEntity rev4 = getAuditReader().find( WhereJoinTableEntity.class, wjte2_id, 4 );
|
WhereJoinTableEntity rev4 = getAuditReader().find( WhereJoinTableEntity.class, wjte2_id, 4 );
|
||||||
|
|
||||||
// Checking 1st list
|
// Checking 1st list
|
||||||
assert TestTools.checkList( rev1.getReferences1() );
|
assert TestTools.checkCollection( rev1.getReferences1() );
|
||||||
assert TestTools.checkList( rev2.getReferences1() );
|
assert TestTools.checkCollection( rev2.getReferences1() );
|
||||||
assert TestTools.checkList( rev3.getReferences1(), ite1_1, ite1_2 );
|
assert TestTools.checkCollection( rev3.getReferences1(), ite1_1, ite1_2 );
|
||||||
assert TestTools.checkList( rev4.getReferences1(), ite1_1, ite1_2 );
|
assert TestTools.checkCollection( rev4.getReferences1(), ite1_1, ite1_2 );
|
||||||
|
|
||||||
// Checking 2nd list
|
// Checking 2nd list
|
||||||
assert TestTools.checkList( rev1.getReferences2() );
|
assert TestTools.checkCollection( rev1.getReferences2() );
|
||||||
assert TestTools.checkList( rev2.getReferences2() );
|
assert TestTools.checkCollection( rev2.getReferences2() );
|
||||||
assert TestTools.checkList( rev3.getReferences2() );
|
assert TestTools.checkCollection( rev3.getReferences2() );
|
||||||
assert TestTools.checkList( rev4.getReferences2(), ite2_2 );
|
assert TestTools.checkCollection( rev4.getReferences2(), ite2_2 );
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -163,11 +163,11 @@ public class BasicBiowned extends BaseEnversJPAFunctionalTestCase {
|
||||||
ListBiowning1Entity rev4 = getAuditReader().find( ListBiowning1Entity.class, o1_1_id, 4 );
|
ListBiowning1Entity rev4 = getAuditReader().find( ListBiowning1Entity.class, o1_1_id, 4 );
|
||||||
ListBiowning1Entity rev5 = getAuditReader().find( ListBiowning1Entity.class, o1_1_id, 5 );
|
ListBiowning1Entity rev5 = getAuditReader().find( ListBiowning1Entity.class, o1_1_id, 5 );
|
||||||
|
|
||||||
assert TestTools.checkList( rev1.getReferences() );
|
assert TestTools.checkCollection( rev1.getReferences() );
|
||||||
assert TestTools.checkList( rev2.getReferences(), o2_1 );
|
assert TestTools.checkCollection( rev2.getReferences(), o2_1 );
|
||||||
assert TestTools.checkList( rev3.getReferences(), o2_1, o2_2 );
|
assert TestTools.checkCollection( rev3.getReferences(), o2_1, o2_2 );
|
||||||
assert TestTools.checkList( rev4.getReferences() );
|
assert TestTools.checkCollection( rev4.getReferences() );
|
||||||
assert TestTools.checkList( rev5.getReferences(), o2_2 );
|
assert TestTools.checkCollection( rev5.getReferences(), o2_2 );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -181,12 +181,11 @@ public class BasicBiowned extends BaseEnversJPAFunctionalTestCase {
|
||||||
ListBiowning1Entity rev4 = getAuditReader().find( ListBiowning1Entity.class, o1_2_id, 4 );
|
ListBiowning1Entity rev4 = getAuditReader().find( ListBiowning1Entity.class, o1_2_id, 4 );
|
||||||
ListBiowning1Entity rev5 = getAuditReader().find( ListBiowning1Entity.class, o1_2_id, 5 );
|
ListBiowning1Entity rev5 = getAuditReader().find( ListBiowning1Entity.class, o1_2_id, 5 );
|
||||||
|
|
||||||
assert TestTools.checkList( rev1.getReferences() );
|
assert TestTools.checkCollection( rev1.getReferences() );
|
||||||
assert TestTools.checkList( rev2.getReferences(), o2_2 );
|
assert TestTools.checkCollection( rev2.getReferences(), o2_2 );
|
||||||
assert TestTools.checkList( rev3.getReferences(), o2_2 );
|
assert TestTools.checkCollection( rev3.getReferences(), o2_2 );
|
||||||
assert TestTools.checkList( rev4.getReferences(), o2_1, o2_2 );
|
assert TestTools.checkCollection( rev4.getReferences(), o2_1, o2_2 );
|
||||||
System.out.println( "rev5.getReferences() = " + rev5.getReferences() );
|
assert TestTools.checkCollection( rev5.getReferences(), o2_2 );
|
||||||
assert TestTools.checkList( rev5.getReferences(), o2_2 );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -200,11 +199,11 @@ public class BasicBiowned extends BaseEnversJPAFunctionalTestCase {
|
||||||
ListBiowning2Entity rev4 = getAuditReader().find( ListBiowning2Entity.class, o2_1_id, 4 );
|
ListBiowning2Entity rev4 = getAuditReader().find( ListBiowning2Entity.class, o2_1_id, 4 );
|
||||||
ListBiowning2Entity rev5 = getAuditReader().find( ListBiowning2Entity.class, o2_1_id, 5 );
|
ListBiowning2Entity rev5 = getAuditReader().find( ListBiowning2Entity.class, o2_1_id, 5 );
|
||||||
|
|
||||||
assert TestTools.checkList( rev1.getReferences() );
|
assert TestTools.checkCollection( rev1.getReferences() );
|
||||||
assert TestTools.checkList( rev2.getReferences(), o1_1 );
|
assert TestTools.checkCollection( rev2.getReferences(), o1_1 );
|
||||||
assert TestTools.checkList( rev3.getReferences(), o1_1 );
|
assert TestTools.checkCollection( rev3.getReferences(), o1_1 );
|
||||||
assert TestTools.checkList( rev4.getReferences(), o1_2 );
|
assert TestTools.checkCollection( rev4.getReferences(), o1_2 );
|
||||||
assert TestTools.checkList( rev5.getReferences() );
|
assert TestTools.checkCollection( rev5.getReferences() );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -218,10 +217,10 @@ public class BasicBiowned extends BaseEnversJPAFunctionalTestCase {
|
||||||
ListBiowning2Entity rev4 = getAuditReader().find( ListBiowning2Entity.class, o2_2_id, 4 );
|
ListBiowning2Entity rev4 = getAuditReader().find( ListBiowning2Entity.class, o2_2_id, 4 );
|
||||||
ListBiowning2Entity rev5 = getAuditReader().find( ListBiowning2Entity.class, o2_2_id, 5 );
|
ListBiowning2Entity rev5 = getAuditReader().find( ListBiowning2Entity.class, o2_2_id, 5 );
|
||||||
|
|
||||||
assert TestTools.checkList( rev1.getReferences() );
|
assert TestTools.checkCollection( rev1.getReferences() );
|
||||||
assert TestTools.checkList( rev2.getReferences(), o1_2 );
|
assert TestTools.checkCollection( rev2.getReferences(), o1_2 );
|
||||||
assert TestTools.checkList( rev3.getReferences(), o1_1, o1_2 );
|
assert TestTools.checkCollection( rev3.getReferences(), o1_1, o1_2 );
|
||||||
assert TestTools.checkList( rev4.getReferences(), o1_2 );
|
assert TestTools.checkCollection( rev4.getReferences(), o1_2 );
|
||||||
assert TestTools.checkList( rev5.getReferences(), o1_1, o1_2 );
|
assert TestTools.checkCollection( rev5.getReferences(), o1_1, o1_2 );
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -199,17 +199,17 @@ public class BasicSametable extends BaseEnversJPAFunctionalTestCase {
|
||||||
ParentEntity rev4 = getAuditReader().find( ParentEntity.class, p1_id, 4 );
|
ParentEntity rev4 = getAuditReader().find( ParentEntity.class, p1_id, 4 );
|
||||||
ParentEntity rev5 = getAuditReader().find( ParentEntity.class, p1_id, 5 );
|
ParentEntity rev5 = getAuditReader().find( ParentEntity.class, p1_id, 5 );
|
||||||
|
|
||||||
assert TestTools.checkList( rev1.getChildren1() );
|
assert TestTools.checkCollection( rev1.getChildren1() );
|
||||||
assert TestTools.checkList( rev2.getChildren1(), c1_1 );
|
assert TestTools.checkCollection( rev2.getChildren1(), c1_1 );
|
||||||
assert TestTools.checkList( rev3.getChildren1(), c1_1, c1_2 );
|
assert TestTools.checkCollection( rev3.getChildren1(), c1_1, c1_2 );
|
||||||
assert TestTools.checkList( rev4.getChildren1(), c1_2 );
|
assert TestTools.checkCollection( rev4.getChildren1(), c1_2 );
|
||||||
assert TestTools.checkList( rev5.getChildren1() );
|
assert TestTools.checkCollection( rev5.getChildren1() );
|
||||||
|
|
||||||
assert TestTools.checkList( rev1.getChildren2() );
|
assert TestTools.checkCollection( rev1.getChildren2() );
|
||||||
assert TestTools.checkList( rev2.getChildren2() );
|
assert TestTools.checkCollection( rev2.getChildren2() );
|
||||||
assert TestTools.checkList( rev3.getChildren2(), c2_2 );
|
assert TestTools.checkCollection( rev3.getChildren2(), c2_2 );
|
||||||
assert TestTools.checkList( rev4.getChildren2(), c2_2 );
|
assert TestTools.checkCollection( rev4.getChildren2(), c2_2 );
|
||||||
assert TestTools.checkList( rev5.getChildren2(), c2_2 );
|
assert TestTools.checkCollection( rev5.getChildren2(), c2_2 );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -224,17 +224,17 @@ public class BasicSametable extends BaseEnversJPAFunctionalTestCase {
|
||||||
ParentEntity rev4 = getAuditReader().find( ParentEntity.class, p2_id, 4 );
|
ParentEntity rev4 = getAuditReader().find( ParentEntity.class, p2_id, 4 );
|
||||||
ParentEntity rev5 = getAuditReader().find( ParentEntity.class, p2_id, 5 );
|
ParentEntity rev5 = getAuditReader().find( ParentEntity.class, p2_id, 5 );
|
||||||
|
|
||||||
assert TestTools.checkList( rev1.getChildren1() );
|
assert TestTools.checkCollection( rev1.getChildren1() );
|
||||||
assert TestTools.checkList( rev2.getChildren1() );
|
assert TestTools.checkCollection( rev2.getChildren1() );
|
||||||
assert TestTools.checkList( rev3.getChildren1(), c1_1 );
|
assert TestTools.checkCollection( rev3.getChildren1(), c1_1 );
|
||||||
assert TestTools.checkList( rev4.getChildren1(), c1_1 );
|
assert TestTools.checkCollection( rev4.getChildren1(), c1_1 );
|
||||||
assert TestTools.checkList( rev5.getChildren1(), c1_1 );
|
assert TestTools.checkCollection( rev5.getChildren1(), c1_1 );
|
||||||
|
|
||||||
assert TestTools.checkList( rev1.getChildren2() );
|
assert TestTools.checkCollection( rev1.getChildren2() );
|
||||||
assert TestTools.checkList( rev2.getChildren2(), c2_1 );
|
assert TestTools.checkCollection( rev2.getChildren2(), c2_1 );
|
||||||
assert TestTools.checkList( rev3.getChildren2(), c2_1 );
|
assert TestTools.checkCollection( rev3.getChildren2(), c2_1 );
|
||||||
assert TestTools.checkList( rev4.getChildren2(), c2_1, c2_2 );
|
assert TestTools.checkCollection( rev4.getChildren2(), c2_1, c2_2 );
|
||||||
assert TestTools.checkList( rev5.getChildren2(), c2_1 );
|
assert TestTools.checkCollection( rev5.getChildren2(), c2_1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -248,11 +248,11 @@ public class BasicSametable extends BaseEnversJPAFunctionalTestCase {
|
||||||
Child1Entity rev4 = getAuditReader().find( Child1Entity.class, c1_1_id, 4 );
|
Child1Entity rev4 = getAuditReader().find( Child1Entity.class, c1_1_id, 4 );
|
||||||
Child1Entity rev5 = getAuditReader().find( Child1Entity.class, c1_1_id, 5 );
|
Child1Entity rev5 = getAuditReader().find( Child1Entity.class, c1_1_id, 5 );
|
||||||
|
|
||||||
assert TestTools.checkList( rev1.getParents() );
|
assert TestTools.checkCollection( rev1.getParents() );
|
||||||
assert TestTools.checkList( rev2.getParents(), p1 );
|
assert TestTools.checkCollection( rev2.getParents(), p1 );
|
||||||
assert TestTools.checkList( rev3.getParents(), p1, p2 );
|
assert TestTools.checkCollection( rev3.getParents(), p1, p2 );
|
||||||
assert TestTools.checkList( rev4.getParents(), p2 );
|
assert TestTools.checkCollection( rev4.getParents(), p2 );
|
||||||
assert TestTools.checkList( rev5.getParents(), p2 );
|
assert TestTools.checkCollection( rev5.getParents(), p2 );
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: was disabled?
|
// TODO: was disabled?
|
||||||
|
@ -266,11 +266,11 @@ public class BasicSametable extends BaseEnversJPAFunctionalTestCase {
|
||||||
Child1Entity rev4 = getAuditReader().find( Child1Entity.class, c1_2_id, 4 );
|
Child1Entity rev4 = getAuditReader().find( Child1Entity.class, c1_2_id, 4 );
|
||||||
Child1Entity rev5 = getAuditReader().find( Child1Entity.class, c1_2_id, 5 );
|
Child1Entity rev5 = getAuditReader().find( Child1Entity.class, c1_2_id, 5 );
|
||||||
|
|
||||||
assert TestTools.checkList( rev1.getParents() );
|
assert TestTools.checkCollection( rev1.getParents() );
|
||||||
assert TestTools.checkList( rev2.getParents() );
|
assert TestTools.checkCollection( rev2.getParents() );
|
||||||
assert TestTools.checkList( rev3.getParents(), p1 );
|
assert TestTools.checkCollection( rev3.getParents(), p1 );
|
||||||
assert TestTools.checkList( rev4.getParents(), p1 );
|
assert TestTools.checkCollection( rev4.getParents(), p1 );
|
||||||
assert TestTools.checkList( rev5.getParents() );
|
assert TestTools.checkCollection( rev5.getParents() );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -283,11 +283,11 @@ public class BasicSametable extends BaseEnversJPAFunctionalTestCase {
|
||||||
Child2Entity rev4 = getAuditReader().find( Child2Entity.class, c2_1_id, 4 );
|
Child2Entity rev4 = getAuditReader().find( Child2Entity.class, c2_1_id, 4 );
|
||||||
Child2Entity rev5 = getAuditReader().find( Child2Entity.class, c2_1_id, 5 );
|
Child2Entity rev5 = getAuditReader().find( Child2Entity.class, c2_1_id, 5 );
|
||||||
|
|
||||||
assert TestTools.checkList( rev1.getParents() );
|
assert TestTools.checkCollection( rev1.getParents() );
|
||||||
assert TestTools.checkList( rev2.getParents(), p2 );
|
assert TestTools.checkCollection( rev2.getParents(), p2 );
|
||||||
assert TestTools.checkList( rev3.getParents(), p2 );
|
assert TestTools.checkCollection( rev3.getParents(), p2 );
|
||||||
assert TestTools.checkList( rev4.getParents(), p2 );
|
assert TestTools.checkCollection( rev4.getParents(), p2 );
|
||||||
assert TestTools.checkList( rev5.getParents(), p2 );
|
assert TestTools.checkCollection( rev5.getParents(), p2 );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -301,10 +301,10 @@ public class BasicSametable extends BaseEnversJPAFunctionalTestCase {
|
||||||
Child2Entity rev4 = getAuditReader().find( Child2Entity.class, c2_2_id, 4 );
|
Child2Entity rev4 = getAuditReader().find( Child2Entity.class, c2_2_id, 4 );
|
||||||
Child2Entity rev5 = getAuditReader().find( Child2Entity.class, c2_2_id, 5 );
|
Child2Entity rev5 = getAuditReader().find( Child2Entity.class, c2_2_id, 5 );
|
||||||
|
|
||||||
assert TestTools.checkList( rev1.getParents() );
|
assert TestTools.checkCollection( rev1.getParents() );
|
||||||
assert TestTools.checkList( rev2.getParents() );
|
assert TestTools.checkCollection( rev2.getParents() );
|
||||||
assert TestTools.checkList( rev3.getParents(), p1 );
|
assert TestTools.checkCollection( rev3.getParents(), p1 );
|
||||||
assert TestTools.checkList( rev4.getParents(), p1, p2 );
|
assert TestTools.checkCollection( rev4.getParents(), p1, p2 );
|
||||||
assert TestTools.checkList( rev5.getParents(), p1 );
|
assert TestTools.checkCollection( rev5.getParents(), p1 );
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -151,9 +151,9 @@ public class BasicUniList extends BaseEnversJPAFunctionalTestCase {
|
||||||
ListUniEntity rev5 = getAuditReader().find( ListUniEntity.class, ing1_id, 5 );
|
ListUniEntity rev5 = getAuditReader().find( ListUniEntity.class, ing1_id, 5 );
|
||||||
|
|
||||||
assert rev1.getReferences().equals( Collections.EMPTY_LIST );
|
assert rev1.getReferences().equals( Collections.EMPTY_LIST );
|
||||||
assert TestTools.checkList( rev2.getReferences(), ed1 );
|
assert TestTools.checkCollection( rev2.getReferences(), ed1 );
|
||||||
assert TestTools.checkList( rev3.getReferences(), ed1, ed2 );
|
assert TestTools.checkCollection( rev3.getReferences(), ed1, ed2 );
|
||||||
assert TestTools.checkList( rev4.getReferences(), ed2 );
|
assert TestTools.checkCollection( rev4.getReferences(), ed2 );
|
||||||
assert rev5.getReferences().equals( Collections.EMPTY_LIST );
|
assert rev5.getReferences().equals( Collections.EMPTY_LIST );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -169,9 +169,9 @@ public class BasicUniList extends BaseEnversJPAFunctionalTestCase {
|
||||||
ListUniEntity rev5 = getAuditReader().find( ListUniEntity.class, ing2_id, 5 );
|
ListUniEntity rev5 = getAuditReader().find( ListUniEntity.class, ing2_id, 5 );
|
||||||
|
|
||||||
assert rev1.getReferences().equals( Collections.EMPTY_LIST );
|
assert rev1.getReferences().equals( Collections.EMPTY_LIST );
|
||||||
assert TestTools.checkList( rev2.getReferences(), ed1, ed2 );
|
assert TestTools.checkCollection( rev2.getReferences(), ed1, ed2 );
|
||||||
assert TestTools.checkList( rev3.getReferences(), ed1, ed2 );
|
assert TestTools.checkCollection( rev3.getReferences(), ed1, ed2 );
|
||||||
assert TestTools.checkList( rev4.getReferences(), ed1, ed2 );
|
assert TestTools.checkCollection( rev4.getReferences(), ed1, ed2 );
|
||||||
assert TestTools.checkList( rev5.getReferences(), ed1, ed2 );
|
assert TestTools.checkCollection( rev5.getReferences(), ed1, ed2 );
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -11,7 +11,7 @@ import org.hibernate.envers.test.entities.manytomany.unidirectional.M2MIndexedLi
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import static org.hibernate.envers.test.tools.TestTools.checkList;
|
import static org.hibernate.envers.test.tools.TestTools.checkCollection;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertNull;
|
import static org.junit.Assert.assertNull;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
|
@ -114,9 +114,9 @@ public class M2MIndexedListNotAuditedTarget extends BaseEnversJPAFunctionalTestC
|
||||||
3
|
3
|
||||||
);
|
);
|
||||||
|
|
||||||
assertTrue( checkList( rev1.getReferences(), uste1, uste2 ) );
|
assertTrue( checkCollection( rev1.getReferences(), uste1, uste2 ) );
|
||||||
assertTrue( checkList( rev2.getReferences(), uste1, uste2 ) );
|
assertTrue( checkCollection( rev2.getReferences(), uste1, uste2 ) );
|
||||||
assertTrue( checkList( rev3.getReferences(), uste2, uste1 ) );
|
assertTrue( checkCollection( rev3.getReferences(), uste2, uste1 ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -138,7 +138,7 @@ public class M2MIndexedListNotAuditedTarget extends BaseEnversJPAFunctionalTestC
|
||||||
);
|
);
|
||||||
|
|
||||||
assertNull( rev1 );
|
assertNull( rev1 );
|
||||||
assertTrue( checkList( rev2.getReferences(), uste2 ) );
|
assertTrue( checkCollection( rev2.getReferences(), uste2 ) );
|
||||||
assertTrue( checkList( rev3.getReferences(), uste2 ) );
|
assertTrue( checkCollection( rev3.getReferences(), uste2 ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,7 +35,7 @@ import org.hibernate.envers.test.entities.manytomany.unidirectional.M2MTargetNot
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import static org.hibernate.envers.test.tools.TestTools.checkList;
|
import static org.hibernate.envers.test.tools.TestTools.checkCollection;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -153,10 +153,10 @@ public class M2MRelationNotAuditedTarget extends BaseEnversJPAFunctionalTestCase
|
||||||
M2MTargetNotAuditedEntity rev3 = getAuditReader().find( M2MTargetNotAuditedEntity.class, tnae1_id, 3 );
|
M2MTargetNotAuditedEntity rev3 = getAuditReader().find( M2MTargetNotAuditedEntity.class, tnae1_id, 3 );
|
||||||
M2MTargetNotAuditedEntity rev4 = getAuditReader().find( M2MTargetNotAuditedEntity.class, tnae1_id, 4 );
|
M2MTargetNotAuditedEntity rev4 = getAuditReader().find( M2MTargetNotAuditedEntity.class, tnae1_id, 4 );
|
||||||
|
|
||||||
assertTrue( checkList( rev1.getReferences() ) );
|
assertTrue( checkCollection( rev1.getReferences() ) );
|
||||||
assertTrue( checkList( rev2.getReferences(), uste1 ) );
|
assertTrue( checkCollection( rev2.getReferences(), uste1 ) );
|
||||||
assertTrue( checkList( rev3.getReferences(), uste1 ) );
|
assertTrue( checkCollection( rev3.getReferences(), uste1 ) );
|
||||||
assertTrue( checkList( rev4.getReferences(), uste1, uste2 ) );
|
assertTrue( checkCollection( rev4.getReferences(), uste1, uste2 ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -169,9 +169,9 @@ public class M2MRelationNotAuditedTarget extends BaseEnversJPAFunctionalTestCase
|
||||||
M2MTargetNotAuditedEntity rev3 = getAuditReader().find( M2MTargetNotAuditedEntity.class, tnae2_id, 3 );
|
M2MTargetNotAuditedEntity rev3 = getAuditReader().find( M2MTargetNotAuditedEntity.class, tnae2_id, 3 );
|
||||||
M2MTargetNotAuditedEntity rev4 = getAuditReader().find( M2MTargetNotAuditedEntity.class, tnae2_id, 4 );
|
M2MTargetNotAuditedEntity rev4 = getAuditReader().find( M2MTargetNotAuditedEntity.class, tnae2_id, 4 );
|
||||||
|
|
||||||
assertTrue( checkList( rev1.getReferences(), uste1, uste2 ) );
|
assertTrue( checkCollection( rev1.getReferences(), uste1, uste2 ) );
|
||||||
assertTrue( checkList( rev2.getReferences(), uste2 ) );
|
assertTrue( checkCollection( rev2.getReferences(), uste2 ) );
|
||||||
assertTrue( checkList( rev3.getReferences() ) );
|
assertTrue( checkCollection( rev3.getReferences() ) );
|
||||||
assertTrue( checkList( rev4.getReferences(), uste1 ) );
|
assertTrue( checkCollection( rev4.getReferences(), uste1 ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -118,9 +118,9 @@ public class BasicList extends BaseEnversJPAFunctionalTestCase {
|
||||||
ListRefEdEntity rev2 = getAuditReader().find( ListRefEdEntity.class, ed1_id, 2 );
|
ListRefEdEntity rev2 = getAuditReader().find( ListRefEdEntity.class, ed1_id, 2 );
|
||||||
ListRefEdEntity rev3 = getAuditReader().find( ListRefEdEntity.class, ed1_id, 3 );
|
ListRefEdEntity rev3 = getAuditReader().find( ListRefEdEntity.class, ed1_id, 3 );
|
||||||
|
|
||||||
assert TestTools.checkList( rev1.getReffering(), ing1, ing2 );
|
assert TestTools.checkCollection( rev1.getReffering(), ing1, ing2 );
|
||||||
assert TestTools.checkList( rev2.getReffering(), ing2 );
|
assert TestTools.checkCollection( rev2.getReffering(), ing2 );
|
||||||
assert TestTools.checkList( rev3.getReffering() );
|
assert TestTools.checkCollection( rev3.getReffering() );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -132,9 +132,9 @@ public class BasicList extends BaseEnversJPAFunctionalTestCase {
|
||||||
ListRefEdEntity rev2 = getAuditReader().find( ListRefEdEntity.class, ed2_id, 2 );
|
ListRefEdEntity rev2 = getAuditReader().find( ListRefEdEntity.class, ed2_id, 2 );
|
||||||
ListRefEdEntity rev3 = getAuditReader().find( ListRefEdEntity.class, ed2_id, 3 );
|
ListRefEdEntity rev3 = getAuditReader().find( ListRefEdEntity.class, ed2_id, 3 );
|
||||||
|
|
||||||
assert TestTools.checkList( rev1.getReffering() );
|
assert TestTools.checkCollection( rev1.getReffering() );
|
||||||
assert TestTools.checkList( rev2.getReffering(), ing1 );
|
assert TestTools.checkCollection( rev2.getReffering(), ing1 );
|
||||||
assert TestTools.checkList( rev3.getReffering(), ing1, ing2 );
|
assert TestTools.checkCollection( rev3.getReffering(), ing1, ing2 );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
@ -126,10 +126,10 @@ public class BasicDetachedList extends BaseEnversJPAFunctionalTestCase {
|
||||||
ListRefCollEntity rev3 = getAuditReader().find( ListRefCollEntity.class, coll1_id, 3 );
|
ListRefCollEntity rev3 = getAuditReader().find( ListRefCollEntity.class, coll1_id, 3 );
|
||||||
ListRefCollEntity rev4 = getAuditReader().find( ListRefCollEntity.class, coll1_id, 4 );
|
ListRefCollEntity rev4 = getAuditReader().find( ListRefCollEntity.class, coll1_id, 4 );
|
||||||
|
|
||||||
assert TestTools.checkList( rev1.getCollection(), str1 );
|
assert TestTools.checkCollection( rev1.getCollection(), str1 );
|
||||||
assert TestTools.checkList( rev2.getCollection(), str1, str2 );
|
assert TestTools.checkCollection( rev2.getCollection(), str1, str2 );
|
||||||
assert TestTools.checkList( rev3.getCollection(), str2 );
|
assert TestTools.checkCollection( rev3.getCollection(), str2 );
|
||||||
assert TestTools.checkList( rev4.getCollection() );
|
assert TestTools.checkCollection( rev4.getCollection() );
|
||||||
|
|
||||||
assert "coll1".equals( rev1.getData() );
|
assert "coll1".equals( rev1.getData() );
|
||||||
assert "coll1".equals( rev2.getData() );
|
assert "coll1".equals( rev2.getData() );
|
||||||
|
|
|
@ -34,7 +34,7 @@ import org.hibernate.envers.test.entities.onetomany.detached.DoubleListJoinColum
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import static org.hibernate.envers.test.tools.TestTools.checkList;
|
import static org.hibernate.envers.test.tools.TestTools.checkCollection;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
@ -266,15 +266,15 @@ public class DoubleJoinColumnBidirectionalList extends BaseEnversJPAFunctionalTe
|
||||||
4
|
4
|
||||||
);
|
);
|
||||||
|
|
||||||
assertTrue( checkList( rev1.getReferences1(), ed1_1_fromRev1 ) );
|
assertTrue( checkCollection( rev1.getReferences1(), ed1_1_fromRev1 ) );
|
||||||
assertTrue( checkList( rev2.getReferences1(), ed1_1_fromRev1, ed1_2 ) );
|
assertTrue( checkCollection( rev2.getReferences1(), ed1_1_fromRev1, ed1_2 ) );
|
||||||
assertTrue( checkList( rev3.getReferences1(), ed1_1_fromRev3, ed1_2 ) );
|
assertTrue( checkCollection( rev3.getReferences1(), ed1_1_fromRev3, ed1_2 ) );
|
||||||
assertTrue( checkList( rev4.getReferences1() ) );
|
assertTrue( checkCollection( rev4.getReferences1() ) );
|
||||||
|
|
||||||
assertTrue( checkList( rev1.getReferences2(), ed2_1 ) );
|
assertTrue( checkCollection( rev1.getReferences2(), ed2_1 ) );
|
||||||
assertTrue( checkList( rev2.getReferences2(), ed2_1, ed2_2_fromRev1 ) );
|
assertTrue( checkCollection( rev2.getReferences2(), ed2_1, ed2_2_fromRev1 ) );
|
||||||
assertTrue( checkList( rev3.getReferences2(), ed2_1, ed2_2_fromRev3 ) );
|
assertTrue( checkCollection( rev3.getReferences2(), ed2_1, ed2_2_fromRev3 ) );
|
||||||
assertTrue( checkList( rev4.getReferences2(), ed2_2_fromRev3 ) );
|
assertTrue( checkCollection( rev4.getReferences2(), ed2_2_fromRev3 ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -319,15 +319,15 @@ public class DoubleJoinColumnBidirectionalList extends BaseEnversJPAFunctionalTe
|
||||||
4
|
4
|
||||||
);
|
);
|
||||||
|
|
||||||
assertTrue( checkList( rev1.getReferences1(), ed1_2 ) );
|
assertTrue( checkCollection( rev1.getReferences1(), ed1_2 ) );
|
||||||
assertTrue( checkList( rev2.getReferences1() ) );
|
assertTrue( checkCollection( rev2.getReferences1() ) );
|
||||||
assertTrue( checkList( rev3.getReferences1() ) );
|
assertTrue( checkCollection( rev3.getReferences1() ) );
|
||||||
assertTrue( checkList( rev4.getReferences1(), ed1_1_fromRev3, ed1_2 ) );
|
assertTrue( checkCollection( rev4.getReferences1(), ed1_1_fromRev3, ed1_2 ) );
|
||||||
|
|
||||||
assertTrue( checkList( rev1.getReferences2(), ed2_2_fromRev1 ) );
|
assertTrue( checkCollection( rev1.getReferences2(), ed2_2_fromRev1 ) );
|
||||||
assertTrue( checkList( rev2.getReferences2() ) );
|
assertTrue( checkCollection( rev2.getReferences2() ) );
|
||||||
assertTrue( checkList( rev3.getReferences2() ) );
|
assertTrue( checkCollection( rev3.getReferences2() ) );
|
||||||
assertTrue( checkList( rev4.getReferences2(), ed2_1 ) );
|
assertTrue( checkCollection( rev4.getReferences2(), ed2_1 ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
@ -33,7 +33,7 @@ import org.hibernate.envers.test.entities.onetomany.detached.ListJoinColumnBidir
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import static org.hibernate.envers.test.tools.TestTools.checkList;
|
import static org.hibernate.envers.test.tools.TestTools.checkCollection;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
@ -199,10 +199,10 @@ public class JoinColumnBidirectionalList extends BaseEnversJPAFunctionalTestCase
|
||||||
4
|
4
|
||||||
);
|
);
|
||||||
|
|
||||||
assertTrue( checkList( rev1.getReferences(), ed1_fromRev1 ) );
|
assertTrue( checkCollection( rev1.getReferences(), ed1_fromRev1 ) );
|
||||||
assertTrue( checkList( rev2.getReferences(), ed1_fromRev1, ed2 ) );
|
assertTrue( checkCollection( rev2.getReferences(), ed1_fromRev1, ed2 ) );
|
||||||
assertTrue( checkList( rev3.getReferences(), ed1_fromRev3, ed2 ) );
|
assertTrue( checkCollection( rev3.getReferences(), ed1_fromRev3, ed2 ) );
|
||||||
assertTrue( checkList( rev4.getReferences() ) );
|
assertTrue( checkCollection( rev4.getReferences() ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -237,10 +237,10 @@ public class JoinColumnBidirectionalList extends BaseEnversJPAFunctionalTestCase
|
||||||
4
|
4
|
||||||
);
|
);
|
||||||
|
|
||||||
assertTrue( checkList( rev1.getReferences(), ed2 ) );
|
assertTrue( checkCollection( rev1.getReferences(), ed2 ) );
|
||||||
assertTrue( checkList( rev2.getReferences() ) );
|
assertTrue( checkCollection( rev2.getReferences() ) );
|
||||||
assertTrue( checkList( rev3.getReferences() ) );
|
assertTrue( checkCollection( rev3.getReferences() ) );
|
||||||
assertTrue( checkList( rev4.getReferences(), ed1, ed2 ) );
|
assertTrue( checkCollection( rev4.getReferences(), ed1, ed2 ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
@ -34,7 +34,7 @@ import org.hibernate.envers.test.entities.onetomany.detached.ListJoinColumnBidir
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import static org.hibernate.envers.test.tools.TestTools.checkList;
|
import static org.hibernate.envers.test.tools.TestTools.checkCollection;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
@ -169,8 +169,8 @@ public class JoinColumnBidirectionalListWithInheritance extends BaseEnversJPAFun
|
||||||
2
|
2
|
||||||
);
|
);
|
||||||
|
|
||||||
assertTrue( checkList( rev1.getReferences(), ed1 ) );
|
assertTrue( checkCollection( rev1.getReferences(), ed1 ) );
|
||||||
assertTrue( checkList( rev2.getReferences(), ed1, ed2 ) );
|
assertTrue( checkCollection( rev2.getReferences(), ed1, ed2 ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -191,8 +191,8 @@ public class JoinColumnBidirectionalListWithInheritance extends BaseEnversJPAFun
|
||||||
2
|
2
|
||||||
);
|
);
|
||||||
|
|
||||||
assertTrue( checkList( rev1.getReferences(), ed2 ) );
|
assertTrue( checkCollection( rev1.getReferences(), ed2 ) );
|
||||||
assertTrue( checkList( rev2.getReferences() ) );
|
assertTrue( checkCollection( rev2.getReferences() ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
@ -75,17 +75,17 @@ public class HierarchyTest extends BaseEnversJPAFunctionalTestCase {
|
||||||
|
|
||||||
Node ver1 = getAuditReader().find( Node.class, parentId, 1 );
|
Node ver1 = getAuditReader().find( Node.class, parentId, 1 );
|
||||||
Assert.assertEquals( parent, ver1 );
|
Assert.assertEquals( parent, ver1 );
|
||||||
Assert.assertTrue( TestTools.checkList( ver1.getChildren(), child1, child2 ) );
|
Assert.assertTrue( TestTools.checkCollection( ver1.getChildren(), child1, child2 ) );
|
||||||
|
|
||||||
child1.setData( "child1 modified" );
|
child1.setData( "child1 modified" );
|
||||||
|
|
||||||
Node ver2 = getAuditReader().find( Node.class, parentId, 2 );
|
Node ver2 = getAuditReader().find( Node.class, parentId, 2 );
|
||||||
Assert.assertEquals( parent, ver2 );
|
Assert.assertEquals( parent, ver2 );
|
||||||
Assert.assertTrue( TestTools.checkList( ver2.getChildren(), child1, child2 ) );
|
Assert.assertTrue( TestTools.checkCollection( ver2.getChildren(), child1, child2 ) );
|
||||||
|
|
||||||
Node ver3 = getAuditReader().find( Node.class, parentId, 3 );
|
Node ver3 = getAuditReader().find( Node.class, parentId, 3 );
|
||||||
Assert.assertEquals( parent, ver3 );
|
Assert.assertEquals( parent, ver3 );
|
||||||
Assert.assertTrue( TestTools.checkList( ver3.getChildren(), child1 ) );
|
Assert.assertTrue( TestTools.checkCollection( ver3.getChildren(), child1 ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package org.hibernate.envers.test.integration.proxy;
|
package org.hibernate.envers.test.integration.proxy;
|
||||||
|
|
||||||
import javax.persistence.EntityManager;
|
import javax.persistence.EntityManager;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
@ -17,9 +18,13 @@ import org.hibernate.envers.test.entities.IntTestPrivSeqEntity;
|
||||||
import org.hibernate.envers.test.entities.StrTestPrivSeqEntity;
|
import org.hibernate.envers.test.entities.StrTestPrivSeqEntity;
|
||||||
import org.hibernate.envers.test.entities.UnversionedStrTestEntity;
|
import org.hibernate.envers.test.entities.UnversionedStrTestEntity;
|
||||||
import org.hibernate.envers.test.entities.collection.StringSetEntity;
|
import org.hibernate.envers.test.entities.collection.StringSetEntity;
|
||||||
|
import org.hibernate.envers.test.entities.manytomany.ListOwnedEntity;
|
||||||
|
import org.hibernate.envers.test.entities.manytomany.ListOwningEntity;
|
||||||
import org.hibernate.envers.test.entities.manytomany.SetOwnedEntity;
|
import org.hibernate.envers.test.entities.manytomany.SetOwnedEntity;
|
||||||
import org.hibernate.envers.test.entities.manytomany.SetOwningEntity;
|
import org.hibernate.envers.test.entities.manytomany.SetOwningEntity;
|
||||||
import org.hibernate.envers.test.entities.manytomany.unidirectional.M2MIndexedListTargetNotAuditedEntity;
|
import org.hibernate.envers.test.entities.manytomany.unidirectional.M2MIndexedListTargetNotAuditedEntity;
|
||||||
|
import org.hibernate.envers.test.entities.onetomany.CollectionRefEdEntity;
|
||||||
|
import org.hibernate.envers.test.entities.onetomany.CollectionRefIngEntity;
|
||||||
import org.hibernate.envers.test.entities.onetomany.SetRefEdEntity;
|
import org.hibernate.envers.test.entities.onetomany.SetRefEdEntity;
|
||||||
import org.hibernate.envers.test.entities.onetomany.SetRefIngEntity;
|
import org.hibernate.envers.test.entities.onetomany.SetRefIngEntity;
|
||||||
import org.hibernate.envers.test.integration.manytomany.ternary.TernaryMapEntity;
|
import org.hibernate.envers.test.integration.manytomany.ternary.TernaryMapEntity;
|
||||||
|
@ -55,7 +60,8 @@ public class RemovedObjectQueryTest extends BaseEnversJPAFunctionalTestCase {
|
||||||
return new Class<?>[] {
|
return new Class<?>[] {
|
||||||
SetRefEdEntity.class, SetRefIngEntity.class, SetOwnedEntity.class, SetOwningEntity.class,
|
SetRefEdEntity.class, SetRefIngEntity.class, SetOwnedEntity.class, SetOwningEntity.class,
|
||||||
StringSetEntity.class, UnversionedStrTestEntity.class, M2MIndexedListTargetNotAuditedEntity.class,
|
StringSetEntity.class, UnversionedStrTestEntity.class, M2MIndexedListTargetNotAuditedEntity.class,
|
||||||
TernaryMapEntity.class, StrTestPrivSeqEntity.class, IntTestPrivSeqEntity.class
|
TernaryMapEntity.class, StrTestPrivSeqEntity.class, IntTestPrivSeqEntity.class,
|
||||||
|
CollectionRefEdEntity.class, CollectionRefIngEntity.class, ListOwnedEntity.class, ListOwningEntity.class
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -212,30 +218,108 @@ public class RemovedObjectQueryTest extends BaseEnversJPAFunctionalTestCase {
|
||||||
|
|
||||||
ternaryMapId = mapEntity.getId();
|
ternaryMapId = mapEntity.getId();
|
||||||
|
|
||||||
// Revision 16 - removing ternary map
|
// Revision 16 - updating ternary map
|
||||||
|
em.getTransaction().begin();
|
||||||
|
intEntity2 = em.find( IntTestPrivSeqEntity.class, intEntity2.getId() );
|
||||||
|
intEntity2.setNumber( 3 );
|
||||||
|
intEntity2 = em.merge( intEntity2 );
|
||||||
|
stringEntity2 = em.find( StrTestPrivSeqEntity.class, stringEntity2.getId() );
|
||||||
|
stringEntity2.setStr( "Value 3" );
|
||||||
|
stringEntity2 = em.merge( stringEntity2 );
|
||||||
|
em.getTransaction().commit();
|
||||||
|
|
||||||
|
// Revision 17 - removing ternary map
|
||||||
em.getTransaction().begin();
|
em.getTransaction().begin();
|
||||||
mapEntity = em.find( TernaryMapEntity.class, mapEntity.getId() );
|
mapEntity = em.find( TernaryMapEntity.class, mapEntity.getId() );
|
||||||
em.remove( mapEntity );
|
em.remove( mapEntity );
|
||||||
em.getTransaction().commit();
|
em.getTransaction().commit();
|
||||||
|
|
||||||
|
CollectionRefEdEntity collEd1 = new CollectionRefEdEntity( 1, "data_ed_1" );
|
||||||
|
CollectionRefIngEntity collIng1 = new CollectionRefIngEntity( 2, "data_ing_1", collEd1 );
|
||||||
|
collEd1.setReffering( new ArrayList<CollectionRefIngEntity>() );
|
||||||
|
collEd1.getReffering().add( collIng1 );
|
||||||
|
|
||||||
|
// Revision 18 - testing one-to-many collection
|
||||||
|
em.getTransaction().begin();
|
||||||
|
em.persist( collEd1 );
|
||||||
|
em.persist( collIng1 );
|
||||||
|
em.getTransaction().commit();
|
||||||
|
|
||||||
|
// Revision 19
|
||||||
|
em.getTransaction().begin();
|
||||||
|
collIng1 = em.find( CollectionRefIngEntity.class, collIng1.getId() );
|
||||||
|
collIng1.setData( "modified data_ing_1" );
|
||||||
|
collIng1 = em.merge( collIng1 );
|
||||||
|
em.getTransaction().commit();
|
||||||
|
|
||||||
|
// Revision 20
|
||||||
|
em.getTransaction().begin();
|
||||||
|
collEd1 = em.find( CollectionRefEdEntity.class, collEd1.getId() );
|
||||||
|
collIng1 = em.find( CollectionRefIngEntity.class, collIng1.getId() );
|
||||||
|
em.remove( collIng1 );
|
||||||
|
em.remove( collEd1 );
|
||||||
|
em.getTransaction().commit();
|
||||||
|
|
||||||
|
ListOwnedEntity listEd1 = new ListOwnedEntity( 1, "data_ed_1" );
|
||||||
|
ListOwningEntity listIng1 = new ListOwningEntity( 2, "data_ing_1" );
|
||||||
|
listEd1.setReferencing( new ArrayList<ListOwningEntity>() );
|
||||||
|
listIng1.setReferences( new ArrayList<ListOwnedEntity>() );
|
||||||
|
listEd1.getReferencing().add( listIng1 );
|
||||||
|
listIng1.getReferences().add( listEd1 );
|
||||||
|
|
||||||
|
// Revision 21 - testing many-to-many collection
|
||||||
|
em.getTransaction().begin();
|
||||||
|
em.persist( listEd1 );
|
||||||
|
em.persist( listIng1 );
|
||||||
|
em.getTransaction().commit();
|
||||||
|
|
||||||
|
// Revision 22
|
||||||
|
em.getTransaction().begin();
|
||||||
|
listIng1 = em.find( ListOwningEntity.class, listIng1.getId() );
|
||||||
|
listIng1.setData( "modified data_ing_1" );
|
||||||
|
listIng1 = em.merge( listIng1 );
|
||||||
|
em.getTransaction().commit();
|
||||||
|
|
||||||
|
// Revision 23
|
||||||
|
em.getTransaction().begin();
|
||||||
|
listIng1 = em.find( ListOwningEntity.class, listIng1.getId() );
|
||||||
|
listEd1 = em.find( ListOwnedEntity.class, listEd1.getId() );
|
||||||
|
em.remove( listIng1 );
|
||||||
|
em.remove( listEd1 );
|
||||||
|
em.getTransaction().commit();
|
||||||
|
|
||||||
em.close();
|
em.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testTernaryMap() {
|
public void testTernaryMap() {
|
||||||
|
final TernaryMapEntity ternaryMap = new TernaryMapEntity();
|
||||||
|
ternaryMap.setId( ternaryMapId );
|
||||||
|
ternaryMap.getMap().put( intEntity1, stringEntity1 );
|
||||||
|
ternaryMap.getMap().put( new IntTestPrivSeqEntity( 2, intEntity2.getId() ) , new StrTestPrivSeqEntity( "Value 2", stringEntity2.getId() ) );
|
||||||
|
|
||||||
|
TernaryMapEntity entity = getAuditReader().find( TernaryMapEntity.class, ternaryMapId, 15 );
|
||||||
|
|
||||||
|
Assert.assertEquals( ternaryMap.getMap(), entity.getMap() );
|
||||||
|
|
||||||
|
ternaryMap.getMap().clear();
|
||||||
|
ternaryMap.getMap().put( intEntity1, stringEntity1 );
|
||||||
|
ternaryMap.getMap().put( intEntity2, stringEntity2 );
|
||||||
|
|
||||||
|
entity = getAuditReader().find( TernaryMapEntity.class, ternaryMapId, 16 );
|
||||||
|
|
||||||
|
Assert.assertEquals( ternaryMap.getMap(), entity.getMap() );
|
||||||
|
|
||||||
List queryResult = getAuditReader().createQuery().forRevisionsOfEntity( TernaryMapEntity.class, false, true )
|
List queryResult = getAuditReader().createQuery().forRevisionsOfEntity( TernaryMapEntity.class, false, true )
|
||||||
.add( AuditEntity.id().eq( ternaryMapId ) )
|
.add( AuditEntity.id().eq( ternaryMapId ) )
|
||||||
.add( AuditEntity.revisionType().eq( RevisionType.DEL ) )
|
.add( AuditEntity.revisionType().eq( RevisionType.DEL ) )
|
||||||
.getResultList();
|
.getResultList();
|
||||||
Object[] objArray = (Object[]) queryResult.get( 0 );
|
Object[] objArray = (Object[]) queryResult.get( 0 );
|
||||||
|
|
||||||
Assert.assertEquals( 16, getRevisionNumber( objArray[1] ) );
|
Assert.assertEquals( 17, getRevisionNumber( objArray[1] ) );
|
||||||
|
|
||||||
TernaryMapEntity mapEntity = (TernaryMapEntity) objArray[0];
|
entity = (TernaryMapEntity) objArray[0];
|
||||||
Assert.assertEquals(
|
Assert.assertEquals( ternaryMap.getMap(), entity.getMap() );
|
||||||
TestTools.makeMap( intEntity1, stringEntity1, intEntity2, stringEntity2 ),
|
|
||||||
mapEntity.getMap()
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -251,7 +335,7 @@ public class RemovedObjectQueryTest extends BaseEnversJPAFunctionalTestCase {
|
||||||
|
|
||||||
M2MIndexedListTargetNotAuditedEntity relationNotAuditedEntity = (M2MIndexedListTargetNotAuditedEntity) objArray[0];
|
M2MIndexedListTargetNotAuditedEntity relationNotAuditedEntity = (M2MIndexedListTargetNotAuditedEntity) objArray[0];
|
||||||
Assert.assertTrue(
|
Assert.assertTrue(
|
||||||
TestTools.checkList(
|
TestTools.checkCollection(
|
||||||
relationNotAuditedEntity.getReferences(),
|
relationNotAuditedEntity.getReferences(),
|
||||||
unversionedEntity1, unversionedEntity2
|
unversionedEntity1, unversionedEntity2
|
||||||
)
|
)
|
||||||
|
@ -274,6 +358,34 @@ public class RemovedObjectQueryTest extends BaseEnversJPAFunctionalTestCase {
|
||||||
|
|
||||||
// One to many tests.
|
// One to many tests.
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testOneToManyCollectionSemantics() {
|
||||||
|
final CollectionRefEdEntity edVer1 = new CollectionRefEdEntity( 1, "data_ed_1" );
|
||||||
|
final CollectionRefIngEntity ingVer1 = new CollectionRefIngEntity( 2, "data_ing_1" );
|
||||||
|
final CollectionRefIngEntity ingVer2 = new CollectionRefIngEntity( 2, "modified data_ing_1" );
|
||||||
|
|
||||||
|
CollectionRefEdEntity entity = getAuditReader().find( CollectionRefEdEntity.class, 1, 18 );
|
||||||
|
|
||||||
|
Assert.assertEquals( edVer1, entity );
|
||||||
|
Assert.assertTrue( TestTools.checkCollection( entity.getReffering(), ingVer1 ) );
|
||||||
|
|
||||||
|
entity = getAuditReader().find( CollectionRefEdEntity.class, 1, 19 );
|
||||||
|
|
||||||
|
Assert.assertTrue( TestTools.checkCollection( entity.getReffering(), ingVer2 ) );
|
||||||
|
|
||||||
|
List queryResult = getAuditReader().createQuery().forRevisionsOfEntity( CollectionRefEdEntity.class, false, true )
|
||||||
|
.add( AuditEntity.id().eq( 1 ) )
|
||||||
|
.add( AuditEntity.revisionType().eq( RevisionType.DEL ) )
|
||||||
|
.getResultList();
|
||||||
|
Object[] objArray = (Object[]) queryResult.get( 0 );
|
||||||
|
|
||||||
|
Assert.assertEquals( 20, getRevisionNumber( objArray[1] ) );
|
||||||
|
|
||||||
|
entity = (CollectionRefEdEntity) objArray[0];
|
||||||
|
Assert.assertEquals( "data_ed_1", entity.getData() );
|
||||||
|
Assert.assertTrue( TestTools.checkCollection( entity.getReffering(), ingVer2 ) );
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testReferencedOneToManySameRevision() {
|
public void testReferencedOneToManySameRevision() {
|
||||||
List queryResult = getAuditReader().createQuery().forRevisionsOfEntity( SetRefIngEntity.class, false, true )
|
List queryResult = getAuditReader().createQuery().forRevisionsOfEntity( SetRefIngEntity.class, false, true )
|
||||||
|
@ -360,6 +472,34 @@ public class RemovedObjectQueryTest extends BaseEnversJPAFunctionalTestCase {
|
||||||
|
|
||||||
// Many to many tests.
|
// Many to many tests.
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testManyToManyCollectionSemantics() {
|
||||||
|
final ListOwnedEntity edVer1 = new ListOwnedEntity( 1, "data_ed_1" );
|
||||||
|
final ListOwningEntity ingVer1 = new ListOwningEntity( 2, "data_ing_1" );
|
||||||
|
final ListOwningEntity ingVer2 = new ListOwningEntity( 2, "modified data_ing_1" );
|
||||||
|
|
||||||
|
ListOwnedEntity entity = getAuditReader().find( ListOwnedEntity.class, 1, 21 );
|
||||||
|
|
||||||
|
Assert.assertEquals( edVer1, entity );
|
||||||
|
Assert.assertTrue( TestTools.checkCollection( entity.getReferencing(), ingVer1 ) );
|
||||||
|
|
||||||
|
entity = getAuditReader().find( ListOwnedEntity.class, 1, 22 );
|
||||||
|
|
||||||
|
Assert.assertTrue( TestTools.checkCollection( entity.getReferencing(), ingVer2 ) );
|
||||||
|
|
||||||
|
List queryResult = getAuditReader().createQuery().forRevisionsOfEntity( ListOwnedEntity.class, false, true )
|
||||||
|
.add( AuditEntity.id().eq( 1 ) )
|
||||||
|
.add( AuditEntity.revisionType().eq( RevisionType.DEL ) )
|
||||||
|
.getResultList();
|
||||||
|
Object[] objArray = (Object[]) queryResult.get( 0 );
|
||||||
|
|
||||||
|
Assert.assertEquals( 23, getRevisionNumber( objArray[1] ) );
|
||||||
|
|
||||||
|
entity = (ListOwnedEntity) objArray[0];
|
||||||
|
Assert.assertEquals( "data_ed_1", entity.getData() );
|
||||||
|
Assert.assertTrue( TestTools.checkCollection( entity.getReferencing(), ingVer2 ) );
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testOwnedManyToManySameRevision() {
|
public void testOwnedManyToManySameRevision() {
|
||||||
List queryResult = getAuditReader().createQuery().forRevisionsOfEntity( SetOwningEntity.class, false, true )
|
List queryResult = getAuditReader().createQuery().forRevisionsOfEntity( SetOwningEntity.class, false, true )
|
||||||
|
|
|
@ -134,7 +134,7 @@ public class AggregateQuery extends BaseEnversJPAFunctionalTestCase {
|
||||||
.add( AuditEntity.id().between( 2, 3 ) )
|
.add( AuditEntity.id().between( 2, 3 ) )
|
||||||
.getResultList();
|
.getResultList();
|
||||||
Assert.assertTrue(
|
Assert.assertTrue(
|
||||||
TestTools.checkList(
|
TestTools.checkCollection(
|
||||||
list,
|
list,
|
||||||
new IntTestEntity( 10, 2 ), new IntTestEntity( 8, 3 ), new IntTestEntity( 52, 2 )
|
new IntTestEntity( 10, 2 ), new IntTestEntity( 8, 3 ), new IntTestEntity( 52, 2 )
|
||||||
)
|
)
|
||||||
|
|
|
@ -311,7 +311,7 @@ public class SimpleQuery extends BaseEnversJPAFunctionalTestCase {
|
||||||
.addProjection( AuditEntity.revisionType() ).add( AuditEntity.id().eq( id1 ) )
|
.addProjection( AuditEntity.revisionType() ).add( AuditEntity.id().eq( id1 ) )
|
||||||
.getSingleResult();
|
.getSingleResult();
|
||||||
|
|
||||||
Assert.assertTrue( TestTools.checkList( result, site1, site2, site3 ) );
|
Assert.assertTrue( TestTools.checkCollection( result, site1, site2, site3 ) );
|
||||||
Assert.assertEquals( revisionType, RevisionType.ADD );
|
Assert.assertEquals( revisionType, RevisionType.ADD );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -330,7 +330,7 @@ public class SimpleQuery extends BaseEnversJPAFunctionalTestCase {
|
||||||
.addProjection( AuditEntity.revisionType() ).add( AuditEntity.id().eq( id1 ) )
|
.addProjection( AuditEntity.revisionType() ).add( AuditEntity.id().eq( id1 ) )
|
||||||
.getSingleResult();
|
.getSingleResult();
|
||||||
|
|
||||||
Assert.assertTrue( TestTools.checkList( result, site1, site2 ) );
|
Assert.assertTrue( TestTools.checkCollection( result, site1, site2 ) );
|
||||||
Assert.assertEquals( revisionType, RevisionType.MOD );
|
Assert.assertEquals( revisionType, RevisionType.MOD );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -348,7 +348,7 @@ public class SimpleQuery extends BaseEnversJPAFunctionalTestCase {
|
||||||
.addProjection( AuditEntity.revisionType() ).add( AuditEntity.id().eq( id1 ) )
|
.addProjection( AuditEntity.revisionType() ).add( AuditEntity.id().eq( id1 ) )
|
||||||
.getSingleResult();
|
.getSingleResult();
|
||||||
|
|
||||||
Assert.assertTrue( TestTools.checkList( result, site1 ) );
|
Assert.assertTrue( TestTools.checkCollection( result, site1 ) );
|
||||||
Assert.assertEquals( revisionType, RevisionType.DEL );
|
Assert.assertEquals( revisionType, RevisionType.DEL );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -91,14 +91,14 @@ public class DefaultTrackingEntitiesTest extends BaseEnversJPAFunctionalTestCase
|
||||||
StrTestEntity ste = new StrTestEntity( "x", steId );
|
StrTestEntity ste = new StrTestEntity( "x", steId );
|
||||||
StrIntTestEntity site = new StrIntTestEntity( "y", 1, siteId );
|
StrIntTestEntity site = new StrIntTestEntity( "y", 1, siteId );
|
||||||
|
|
||||||
assert TestTools.checkList( getCrossTypeRevisionChangesReader().findEntities( 1 ), ste, site );
|
assert TestTools.checkCollection( getCrossTypeRevisionChangesReader().findEntities( 1 ), ste, site );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testTrackModifiedEntities() {
|
public void testTrackModifiedEntities() {
|
||||||
StrIntTestEntity site = new StrIntTestEntity( "y", 2, siteId );
|
StrIntTestEntity site = new StrIntTestEntity( "y", 2, siteId );
|
||||||
|
|
||||||
assert TestTools.checkList( getCrossTypeRevisionChangesReader().findEntities( 2 ), site );
|
assert TestTools.checkCollection( getCrossTypeRevisionChangesReader().findEntities( 2 ), site );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -106,7 +106,7 @@ public class DefaultTrackingEntitiesTest extends BaseEnversJPAFunctionalTestCase
|
||||||
StrTestEntity ste = new StrTestEntity( null, steId );
|
StrTestEntity ste = new StrTestEntity( null, steId );
|
||||||
StrIntTestEntity site = new StrIntTestEntity( null, null, siteId );
|
StrIntTestEntity site = new StrIntTestEntity( null, null, siteId );
|
||||||
|
|
||||||
assert TestTools.checkList( getCrossTypeRevisionChangesReader().findEntities( 3 ), site, ste );
|
assert TestTools.checkCollection( getCrossTypeRevisionChangesReader().findEntities( 3 ), site, ste );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -120,9 +120,9 @@ public class DefaultTrackingEntitiesTest extends BaseEnversJPAFunctionalTestCase
|
||||||
StrIntTestEntity site = new StrIntTestEntity( "y", 1, siteId );
|
StrIntTestEntity site = new StrIntTestEntity( "y", 1, siteId );
|
||||||
|
|
||||||
Map<RevisionType, List<Object>> result = getCrossTypeRevisionChangesReader().findEntitiesGroupByRevisionType( 1 );
|
Map<RevisionType, List<Object>> result = getCrossTypeRevisionChangesReader().findEntitiesGroupByRevisionType( 1 );
|
||||||
assert TestTools.checkList( result.get( RevisionType.ADD ), site, ste );
|
assert TestTools.checkCollection( result.get( RevisionType.ADD ), site, ste );
|
||||||
assert TestTools.checkList( result.get( RevisionType.MOD ) );
|
assert TestTools.checkCollection( result.get( RevisionType.MOD ) );
|
||||||
assert TestTools.checkList( result.get( RevisionType.DEL ) );
|
assert TestTools.checkCollection( result.get( RevisionType.DEL ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -130,9 +130,9 @@ public class DefaultTrackingEntitiesTest extends BaseEnversJPAFunctionalTestCase
|
||||||
StrIntTestEntity site = new StrIntTestEntity( "y", 2, siteId );
|
StrIntTestEntity site = new StrIntTestEntity( "y", 2, siteId );
|
||||||
|
|
||||||
Map<RevisionType, List<Object>> result = getCrossTypeRevisionChangesReader().findEntitiesGroupByRevisionType( 2 );
|
Map<RevisionType, List<Object>> result = getCrossTypeRevisionChangesReader().findEntitiesGroupByRevisionType( 2 );
|
||||||
assert TestTools.checkList( result.get( RevisionType.ADD ) );
|
assert TestTools.checkCollection( result.get( RevisionType.ADD ) );
|
||||||
assert TestTools.checkList( result.get( RevisionType.MOD ), site );
|
assert TestTools.checkCollection( result.get( RevisionType.MOD ), site );
|
||||||
assert TestTools.checkList( result.get( RevisionType.DEL ) );
|
assert TestTools.checkCollection( result.get( RevisionType.DEL ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -141,9 +141,9 @@ public class DefaultTrackingEntitiesTest extends BaseEnversJPAFunctionalTestCase
|
||||||
StrIntTestEntity site = new StrIntTestEntity( null, null, siteId );
|
StrIntTestEntity site = new StrIntTestEntity( null, null, siteId );
|
||||||
|
|
||||||
Map<RevisionType, List<Object>> result = getCrossTypeRevisionChangesReader().findEntitiesGroupByRevisionType( 3 );
|
Map<RevisionType, List<Object>> result = getCrossTypeRevisionChangesReader().findEntitiesGroupByRevisionType( 3 );
|
||||||
assert TestTools.checkList( result.get( RevisionType.ADD ) );
|
assert TestTools.checkCollection( result.get( RevisionType.ADD ) );
|
||||||
assert TestTools.checkList( result.get( RevisionType.MOD ) );
|
assert TestTools.checkCollection( result.get( RevisionType.MOD ) );
|
||||||
assert TestTools.checkList( result.get( RevisionType.DEL ), site, ste );
|
assert TestTools.checkCollection( result.get( RevisionType.DEL ), site, ste );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -151,7 +151,7 @@ public class DefaultTrackingEntitiesTest extends BaseEnversJPAFunctionalTestCase
|
||||||
StrTestEntity ste = new StrTestEntity( "x", steId );
|
StrTestEntity ste = new StrTestEntity( "x", steId );
|
||||||
StrIntTestEntity site = new StrIntTestEntity( "y", 1, siteId );
|
StrIntTestEntity site = new StrIntTestEntity( "y", 1, siteId );
|
||||||
|
|
||||||
assert TestTools.checkList(
|
assert TestTools.checkCollection(
|
||||||
getCrossTypeRevisionChangesReader().findEntities( 1, RevisionType.ADD ),
|
getCrossTypeRevisionChangesReader().findEntities( 1, RevisionType.ADD ),
|
||||||
ste,
|
ste,
|
||||||
site
|
site
|
||||||
|
@ -162,7 +162,10 @@ public class DefaultTrackingEntitiesTest extends BaseEnversJPAFunctionalTestCase
|
||||||
public void testFindChangedEntitiesByRevisionTypeMOD() {
|
public void testFindChangedEntitiesByRevisionTypeMOD() {
|
||||||
StrIntTestEntity site = new StrIntTestEntity( "y", 2, siteId );
|
StrIntTestEntity site = new StrIntTestEntity( "y", 2, siteId );
|
||||||
|
|
||||||
assert TestTools.checkList( getCrossTypeRevisionChangesReader().findEntities( 2, RevisionType.MOD ), site );
|
assert TestTools.checkCollection(
|
||||||
|
getCrossTypeRevisionChangesReader().findEntities( 2, RevisionType.MOD ),
|
||||||
|
site
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -170,7 +173,7 @@ public class DefaultTrackingEntitiesTest extends BaseEnversJPAFunctionalTestCase
|
||||||
StrTestEntity ste = new StrTestEntity( null, steId );
|
StrTestEntity ste = new StrTestEntity( null, steId );
|
||||||
StrIntTestEntity site = new StrIntTestEntity( null, null, siteId );
|
StrIntTestEntity site = new StrIntTestEntity( null, null, siteId );
|
||||||
|
|
||||||
assert TestTools.checkList(
|
assert TestTools.checkCollection(
|
||||||
getCrossTypeRevisionChangesReader().findEntities( 3, RevisionType.DEL ),
|
getCrossTypeRevisionChangesReader().findEntities( 3, RevisionType.DEL ),
|
||||||
ste,
|
ste,
|
||||||
site
|
site
|
||||||
|
|
|
@ -0,0 +1,73 @@
|
||||||
|
package org.hibernate.envers.test.integration.strategy;
|
||||||
|
|
||||||
|
import javax.persistence.EntityManager;
|
||||||
|
import javax.persistence.EntityTransaction;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.hibernate.envers.configuration.EnversSettings;
|
||||||
|
import org.hibernate.envers.test.BaseEnversJPAFunctionalTestCase;
|
||||||
|
import org.hibernate.envers.test.entities.IntNoAutoIdTestEntity;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import org.hibernate.testing.TestForIssue;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertNotNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests that reusing identifiers doesn't cause auditing misbehavior.
|
||||||
|
*
|
||||||
|
* @author adar
|
||||||
|
*/
|
||||||
|
@TestForIssue(jiraKey = "HHH-8280")
|
||||||
|
public class IdentifierReuseTest extends BaseEnversJPAFunctionalTestCase {
|
||||||
|
@Override
|
||||||
|
protected void addConfigOptions(Map options) {
|
||||||
|
options.put( EnversSettings.ALLOW_IDENTIFIER_REUSE, "true" );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Class<?>[] getAnnotatedClasses() {
|
||||||
|
return new Class[] { IntNoAutoIdTestEntity.class };
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testIdentifierReuse() {
|
||||||
|
final Integer reusedId = 1;
|
||||||
|
|
||||||
|
EntityManager entityManager = getEntityManager();
|
||||||
|
saveUpdateAndRemoveEntity( entityManager, reusedId );
|
||||||
|
saveUpdateAndRemoveEntity( entityManager, reusedId );
|
||||||
|
entityManager.close();
|
||||||
|
|
||||||
|
assertEquals(
|
||||||
|
Arrays.asList( 1, 2, 3, 4, 5, 6 ),
|
||||||
|
getAuditReader().getRevisions( IntNoAutoIdTestEntity.class, reusedId )
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void saveUpdateAndRemoveEntity(EntityManager entityManager, Integer id) {
|
||||||
|
EntityTransaction transaction = entityManager.getTransaction();
|
||||||
|
|
||||||
|
transaction.begin();
|
||||||
|
IntNoAutoIdTestEntity entity = new IntNoAutoIdTestEntity( 0, id );
|
||||||
|
entityManager.persist( entity );
|
||||||
|
assertEquals( id, entity.getId() );
|
||||||
|
transaction.commit();
|
||||||
|
|
||||||
|
transaction.begin();
|
||||||
|
entity = entityManager.find( IntNoAutoIdTestEntity.class, id );
|
||||||
|
entity.setNumVal( 1 );
|
||||||
|
entity = entityManager.merge( entity );
|
||||||
|
assertEquals( id, entity.getId() );
|
||||||
|
transaction.commit();
|
||||||
|
|
||||||
|
transaction.begin();
|
||||||
|
entity = entityManager.find( IntNoAutoIdTestEntity.class, id );
|
||||||
|
assertNotNull( entity );
|
||||||
|
entityManager.remove( entity );
|
||||||
|
transaction.commit();
|
||||||
|
}
|
||||||
|
}
|
|
@ -291,17 +291,17 @@ public class ValidityAuditStrategyRevEndTestCustomRevEnt extends BaseEnversJPAFu
|
||||||
ParentEntity rev4 = getAuditReader().find( ParentEntity.class, p1_id, 4 );
|
ParentEntity rev4 = getAuditReader().find( ParentEntity.class, p1_id, 4 );
|
||||||
ParentEntity rev5 = getAuditReader().find( ParentEntity.class, p1_id, 5 );
|
ParentEntity rev5 = getAuditReader().find( ParentEntity.class, p1_id, 5 );
|
||||||
|
|
||||||
assert TestTools.checkList( rev1.getChildren1() );
|
assert TestTools.checkCollection( rev1.getChildren1() );
|
||||||
assert TestTools.checkList( rev2.getChildren1(), c1_1 );
|
assert TestTools.checkCollection( rev2.getChildren1(), c1_1 );
|
||||||
assert TestTools.checkList( rev3.getChildren1(), c1_1, c1_2 );
|
assert TestTools.checkCollection( rev3.getChildren1(), c1_1, c1_2 );
|
||||||
assert TestTools.checkList( rev4.getChildren1(), c1_2 );
|
assert TestTools.checkCollection( rev4.getChildren1(), c1_2 );
|
||||||
assert TestTools.checkList( rev5.getChildren1() );
|
assert TestTools.checkCollection( rev5.getChildren1() );
|
||||||
|
|
||||||
assert TestTools.checkList( rev1.getChildren2() );
|
assert TestTools.checkCollection( rev1.getChildren2() );
|
||||||
assert TestTools.checkList( rev2.getChildren2() );
|
assert TestTools.checkCollection( rev2.getChildren2() );
|
||||||
assert TestTools.checkList( rev3.getChildren2(), c2_2 );
|
assert TestTools.checkCollection( rev3.getChildren2(), c2_2 );
|
||||||
assert TestTools.checkList( rev4.getChildren2(), c2_2 );
|
assert TestTools.checkCollection( rev4.getChildren2(), c2_2 );
|
||||||
assert TestTools.checkList( rev5.getChildren2(), c2_2 );
|
assert TestTools.checkCollection( rev5.getChildren2(), c2_2 );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -319,17 +319,17 @@ public class ValidityAuditStrategyRevEndTestCustomRevEnt extends BaseEnversJPAFu
|
||||||
ParentEntity rev4 = getAuditReader().find( ParentEntity.class, p2_id, 4 );
|
ParentEntity rev4 = getAuditReader().find( ParentEntity.class, p2_id, 4 );
|
||||||
ParentEntity rev5 = getAuditReader().find( ParentEntity.class, p2_id, 5 );
|
ParentEntity rev5 = getAuditReader().find( ParentEntity.class, p2_id, 5 );
|
||||||
|
|
||||||
assert TestTools.checkList( rev1.getChildren1() );
|
assert TestTools.checkCollection( rev1.getChildren1() );
|
||||||
assert TestTools.checkList( rev2.getChildren1() );
|
assert TestTools.checkCollection( rev2.getChildren1() );
|
||||||
assert TestTools.checkList( rev3.getChildren1(), c1_1 );
|
assert TestTools.checkCollection( rev3.getChildren1(), c1_1 );
|
||||||
assert TestTools.checkList( rev4.getChildren1(), c1_1 );
|
assert TestTools.checkCollection( rev4.getChildren1(), c1_1 );
|
||||||
assert TestTools.checkList( rev5.getChildren1(), c1_1 );
|
assert TestTools.checkCollection( rev5.getChildren1(), c1_1 );
|
||||||
|
|
||||||
assert TestTools.checkList( rev1.getChildren2() );
|
assert TestTools.checkCollection( rev1.getChildren2() );
|
||||||
assert TestTools.checkList( rev2.getChildren2(), c2_1 );
|
assert TestTools.checkCollection( rev2.getChildren2(), c2_1 );
|
||||||
assert TestTools.checkList( rev3.getChildren2(), c2_1 );
|
assert TestTools.checkCollection( rev3.getChildren2(), c2_1 );
|
||||||
assert TestTools.checkList( rev4.getChildren2(), c2_1, c2_2 );
|
assert TestTools.checkCollection( rev4.getChildren2(), c2_1, c2_2 );
|
||||||
assert TestTools.checkList( rev5.getChildren2(), c2_1 );
|
assert TestTools.checkCollection( rev5.getChildren2(), c2_1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -358,11 +358,11 @@ public class ValidityAuditStrategyRevEndTestCustomRevEnt extends BaseEnversJPAFu
|
||||||
5
|
5
|
||||||
);
|
);
|
||||||
|
|
||||||
assert TestTools.checkList( rev1.getParents() );
|
assert TestTools.checkCollection( rev1.getParents() );
|
||||||
assert TestTools.checkList( rev2.getParents(), p1 );
|
assert TestTools.checkCollection( rev2.getParents(), p1 );
|
||||||
assert TestTools.checkList( rev3.getParents(), p1, p2 );
|
assert TestTools.checkCollection( rev3.getParents(), p1, p2 );
|
||||||
assert TestTools.checkList( rev4.getParents(), p2 );
|
assert TestTools.checkCollection( rev4.getParents(), p2 );
|
||||||
assert TestTools.checkList( rev5.getParents(), p2 );
|
assert TestTools.checkCollection( rev5.getParents(), p2 );
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: this was disabled?
|
// TODO: this was disabled?
|
||||||
|
@ -391,11 +391,11 @@ public class ValidityAuditStrategyRevEndTestCustomRevEnt extends BaseEnversJPAFu
|
||||||
5
|
5
|
||||||
);
|
);
|
||||||
|
|
||||||
assert TestTools.checkList( rev1.getParents() );
|
assert TestTools.checkCollection( rev1.getParents() );
|
||||||
assert TestTools.checkList( rev2.getParents() );
|
assert TestTools.checkCollection( rev2.getParents() );
|
||||||
assert TestTools.checkList( rev3.getParents(), p1 );
|
assert TestTools.checkCollection( rev3.getParents(), p1 );
|
||||||
assert TestTools.checkList( rev4.getParents(), p1 );
|
assert TestTools.checkCollection( rev4.getParents(), p1 );
|
||||||
assert TestTools.checkList( rev5.getParents() );
|
assert TestTools.checkCollection( rev5.getParents() );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -423,11 +423,11 @@ public class ValidityAuditStrategyRevEndTestCustomRevEnt extends BaseEnversJPAFu
|
||||||
5
|
5
|
||||||
);
|
);
|
||||||
|
|
||||||
assert TestTools.checkList( rev1.getParents() );
|
assert TestTools.checkCollection( rev1.getParents() );
|
||||||
assert TestTools.checkList( rev2.getParents(), p2 );
|
assert TestTools.checkCollection( rev2.getParents(), p2 );
|
||||||
assert TestTools.checkList( rev3.getParents(), p2 );
|
assert TestTools.checkCollection( rev3.getParents(), p2 );
|
||||||
assert TestTools.checkList( rev4.getParents(), p2 );
|
assert TestTools.checkCollection( rev4.getParents(), p2 );
|
||||||
assert TestTools.checkList( rev5.getParents(), p2 );
|
assert TestTools.checkCollection( rev5.getParents(), p2 );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -456,11 +456,11 @@ public class ValidityAuditStrategyRevEndTestCustomRevEnt extends BaseEnversJPAFu
|
||||||
5
|
5
|
||||||
);
|
);
|
||||||
|
|
||||||
assert TestTools.checkList( rev1.getParents() );
|
assert TestTools.checkCollection( rev1.getParents() );
|
||||||
assert TestTools.checkList( rev2.getParents() );
|
assert TestTools.checkCollection( rev2.getParents() );
|
||||||
assert TestTools.checkList( rev3.getParents(), p1 );
|
assert TestTools.checkCollection( rev3.getParents(), p1 );
|
||||||
assert TestTools.checkList( rev4.getParents(), p1, p2 );
|
assert TestTools.checkCollection( rev4.getParents(), p1, p2 );
|
||||||
assert TestTools.checkList( rev5.getParents(), p1 );
|
assert TestTools.checkCollection( rev5.getParents(), p1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<Map<String, Object>> getRevisions(
|
private List<Map<String, Object>> getRevisions(
|
||||||
|
|
|
@ -289,17 +289,17 @@ public class ValidityAuditStrategyRevEndTsTest extends BaseEnversJPAFunctionalTe
|
||||||
ParentEntity rev4 = getAuditReader().find( ParentEntity.class, p1_id, 4 );
|
ParentEntity rev4 = getAuditReader().find( ParentEntity.class, p1_id, 4 );
|
||||||
ParentEntity rev5 = getAuditReader().find( ParentEntity.class, p1_id, 5 );
|
ParentEntity rev5 = getAuditReader().find( ParentEntity.class, p1_id, 5 );
|
||||||
|
|
||||||
assert TestTools.checkList( rev1.getChildren1() );
|
assert TestTools.checkCollection( rev1.getChildren1() );
|
||||||
assert TestTools.checkList( rev2.getChildren1(), c1_1 );
|
assert TestTools.checkCollection( rev2.getChildren1(), c1_1 );
|
||||||
assert TestTools.checkList( rev3.getChildren1(), c1_1, c1_2 );
|
assert TestTools.checkCollection( rev3.getChildren1(), c1_1, c1_2 );
|
||||||
assert TestTools.checkList( rev4.getChildren1(), c1_2 );
|
assert TestTools.checkCollection( rev4.getChildren1(), c1_2 );
|
||||||
assert TestTools.checkList( rev5.getChildren1() );
|
assert TestTools.checkCollection( rev5.getChildren1() );
|
||||||
|
|
||||||
assert TestTools.checkList( rev1.getChildren2() );
|
assert TestTools.checkCollection( rev1.getChildren2() );
|
||||||
assert TestTools.checkList( rev2.getChildren2() );
|
assert TestTools.checkCollection( rev2.getChildren2() );
|
||||||
assert TestTools.checkList( rev3.getChildren2(), c2_2 );
|
assert TestTools.checkCollection( rev3.getChildren2(), c2_2 );
|
||||||
assert TestTools.checkList( rev4.getChildren2(), c2_2 );
|
assert TestTools.checkCollection( rev4.getChildren2(), c2_2 );
|
||||||
assert TestTools.checkList( rev5.getChildren2(), c2_2 );
|
assert TestTools.checkCollection( rev5.getChildren2(), c2_2 );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -317,17 +317,17 @@ public class ValidityAuditStrategyRevEndTsTest extends BaseEnversJPAFunctionalTe
|
||||||
ParentEntity rev4 = getAuditReader().find( ParentEntity.class, p2_id, 4 );
|
ParentEntity rev4 = getAuditReader().find( ParentEntity.class, p2_id, 4 );
|
||||||
ParentEntity rev5 = getAuditReader().find( ParentEntity.class, p2_id, 5 );
|
ParentEntity rev5 = getAuditReader().find( ParentEntity.class, p2_id, 5 );
|
||||||
|
|
||||||
assert TestTools.checkList( rev1.getChildren1() );
|
assert TestTools.checkCollection( rev1.getChildren1() );
|
||||||
assert TestTools.checkList( rev2.getChildren1() );
|
assert TestTools.checkCollection( rev2.getChildren1() );
|
||||||
assert TestTools.checkList( rev3.getChildren1(), c1_1 );
|
assert TestTools.checkCollection( rev3.getChildren1(), c1_1 );
|
||||||
assert TestTools.checkList( rev4.getChildren1(), c1_1 );
|
assert TestTools.checkCollection( rev4.getChildren1(), c1_1 );
|
||||||
assert TestTools.checkList( rev5.getChildren1(), c1_1 );
|
assert TestTools.checkCollection( rev5.getChildren1(), c1_1 );
|
||||||
|
|
||||||
assert TestTools.checkList( rev1.getChildren2() );
|
assert TestTools.checkCollection( rev1.getChildren2() );
|
||||||
assert TestTools.checkList( rev2.getChildren2(), c2_1 );
|
assert TestTools.checkCollection( rev2.getChildren2(), c2_1 );
|
||||||
assert TestTools.checkList( rev3.getChildren2(), c2_1 );
|
assert TestTools.checkCollection( rev3.getChildren2(), c2_1 );
|
||||||
assert TestTools.checkList( rev4.getChildren2(), c2_1, c2_2 );
|
assert TestTools.checkCollection( rev4.getChildren2(), c2_1, c2_2 );
|
||||||
assert TestTools.checkList( rev5.getChildren2(), c2_1 );
|
assert TestTools.checkCollection( rev5.getChildren2(), c2_1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -356,11 +356,11 @@ public class ValidityAuditStrategyRevEndTsTest extends BaseEnversJPAFunctionalTe
|
||||||
5
|
5
|
||||||
);
|
);
|
||||||
|
|
||||||
assert TestTools.checkList( rev1.getParents() );
|
assert TestTools.checkCollection( rev1.getParents() );
|
||||||
assert TestTools.checkList( rev2.getParents(), p1 );
|
assert TestTools.checkCollection( rev2.getParents(), p1 );
|
||||||
assert TestTools.checkList( rev3.getParents(), p1, p2 );
|
assert TestTools.checkCollection( rev3.getParents(), p1, p2 );
|
||||||
assert TestTools.checkList( rev4.getParents(), p2 );
|
assert TestTools.checkCollection( rev4.getParents(), p2 );
|
||||||
assert TestTools.checkList( rev5.getParents(), p2 );
|
assert TestTools.checkCollection( rev5.getParents(), p2 );
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: this was disabled?
|
// TODO: this was disabled?
|
||||||
|
@ -389,11 +389,11 @@ public class ValidityAuditStrategyRevEndTsTest extends BaseEnversJPAFunctionalTe
|
||||||
5
|
5
|
||||||
);
|
);
|
||||||
|
|
||||||
assert TestTools.checkList( rev1.getParents() );
|
assert TestTools.checkCollection( rev1.getParents() );
|
||||||
assert TestTools.checkList( rev2.getParents() );
|
assert TestTools.checkCollection( rev2.getParents() );
|
||||||
assert TestTools.checkList( rev3.getParents(), p1 );
|
assert TestTools.checkCollection( rev3.getParents(), p1 );
|
||||||
assert TestTools.checkList( rev4.getParents(), p1 );
|
assert TestTools.checkCollection( rev4.getParents(), p1 );
|
||||||
assert TestTools.checkList( rev5.getParents() );
|
assert TestTools.checkCollection( rev5.getParents() );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -421,11 +421,11 @@ public class ValidityAuditStrategyRevEndTsTest extends BaseEnversJPAFunctionalTe
|
||||||
5
|
5
|
||||||
);
|
);
|
||||||
|
|
||||||
assert TestTools.checkList( rev1.getParents() );
|
assert TestTools.checkCollection( rev1.getParents() );
|
||||||
assert TestTools.checkList( rev2.getParents(), p2 );
|
assert TestTools.checkCollection( rev2.getParents(), p2 );
|
||||||
assert TestTools.checkList( rev3.getParents(), p2 );
|
assert TestTools.checkCollection( rev3.getParents(), p2 );
|
||||||
assert TestTools.checkList( rev4.getParents(), p2 );
|
assert TestTools.checkCollection( rev4.getParents(), p2 );
|
||||||
assert TestTools.checkList( rev5.getParents(), p2 );
|
assert TestTools.checkCollection( rev5.getParents(), p2 );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -454,11 +454,11 @@ public class ValidityAuditStrategyRevEndTsTest extends BaseEnversJPAFunctionalTe
|
||||||
5
|
5
|
||||||
);
|
);
|
||||||
|
|
||||||
assert TestTools.checkList( rev1.getParents() );
|
assert TestTools.checkCollection( rev1.getParents() );
|
||||||
assert TestTools.checkList( rev2.getParents() );
|
assert TestTools.checkCollection( rev2.getParents() );
|
||||||
assert TestTools.checkList( rev3.getParents(), p1 );
|
assert TestTools.checkCollection( rev3.getParents(), p1 );
|
||||||
assert TestTools.checkList( rev4.getParents(), p1, p2 );
|
assert TestTools.checkCollection( rev4.getParents(), p1, p2 );
|
||||||
assert TestTools.checkList( rev5.getParents(), p1 );
|
assert TestTools.checkCollection( rev5.getParents(), p1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<Map<String, Object>> getRevisions(
|
private List<Map<String, Object>> getRevisions(
|
||||||
|
|
|
@ -25,6 +25,7 @@ package org.hibernate.envers.test.tools;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
@ -63,7 +64,7 @@ public class TestTools {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T> boolean checkList(List<T> list, T... objects) {
|
public static <T> boolean checkCollection(Collection<T> list, T... objects) {
|
||||||
if ( list.size() != objects.length ) {
|
if ( list.size() != objects.length ) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,12 +35,10 @@ dependencies {
|
||||||
|
|
||||||
// Local copies of all jars needed fur the OSGi runtime.
|
// Local copies of all jars needed fur the OSGi runtime.
|
||||||
osgiRuntime( "org.jboss.arquillian.osgi:arquillian-osgi-bundle:1.0.3.Final" )
|
osgiRuntime( "org.jboss.arquillian.osgi:arquillian-osgi-bundle:1.0.3.Final" )
|
||||||
osgiRuntime( "org.ops4j.pax.url:pax-url-wrap:1.5.2" )
|
osgiRuntime( libraries.jpa )
|
||||||
// TODO: Temporarily using a pre-built jar in src/test/resources. It's needed for a recent manifest change. Once this is available in Maven, use it.
|
|
||||||
//osgiRuntime( "org.hibernate.javax.persistence:hibernate-jpa-2.1-api:1.0.0-SNAPSHOT" )
|
|
||||||
osgiRuntime( "javax.enterprise:cdi-api:1.1-PFD" )
|
osgiRuntime( "javax.enterprise:cdi-api:1.1-PFD" )
|
||||||
osgiRuntime( "org.jboss.spec.javax.interceptor:jboss-interceptors-api_1.2_spec:1.0.0.Alpha1" )
|
osgiRuntime( "org.jboss.spec.javax.interceptor:jboss-interceptors-api_1.2_spec:1.0.0.Alpha1" )
|
||||||
osgiRuntime( "org.jboss.spec.javax.transaction:jboss-transaction-api_1.2_spec:1.0.0.Alpha1" )
|
osgiRuntime( libraries.jta )
|
||||||
osgiRuntime( "commons-collections:commons-collections:3.2.1" )
|
osgiRuntime( "commons-collections:commons-collections:3.2.1" )
|
||||||
osgiRuntime( "commons-pool:commons-pool:1.6" )
|
osgiRuntime( "commons-pool:commons-pool:1.6" )
|
||||||
osgiRuntime( "commons-dbcp:commons-dbcp:1.4" )
|
osgiRuntime( "commons-dbcp:commons-dbcp:1.4" )
|
||||||
|
@ -93,7 +91,7 @@ task copyBnd(type: Copy) {
|
||||||
|
|
||||||
task runBnd(type: JavaExec){
|
task runBnd(type: JavaExec){
|
||||||
main = "-jar"
|
main = "-jar"
|
||||||
args "$buildDir/osgi-lib/bnd/bnd.jar", "$buildDir/osgi-lib/bnd/cdi-api.bnd", "$buildDir/osgi-lib/bnd/el-api.bnd", "$buildDir/osgi-lib/bnd/jandex.bnd", "$buildDir/osgi-lib/bnd/javassist.bnd", "$buildDir/osgi-lib/bnd/serp.bnd"
|
args "$buildDir/osgi-lib/bnd/bnd.jar", "$buildDir/osgi-lib/bnd/cdi-api.bnd", "$buildDir/osgi-lib/bnd/el-api.bnd", "$buildDir/osgi-lib/bnd/jandex.bnd", "$buildDir/osgi-lib/bnd/serp.bnd"
|
||||||
}
|
}
|
||||||
|
|
||||||
task copyToLib(type: Copy) {
|
task copyToLib(type: Copy) {
|
||||||
|
|
|
@ -35,6 +35,7 @@ import org.hibernate.jpa.HibernatePersistenceProvider;
|
||||||
import org.osgi.framework.BundleActivator;
|
import org.osgi.framework.BundleActivator;
|
||||||
import org.osgi.framework.BundleContext;
|
import org.osgi.framework.BundleContext;
|
||||||
import org.osgi.framework.FrameworkUtil;
|
import org.osgi.framework.FrameworkUtil;
|
||||||
|
import org.osgi.framework.ServiceRegistration;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This BundleActivator provides three different uses of Hibernate in OSGi
|
* This BundleActivator provides three different uses of Hibernate in OSGi
|
||||||
|
@ -59,6 +60,10 @@ import org.osgi.framework.FrameworkUtil;
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("UnusedDeclaration")
|
@SuppressWarnings("UnusedDeclaration")
|
||||||
public class HibernateBundleActivator implements BundleActivator {
|
public class HibernateBundleActivator implements BundleActivator {
|
||||||
|
|
||||||
|
private ServiceRegistration<?> persistenceProviderService;
|
||||||
|
private ServiceRegistration<?> sessionFactoryService;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public void start(BundleContext context) throws Exception {
|
public void start(BundleContext context) throws Exception {
|
||||||
|
@ -75,12 +80,12 @@ public class HibernateBundleActivator implements BundleActivator {
|
||||||
final Dictionary properties = new Hashtable();
|
final Dictionary properties = new Hashtable();
|
||||||
// In order to support existing persistence.xml files, register using the legacy provider name.
|
// In order to support existing persistence.xml files, register using the legacy provider name.
|
||||||
properties.put( "javax.persistence.provider", HibernatePersistenceProvider.class.getName() );
|
properties.put( "javax.persistence.provider", HibernatePersistenceProvider.class.getName() );
|
||||||
context.registerService(
|
persistenceProviderService = context.registerService(
|
||||||
PersistenceProvider.class.getName(),
|
PersistenceProvider.class.getName(),
|
||||||
new OsgiPersistenceProviderService( osgiClassLoader, osgiJtaPlatform, context ),
|
new OsgiPersistenceProviderService( osgiClassLoader, osgiJtaPlatform, context ),
|
||||||
properties
|
properties
|
||||||
);
|
);
|
||||||
context.registerService(
|
sessionFactoryService = context.registerService(
|
||||||
SessionFactory.class.getName(),
|
SessionFactory.class.getName(),
|
||||||
new OsgiSessionFactoryService( osgiClassLoader, osgiJtaPlatform, context ),
|
new OsgiSessionFactoryService( osgiClassLoader, osgiJtaPlatform, context ),
|
||||||
new Hashtable()
|
new Hashtable()
|
||||||
|
@ -89,6 +94,11 @@ public class HibernateBundleActivator implements BundleActivator {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void stop(BundleContext context) throws Exception {
|
public void stop(BundleContext context) throws Exception {
|
||||||
// Nothing else to do?
|
persistenceProviderService.unregister();
|
||||||
|
persistenceProviderService = null;
|
||||||
|
sessionFactoryService.unregister();
|
||||||
|
sessionFactoryService = null;
|
||||||
|
|
||||||
|
ClassLoaderHelper.overridenClassLoader = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,13 +18,17 @@ package org.hibernate.osgi.test;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertNotNull;
|
import static org.junit.Assert.assertNotNull;
|
||||||
|
import static org.junit.Assert.assertNull;
|
||||||
import static org.junit.Assert.fail;
|
import static org.junit.Assert.fail;
|
||||||
|
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
import org.hibernate.osgi.OsgiPersistenceProviderService;
|
||||||
|
import org.hibernate.osgi.OsgiSessionFactoryService;
|
||||||
import org.hibernate.osgi.test.result.OsgiTestResults;
|
import org.hibernate.osgi.test.result.OsgiTestResults;
|
||||||
import org.jboss.arquillian.container.test.api.Deployment;
|
import org.jboss.arquillian.container.test.api.Deployment;
|
||||||
import org.jboss.arquillian.junit.Arquillian;
|
import org.jboss.arquillian.junit.Arquillian;
|
||||||
|
import org.jboss.arquillian.junit.InSequence;
|
||||||
import org.jboss.arquillian.test.api.ArquillianResource;
|
import org.jboss.arquillian.test.api.ArquillianResource;
|
||||||
import org.jboss.osgi.metadata.OSGiManifestBuilder;
|
import org.jboss.osgi.metadata.OSGiManifestBuilder;
|
||||||
import org.jboss.shrinkwrap.api.ShrinkWrap;
|
import org.jboss.shrinkwrap.api.ShrinkWrap;
|
||||||
|
@ -94,6 +98,8 @@ public class OsgiTestCase {
|
||||||
builder.addBundleSymbolicName( archive.getName() );
|
builder.addBundleSymbolicName( archive.getName() );
|
||||||
builder.addBundleManifestVersion( 2 );
|
builder.addBundleManifestVersion( 2 );
|
||||||
builder.addImportPackages( OsgiTestResults.class );
|
builder.addImportPackages( OsgiTestResults.class );
|
||||||
|
// needed primarily to test service cleanup in #testStop
|
||||||
|
builder.addImportPackages( OsgiSessionFactoryService.class );
|
||||||
return builder.openStream();
|
return builder.openStream();
|
||||||
}
|
}
|
||||||
} );
|
} );
|
||||||
|
@ -107,19 +113,16 @@ public class OsgiTestCase {
|
||||||
* @throws Exception
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
|
@InSequence(1)
|
||||||
public void testClientBundle() throws Exception {
|
public void testClientBundle() throws Exception {
|
||||||
assertNotNull( "BundleContext injected", context );
|
commonTests();
|
||||||
assertEquals( "System Bundle ID", 0, context.getBundle().getBundleId() );
|
|
||||||
|
|
||||||
testHibernateBundle( "org.hibernate.core" );
|
|
||||||
testHibernateBundle( "org.hibernate.entitymanager" );
|
|
||||||
|
|
||||||
final Bundle testClientBundle = findHibernateBundle( "testClientBundle" );
|
final Bundle testClientBundle = findHibernateBundle( "testClientBundle" );
|
||||||
assertNotNull( "The test client bundle was not found!", testClientBundle );
|
assertNotNull( "The test client bundle was not found!", testClientBundle );
|
||||||
testClientBundle.start();
|
testClientBundle.start();
|
||||||
assertEquals( "The test client bundle was not activated!", Bundle.ACTIVE, testClientBundle.getState() );
|
assertEquals( "The test client bundle was not activated!", Bundle.ACTIVE, testClientBundle.getState() );
|
||||||
|
|
||||||
final ServiceReference serviceReference = context.getServiceReference( OsgiTestResults.class.getName() );
|
final ServiceReference<?> serviceReference = context.getServiceReference( OsgiTestResults.class.getName() );
|
||||||
final OsgiTestResults testResults = (OsgiTestResults) context.getService( serviceReference );
|
final OsgiTestResults testResults = (OsgiTestResults) context.getService( serviceReference );
|
||||||
|
|
||||||
if ( testResults.getFailures().size() > 0 ) {
|
if ( testResults.getFailures().size() > 0 ) {
|
||||||
|
@ -127,6 +130,36 @@ public class OsgiTestCase {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test that stopping the hibernate-osgi bundle happens cleanly.
|
||||||
|
*
|
||||||
|
* TODO: This will be really simplistic at first, but should be expanded upon.
|
||||||
|
*
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
// Arquillian does not restart the container between runs (afaik). Without the ordering, the tests will
|
||||||
|
// intermittently fail since this method stops the bundle.
|
||||||
|
@InSequence(2)
|
||||||
|
public void testStop() throws Exception {
|
||||||
|
commonTests();
|
||||||
|
|
||||||
|
findHibernateBundle( "org.hibernate.osgi" ).stop();
|
||||||
|
testHibernateBundle( "org.hibernate.osgi", Bundle.RESOLVED );
|
||||||
|
|
||||||
|
assertNull( context.getServiceReference( OsgiSessionFactoryService.class ) );
|
||||||
|
assertNull( context.getServiceReference( OsgiPersistenceProviderService.class ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
private void commonTests() {
|
||||||
|
assertNotNull( "BundleContext injected", context );
|
||||||
|
assertEquals( "System Bundle ID", 0, context.getBundle().getBundleId() );
|
||||||
|
|
||||||
|
testHibernateBundle( "org.hibernate.core", Bundle.ACTIVE );
|
||||||
|
testHibernateBundle( "org.hibernate.entitymanager", Bundle.ACTIVE );
|
||||||
|
testHibernateBundle( "org.hibernate.osgi", Bundle.ACTIVE );
|
||||||
|
}
|
||||||
|
|
||||||
private Bundle findHibernateBundle(String symbolicName) {
|
private Bundle findHibernateBundle(String symbolicName) {
|
||||||
for ( Bundle bundle : context.getBundles() ) {
|
for ( Bundle bundle : context.getBundles() ) {
|
||||||
if ( bundle.getSymbolicName().equals( symbolicName ) ) {
|
if ( bundle.getSymbolicName().equals( symbolicName ) ) {
|
||||||
|
@ -136,10 +169,10 @@ public class OsgiTestCase {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void testHibernateBundle(String symbolicName) {
|
private void testHibernateBundle(String symbolicName, int state) {
|
||||||
final Bundle bundle = findHibernateBundle( symbolicName );
|
final Bundle bundle = findHibernateBundle( symbolicName );
|
||||||
|
|
||||||
assertNotNull( "Bundle " + symbolicName + " was not found!", bundle );
|
assertNotNull( "Bundle " + symbolicName + " was not found!", bundle );
|
||||||
assertEquals( "Bundle " + symbolicName + " was not activated!", Bundle.ACTIVE, bundle.getState() );
|
assertEquals( "Bundle " + symbolicName + " was not in the expected state!", state, bundle.getState() );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +0,0 @@
|
||||||
Bundle-SymbolicName: javassist
|
|
||||||
Bundle-Version: 3.18.0
|
|
||||||
|
|
||||||
Include-Resource: @../javassist-3.18.0-GA.jar
|
|
||||||
Import-Package: com.sun.jdi;resolution:=optional,com.sun.jdi.connect;resolution:=optional,com.sun.jdi.event;resolution:=optional,com.sun.jdi.request;resolution:=optional
|
|
||||||
-exportcontents: javassist,javassist.bytecode,javassist.bytecode.analysis,javassist.bytecode.annotation,javassist.bytecode.stackmap,javassist.compiler,javassist.compiler.ast,javassist.convert,javassist.expr,javassist.runtime,javassist.scopedpool,javassist.tools,javassist.tools.reflect,javassist.tools.rmi,javassist.tools.web,javassist.util,javassist.util.proxy
|
|
|
@ -14,11 +14,9 @@ felix.log.level=4
|
||||||
felix.auto.install.1=\
|
felix.auto.install.1=\
|
||||||
file:target/osgi-lib/testClientBundle.jar
|
file:target/osgi-lib/testClientBundle.jar
|
||||||
|
|
||||||
# TODO: Temporarily using a pre-built hibernate-jpa-2.1-api-1.0.0-SNAPSHOT.jar in src/test/resources.
|
|
||||||
# It's needed for a recent manifest change. Once this is available in Maven, use it.
|
|
||||||
felix.auto.start.1=\
|
felix.auto.start.1=\
|
||||||
file:target/osgi-lib/arquillian-osgi-bundle-1.0.3.Final.jar \
|
file:target/osgi-lib/arquillian-osgi-bundle-1.0.3.Final.jar \
|
||||||
file:src/test/resources/hibernate-jpa-2.1-api-1.0.0-SNAPSHOT.jar \
|
file:target/osgi-lib/hibernate-jpa-2.1-api-1.0.0.Final.jar \
|
||||||
file:target/osgi-lib/bnd/el-api-2.2.0.jar \
|
file:target/osgi-lib/bnd/el-api-2.2.0.jar \
|
||||||
file:target/osgi-lib/bnd/cdi-api-1.1.0.jar \
|
file:target/osgi-lib/bnd/cdi-api-1.1.0.jar \
|
||||||
file:target/osgi-lib/jboss-interceptors-api_1.2_spec-1.0.0.Alpha1.jar \
|
file:target/osgi-lib/jboss-interceptors-api_1.2_spec-1.0.0.Alpha1.jar \
|
||||||
|
@ -30,7 +28,7 @@ felix.auto.start.1=\
|
||||||
file:target/osgi-lib/bnd/serp-1.14.1.jar \
|
file:target/osgi-lib/bnd/serp-1.14.1.jar \
|
||||||
file:target/osgi-lib/h2-1.3.170.jar \
|
file:target/osgi-lib/h2-1.3.170.jar \
|
||||||
file:target/osgi-lib/org.apache.servicemix.bundles.antlr-2.7.7_5.jar \
|
file:target/osgi-lib/org.apache.servicemix.bundles.antlr-2.7.7_5.jar \
|
||||||
file:target/osgi-lib/bnd/javassist-3.18.0.jar \
|
file:target/osgi-lib/javassist-3.18.1-Beta1.jar \
|
||||||
file:target/osgi-lib/org.apache.servicemix.specs.jsr303-api-1.0.0-2.2.0.jar \
|
file:target/osgi-lib/org.apache.servicemix.specs.jsr303-api-1.0.0-2.2.0.jar \
|
||||||
file:target/osgi-lib/org.apache.servicemix.bundles.ant-1.8.2_2.jar \
|
file:target/osgi-lib/org.apache.servicemix.bundles.ant-1.8.2_2.jar \
|
||||||
file:target/osgi-lib/org.apache.servicemix.specs.stax-api-1.2-2.2.0.jar \
|
file:target/osgi-lib/org.apache.servicemix.specs.stax-api-1.2-2.2.0.jar \
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue