merge master

This commit is contained in:
Strong Liu 2013-08-03 23:10:54 +08:00
commit 0e62ff4856
103 changed files with 2671 additions and 1001 deletions

View File

@ -326,6 +326,19 @@
Name of column used for storing ordinal of the change in sets of embeddable elements.
</entry>
</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>
</tgroup>
</table>

View File

@ -17,7 +17,7 @@
<bundle start-level="30">mvn:org.apache.aries.transaction/org.apache.aries.transaction.manager/1.0.1</bundle>
<!-- 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
JPA 2.1). Aries should be upgrading as soon as the spec is out.
https://github.com/brmeyer/aries/tree/jpa21 -->
@ -46,7 +46,6 @@
<!-- 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>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.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>
@ -55,8 +54,9 @@
<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>mvn:com.fasterxml/classmate/0.8.0</bundle>
<bundle>mvn:org.jboss.logging/jboss-logging/3.1.1.GA</bundle>
<bundle>mvn:com.fasterxml/classmate/0.5.4</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-entitymanager/5.0.0-SNAPSHOT</bundle>

View File

@ -10,7 +10,7 @@
<dependency>
<groupId>org.hibernate.javax.persistence</groupId>
<artifactId>hibernate-jpa-2.1-api</artifactId>
<version>1.0.0-SNAPSHOT</version>
<version>1.0.0.Final</version>
</dependency>
<dependency>
<groupId>org.osgi</groupId>

View File

@ -8,7 +8,7 @@
<bundle start-level="30">mvn:org.apache.geronimo.specs/geronimo-jta_1.1_spec/1.1.1</bundle>
<!-- 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 -->
<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. -->
<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.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>
@ -30,8 +29,9 @@
<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>mvn:com.fasterxml/classmate/0.8.0</bundle>
<bundle>mvn:org.jboss.logging/jboss-logging/3.1.1.GA</bundle>
<bundle>mvn:com.fasterxml/classmate/0.5.4</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-entitymanager/5.0.0-SNAPSHOT</bundle>

View File

@ -10,7 +10,7 @@
<dependency>
<groupId>org.hibernate.javax.persistence</groupId>
<artifactId>hibernate-jpa-2.1-api</artifactId>
<version>1.0.0-SNAPSHOT</version>
<version>1.0.0.Final</version>
</dependency>
<dependency>
<groupId>org.osgi</groupId>

View File

@ -8,7 +8,7 @@
<bundle start-level="30">mvn:org.apache.geronimo.specs/geronimo-jta_1.1_spec/1.1.1</bundle>
<!-- 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 -->
<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. -->
<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.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>
@ -36,8 +35,9 @@
<!-- Optional. Needed to test ehcache 2lc. -->
<!-- <bundle>wrap:mvn:net.sf.ehcache/ehcache-core/2.4.3</bundle> -->
<bundle>mvn:com.fasterxml/classmate/0.8.0</bundle>
<bundle>mvn:org.jboss.logging/jboss-logging/3.1.1.GA</bundle>
<bundle>mvn:com.fasterxml/classmate/0.5.4</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. -->
<!--<bundle>mvn:javax.servlet/javax.servlet-api/3.0.1</bundle>

View File

@ -10,7 +10,7 @@
<dependency>
<groupId>org.hibernate.javax.persistence</groupId>
<artifactId>hibernate-jpa-2.1-api</artifactId>
<version>1.0.0-SNAPSHOT</version>
<version>1.0.0.Final</version>
</dependency>
<dependency>
<groupId>org.osgi</groupId>

View File

@ -29,6 +29,9 @@ dependencies {
// for test runtime
transitive = true
}
// for testing stored procedure support
testCompile( libraries.derby )
testRuntime( 'jaxen:jaxen:1.1' )
testRuntime( libraries.javassist )

View File

@ -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() ) {
subIter = table.getForeignKeyIterator();
Iterator subIter = table.getForeignKeyIterator();
while ( subIter.hasNext() ) {
ForeignKey fk = (ForeignKey) subIter.next();
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() ) {
Iterator subIter = table.getForeignKeyIterator();
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 ) );
}
}
}

View File

@ -173,7 +173,8 @@ public class NamedProcedureCallDefinition {
: ParameterStrategy.POSITIONAL;
parameterDefinitions = new ParameterDefinition[ parameters.length ];
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] );
}
}
}

View File

@ -28,6 +28,8 @@ import java.sql.Types;
import org.hibernate.MappingException;
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.ViolatedConstraintNameExtracter;
import org.hibernate.internal.util.JdbcExceptionHelper;
@ -43,6 +45,8 @@ import org.hibernate.type.StandardBasicTypes;
*/
public class InformixDialect extends Dialect {
private final UniqueDelegate uniqueDelegate;
/**
* Creates new <code>InformixDialect</code> instance. Sets up the JDBC /
* Informix type mappings.
@ -77,6 +81,8 @@ public class InformixDialect extends Dialect {
registerColumnType( Types.VARCHAR, 32739, "lvarchar($l)" );
registerFunction( "concat", new VarArgsSQLFunction( StandardBasicTypes.STRING, "(", "||", ")" ) );
uniqueDelegate = new InformixUniqueDelegate( this );
}
@Override
@ -286,4 +292,9 @@ public class InformixDialect extends Dialect {
public String getCreateTemporaryTablePostfix() {
return "with no log";
}
@Override
public UniqueDelegate getUniqueDelegate() {
return uniqueDelegate;
}
}

View File

@ -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;
}
}

View File

@ -55,7 +55,7 @@ public class NaturalIdXrefDelegate {
private static final Logger LOG = Logger.getLogger( NaturalIdXrefDelegate.class );
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
@ -92,7 +92,10 @@ public class NaturalIdXrefDelegate {
NaturalIdResolutionCache entityNaturalIdResolutionCache = naturalIdResolutionCacheMap.get( persister );
if ( entityNaturalIdResolutionCache == null ) {
entityNaturalIdResolutionCache = new NaturalIdResolutionCache( persister );
naturalIdResolutionCacheMap.put( persister, entityNaturalIdResolutionCache );
NaturalIdResolutionCache previousInstance = naturalIdResolutionCacheMap.putIfAbsent( persister, entityNaturalIdResolutionCache );
if ( previousInstance != null ) {
entityNaturalIdResolutionCache = previousInstance;
}
}
return entityNaturalIdResolutionCache.cache( pk, naturalIdValues );
}
@ -279,7 +282,10 @@ public class NaturalIdXrefDelegate {
if ( entityNaturalIdResolutionCache == null ) {
entityNaturalIdResolutionCache = new NaturalIdResolutionCache( persister );
naturalIdResolutionCacheMap.put( persister, entityNaturalIdResolutionCache );
NaturalIdResolutionCache existingCache = naturalIdResolutionCacheMap.putIfAbsent( persister, entityNaturalIdResolutionCache );
if ( existingCache != null ) {
entityNaturalIdResolutionCache = existingCache;
}
}
entityNaturalIdResolutionCache.pkToNaturalIdMap.put( pk, cachedNaturalId );

View File

@ -37,6 +37,7 @@ import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentMap;
import org.jboss.logging.Logger;
@ -109,7 +110,7 @@ public class StatefulPersistenceContext implements PersistenceContext {
// private Map<Object,EntityEntry> entityEntries;
// Entity proxies, by EntityKey
private Map<EntityKey, Object> proxiesByKey;
private ConcurrentMap<EntityKey, Object> proxiesByKey;
// Snapshots of current database state for entities
// that have *not* been loaded
@ -563,9 +564,7 @@ public class StatefulPersistenceContext implements PersistenceContext {
final EntityPersister persister = session.getFactory().getEntityPersister( li.getEntityName() );
final EntityKey key = session.generateEntityKey( li.getIdentifier(), persister );
// any earlier proxy takes precedence
if ( !proxiesByKey.containsKey( key ) ) {
proxiesByKey.put( key, proxy );
}
proxiesByKey.putIfAbsent( key, proxy );
proxy.getHibernateLazyInitializer().setSession( session );
}
}

View File

@ -71,6 +71,7 @@ public class DriverManagerConnectionProviderImpl
private int poolSize;
private boolean autocommit;
//Access guarded by synchronization on the pool instance
private final ArrayList<Connection> pool = new ArrayList<Connection>();
private final AtomicInteger checkedOut = new AtomicInteger();
@ -170,15 +171,17 @@ public class DriverManagerConnectionProviderImpl
public void stop() {
LOG.cleaningUpConnectionPool( url );
for ( Connection connection : pool ) {
try {
connection.close();
}
catch (SQLException sqle) {
LOG.unableToClosePooledConnection( sqle );
synchronized ( pool ) {
for ( Connection connection : pool ) {
try {
connection.close();
}
catch (SQLException sqle) {
LOG.unableToClosePooledConnection( sqle );
}
}
pool.clear();
}
pool.clear();
stopped = true;
}

View File

@ -152,7 +152,7 @@ public class HiLoOptimizer extends AbstractOptimizer {
}
@Override
public IntegralDataTypeHolder getLastSourceValue() {
public synchronized IntegralDataTypeHolder getLastSourceValue() {
return noTenantGenerationState().lastSourceValue;
}
@ -168,7 +168,7 @@ public class HiLoOptimizer extends AbstractOptimizer {
*
* @return Value for property 'lastValue'.
*/
public IntegralDataTypeHolder getLastValue() {
public synchronized IntegralDataTypeHolder getLastValue() {
return noTenantGenerationState().value.copy().decrement();
}
@ -179,7 +179,7 @@ public class HiLoOptimizer extends AbstractOptimizer {
*
* @return Value for property 'upperLimit'.
*/
public IntegralDataTypeHolder getHiValue() {
public synchronized IntegralDataTypeHolder getHiValue() {
return noTenantGenerationState().upperLimit;
}
}

View File

@ -125,7 +125,7 @@ public class LegacyHiLoAlgorithmOptimizer extends AbstractOptimizer {
}
@Override
public IntegralDataTypeHolder getLastSourceValue() {
public synchronized IntegralDataTypeHolder getLastSourceValue() {
return noTenantGenerationState().lastSourceValue.copy();
}
@ -142,7 +142,7 @@ public class LegacyHiLoAlgorithmOptimizer extends AbstractOptimizer {
* @return Value for property 'lastValue'.
*/
@SuppressWarnings( {"UnusedDeclaration"})
public IntegralDataTypeHolder getLastValue() {
public synchronized IntegralDataTypeHolder getLastValue() {
return noTenantGenerationState().value;
}
}

View File

@ -53,7 +53,8 @@ public final class StringHelper {
public static int lastIndexOfLetter(String string) {
for ( int i=0; i<string.length(); 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;
}

View File

@ -594,23 +594,7 @@ public class CustomLoader extends Loader {
rowProcessor.columnProcessors[i].performDiscovery( metadata, types, aliases );
}
// 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.:
// select u.username, u2.username from t_user u, t_user u2 ...
//
// the above will lead to an unworkable situation in most cases (the difference is how the driver/db
// handle this situation. But if the 'aliases' variable contains duplicate names, then we have that
// troublesome condition, so lets throw an error. See HHH-5992
final HashSet<String> aliasesSet = new HashSet<String>();
for ( String alias : aliases ) {
boolean alreadyExisted = !aliasesSet.add( alias );
if ( alreadyExisted ) {
throw new NonUniqueDiscoveredSqlAliasException(
"Encountered a duplicated sql alias [" + alias +
"] during auto-discovery of a native-sql query"
);
}
}
validateAliases( aliases );
resultTypes = ArrayHelper.toTypeArray( types );
transformerAliases = ArrayHelper.toStringArray( aliases );
@ -620,6 +604,30 @@ public class CustomLoader extends Loader {
}
}
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
// did not rename same-named columns. e.g.:
// select u.username, u2.username from t_user u, t_user u2 ...
//
// the above will lead to an unworkable situation in most cases (the difference is how the driver/db
// handle this situation. But if the 'aliases' variable contains duplicate names, then we have that
// troublesome condition, so lets throw an error. See HHH-5992
final HashSet<String> aliasesSet = new HashSet<String>();
for ( String alias : aliases ) {
validateAlias( alias );
boolean alreadyExisted = !aliasesSet.add( alias );
if ( alreadyExisted ) {
throw new NonUniqueDiscoveredSqlAliasException(
"Encountered a duplicated sql alias [" + alias +
"] during auto-discovery of a native-sql query"
);
}
}
}
protected void validateAlias(String alias) {
}
private static class Metadata {
private final SessionFactoryImplementor factory;
private final ResultSet resultSet;

View File

@ -111,7 +111,7 @@ public class Column implements Selectable, Serializable, Cloneable {
@Override
public String getAlias(Dialect dialect) {
final int lastLetter = StringHelper.lastIndexOfLetter( name );
String suffix = Integer.toString(uniqueInteger) + '_';
final String suffix = Integer.toString(uniqueInteger) + '_';
String alias = name;
if ( lastLetter == -1 ) {

View File

@ -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 );
}
}

View File

@ -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 );
}
}

View File

@ -82,6 +82,9 @@ public interface ProcedureCall extends BasicQueryContract, SynchronizeableQuery
* @param position The parameter position
*
* @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);
@ -122,6 +125,9 @@ public interface ProcedureCall extends BasicQueryContract, SynchronizeableQuery
* @param name The parameter name
*
* @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);
@ -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
* Output instance each time.
* ProcedureResult instance each time.
* <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

View File

@ -29,7 +29,7 @@ import org.hibernate.Session;
import org.hibernate.engine.spi.SessionImplementor;
/**
* Represents a "memento" of a ProcedureCall
* Represents a "memento" (disconnected, externalizable form) of a ProcedureCall
*
* @author Steve Ebersole
*/

View File

@ -23,20 +23,20 @@
*/
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.
*
* @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.
* <p/>
* 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.
*
@ -53,6 +53,9 @@ public interface ProcedureResult extends Result {
*
* @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)
*/
public Object getOutputParameterValue(String name);
@ -64,6 +67,9 @@ public interface ProcedureResult extends Result {
*
* @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)
*/
public Object getOutputParameterValue(int position);

View File

@ -50,10 +50,12 @@ import org.hibernate.internal.util.StringHelper;
import org.hibernate.internal.util.collections.CollectionHelper;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.procedure.NamedParametersNotSupportedException;
import org.hibernate.procedure.NoSuchParameterException;
import org.hibernate.procedure.ParameterRegistration;
import org.hibernate.procedure.ParameterStrategyException;
import org.hibernate.procedure.ProcedureCall;
import org.hibernate.procedure.ProcedureCallMemento;
import org.hibernate.procedure.ProcedureResult;
import org.hibernate.procedure.ProcedureOutputs;
import org.hibernate.result.spi.ResultContext;
import org.hibernate.type.Type;
@ -75,7 +77,7 @@ public class ProcedureCallImpl extends AbstractBasicQueryContractImpl implements
private Set<String> synchronizedQuerySpaces;
private ProcedureResultImpl outputs;
private ProcedureOutputsImpl outputs;
/**
* The no-returns form.
@ -321,21 +323,22 @@ public class ProcedureCallImpl extends AbstractBasicQueryContractImpl implements
@Override
public ParameterRegistrationImplementor getParameterRegistration(int position) {
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 {
return registeredParameters.get( position );
}
catch ( Exception e ) {
throw new QueryException( "Could not locate parameter registered using that position [" + position + "]" );
for ( ParameterRegistrationImplementor parameter : registeredParameters ) {
if ( position == parameter.getPosition() ) {
return parameter;
}
}
throw new NoSuchParameterException( "Could not locate parameter registered using that position [" + position + "]" );
}
@Override
@SuppressWarnings("unchecked")
public <T> ParameterRegistration<T> registerParameter(String name, Class<T> type, ParameterMode mode) {
final NamedParameterRegistration parameterRegistration
= new NamedParameterRegistration( this, name, mode, type );
final NamedParameterRegistration parameterRegistration = new NamedParameterRegistration( this, name, mode, type );
registerParameter( parameterRegistration );
return parameterRegistration;
}
@ -350,14 +353,14 @@ public class ProcedureCallImpl extends AbstractBasicQueryContractImpl implements
@Override
public ParameterRegistrationImplementor getParameterRegistration(String name) {
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 ) {
if ( name.equals( parameter.getName() ) ) {
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
@ -367,7 +370,7 @@ public class ProcedureCallImpl extends AbstractBasicQueryContractImpl implements
}
@Override
public ProcedureResult getResult() {
public ProcedureOutputs getResult() {
if ( outputs == null ) {
outputs = buildOutputs();
}
@ -375,7 +378,7 @@ public class ProcedureCallImpl extends AbstractBasicQueryContractImpl implements
return outputs;
}
private ProcedureResultImpl buildOutputs() {
private ProcedureOutputsImpl buildOutputs() {
// todo : going to need a very specialized Loader for this.
// or, might be a good time to look at splitting Loader up into:
// 1) building statement objects
@ -385,6 +388,11 @@ public class ProcedureCallImpl extends AbstractBasicQueryContractImpl implements
// for now assume there are no resultClasses nor mappings defined..
// 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 " )
.append( procedureName )
.append( "(" );
@ -414,7 +422,7 @@ public class ProcedureCallImpl extends AbstractBasicQueryContractImpl implements
i += parameter.getSqlTypes().length;
}
return new ProcedureResultImpl( this, statement );
return new ProcedureOutputsImpl( this, statement );
}
catch (SQLException e) {
throw getSession().getFactory().getSQLExceptionHelper().convert(

View File

@ -25,28 +25,26 @@ package org.hibernate.procedure.internal;
import java.sql.CallableStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.hibernate.JDBCException;
import org.hibernate.engine.jdbc.cursor.spi.RefCursorSupport;
import org.hibernate.procedure.ParameterRegistration;
import org.hibernate.procedure.ProcedureResult;
import org.hibernate.result.Return;
import org.hibernate.result.internal.ResultImpl;
import org.hibernate.procedure.ProcedureOutputs;
import org.hibernate.result.Output;
import org.hibernate.result.internal.OutputsImpl;
/**
* Implementation of ProcedureResult. Defines centralized access to all of the results of a procedure call.
*
* @author Steve Ebersole
*/
public class ProcedureResultImpl extends ResultImpl implements ProcedureResult {
public class ProcedureOutputsImpl extends OutputsImpl implements ProcedureOutputs {
private final ProcedureCallImpl procedureCall;
private final CallableStatement callableStatement;
private final ParameterRegistrationImplementor[] refCursorParameters;
private int refCursorParamIndex;
ProcedureResultImpl(ProcedureCallImpl procedureCall, CallableStatement callableStatement) {
ProcedureOutputsImpl(ProcedureCallImpl procedureCall, CallableStatement callableStatement) {
super( procedureCall, callableStatement );
this.procedureCall = procedureCall;
this.callableStatement = callableStatement;
@ -70,49 +68,46 @@ public class ProcedureResultImpl extends ResultImpl implements ProcedureResult {
}
@Override
protected CurrentReturnDescriptor buildCurrentReturnDescriptor(boolean isResultSet, int updateCount) {
return new ProcedureCurrentReturnDescriptor( isResultSet, updateCount, refCursorParamIndex );
protected CurrentReturnState buildCurrentReturnState(boolean isResultSet, int updateCount) {
return new ProcedureCurrentReturnState( isResultSet, updateCount, refCursorParamIndex );
}
protected boolean hasMoreReturns(CurrentReturnDescriptor descriptor) {
return super.hasMoreReturns( descriptor )
|| ( (ProcedureCurrentReturnDescriptor) descriptor ).refCursorParamIndex < refCursorParameters.length;
}
@Override
protected Return buildExtendedReturn(CurrentReturnDescriptor returnDescriptor) {
this.refCursorParamIndex++;
final int refCursorParamIndex = ( (ProcedureCurrentReturnDescriptor) returnDescriptor ).refCursorParamIndex;
final ParameterRegistrationImplementor refCursorParam = refCursorParameters[refCursorParamIndex];
ResultSet resultSet;
if ( refCursorParam.getName() != null ) {
resultSet = procedureCall.getSession().getFactory().getServiceRegistry()
.getService( RefCursorSupport.class )
.getResultSet( callableStatement, refCursorParam.getName() );
}
else {
resultSet = procedureCall.getSession().getFactory().getServiceRegistry()
.getService( RefCursorSupport.class )
.getResultSet( callableStatement, refCursorParam.getPosition() );
}
return new ResultSetReturn( this, resultSet );
}
protected JDBCException convert(SQLException e, String message) {
return procedureCall.getSession().getFactory().getSQLExceptionHelper().convert(
e,
message,
procedureCall.getProcedureName()
);
}
protected static class ProcedureCurrentReturnDescriptor extends CurrentReturnDescriptor {
protected class ProcedureCurrentReturnState extends CurrentReturnState {
private final int refCursorParamIndex;
private ProcedureCurrentReturnDescriptor(boolean isResultSet, int updateCount, int refCursorParamIndex) {
private ProcedureCurrentReturnState(boolean isResultSet, int updateCount, int refCursorParamIndex) {
super( isResultSet, updateCount );
this.refCursorParamIndex = refCursorParamIndex;
}
@Override
public boolean indicatesMoreOutputs() {
return super.indicatesMoreOutputs()
|| ProcedureOutputsImpl.this.refCursorParamIndex < ProcedureOutputsImpl.this.refCursorParameters.length;
}
@Override
protected boolean hasExtendedReturns() {
return refCursorParamIndex < refCursorParameters.length;
}
@Override
protected Output buildExtendedReturn() {
ProcedureOutputsImpl.this.refCursorParamIndex++;
final ParameterRegistrationImplementor refCursorParam = ProcedureOutputsImpl.this.refCursorParameters[refCursorParamIndex];
ResultSet resultSet;
if ( refCursorParam.getName() != null ) {
resultSet = ProcedureOutputsImpl.this.procedureCall.getSession().getFactory().getServiceRegistry()
.getService( RefCursorSupport.class )
.getResultSet( ProcedureOutputsImpl.this.callableStatement, refCursorParam.getName() );
}
else {
resultSet = ProcedureOutputsImpl.this.procedureCall.getSession().getFactory().getServiceRegistry()
.getService( RefCursorSupport.class )
.getResultSet( ProcedureOutputsImpl.this.callableStatement, refCursorParam.getPosition() );
}
return buildResultSetOutput( extractResults( resultSet ) );
}
}
}

View File

@ -32,4 +32,8 @@ public class NoMoreReturnsException extends HibernateException {
public NoMoreReturnsException(String message) {
super( message );
}
public NoMoreReturnsException() {
super( "Results have been exhausted" );
}
}

View File

@ -24,18 +24,18 @@
package org.hibernate.result;
/**
* Common contract for individual return objects which can be either results ({@link ResultSetReturn}) or update
* counts ({@link UpdateCountReturn}).
* Common contract for individual return objects which can be either results ({@link ResultSetOutput}) or update
* counts ({@link UpdateCountOutput}).
*
* @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
* an update count (castable to {@link UpdateCountReturn}).
* Determine if this return is a result (castable to {@link ResultSetOutput}). The alternative is that it is
* an update count (castable to {@link UpdateCountOutput}).
*
* @return {@code true} indicates that {@code this} can be safely cast to {@link ResultSetReturn}), other wise
* it can be cast to {@link UpdateCountReturn}.
* @return {@code true} indicates that {@code this} can be safely cast to {@link ResultSetOutput}), other wise
* it can be cast to {@link UpdateCountOutput}.
*/
public boolean isResultSet();
}

View File

@ -24,27 +24,32 @@
package org.hibernate.result;
/**
* Represents the result of executing a JDBC statement accounting for mixing of result sets and update counts hiding the
* complexity (IMO) of how this is exposed in the JDBC API.
*
* A result is made up of group of {@link Return} objects, each representing a single result set or update count.
* Represents the outputs of executing a JDBC statement accounting for mixing of result sets and update counts
* hiding the complexity (IMO) of how this is exposed in the JDBC API.
* <p/>
* 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.
*
* @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}
* indicates that calling {@link #getNextReturn()} will certainly result in an exception.
* @return The current Output object. Can be {@code null}
*/
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();
}

View File

@ -30,7 +30,7 @@ import java.util.List;
*
* @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.
*

View File

@ -28,7 +28,7 @@ package org.hibernate.result;
*
* @author Steve Ebersole
*/
public interface UpdateCountReturn extends Return {
public interface UpdateCountOutput extends Output {
/**
* Retrieve the associated update count
*

View File

@ -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()
);
}
}
}

View File

@ -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()
);
}
}
}

View File

@ -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 );
}
}
}

View File

@ -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;
}
}

View File

@ -38,6 +38,7 @@ import org.hibernate.testing.junit4.BaseCoreFunctionalTestMethod;
import org.hibernate.testing.junit4.BaseUnitTestCase;
import org.hibernate.type.SerializationException;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.fail;
@ -66,7 +67,11 @@ public class SessionFactorySerializationTest extends BaseCoreFunctionalTestMetho
SessionFactory factory2 = (SessionFactory) SerializationHelper.clone( factory );
assertSame( factory, factory2 );
SessionFactoryRegistry.INSTANCE.removeSessionFactory( "some-other-uuid", NAME, false, null );
factory.close();
assertFalse( SessionFactoryRegistry.INSTANCE.hasRegistrations() );
}
@Test
@ -82,17 +87,20 @@ public class SessionFactorySerializationTest extends BaseCoreFunctionalTestMetho
StringRefAddr refAddr = (StringRefAddr) reference.get( "uuid" );
String uuid = (String) refAddr.getContent();
// 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...
SessionFactoryRegistry.INSTANCE.addSessionFactory( "some-other-uuid", NAME, false, factory, null );
SessionFactoryRegistry.INSTANCE.addSessionFactory( "some-other-uuid", null, false, factory, null );
try {
SerializationHelper.clone( factory );
fail( "Expecting an error" );
}
catch ( SerializationException expected ) {
}
SessionFactoryRegistry.INSTANCE.removeSessionFactory( "some-other-uuid", null, false, null );
factory.close();
assertFalse( SessionFactoryRegistry.INSTANCE.hasRegistrations() );
}
}

View File

@ -56,50 +56,56 @@ public class EmbeddableIntegratorTest extends BaseUnitTestCase {
*/
@Test(expected = GenericJDBCException.class)
public void testWithoutIntegrator() {
ServiceRegistry reg = new StandardServiceRegistryBuilder( new BootstrapServiceRegistryImpl() ).build();
SessionFactory sf = new Configuration().addAnnotatedClass( Investor.class )
.setProperty( "hibernate.hbm2ddl.auto", "create-drop" ).buildSessionFactory( reg );
Session sess = sf.openSession();
Investor myInv = getInvestor();
myInv.setId( 1L );
try {
Session sess = sf.openSession();
Investor myInv = getInvestor();
myInv.setId( 1L );
sess.save( myInv );
sess.flush();
sess.clear();
sess.save( myInv );
sess.flush();
sess.clear();
Investor inv = (Investor) sess.get( Investor.class, 1L );
assertEquals( new BigDecimal( "100" ), inv.getInvestments().get( 0 ).getAmount().getAmount() );
Investor inv = (Investor) sess.get( Investor.class, 1L );
assertEquals( new BigDecimal( "100" ), inv.getInvestments().get( 0 ).getAmount().getAmount() );
sess.close();
sf.close();
StandardServiceRegistryBuilder.destroy( reg );
sess.close();
}
finally {
sf.close();
StandardServiceRegistryBuilder.destroy( reg );
}
}
@Test
public void testWithIntegrator() {
StandardServiceRegistry reg = new StandardServiceRegistryBuilder( new BootstrapServiceRegistryBuilder().with(
new InvestorIntegrator() ).build() ).build();
StandardServiceRegistry reg = new StandardServiceRegistryBuilder(
new BootstrapServiceRegistryBuilder().with( new InvestorIntegrator() ).build()
).build();
SessionFactory sf = new Configuration().addAnnotatedClass( Investor.class )
.setProperty( "hibernate.hbm2ddl.auto", "create-drop" ).buildSessionFactory( reg );
Session sess = sf.openSession();
Investor myInv = getInvestor();
myInv.setId( 2L );
try {
Session sess = sf.openSession();
Investor myInv = getInvestor();
myInv.setId( 2L );
sess.save( myInv );
sess.flush();
sess.clear();
sess.save( myInv );
sess.flush();
sess.clear();
Investor inv = (Investor) sess.get( Investor.class, 2L );
assertEquals( new BigDecimal( "100" ), inv.getInvestments().get( 0 ).getAmount().getAmount() );
Investor inv = (Investor) sess.get( Investor.class, 2L );
assertEquals( new BigDecimal( "100" ), inv.getInvestments().get( 0 ).getAmount().getAmount() );
sess.close();
sf.close();
StandardServiceRegistryBuilder.destroy( reg );
sess.close();
}
finally {
sf.close();
StandardServiceRegistryBuilder.destroy( reg );
}
}
private Investor getInvestor() {

View File

@ -70,6 +70,9 @@ public class OrmVersion1SupportedTest extends BaseCoreFunctionalTestCase {
s.close();
assertEquals( "HHH00196 should not be called", 0, BytemanHelper.getAndResetInvocationCount() );
// which means we also need to close it manually
releaseSessionFactory();
}
@Override

View File

@ -25,7 +25,6 @@ package org.hibernate.test.cfg.cache;
import org.junit.Test;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.testing.FailureExpectedWithNewMetamodel;
import org.hibernate.testing.junit4.BaseUnitTestCase;
@ -44,7 +43,8 @@ public class CacheConfigurationTest extends BaseUnitTestCase {
if(isMetadataUsed()){
throw new IllegalStateException( "what should we do here " );
}
// we only care if the SF builds successfully.
Configuration cfg = new Configuration().configure(CFG_XML);
SessionFactory sessionFactory = cfg.buildSessionFactory();
cfg.buildSessionFactory().close();
}
}

View File

@ -37,14 +37,15 @@ import org.hibernate.dialect.Dialect;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.internal.CriteriaImpl;
import org.hibernate.loader.criteria.CriteriaQueryTranslator;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import org.hibernate.testing.junit4.BaseUnitTestCase;
import static org.junit.Assert.assertEquals;
/**
* @author Steve Ebersole
*/
public class CriterionTest extends BaseCoreFunctionalTestCase {
public class CriterionTest extends BaseUnitTestCase {
@Test
public void testIlikeRendering() {
SessionFactory sf = new Configuration()
@ -52,16 +53,21 @@ public class CriterionTest extends BaseCoreFunctionalTestCase {
.setProperty( AvailableSettings.DIALECT, IlikeSupportingDialect.class.getName() )
.setProperty( Environment.HBM2DDL_AUTO, "create-drop" )
.buildSessionFactory();
final Criteria criteria = sf.openSession().createCriteria( IrrelevantEntity.class );
final CriteriaQueryTranslator translator = new CriteriaQueryTranslator(
(SessionFactoryImplementor) sf,
(CriteriaImpl) criteria,
IrrelevantEntity.class.getName(),
"a"
);
final Criterion ilikeExpression = Restrictions.ilike( "name", "abc" );
final String ilikeExpressionSqlFragment = ilikeExpression.toSqlString( criteria, translator );
assertEquals( "a.name insensitiveLike ?", ilikeExpressionSqlFragment );
try {
final Criteria criteria = sf.openSession().createCriteria( IrrelevantEntity.class );
final CriteriaQueryTranslator translator = new CriteriaQueryTranslator(
(SessionFactoryImplementor) sf,
(CriteriaImpl) criteria,
IrrelevantEntity.class.getName(),
"a"
);
final Criterion ilikeExpression = Restrictions.ilike( "name", "abc" );
final String ilikeExpressionSqlFragment = ilikeExpression.toSqlString( criteria, translator );
assertEquals( "a.name insensitiveLike ?", ilikeExpressionSqlFragment );
}
finally {
sf.close();
}
}
@Test
@ -71,16 +77,21 @@ public class CriterionTest extends BaseCoreFunctionalTestCase {
.setProperty( AvailableSettings.DIALECT, NonIlikeSupportingDialect.class.getName() )
.setProperty( Environment.HBM2DDL_AUTO, "create-drop" )
.buildSessionFactory();
final Criteria criteria = sf.openSession().createCriteria( IrrelevantEntity.class );
final CriteriaQueryTranslator translator = new CriteriaQueryTranslator(
(SessionFactoryImplementor) sf,
(CriteriaImpl) criteria,
IrrelevantEntity.class.getName(),
"a"
);
final Criterion ilikeExpression = Restrictions.ilike( "name", "abc" );
final String ilikeExpressionSqlFragment = ilikeExpression.toSqlString( criteria, translator );
assertEquals( "lowLowLow(a.name) like ?", ilikeExpressionSqlFragment );
try {
final Criteria criteria = sf.openSession().createCriteria( IrrelevantEntity.class );
final CriteriaQueryTranslator translator = new CriteriaQueryTranslator(
(SessionFactoryImplementor) sf,
(CriteriaImpl) criteria,
IrrelevantEntity.class.getName(),
"a"
);
final Criterion ilikeExpression = Restrictions.ilike( "name", "abc" );
final String ilikeExpressionSqlFragment = ilikeExpression.toSqlString( criteria, translator );
assertEquals( "lowLowLow(a.name) like ?", ilikeExpressionSqlFragment );
}
finally {
sf.close();
}
}
public static class IlikeSupportingDialect extends Dialect {

View File

@ -21,15 +21,19 @@
package org.hibernate.test.mapping;
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.metamodel.spi.relational.TableSpecification;
import org.hibernate.test.util.SchemaUtil;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import static org.junit.Assert.assertTrue;
/**
* Column aliases utilize {@link Table#getUniqueInteger()} for naming. The
* 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
*/
@TestForIssue( jiraKey = "HHH-2448" )
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
@TestForIssue( jiraKey = "HHH-2448" )
public void testAliasOrdering() {
TableSpecification table1 = SchemaUtil.getTable( "Table1", metadata() );
TableSpecification table2 = SchemaUtil.getTable( "Table2", metadata() );
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
protected Class<?>[] getAnnotatedClasses() {
return new Class<?>[] { Table1.class, Table2.class };
return new Class<?>[] { Table1.class, Table2.class, ConfEntity.class, UserConfEntity.class, UserEntity.class };
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -27,6 +27,6 @@ public class MappingReorderedAliasTest extends AliasTest {
@Override
protected Class<?>[] getAnnotatedClasses() {
return new Class<?>[] { Table2.class, Table1.class };
return new Class<?>[] { Table2.class, Table1.class, ConfEntity.class, UserConfEntity.class, UserEntity.class };
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -30,24 +30,20 @@ import org.junit.Test;
import org.hibernate.JDBCException;
import org.hibernate.Session;
import org.hibernate.cfg.Configuration;
import org.hibernate.dialect.Dialect;
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.relational.Database;
import org.hibernate.procedure.ProcedureCall;
import org.hibernate.procedure.ProcedureResult;
import org.hibernate.result.ResultSetReturn;
import org.hibernate.result.Return;
import org.hibernate.procedure.ProcedureOutputs;
import org.hibernate.result.ResultSetOutput;
import org.hibernate.result.Output;
import org.hibernate.testing.RequiresDialect;
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.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
/**
@ -305,13 +301,11 @@ public class StoredProcedureTest extends BaseCoreFunctionalTestCase {
Session session = openSession();
session.beginTransaction();
ProcedureCall query = session.createStoredProcedureCall( "user");
ProcedureResult procedureResult = query.getResult();
assertTrue( "Checking ProcedureResult has more returns", procedureResult.hasMoreReturns() );
Return nextReturn = procedureResult.getNextReturn();
assertNotNull( nextReturn );
ExtraAssertions.assertClassAssignability( ResultSetReturn.class, nextReturn.getClass() );
ResultSetReturn resultSetReturn = (ResultSetReturn) nextReturn;
ProcedureCall procedureCall = session.createStoredProcedureCall( "user");
ProcedureOutputs procedureOutputs = procedureCall.getResult();
Output currentOutput = procedureOutputs.getCurrent();
assertNotNull( currentOutput );
ResultSetOutput resultSetReturn = assertTyping( ResultSetOutput.class, currentOutput );
String name = (String) resultSetReturn.getSingleResult();
assertEquals( "SA", name );
@ -325,14 +319,12 @@ public class StoredProcedureTest extends BaseCoreFunctionalTestCase {
session.beginTransaction();
ProcedureCall query = session.createStoredProcedureCall( "findOneUser" );
ProcedureResult procedureResult = query.getResult();
assertTrue( "Checking ProcedureResult has more returns", procedureResult.hasMoreReturns() );
Return nextReturn = procedureResult.getNextReturn();
assertNotNull( nextReturn );
ExtraAssertions.assertClassAssignability( ResultSetReturn.class, nextReturn.getClass() );
ResultSetReturn resultSetReturn = (ResultSetReturn) nextReturn;
ProcedureOutputs procedureResult = query.getResult();
Output currentOutput = procedureResult.getCurrent();
assertNotNull( currentOutput );
ResultSetOutput resultSetReturn = assertTyping( ResultSetOutput.class, currentOutput );
Object result = resultSetReturn.getSingleResult();
ExtraAssertions.assertTyping( Object[].class, result );
assertTyping( Object[].class, result );
String name = (String) ( (Object[]) result )[1];
assertEquals( "Steve", name );
@ -346,17 +338,15 @@ public class StoredProcedureTest extends BaseCoreFunctionalTestCase {
session.beginTransaction();
ProcedureCall query = session.createStoredProcedureCall( "findUsers" );
ProcedureResult procedureResult = query.getResult();
assertTrue( "Checking ProcedureResult has more returns", procedureResult.hasMoreReturns() );
Return nextReturn = procedureResult.getNextReturn();
assertNotNull( nextReturn );
ExtraAssertions.assertClassAssignability( ResultSetReturn.class, nextReturn.getClass() );
ResultSetReturn resultSetReturn = (ResultSetReturn) nextReturn;
ProcedureOutputs procedureResult = query.getResult();
Output currentOutput = procedureResult.getCurrent();
assertNotNull( currentOutput );
ResultSetOutput resultSetReturn = assertTyping( ResultSetOutput.class, currentOutput );
List results = resultSetReturn.getResultList();
assertEquals( 3, results.size() );
for ( Object result : results ) {
ExtraAssertions.assertTyping( Object[].class, result );
assertTyping( Object[].class, result );
Integer id = (Integer) ( (Object[]) result )[0];
String name = (String) ( (Object[]) result )[1];
if ( id.equals( 1 ) ) {
@ -385,16 +375,14 @@ public class StoredProcedureTest extends BaseCoreFunctionalTestCase {
ProcedureCall query = session.createStoredProcedureCall( "findUserRange" );
query.registerParameter( "start", Integer.class, ParameterMode.IN ).bindValue( 1 );
query.registerParameter( "end", Integer.class, ParameterMode.IN ).bindValue( 2 );
ProcedureResult procedureResult = query.getResult();
assertTrue( "Checking ProcedureResult has more returns", procedureResult.hasMoreReturns() );
Return nextReturn = procedureResult.getNextReturn();
assertNotNull( nextReturn );
ExtraAssertions.assertClassAssignability( ResultSetReturn.class, nextReturn.getClass() );
ResultSetReturn resultSetReturn = (ResultSetReturn) nextReturn;
ProcedureOutputs procedureResult = query.getResult();
Output currentOutput = procedureResult.getCurrent();
assertNotNull( currentOutput );
ResultSetOutput resultSetReturn = assertTyping( ResultSetOutput.class, currentOutput );
List results = resultSetReturn.getResultList();
assertEquals( 1, results.size() );
Object result = results.get( 0 );
ExtraAssertions.assertTyping( Object[].class, result );
assertTyping( Object[].class, result );
Integer id = (Integer) ( (Object[]) result )[0];
String name = (String) ( (Object[]) result )[1];
assertEquals( 1, (int) id );
@ -412,16 +400,14 @@ public class StoredProcedureTest extends BaseCoreFunctionalTestCase {
ProcedureCall query = session.createStoredProcedureCall( "findUserRange" );
query.registerParameter( 1, Integer.class, ParameterMode.IN ).bindValue( 1 );
query.registerParameter( 2, Integer.class, ParameterMode.IN ).bindValue( 2 );
ProcedureResult procedureResult = query.getResult();
assertTrue( "Checking ProcedureResult has more returns", procedureResult.hasMoreReturns() );
Return nextReturn = procedureResult.getNextReturn();
assertNotNull( nextReturn );
ExtraAssertions.assertClassAssignability( ResultSetReturn.class, nextReturn.getClass() );
ResultSetReturn resultSetReturn = (ResultSetReturn) nextReturn;
ProcedureOutputs procedureResult = query.getResult();
Output currentOutput = procedureResult.getCurrent();
assertNotNull( currentOutput );
ResultSetOutput resultSetReturn = assertTyping( ResultSetOutput.class, currentOutput );
List results = resultSetReturn.getResultList();
assertEquals( 1, results.size() );
Object result = results.get( 0 );
ExtraAssertions.assertTyping( Object[].class, result );
assertTyping( Object[].class, result );
Integer id = (Integer) ( (Object[]) result )[0];
String name = (String) ( (Object[]) result )[1];
assertEquals( 1, (int) id );
@ -443,9 +429,8 @@ public class StoredProcedureTest extends BaseCoreFunctionalTestCase {
ProcedureCall query = session.createStoredProcedureCall( "findUserRange" );
query.registerParameter( 1, Integer.class, ParameterMode.IN );
query.registerParameter( 2, Integer.class, ParameterMode.IN ).bindValue( 2 );
ProcedureResult procedureResult = query.getResult();
try {
procedureResult.hasMoreReturns();
query.getResult();
fail( "Expecting failure due to missing parameter bind" );
}
catch (JDBCException expected) {
@ -456,9 +441,8 @@ public class StoredProcedureTest extends BaseCoreFunctionalTestCase {
ProcedureCall query = session.createStoredProcedureCall( "findUserRange" );
query.registerParameter( "start", Integer.class, ParameterMode.IN );
query.registerParameter( "end", Integer.class, ParameterMode.IN ).bindValue( 2 );
ProcedureResult procedureResult = query.getResult();
try {
procedureResult.hasMoreReturns();
query.getResult();
fail( "Expecting failure due to missing parameter bind" );
}
catch (JDBCException expected) {

View File

@ -34,6 +34,7 @@ import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.cfg.Configuration;
import org.hibernate.cfg.Environment;
import org.hibernate.engine.FetchStyle;
@ -58,56 +59,59 @@ public class StatsTest extends BaseCoreFunctionalTestCase {
public String[] getMappings() {
return new String[] { "stats/Continent.hbm.xml" };
}
@Override
public void configure(Configuration cfg) {
super.configure( cfg );
cfg.setProperty( Environment.GENERATE_STATISTICS, "true" );
protected void initialize(){
super.initialize();
getTestConfiguration().getProperties().setProperty( Environment.GENERATE_STATISTICS, "true" );
getTestConfiguration().getProperties().setProperty( AvailableSettings.HBM2DDL_AUTO, "create");
}
@Override
protected void prepareStandardServiceRegistryBuilder(StandardServiceRegistryBuilder serviceRegistryBuilder) {
serviceRegistryBuilder.applySetting( Environment.GENERATE_STATISTICS, "true" );
protected boolean createSchema() {
return false;
}
@Test
@SuppressWarnings( {"UnusedAssignment"})
public void testCollectionFetchVsLoad() throws Exception {
Statistics stats = sessionFactory().getStatistics();
stats.clear();
SessionFactory sf =sessionFactory();
Session s = openSession();
Session s = sf.openSession();
Transaction tx = s.beginTransaction();
Continent europe = fillDb(s);
tx.commit();
s.clear();
s.close();
s = sf.openSession();
tx = s.beginTransaction();
assertEquals(0, stats.getCollectionLoadCount() );
assertEquals(0, stats.getCollectionFetchCount() );
assertEquals(0, sf.getStatistics().getCollectionLoadCount() );
assertEquals(0, sf.getStatistics().getCollectionFetchCount() );
Continent europe2 = (Continent) s.get( Continent.class, europe.getId() );
assertEquals("Lazy true: no collection should be loaded", 0, stats.getCollectionLoadCount() );
assertEquals( 0, stats.getCollectionFetchCount() );
assertEquals("Lazy true: no collection should be loaded", 0, sf.getStatistics().getCollectionLoadCount() );
assertEquals( 0, sf.getStatistics().getCollectionFetchCount() );
europe2.getCountries().size();
assertEquals( 1, stats.getCollectionLoadCount() );
assertEquals("Explicit fetch of the collection state", 1, stats.getCollectionFetchCount() );
assertEquals( 1, sf.getStatistics().getCollectionLoadCount() );
assertEquals("Explicit fetch of the collection state", 1, sf.getStatistics().getCollectionFetchCount() );
tx.commit();
s.close();
s = openSession();
sf.getStatistics().clear();
s = sf.openSession();
tx = s.beginTransaction();
stats.clear();
europe = fillDb(s);
tx.commit();
s.clear();
tx = s.beginTransaction();
assertEquals( 0, stats.getCollectionLoadCount() );
assertEquals( 0, stats.getCollectionFetchCount() );
assertEquals( 0, sf.getStatistics().getCollectionLoadCount() );
assertEquals( 0, sf.getStatistics().getCollectionFetchCount() );
europe2 = (Continent) s.createQuery(
"from " + Continent.class.getName() + " a join fetch a.countries where a.id = " + europe.getId()
).uniqueResult();
assertEquals( 1, stats.getCollectionLoadCount() );
assertEquals( "collection should be loaded in the same query as its parent", 0, stats.getCollectionFetchCount() );
assertEquals( 1, sf.getStatistics().getCollectionLoadCount() );
assertEquals( "collection should be loaded in the same query as its parent", 0, sf.getStatistics().getCollectionFetchCount() );
tx.commit();
s.close();
@ -115,21 +119,23 @@ public class StatsTest extends BaseCoreFunctionalTestCase {
PluralAttributeBinding coll = SchemaUtil.getCollection( Continent.class, "countries", metadata() );
coll.setFetchStyle( FetchStyle.JOIN );
coll.setFetchTiming( FetchTiming.IMMEDIATE );
SessionFactory sf = metadata().getSessionFactoryBuilder().build();
stats = sf.getStatistics();
sf = metadata().getSessionFactoryBuilder().build();
Statistics stats = sf.getStatistics();
stats.clear();
stats.setStatisticsEnabled(true);
s = sf.openSession();
tx = s.beginTransaction();
europe = fillDb(s);
tx.commit();
s.clear();
s.close();
s = sf.openSession();
tx = s.beginTransaction();
assertEquals( 0, stats.getCollectionLoadCount() );
assertEquals( 0, stats.getCollectionFetchCount() );
assertEquals( 0, sf.getStatistics().getCollectionLoadCount() );
assertEquals( 0, sf.getStatistics().getCollectionFetchCount() );
europe2 = (Continent) s.get( Continent.class, europe.getId() );
assertEquals( 1, stats.getCollectionLoadCount() );
assertEquals( "Should do direct load, not indirect second load when lazy false and JOIN", 0, stats.getCollectionFetchCount() );
assertEquals( 1, sf.getStatistics().getCollectionLoadCount() );
assertEquals( "Should do direct load, not indirect second load when lazy false and JOIN", 0, sf.getStatistics().getCollectionFetchCount() );
tx.commit();
s.close();
sf.close();
@ -146,42 +152,45 @@ public class StatsTest extends BaseCoreFunctionalTestCase {
tx = s.beginTransaction();
europe = fillDb(s);
tx.commit();
s.clear();
s.close();
s = sf.openSession();
tx = s.beginTransaction();
assertEquals( 0, stats.getCollectionLoadCount() );
assertEquals( 0, stats.getCollectionFetchCount() );
assertEquals( 0, sf.getStatistics().getCollectionLoadCount() );
assertEquals( 0, sf.getStatistics().getCollectionFetchCount() );
europe2 = (Continent) s.get( Continent.class, europe.getId() );
assertEquals( 1, stats.getCollectionLoadCount() );
assertEquals( "Should do explicit collection load, not part of the first one", 1, stats.getCollectionFetchCount() );
assertEquals( 1, sf.getStatistics().getCollectionLoadCount() );
assertEquals( "Should do explicit collection load, not part of the first one", 1, sf.getStatistics().getCollectionFetchCount() );
for ( Object o : europe2.getCountries() ) {
s.delete( o );
}
cleanDb( s );
tx.commit();
s.close();
sf.close();
}
@Test
public void testQueryStatGathering() {
Statistics stats = sessionFactory().getStatistics();
stats.clear();
SessionFactory sf = sessionFactory();
Session s = openSession();
Session s = sf.openSession();
Transaction tx = s.beginTransaction();
fillDb(s);
tx.commit();
s.close();
s = openSession();
s = sf.openSession();
tx = s.beginTransaction();
final String continents = "from Continent";
int results = s.createQuery( continents ).list().size();
QueryStatistics continentStats = stats.getQueryStatistics( continents );
QueryStatistics continentStats = sf.getStatistics().getQueryStatistics( continents );
assertNotNull( "stats were null", continentStats );
assertEquals( "unexpected execution count", 1, continentStats.getExecutionCount() );
assertEquals( "unexpected row count", results, continentStats.getExecutionRowCount() );
long maxTime = continentStats.getExecutionMaxTime();
assertEquals( maxTime, stats.getQueryExecutionMaxTime() );
assertEquals( maxTime, sf.getStatistics().getQueryExecutionMaxTime() );
// assertEquals( continents, stats.getQueryExecutionMaxTimeQueryString() );
Iterator itr = s.createQuery( continents ).iterate();
@ -206,44 +215,47 @@ public class StatsTest extends BaseCoreFunctionalTestCase {
// explicitly check that statistics for "split queries" get collected
// under the original query
stats.clear();
s = openSession();
sf.getStatistics().clear();
s = sf.openSession();
tx = s.beginTransaction();
final String localities = "from Locality";
results = s.createQuery( localities ).list().size();
QueryStatistics localityStats = stats.getQueryStatistics( localities );
QueryStatistics localityStats = sf.getStatistics().getQueryStatistics( localities );
assertNotNull( "stats were null", localityStats );
// ...one for each split query
assertEquals( "unexpected execution count", 2, localityStats.getExecutionCount() );
assertEquals( "unexpected row count", results, localityStats.getExecutionRowCount() );
maxTime = localityStats.getExecutionMaxTime();
assertEquals( maxTime, stats.getQueryExecutionMaxTime() );
assertEquals( maxTime, sf.getStatistics().getQueryExecutionMaxTime() );
// assertEquals( localities, stats.getQueryExecutionMaxTimeQueryString() );
tx.commit();
s.close();
assertFalse( s.isOpen() );
// native sql queries
stats.clear();
s = openSession();
sf.getStatistics().clear();
s = sf.openSession();
tx = s.beginTransaction();
final String sql = "select id, name from Country";
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 );
assertEquals( "unexpected execution count", 1, sqlStats.getExecutionCount() );
assertEquals( "unexpected row count", results, sqlStats.getExecutionRowCount() );
maxTime = sqlStats.getExecutionMaxTime();
assertEquals( maxTime, stats.getQueryExecutionMaxTime() );
assertEquals( maxTime, sf.getStatistics().getQueryExecutionMaxTime() );
// assertEquals( sql, stats.getQueryExecutionMaxTimeQueryString() );
tx.commit();
s.close();
s = openSession();
s = sf.openSession();
tx = s.beginTransaction();
cleanDb( s );
tx.commit();
s.close();
sf.close();
}
private Continent fillDb(Session s) {

View File

@ -22,6 +22,9 @@ dependencies {
testRuntime( libraries.validator )
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" )
// for testing stored procedure support
testCompile( libraries.derby )
}
def pomName() {

View File

@ -24,7 +24,6 @@
package org.hibernate.jpa.event.internal.jpa;
import javax.persistence.PersistenceException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.hibernate.jpa.event.spi.jpa.ListenerFactory;
@ -36,7 +35,8 @@ import org.hibernate.jpa.event.spi.jpa.ListenerFactory;
* @author Steve Ebersole
*/
public class StandardListenerFactory implements ListenerFactory {
private Map listenerInstances = new ConcurrentHashMap();
private final ConcurrentHashMap listenerInstances = new ConcurrentHashMap();
@Override
@SuppressWarnings("unchecked")
@ -52,7 +52,10 @@ public class StandardListenerFactory implements ListenerFactory {
e
);
}
listenerInstances.put( listenerClass, listenerInstance );
Object existing = listenerInstances.putIfAbsent( listenerClass, listenerInstance );
if ( existing != null ) {
listenerInstance = existing;
}
}
return (T) listenerInstance;
}

View File

@ -269,6 +269,8 @@ public class EntityManagerFactoryImpl implements HibernateEntityManagerFactory {
@Override
public EntityManager createEntityManager(SynchronizationType synchronizationType, Map map) {
validateNotClosed();
//TODO support discardOnClose, persistencecontexttype?, interceptor,
return new EntityManagerImpl(
this,
@ -282,42 +284,49 @@ public class EntityManagerFactoryImpl implements HibernateEntityManagerFactory {
}
public CriteriaBuilder getCriteriaBuilder() {
validateNotClosed();
return criteriaBuilder;
}
public Metamodel getMetamodel() {
validateNotClosed();
return metamodel;
}
public void close() {
// The spec says so, that's why :(
validateNotClosed();
sessionFactory.close();
EntityManagerFactoryRegistry.INSTANCE.removeEntityManagerFactory(entityManagerFactoryName, this);
}
public Map<String, Object> getProperties() {
validateNotClosed();
return properties;
}
public Cache getCache() {
validateNotClosed();
// TODO : cache the cache reference?
if ( ! isOpen() ) {
throw new IllegalStateException("EntityManagerFactory is closed");
}
return new JPACache( sessionFactory );
}
public PersistenceUnitUtil getPersistenceUnitUtil() {
protected void validateNotClosed() {
if ( ! isOpen() ) {
throw new IllegalStateException("EntityManagerFactory is closed");
throw new IllegalStateException( "EntityManagerFactory is closed" );
}
}
public PersistenceUnitUtil getPersistenceUnitUtil() {
validateNotClosed();
return util;
}
@Override
public void addNamedQuery(String name, Query query) {
if ( ! isOpen() ) {
throw new IllegalStateException( "EntityManagerFactory is closed" );
}
validateNotClosed();
if ( StoredProcedureQueryImpl.class.isInstance( query ) ) {
final ProcedureCall procedureCall = ( (StoredProcedureQueryImpl) query ).getHibernateProcedureCall();

View File

@ -197,7 +197,7 @@ public class EntityManagerImpl extends AbstractEntityManagerImpl implements Sess
@Override
@SuppressWarnings("unchecked")
public <T> EntityGraph<T> getEntityGraph(String graphName) {
public EntityGraph<?> getEntityGraph(String graphName) {
checkOpen();
final EntityGraphImpl named = getEntityManagerFactory().findEntityGraphByName( graphName );
if ( named == null ) {

View File

@ -23,13 +23,10 @@
*/
package org.hibernate.jpa.internal;
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 static javax.persistence.TemporalType.DATE;
import static javax.persistence.TemporalType.TIME;
import static javax.persistence.TemporalType.TIMESTAMP;
import java.util.Calendar;
import java.util.Collection;
import java.util.Collections;
@ -39,7 +36,13 @@ import java.util.List;
import java.util.Map;
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.FlushMode;
@ -59,10 +62,8 @@ import org.hibernate.jpa.internal.util.LockModeTypeHelper;
import org.hibernate.jpa.spi.AbstractEntityManagerImpl;
import org.hibernate.jpa.spi.AbstractQueryImpl;
import org.hibernate.type.CompositeCustomType;
import static javax.persistence.TemporalType.DATE;
import static javax.persistence.TemporalType.TIME;
import static javax.persistence.TemporalType.TIMESTAMP;
import org.hibernate.type.Type;
import org.jboss.logging.Logger;
/**
* 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() ) {
final NamedParameterDescriptor descriptor = parameterMetadata.getNamedParameterDescriptor( name );
Class javaType = namedParameterTypeRedefinition.get( name );
if ( javaType != null && mightNeedRedefinition( javaType, descriptor.getExpectedType().getClass() ) ) {
if ( javaType != null && mightNeedRedefinition( javaType, descriptor.getExpectedType() ) ) {
descriptor.resetExpectedType(
sfi().getTypeResolver().heuristicType( javaType.getName() )
);
@ -136,10 +137,13 @@ public class QueryImpl<X> extends AbstractQueryImpl<X> implements TypedQuery<X>,
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
return java.util.Date.class.isAssignableFrom( javaType )
&& !CompositeCustomType.class.isAssignableFrom( expectedType );
if ( expectedType == null )
return java.util.Date.class.isAssignableFrom( javaType );
else
return java.util.Date.class.isAssignableFrom( javaType )
&& !CompositeCustomType.class.isAssignableFrom( expectedType.getClass() );
}
private static class ParameterRegistrationImpl<T> implements ParameterRegistration<T> {

View File

@ -25,11 +25,15 @@ package org.hibernate.jpa.internal;
import javax.persistence.FlushModeType;
import javax.persistence.LockModeType;
import javax.persistence.NoResultException;
import javax.persistence.NonUniqueResultException;
import javax.persistence.Parameter;
import javax.persistence.ParameterMode;
import javax.persistence.PersistenceException;
import javax.persistence.Query;
import javax.persistence.StoredProcedureQuery;
import javax.persistence.TemporalType;
import javax.persistence.TransactionRequiredException;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
@ -37,11 +41,15 @@ import java.util.List;
import org.hibernate.CacheMode;
import org.hibernate.FlushMode;
import org.hibernate.LockMode;
import org.hibernate.procedure.NoSuchParameterException;
import org.hibernate.procedure.ParameterStrategyException;
import org.hibernate.procedure.ProcedureCall;
import org.hibernate.procedure.ProcedureResult;
import org.hibernate.result.ResultSetReturn;
import org.hibernate.result.Return;
import org.hibernate.result.UpdateCountReturn;
import org.hibernate.procedure.ProcedureCallMemento;
import org.hibernate.procedure.ProcedureOutputs;
import org.hibernate.result.NoMoreReturnsException;
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.HibernateEntityManagerImplementor;
@ -50,13 +58,28 @@ import org.hibernate.jpa.spi.HibernateEntityManagerImplementor;
*/
public class StoredProcedureQueryImpl extends BaseQueryImpl implements StoredProcedureQuery {
private final ProcedureCall procedureCall;
private ProcedureResult procedureResult;
private ProcedureOutputs procedureResult;
public StoredProcedureQueryImpl(ProcedureCall procedureCall, HibernateEntityManagerImplementor entityManager) {
super( entityManager );
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
protected boolean applyTimeoutHint(int timeout) {
procedureCall.setTimeout( timeout );
@ -178,81 +201,162 @@ public class StoredProcedureQueryImpl extends BaseQueryImpl implements StoredPro
// 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 ) {
procedureResult = procedureCall.getResult();
}
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
public Object getOutputParameterValue(int position) {
return outputs().getOutputParameterValue( position );
try {
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
public Object getOutputParameterValue(String parameterName) {
return outputs().getOutputParameterValue( parameterName );
}
@Override
public boolean execute() {
return outputs().hasMoreReturns();
}
@Override
public int executeUpdate() {
return getUpdateCount();
try {
return outputs().getOutputParameterValue( parameterName );
}
catch (ParameterStrategyException e) {
throw new IllegalArgumentException( "Invalid mix of named and positional parameters", e );
}
catch (NoSuchParameterException e) {
throw new IllegalArgumentException( e.getMessage(), e );
}
}
@Override
public boolean hasMoreResults() {
return outputs().hasMoreReturns();
return outputs().goToNext() && ResultSetOutput.class.isInstance( outputs().getCurrent() );
}
@Override
public int getUpdateCount() {
final Return nextReturn = outputs().getNextReturn();
if ( nextReturn.isResultSet() ) {
try {
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 ( (UpdateCountReturn) nextReturn ).getUpdateCount();
}
@Override
public List getResultList() {
final Return nextReturn = outputs().getNextReturn();
if ( ! nextReturn.isResultSet() ) {
return null; // todo : what should be thrown/returned here?
try {
final Output rtn = outputs().getCurrent();
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
public Object getSingleResult() {
final Return nextReturn = outputs().getNextReturn();
if ( ! nextReturn.isResultSet() ) {
return null; // todo : what should be thrown/returned here?
final List resultList = getResultList();
if ( resultList == null || resultList.isEmpty() ) {
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
@SuppressWarnings("unchecked")
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(
String.format(
"Unsure how to unwrap %s impl [%s] as requested type [%s]",
StoredProcedureQuery.class.getSimpleName(),
this.getClass().getName(),
cls.getName()
)
);
}
// ugh ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@Override
public Query setLockMode(LockModeType lockMode) {
return null;
throw new IllegalStateException( "javax.persistence.Query.setLockMode not valid on javax.persistence.StoredProcedureQuery" );
}
@Override
public LockModeType getLockMode() {
return null;
throw new IllegalStateException( "javax.persistence.Query.getLockMode not valid on javax.persistence.StoredProcedureQuery" );
}

View File

@ -28,6 +28,7 @@ import java.sql.Connection;
import java.sql.SQLException;
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.spi.SqlStatementLogger;
@ -38,6 +39,8 @@ import org.hibernate.engine.jdbc.spi.SqlStatementLogger;
* @author Steve Ebersole
*/
class JdbcConnectionContext {
private static final Logger log = Logger.getLogger( JdbcConnectionContext.class );
private final JdbcConnectionAccess jdbcConnectionAccess;
private final SqlStatementLogger sqlStatementLogger;
@ -62,6 +65,15 @@ class JdbcConnectionContext {
public void release() {
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 {
jdbcConnectionAccess.releaseConnection( jdbcConnection );
}

View File

@ -838,8 +838,7 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage
if ( memento == null ) {
throw new IllegalArgumentException( "No @NamedStoredProcedureQuery was found with that name : " + name );
}
final ProcedureCall procedureCall = memento.makeProcedureCall( internalGetSession() );
final StoredProcedureQueryImpl jpaImpl = new StoredProcedureQueryImpl( procedureCall, this );
final StoredProcedureQueryImpl jpaImpl = new StoredProcedureQueryImpl( memento, this );
// apply hints
if ( memento.getHintsMap() != null ) {
for ( Map.Entry<String,Object> hintEntry : memento.getHintsMap().entrySet() ) {

View File

@ -51,6 +51,8 @@ import org.hibernate.jpa.internal.EntityManagerMessageLogger;
import org.hibernate.jpa.internal.util.CacheModeHelper;
import org.hibernate.jpa.internal.util.ConfigurationHelper;
import org.hibernate.jpa.internal.util.LockModeTypeHelper;
import org.hibernate.procedure.NoSuchParameterException;
import org.hibernate.procedure.ParameterStrategyException;
import static org.hibernate.jpa.QueryHints.HINT_CACHEABLE;
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);
/**
* 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> {
/**
@ -450,6 +453,12 @@ public abstract class BaseQueryImpl implements Query {
*/
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 void bindValue(T value);
@ -459,6 +468,11 @@ public abstract class BaseQueryImpl implements Query {
public ParameterBind<T> getBind();
}
/**
* Represents the value currently bound to a particular parameter.
*
* @param <T>
*/
protected static interface ParameterBind<T> {
public T getValue();
@ -648,6 +662,12 @@ public abstract class BaseQueryImpl implements Query {
try {
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) {
throw new IllegalArgumentException( e );
}
@ -755,16 +775,20 @@ public abstract class BaseQueryImpl implements Query {
checkOpen( false );
final ParameterRegistration<T> registration = findParameterRegistration( param );
if ( registration != null ) {
if ( ! registration.isBindable() ) {
throw new IllegalArgumentException( "Passed parameter [" + param + "] is not bindable" );
}
final ParameterBind<T> bind = registration.getBind();
if ( bind != null ) {
return bind.getValue();
}
if ( registration == null ) {
throw new IllegalArgumentException( "Passed parameter [" + param + "] is not a (registered) parameter of this query" );
}
throw new IllegalStateException( "Parameter [" + param + "] has not yet been bound" );
if ( ! registration.isBindable() ) {
throw new IllegalStateException( "Passed parameter [" + param + "] is not bindable" );
}
final ParameterBind<T> bind = registration.getBind();
if ( bind == null ) {
throw new IllegalStateException( "Parameter [" + param + "] has not yet been bound" );
}
return bind.getValue();
}
@Override

View File

@ -32,6 +32,7 @@ import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.ParameterExpression;
import javax.persistence.criteria.Predicate;
@ -103,4 +104,26 @@ public class BasicCriteriaUsageTest extends BaseEntityManagerFunctionalTestCase
em.getTransaction().commit();
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();
}
}

View File

@ -91,7 +91,7 @@ public class BasicEntityGraphTests extends BaseEntityManagerFunctionalTestCase {
em.getEntityManagerFactory().addNamedEntityGraph( "immutable", graphRoot );
graphRoot = em.getEntityGraph( "immutable" );
graphRoot = (EntityGraph<Entity1>) em.getEntityGraph( "immutable" );
assertEquals( "immutable", graphRoot.getName() );
assertEquals( 2, graphRoot.getAttributeNodes().size() );

View File

@ -52,13 +52,13 @@ public abstract class AbstractStoredProcedureTest extends BaseEntityManagerFunct
list = m2.getParameterDeclarations();
memento = list.get( 0 );
assertEquals( Integer.valueOf( 0 ), memento.getPosition() );
assertEquals( Integer.valueOf( 1 ), memento.getPosition() );
assertEquals( javax.persistence.ParameterMode.INOUT, memento.getMode() );
assertEquals( StringType.INSTANCE, memento.getHibernateType() );
assertEquals( String.class, memento.getType() );
memento = list.get( 1 );
assertEquals( Integer.valueOf( 1 ), memento.getPosition() );
assertEquals( Integer.valueOf( 2 ), memento.getPosition() );
assertEquals( javax.persistence.ParameterMode.INOUT, memento.getMode() );
assertEquals( LongType.INSTANCE, memento.getHibernateType() );
assertEquals( Long.class, memento.getType() );

View File

@ -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 );
}
}
}

View File

@ -9,6 +9,7 @@ import javax.persistence.NamedStoredProcedureQuery;
import javax.persistence.ParameterMode;
import javax.persistence.SqlResultSetMapping;
import javax.persistence.StoredProcedureParameter;
import javax.persistence.Table;
/**
* @author Strong Liu <stliu@hibernate.org>
@ -43,6 +44,13 @@ import javax.persistence.StoredProcedureParameter;
},
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 {
@Id
private int id;
private String name;
public User() {
}
public User(int id, String name) {
this.id = id;
this.name = name;
}
public int getId() {
return id;
}

View File

@ -21,6 +21,7 @@
# 51 Franklin Street, Fifth Floor
# Boston, MA 02110-1301 USA
#
hibernate.dialect org.hibernate.dialect.H2Dialect
hibernate.connection.driver_class org.h2.Driver
hibernate.connection.url jdbc:h2:mem:db1;DB_CLOSE_DELAY=-1;MVCC=TRUE;LOCK_TIMEOUT=10000

View File

@ -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}.
*/
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";
}

View File

@ -75,12 +75,15 @@ public class GlobalConfiguration {
// Use revision entity with native id generator
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
a correlated subquery, for example: e.p <operator> (select max(e2.p) where e2.p2 = e.p2 ...).
Normally, this should be "=". However, HSQLDB has an issue related to that, so as a workaround,
"in" is used. See {@link org.hibernate.envers.test.various.HsqlTest}.
*/
*/
private final String correlatedSubqueryOperator;
public GlobalConfiguration(Properties properties, ClassLoaderService classLoaderService) {
@ -131,6 +134,10 @@ public class GlobalConfiguration {
else {
revisionListenerClass = null;
}
allowIdentifierReuse = ConfigurationHelper.getBoolean(
EnversSettings.ALLOW_IDENTIFIER_REUSE, properties, false
);
}
public boolean isGenerateRevisionsForCollections() {
@ -184,4 +191,8 @@ public class GlobalConfiguration {
public boolean isUseRevisionEntityWithNativeId() {
return useRevisionEntityWithNativeId;
}
public boolean isAllowIdentifierReuse() {
return allowIdentifierReuse;
}
}

View File

@ -73,7 +73,7 @@ public final class OneAuditEntityQueryGenerator extends AbstractRelationQueryGen
final QueryBuilder validQuery = commonPart.deepCopy();
final QueryBuilder removedQuery = commonPart.deepCopy();
createValidDataRestrictions(
globalCfg, auditStrategy, referencedIdData, validQuery, validQuery.getRootParameters(), true
globalCfg, auditStrategy, referencedIdData, validQuery, validQuery.getRootParameters()
);
createValidAndRemovedDataRestrictions( globalCfg, auditStrategy, referencedIdData, removedQuery );
@ -99,8 +99,7 @@ public final class OneAuditEntityQueryGenerator extends AbstractRelationQueryGen
*/
private void createValidDataRestrictions(
GlobalConfiguration globalCfg, AuditStrategy auditStrategy,
MiddleIdData referencedIdData, QueryBuilder qb, Parameters rootParameters,
boolean inclusive) {
MiddleIdData referencedIdData, QueryBuilder qb, Parameters rootParameters) {
final String revisionPropertyPath = verEntCfg.getRevisionNumberPath();
// (selecting e entities at revision :revision)
// --> based on auditStrategy (see above)
@ -108,7 +107,7 @@ public final class OneAuditEntityQueryGenerator extends AbstractRelationQueryGen
globalCfg, qb, rootParameters, revisionPropertyPath,
verEntCfg.getRevisionEndFieldName(), true, referencedIdData, revisionPropertyPath,
verEntCfg.getOriginalIdPropName(), REFERENCED_ENTITY_ALIAS, REFERENCED_ENTITY_ALIAS_DEF_AUD_STR,
inclusive
true
);
// e.revision_type != DEL
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.
final Parameters removed = disjoint.addSubParameters( "and" );
// 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
removed.addWhereWithNamedParam( verEntCfg.getRevisionNumberPath(), false, "=", REVISION_PARAMETER );
// e.revision_type = DEL

View File

@ -180,7 +180,7 @@ public final class ThreeEntityQueryGenerator extends AbstractRelationQueryGenera
originalIdPropertyName,
REFERENCED_ENTITY_ALIAS,
REFERENCED_ENTITY_ALIAS_DEF_AUD_STR,
inclusive
true
);
// (selecting f entities at revision :revision)
// --> based on auditStrategy (see above)
@ -188,15 +188,15 @@ public final class ThreeEntityQueryGenerator extends AbstractRelationQueryGenera
globalCfg,
qb,
rootParameters,
REFERENCED_ENTITY_ALIAS + "." + revisionPropertyPath,
REFERENCED_ENTITY_ALIAS + "." + verEntCfg.getRevisionEndFieldName(),
INDEX_ENTITY_ALIAS + "." + revisionPropertyPath,
INDEX_ENTITY_ALIAS + "." + verEntCfg.getRevisionEndFieldName(),
false,
referencedIdData,
revisionPropertyPath,
originalIdPropertyName,
INDEX_ENTITY_ALIAS,
INDEX_ENTITY_ALIAS_DEF_AUD_STR,
inclusive
true
);
// (with ee association at revision :revision)
// --> based on auditStrategy (see above)

View File

@ -152,7 +152,7 @@ public final class TwoEntityQueryGenerator extends AbstractRelationQueryGenerato
originalIdPropertyName,
REFERENCED_ENTITY_ALIAS,
REFERENCED_ENTITY_ALIAS_DEF_AUD_STR,
inclusive
true
);
// (with ee association at revision :revision)
// --> based on auditStrategy (see above)

View File

@ -98,8 +98,15 @@ public class ValidityAuditStrategy implements AuditStrategy {
session.save( auditedEntityName, data );
sessionCacheCleaner.scheduleAuditDataRemoval( session, data );
// Update the end date of the previous row if this operation is expected to have a previous row
if ( getRevisionType( auditCfg, data ) != RevisionType.ADD ) {
// Update the end date of the previous row.
//
// 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 rootProductionEntityQueryable = getQueryable(
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(
"Cannot update previous revision for entity " + auditedEntityName + " and id " + id
);

View File

@ -58,9 +58,9 @@ public class CollectionRefIngEntity implements Serializable {
this.reference = reference;
}
public CollectionRefIngEntity(String data, CollectionRefEdEntity reference) {
public CollectionRefIngEntity(Integer id, String data) {
this.id = id;
this.data = data;
this.reference = reference;
}
public Integer getId() {

View File

@ -106,7 +106,6 @@ public class NotOwnedBidirectional extends BaseEnversJPAFunctionalTestCase {
@Test
public void testHistoryOfPersonalContact() {
System.out.println( getAuditReader().find( PersonalContact.class, pc_id, 1 ).getAddresses() );
assert getAuditReader().find( PersonalContact.class, pc_id, 1 ).getAddresses().equals(
TestTools.makeSet( new Address( a1_id, "a1" ) )
);

View File

@ -106,7 +106,6 @@ public class NotOwnedBidirectional extends BaseEnversJPAFunctionalTestCase {
@Test
public void testHistoryOfPersonalContact() {
System.out.println( getAuditReader().find( PersonalContact.class, pc_id, 1 ).getAddresses() );
assert getAuditReader().find( PersonalContact.class, pc_id, 1 ).getAddresses().equals(
TestTools.makeSet( new Address( a1_id, "a1" ) )
);

View File

@ -156,10 +156,10 @@ public class BasicList extends BaseEnversJPAFunctionalTestCase {
ListOwnedEntity rev5 = getAuditReader().find( ListOwnedEntity.class, ed1_id, 5 );
assert rev1.getReferencing().equals( Collections.EMPTY_LIST );
assert TestTools.checkList( rev2.getReferencing(), ing1, ing2 );
assert TestTools.checkList( rev3.getReferencing(), ing1, ing2 );
assert TestTools.checkList( rev4.getReferencing(), ing2 );
assert TestTools.checkList( rev5.getReferencing(), ing2 );
assert TestTools.checkCollection( rev2.getReferencing(), ing1, ing2 );
assert TestTools.checkCollection( rev3.getReferencing(), ing1, ing2 );
assert TestTools.checkCollection( rev4.getReferencing(), ing2 );
assert TestTools.checkCollection( rev5.getReferencing(), ing2 );
}
@Test
@ -174,10 +174,10 @@ public class BasicList extends BaseEnversJPAFunctionalTestCase {
ListOwnedEntity rev5 = getAuditReader().find( ListOwnedEntity.class, ed2_id, 5 );
assert rev1.getReferencing().equals( Collections.EMPTY_LIST );
assert TestTools.checkList( rev2.getReferencing(), ing2 );
assert TestTools.checkList( rev3.getReferencing(), ing1, ing2 );
assert TestTools.checkList( rev4.getReferencing(), ing1, ing2 );
assert TestTools.checkList( rev5.getReferencing(), ing2 );
assert TestTools.checkCollection( rev2.getReferencing(), ing2 );
assert TestTools.checkCollection( rev3.getReferencing(), ing1, ing2 );
assert TestTools.checkCollection( rev4.getReferencing(), ing1, ing2 );
assert TestTools.checkCollection( rev5.getReferencing(), ing2 );
}
@Test
@ -192,9 +192,9 @@ public class BasicList extends BaseEnversJPAFunctionalTestCase {
ListOwningEntity rev5 = getAuditReader().find( ListOwningEntity.class, ing1_id, 5 );
assert rev1.getReferences().equals( Collections.EMPTY_LIST );
assert TestTools.checkList( rev2.getReferences(), ed1 );
assert TestTools.checkList( rev3.getReferences(), ed1, ed2 );
assert TestTools.checkList( rev4.getReferences(), ed2 );
assert TestTools.checkCollection( rev2.getReferences(), ed1 );
assert TestTools.checkCollection( rev3.getReferences(), ed1, ed2 );
assert TestTools.checkCollection( rev4.getReferences(), ed2 );
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 );
assert rev1.getReferences().equals( Collections.EMPTY_LIST );
assert TestTools.checkList( rev2.getReferences(), ed1, ed2 );
assert TestTools.checkList( rev3.getReferences(), ed1, ed2 );
assert TestTools.checkList( rev4.getReferences(), ed1, ed2 );
assert TestTools.checkList( rev5.getReferences(), ed1, ed2 );
assert TestTools.checkCollection( rev2.getReferences(), ed1, ed2 );
assert TestTools.checkCollection( rev3.getReferences(), ed1, ed2 );
assert TestTools.checkCollection( rev4.getReferences(), ed1, ed2 );
assert TestTools.checkCollection( rev5.getReferences(), ed1, ed2 );
}
}

View File

@ -150,16 +150,16 @@ public class BasicWhereJoinTable extends BaseEnversJPAFunctionalTestCase {
WhereJoinTableEntity rev4 = getAuditReader().find( WhereJoinTableEntity.class, wjte1_id, 4 );
// Checking 1st list
assert TestTools.checkList( rev1.getReferences1() );
assert TestTools.checkList( rev2.getReferences1(), ite1_1 );
assert TestTools.checkList( rev3.getReferences1(), ite1_1 );
assert TestTools.checkList( rev4.getReferences1() );
assert TestTools.checkCollection( rev1.getReferences1() );
assert TestTools.checkCollection( rev2.getReferences1(), ite1_1 );
assert TestTools.checkCollection( rev3.getReferences1(), ite1_1 );
assert TestTools.checkCollection( rev4.getReferences1() );
// Checking 2nd list
assert TestTools.checkList( rev1.getReferences2() );
assert TestTools.checkList( rev2.getReferences2(), ite2_1 );
assert TestTools.checkList( rev3.getReferences2(), ite2_1 );
assert TestTools.checkList( rev4.getReferences2(), ite2_1 );
assert TestTools.checkCollection( rev1.getReferences2() );
assert TestTools.checkCollection( rev2.getReferences2(), ite2_1 );
assert TestTools.checkCollection( rev3.getReferences2(), ite2_1 );
assert TestTools.checkCollection( rev4.getReferences2(), ite2_1 );
}
@Test
@ -174,15 +174,15 @@ public class BasicWhereJoinTable extends BaseEnversJPAFunctionalTestCase {
WhereJoinTableEntity rev4 = getAuditReader().find( WhereJoinTableEntity.class, wjte2_id, 4 );
// Checking 1st list
assert TestTools.checkList( rev1.getReferences1() );
assert TestTools.checkList( rev2.getReferences1() );
assert TestTools.checkList( rev3.getReferences1(), ite1_1, ite1_2 );
assert TestTools.checkList( rev4.getReferences1(), ite1_1, ite1_2 );
assert TestTools.checkCollection( rev1.getReferences1() );
assert TestTools.checkCollection( rev2.getReferences1() );
assert TestTools.checkCollection( rev3.getReferences1(), ite1_1, ite1_2 );
assert TestTools.checkCollection( rev4.getReferences1(), ite1_1, ite1_2 );
// Checking 2nd list
assert TestTools.checkList( rev1.getReferences2() );
assert TestTools.checkList( rev2.getReferences2() );
assert TestTools.checkList( rev3.getReferences2() );
assert TestTools.checkList( rev4.getReferences2(), ite2_2 );
assert TestTools.checkCollection( rev1.getReferences2() );
assert TestTools.checkCollection( rev2.getReferences2() );
assert TestTools.checkCollection( rev3.getReferences2() );
assert TestTools.checkCollection( rev4.getReferences2(), ite2_2 );
}
}

View File

@ -163,11 +163,11 @@ public class BasicBiowned extends BaseEnversJPAFunctionalTestCase {
ListBiowning1Entity rev4 = getAuditReader().find( ListBiowning1Entity.class, o1_1_id, 4 );
ListBiowning1Entity rev5 = getAuditReader().find( ListBiowning1Entity.class, o1_1_id, 5 );
assert TestTools.checkList( rev1.getReferences() );
assert TestTools.checkList( rev2.getReferences(), o2_1 );
assert TestTools.checkList( rev3.getReferences(), o2_1, o2_2 );
assert TestTools.checkList( rev4.getReferences() );
assert TestTools.checkList( rev5.getReferences(), o2_2 );
assert TestTools.checkCollection( rev1.getReferences() );
assert TestTools.checkCollection( rev2.getReferences(), o2_1 );
assert TestTools.checkCollection( rev3.getReferences(), o2_1, o2_2 );
assert TestTools.checkCollection( rev4.getReferences() );
assert TestTools.checkCollection( rev5.getReferences(), o2_2 );
}
@Test
@ -181,12 +181,11 @@ public class BasicBiowned extends BaseEnversJPAFunctionalTestCase {
ListBiowning1Entity rev4 = getAuditReader().find( ListBiowning1Entity.class, o1_2_id, 4 );
ListBiowning1Entity rev5 = getAuditReader().find( ListBiowning1Entity.class, o1_2_id, 5 );
assert TestTools.checkList( rev1.getReferences() );
assert TestTools.checkList( rev2.getReferences(), o2_2 );
assert TestTools.checkList( rev3.getReferences(), o2_2 );
assert TestTools.checkList( rev4.getReferences(), o2_1, o2_2 );
System.out.println( "rev5.getReferences() = " + rev5.getReferences() );
assert TestTools.checkList( rev5.getReferences(), o2_2 );
assert TestTools.checkCollection( rev1.getReferences() );
assert TestTools.checkCollection( rev2.getReferences(), o2_2 );
assert TestTools.checkCollection( rev3.getReferences(), o2_2 );
assert TestTools.checkCollection( rev4.getReferences(), o2_1, o2_2 );
assert TestTools.checkCollection( rev5.getReferences(), o2_2 );
}
@Test
@ -200,11 +199,11 @@ public class BasicBiowned extends BaseEnversJPAFunctionalTestCase {
ListBiowning2Entity rev4 = getAuditReader().find( ListBiowning2Entity.class, o2_1_id, 4 );
ListBiowning2Entity rev5 = getAuditReader().find( ListBiowning2Entity.class, o2_1_id, 5 );
assert TestTools.checkList( rev1.getReferences() );
assert TestTools.checkList( rev2.getReferences(), o1_1 );
assert TestTools.checkList( rev3.getReferences(), o1_1 );
assert TestTools.checkList( rev4.getReferences(), o1_2 );
assert TestTools.checkList( rev5.getReferences() );
assert TestTools.checkCollection( rev1.getReferences() );
assert TestTools.checkCollection( rev2.getReferences(), o1_1 );
assert TestTools.checkCollection( rev3.getReferences(), o1_1 );
assert TestTools.checkCollection( rev4.getReferences(), o1_2 );
assert TestTools.checkCollection( rev5.getReferences() );
}
@Test
@ -218,10 +217,10 @@ public class BasicBiowned extends BaseEnversJPAFunctionalTestCase {
ListBiowning2Entity rev4 = getAuditReader().find( ListBiowning2Entity.class, o2_2_id, 4 );
ListBiowning2Entity rev5 = getAuditReader().find( ListBiowning2Entity.class, o2_2_id, 5 );
assert TestTools.checkList( rev1.getReferences() );
assert TestTools.checkList( rev2.getReferences(), o1_2 );
assert TestTools.checkList( rev3.getReferences(), o1_1, o1_2 );
assert TestTools.checkList( rev4.getReferences(), o1_2 );
assert TestTools.checkList( rev5.getReferences(), o1_1, o1_2 );
assert TestTools.checkCollection( rev1.getReferences() );
assert TestTools.checkCollection( rev2.getReferences(), o1_2 );
assert TestTools.checkCollection( rev3.getReferences(), o1_1, o1_2 );
assert TestTools.checkCollection( rev4.getReferences(), o1_2 );
assert TestTools.checkCollection( rev5.getReferences(), o1_1, o1_2 );
}
}

View File

@ -199,17 +199,17 @@ public class BasicSametable extends BaseEnversJPAFunctionalTestCase {
ParentEntity rev4 = getAuditReader().find( ParentEntity.class, p1_id, 4 );
ParentEntity rev5 = getAuditReader().find( ParentEntity.class, p1_id, 5 );
assert TestTools.checkList( rev1.getChildren1() );
assert TestTools.checkList( rev2.getChildren1(), c1_1 );
assert TestTools.checkList( rev3.getChildren1(), c1_1, c1_2 );
assert TestTools.checkList( rev4.getChildren1(), c1_2 );
assert TestTools.checkList( rev5.getChildren1() );
assert TestTools.checkCollection( rev1.getChildren1() );
assert TestTools.checkCollection( rev2.getChildren1(), c1_1 );
assert TestTools.checkCollection( rev3.getChildren1(), c1_1, c1_2 );
assert TestTools.checkCollection( rev4.getChildren1(), c1_2 );
assert TestTools.checkCollection( rev5.getChildren1() );
assert TestTools.checkList( rev1.getChildren2() );
assert TestTools.checkList( rev2.getChildren2() );
assert TestTools.checkList( rev3.getChildren2(), c2_2 );
assert TestTools.checkList( rev4.getChildren2(), c2_2 );
assert TestTools.checkList( rev5.getChildren2(), c2_2 );
assert TestTools.checkCollection( rev1.getChildren2() );
assert TestTools.checkCollection( rev2.getChildren2() );
assert TestTools.checkCollection( rev3.getChildren2(), c2_2 );
assert TestTools.checkCollection( rev4.getChildren2(), c2_2 );
assert TestTools.checkCollection( rev5.getChildren2(), c2_2 );
}
@Test
@ -224,17 +224,17 @@ public class BasicSametable extends BaseEnversJPAFunctionalTestCase {
ParentEntity rev4 = getAuditReader().find( ParentEntity.class, p2_id, 4 );
ParentEntity rev5 = getAuditReader().find( ParentEntity.class, p2_id, 5 );
assert TestTools.checkList( rev1.getChildren1() );
assert TestTools.checkList( rev2.getChildren1() );
assert TestTools.checkList( rev3.getChildren1(), c1_1 );
assert TestTools.checkList( rev4.getChildren1(), c1_1 );
assert TestTools.checkList( rev5.getChildren1(), c1_1 );
assert TestTools.checkCollection( rev1.getChildren1() );
assert TestTools.checkCollection( rev2.getChildren1() );
assert TestTools.checkCollection( rev3.getChildren1(), c1_1 );
assert TestTools.checkCollection( rev4.getChildren1(), c1_1 );
assert TestTools.checkCollection( rev5.getChildren1(), c1_1 );
assert TestTools.checkList( rev1.getChildren2() );
assert TestTools.checkList( rev2.getChildren2(), c2_1 );
assert TestTools.checkList( rev3.getChildren2(), c2_1 );
assert TestTools.checkList( rev4.getChildren2(), c2_1, c2_2 );
assert TestTools.checkList( rev5.getChildren2(), c2_1 );
assert TestTools.checkCollection( rev1.getChildren2() );
assert TestTools.checkCollection( rev2.getChildren2(), c2_1 );
assert TestTools.checkCollection( rev3.getChildren2(), c2_1 );
assert TestTools.checkCollection( rev4.getChildren2(), c2_1, c2_2 );
assert TestTools.checkCollection( rev5.getChildren2(), c2_1 );
}
@Test
@ -248,11 +248,11 @@ public class BasicSametable extends BaseEnversJPAFunctionalTestCase {
Child1Entity rev4 = getAuditReader().find( Child1Entity.class, c1_1_id, 4 );
Child1Entity rev5 = getAuditReader().find( Child1Entity.class, c1_1_id, 5 );
assert TestTools.checkList( rev1.getParents() );
assert TestTools.checkList( rev2.getParents(), p1 );
assert TestTools.checkList( rev3.getParents(), p1, p2 );
assert TestTools.checkList( rev4.getParents(), p2 );
assert TestTools.checkList( rev5.getParents(), p2 );
assert TestTools.checkCollection( rev1.getParents() );
assert TestTools.checkCollection( rev2.getParents(), p1 );
assert TestTools.checkCollection( rev3.getParents(), p1, p2 );
assert TestTools.checkCollection( rev4.getParents(), p2 );
assert TestTools.checkCollection( rev5.getParents(), p2 );
}
// TODO: was disabled?
@ -266,11 +266,11 @@ public class BasicSametable extends BaseEnversJPAFunctionalTestCase {
Child1Entity rev4 = getAuditReader().find( Child1Entity.class, c1_2_id, 4 );
Child1Entity rev5 = getAuditReader().find( Child1Entity.class, c1_2_id, 5 );
assert TestTools.checkList( rev1.getParents() );
assert TestTools.checkList( rev2.getParents() );
assert TestTools.checkList( rev3.getParents(), p1 );
assert TestTools.checkList( rev4.getParents(), p1 );
assert TestTools.checkList( rev5.getParents() );
assert TestTools.checkCollection( rev1.getParents() );
assert TestTools.checkCollection( rev2.getParents() );
assert TestTools.checkCollection( rev3.getParents(), p1 );
assert TestTools.checkCollection( rev4.getParents(), p1 );
assert TestTools.checkCollection( rev5.getParents() );
}
@Test
@ -283,11 +283,11 @@ public class BasicSametable extends BaseEnversJPAFunctionalTestCase {
Child2Entity rev4 = getAuditReader().find( Child2Entity.class, c2_1_id, 4 );
Child2Entity rev5 = getAuditReader().find( Child2Entity.class, c2_1_id, 5 );
assert TestTools.checkList( rev1.getParents() );
assert TestTools.checkList( rev2.getParents(), p2 );
assert TestTools.checkList( rev3.getParents(), p2 );
assert TestTools.checkList( rev4.getParents(), p2 );
assert TestTools.checkList( rev5.getParents(), p2 );
assert TestTools.checkCollection( rev1.getParents() );
assert TestTools.checkCollection( rev2.getParents(), p2 );
assert TestTools.checkCollection( rev3.getParents(), p2 );
assert TestTools.checkCollection( rev4.getParents(), p2 );
assert TestTools.checkCollection( rev5.getParents(), p2 );
}
@Test
@ -301,10 +301,10 @@ public class BasicSametable extends BaseEnversJPAFunctionalTestCase {
Child2Entity rev4 = getAuditReader().find( Child2Entity.class, c2_2_id, 4 );
Child2Entity rev5 = getAuditReader().find( Child2Entity.class, c2_2_id, 5 );
assert TestTools.checkList( rev1.getParents() );
assert TestTools.checkList( rev2.getParents() );
assert TestTools.checkList( rev3.getParents(), p1 );
assert TestTools.checkList( rev4.getParents(), p1, p2 );
assert TestTools.checkList( rev5.getParents(), p1 );
assert TestTools.checkCollection( rev1.getParents() );
assert TestTools.checkCollection( rev2.getParents() );
assert TestTools.checkCollection( rev3.getParents(), p1 );
assert TestTools.checkCollection( rev4.getParents(), p1, p2 );
assert TestTools.checkCollection( rev5.getParents(), p1 );
}
}

View File

@ -151,9 +151,9 @@ public class BasicUniList extends BaseEnversJPAFunctionalTestCase {
ListUniEntity rev5 = getAuditReader().find( ListUniEntity.class, ing1_id, 5 );
assert rev1.getReferences().equals( Collections.EMPTY_LIST );
assert TestTools.checkList( rev2.getReferences(), ed1 );
assert TestTools.checkList( rev3.getReferences(), ed1, ed2 );
assert TestTools.checkList( rev4.getReferences(), ed2 );
assert TestTools.checkCollection( rev2.getReferences(), ed1 );
assert TestTools.checkCollection( rev3.getReferences(), ed1, ed2 );
assert TestTools.checkCollection( rev4.getReferences(), ed2 );
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 );
assert rev1.getReferences().equals( Collections.EMPTY_LIST );
assert TestTools.checkList( rev2.getReferences(), ed1, ed2 );
assert TestTools.checkList( rev3.getReferences(), ed1, ed2 );
assert TestTools.checkList( rev4.getReferences(), ed1, ed2 );
assert TestTools.checkList( rev5.getReferences(), ed1, ed2 );
assert TestTools.checkCollection( rev2.getReferences(), ed1, ed2 );
assert TestTools.checkCollection( rev3.getReferences(), ed1, ed2 );
assert TestTools.checkCollection( rev4.getReferences(), ed1, ed2 );
assert TestTools.checkCollection( rev5.getReferences(), ed1, ed2 );
}
}

View File

@ -11,7 +11,7 @@ import org.hibernate.envers.test.entities.manytomany.unidirectional.M2MIndexedLi
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.assertNull;
import static org.junit.Assert.assertTrue;
@ -114,9 +114,9 @@ public class M2MIndexedListNotAuditedTarget extends BaseEnversJPAFunctionalTestC
3
);
assertTrue( checkList( rev1.getReferences(), uste1, uste2 ) );
assertTrue( checkList( rev2.getReferences(), uste1, uste2 ) );
assertTrue( checkList( rev3.getReferences(), uste2, uste1 ) );
assertTrue( checkCollection( rev1.getReferences(), uste1, uste2 ) );
assertTrue( checkCollection( rev2.getReferences(), uste1, uste2 ) );
assertTrue( checkCollection( rev3.getReferences(), uste2, uste1 ) );
}
@Test
@ -138,7 +138,7 @@ public class M2MIndexedListNotAuditedTarget extends BaseEnversJPAFunctionalTestC
);
assertNull( rev1 );
assertTrue( checkList( rev2.getReferences(), uste2 ) );
assertTrue( checkList( rev3.getReferences(), uste2 ) );
assertTrue( checkCollection( rev2.getReferences(), uste2 ) );
assertTrue( checkCollection( rev3.getReferences(), uste2 ) );
}
}

View File

@ -35,7 +35,7 @@ import org.hibernate.envers.test.entities.manytomany.unidirectional.M2MTargetNot
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;
/**
@ -153,10 +153,10 @@ public class M2MRelationNotAuditedTarget extends BaseEnversJPAFunctionalTestCase
M2MTargetNotAuditedEntity rev3 = getAuditReader().find( M2MTargetNotAuditedEntity.class, tnae1_id, 3 );
M2MTargetNotAuditedEntity rev4 = getAuditReader().find( M2MTargetNotAuditedEntity.class, tnae1_id, 4 );
assertTrue( checkList( rev1.getReferences() ) );
assertTrue( checkList( rev2.getReferences(), uste1 ) );
assertTrue( checkList( rev3.getReferences(), uste1 ) );
assertTrue( checkList( rev4.getReferences(), uste1, uste2 ) );
assertTrue( checkCollection( rev1.getReferences() ) );
assertTrue( checkCollection( rev2.getReferences(), uste1 ) );
assertTrue( checkCollection( rev3.getReferences(), uste1 ) );
assertTrue( checkCollection( rev4.getReferences(), uste1, uste2 ) );
}
@Test
@ -169,9 +169,9 @@ public class M2MRelationNotAuditedTarget extends BaseEnversJPAFunctionalTestCase
M2MTargetNotAuditedEntity rev3 = getAuditReader().find( M2MTargetNotAuditedEntity.class, tnae2_id, 3 );
M2MTargetNotAuditedEntity rev4 = getAuditReader().find( M2MTargetNotAuditedEntity.class, tnae2_id, 4 );
assertTrue( checkList( rev1.getReferences(), uste1, uste2 ) );
assertTrue( checkList( rev2.getReferences(), uste2 ) );
assertTrue( checkList( rev3.getReferences() ) );
assertTrue( checkList( rev4.getReferences(), uste1 ) );
assertTrue( checkCollection( rev1.getReferences(), uste1, uste2 ) );
assertTrue( checkCollection( rev2.getReferences(), uste2 ) );
assertTrue( checkCollection( rev3.getReferences() ) );
assertTrue( checkCollection( rev4.getReferences(), uste1 ) );
}
}

View File

@ -118,9 +118,9 @@ public class BasicList extends BaseEnversJPAFunctionalTestCase {
ListRefEdEntity rev2 = getAuditReader().find( ListRefEdEntity.class, ed1_id, 2 );
ListRefEdEntity rev3 = getAuditReader().find( ListRefEdEntity.class, ed1_id, 3 );
assert TestTools.checkList( rev1.getReffering(), ing1, ing2 );
assert TestTools.checkList( rev2.getReffering(), ing2 );
assert TestTools.checkList( rev3.getReffering() );
assert TestTools.checkCollection( rev1.getReffering(), ing1, ing2 );
assert TestTools.checkCollection( rev2.getReffering(), ing2 );
assert TestTools.checkCollection( rev3.getReffering() );
}
@Test
@ -132,9 +132,9 @@ public class BasicList extends BaseEnversJPAFunctionalTestCase {
ListRefEdEntity rev2 = getAuditReader().find( ListRefEdEntity.class, ed2_id, 2 );
ListRefEdEntity rev3 = getAuditReader().find( ListRefEdEntity.class, ed2_id, 3 );
assert TestTools.checkList( rev1.getReffering() );
assert TestTools.checkList( rev2.getReffering(), ing1 );
assert TestTools.checkList( rev3.getReffering(), ing1, ing2 );
assert TestTools.checkCollection( rev1.getReffering() );
assert TestTools.checkCollection( rev2.getReffering(), ing1 );
assert TestTools.checkCollection( rev3.getReffering(), ing1, ing2 );
}
@Test

View File

@ -126,10 +126,10 @@ public class BasicDetachedList extends BaseEnversJPAFunctionalTestCase {
ListRefCollEntity rev3 = getAuditReader().find( ListRefCollEntity.class, coll1_id, 3 );
ListRefCollEntity rev4 = getAuditReader().find( ListRefCollEntity.class, coll1_id, 4 );
assert TestTools.checkList( rev1.getCollection(), str1 );
assert TestTools.checkList( rev2.getCollection(), str1, str2 );
assert TestTools.checkList( rev3.getCollection(), str2 );
assert TestTools.checkList( rev4.getCollection() );
assert TestTools.checkCollection( rev1.getCollection(), str1 );
assert TestTools.checkCollection( rev2.getCollection(), str1, str2 );
assert TestTools.checkCollection( rev3.getCollection(), str2 );
assert TestTools.checkCollection( rev4.getCollection() );
assert "coll1".equals( rev1.getData() );
assert "coll1".equals( rev2.getData() );

View File

@ -34,7 +34,7 @@ import org.hibernate.envers.test.entities.onetomany.detached.DoubleListJoinColum
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.assertTrue;
@ -266,15 +266,15 @@ public class DoubleJoinColumnBidirectionalList extends BaseEnversJPAFunctionalTe
4
);
assertTrue( checkList( rev1.getReferences1(), ed1_1_fromRev1 ) );
assertTrue( checkList( rev2.getReferences1(), ed1_1_fromRev1, ed1_2 ) );
assertTrue( checkList( rev3.getReferences1(), ed1_1_fromRev3, ed1_2 ) );
assertTrue( checkList( rev4.getReferences1() ) );
assertTrue( checkCollection( rev1.getReferences1(), ed1_1_fromRev1 ) );
assertTrue( checkCollection( rev2.getReferences1(), ed1_1_fromRev1, ed1_2 ) );
assertTrue( checkCollection( rev3.getReferences1(), ed1_1_fromRev3, ed1_2 ) );
assertTrue( checkCollection( rev4.getReferences1() ) );
assertTrue( checkList( rev1.getReferences2(), ed2_1 ) );
assertTrue( checkList( rev2.getReferences2(), ed2_1, ed2_2_fromRev1 ) );
assertTrue( checkList( rev3.getReferences2(), ed2_1, ed2_2_fromRev3 ) );
assertTrue( checkList( rev4.getReferences2(), ed2_2_fromRev3 ) );
assertTrue( checkCollection( rev1.getReferences2(), ed2_1 ) );
assertTrue( checkCollection( rev2.getReferences2(), ed2_1, ed2_2_fromRev1 ) );
assertTrue( checkCollection( rev3.getReferences2(), ed2_1, ed2_2_fromRev3 ) );
assertTrue( checkCollection( rev4.getReferences2(), ed2_2_fromRev3 ) );
}
@Test
@ -319,15 +319,15 @@ public class DoubleJoinColumnBidirectionalList extends BaseEnversJPAFunctionalTe
4
);
assertTrue( checkList( rev1.getReferences1(), ed1_2 ) );
assertTrue( checkList( rev2.getReferences1() ) );
assertTrue( checkList( rev3.getReferences1() ) );
assertTrue( checkList( rev4.getReferences1(), ed1_1_fromRev3, ed1_2 ) );
assertTrue( checkCollection( rev1.getReferences1(), ed1_2 ) );
assertTrue( checkCollection( rev2.getReferences1() ) );
assertTrue( checkCollection( rev3.getReferences1() ) );
assertTrue( checkCollection( rev4.getReferences1(), ed1_1_fromRev3, ed1_2 ) );
assertTrue( checkList( rev1.getReferences2(), ed2_2_fromRev1 ) );
assertTrue( checkList( rev2.getReferences2() ) );
assertTrue( checkList( rev3.getReferences2() ) );
assertTrue( checkList( rev4.getReferences2(), ed2_1 ) );
assertTrue( checkCollection( rev1.getReferences2(), ed2_2_fromRev1 ) );
assertTrue( checkCollection( rev2.getReferences2() ) );
assertTrue( checkCollection( rev3.getReferences2() ) );
assertTrue( checkCollection( rev4.getReferences2(), ed2_1 ) );
}
@Test

View File

@ -33,7 +33,7 @@ import org.hibernate.envers.test.entities.onetomany.detached.ListJoinColumnBidir
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.assertTrue;
@ -199,10 +199,10 @@ public class JoinColumnBidirectionalList extends BaseEnversJPAFunctionalTestCase
4
);
assertTrue( checkList( rev1.getReferences(), ed1_fromRev1 ) );
assertTrue( checkList( rev2.getReferences(), ed1_fromRev1, ed2 ) );
assertTrue( checkList( rev3.getReferences(), ed1_fromRev3, ed2 ) );
assertTrue( checkList( rev4.getReferences() ) );
assertTrue( checkCollection( rev1.getReferences(), ed1_fromRev1 ) );
assertTrue( checkCollection( rev2.getReferences(), ed1_fromRev1, ed2 ) );
assertTrue( checkCollection( rev3.getReferences(), ed1_fromRev3, ed2 ) );
assertTrue( checkCollection( rev4.getReferences() ) );
}
@Test
@ -237,10 +237,10 @@ public class JoinColumnBidirectionalList extends BaseEnversJPAFunctionalTestCase
4
);
assertTrue( checkList( rev1.getReferences(), ed2 ) );
assertTrue( checkList( rev2.getReferences() ) );
assertTrue( checkList( rev3.getReferences() ) );
assertTrue( checkList( rev4.getReferences(), ed1, ed2 ) );
assertTrue( checkCollection( rev1.getReferences(), ed2 ) );
assertTrue( checkCollection( rev2.getReferences() ) );
assertTrue( checkCollection( rev3.getReferences() ) );
assertTrue( checkCollection( rev4.getReferences(), ed1, ed2 ) );
}
@Test

View File

@ -34,7 +34,7 @@ import org.hibernate.envers.test.entities.onetomany.detached.ListJoinColumnBidir
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.assertTrue;
@ -169,8 +169,8 @@ public class JoinColumnBidirectionalListWithInheritance extends BaseEnversJPAFun
2
);
assertTrue( checkList( rev1.getReferences(), ed1 ) );
assertTrue( checkList( rev2.getReferences(), ed1, ed2 ) );
assertTrue( checkCollection( rev1.getReferences(), ed1 ) );
assertTrue( checkCollection( rev2.getReferences(), ed1, ed2 ) );
}
@Test
@ -191,8 +191,8 @@ public class JoinColumnBidirectionalListWithInheritance extends BaseEnversJPAFun
2
);
assertTrue( checkList( rev1.getReferences(), ed2 ) );
assertTrue( checkList( rev2.getReferences() ) );
assertTrue( checkCollection( rev1.getReferences(), ed2 ) );
assertTrue( checkCollection( rev2.getReferences() ) );
}
@Test

View File

@ -75,17 +75,17 @@ public class HierarchyTest extends BaseEnversJPAFunctionalTestCase {
Node ver1 = getAuditReader().find( Node.class, parentId, 1 );
Assert.assertEquals( parent, ver1 );
Assert.assertTrue( TestTools.checkList( ver1.getChildren(), child1, child2 ) );
Assert.assertTrue( TestTools.checkCollection( ver1.getChildren(), child1, child2 ) );
child1.setData( "child1 modified" );
Node ver2 = getAuditReader().find( Node.class, parentId, 2 );
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 );
Assert.assertEquals( parent, ver3 );
Assert.assertTrue( TestTools.checkList( ver3.getChildren(), child1 ) );
Assert.assertTrue( TestTools.checkCollection( ver3.getChildren(), child1 ) );
}
@Test

View File

@ -1,6 +1,7 @@
package org.hibernate.envers.test.integration.proxy;
import javax.persistence.EntityManager;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
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.UnversionedStrTestEntity;
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.SetOwningEntity;
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.SetRefIngEntity;
import org.hibernate.envers.test.integration.manytomany.ternary.TernaryMapEntity;
@ -55,7 +60,8 @@ public class RemovedObjectQueryTest extends BaseEnversJPAFunctionalTestCase {
return new Class<?>[] {
SetRefEdEntity.class, SetRefIngEntity.class, SetOwnedEntity.class, SetOwningEntity.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();
// 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();
mapEntity = em.find( TernaryMapEntity.class, mapEntity.getId() );
em.remove( mapEntity );
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();
}
@Test
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 )
.add( AuditEntity.id().eq( ternaryMapId ) )
.add( AuditEntity.revisionType().eq( RevisionType.DEL ) )
.getResultList();
Object[] objArray = (Object[]) queryResult.get( 0 );
Assert.assertEquals( 16, getRevisionNumber( objArray[1] ) );
Assert.assertEquals( 17, getRevisionNumber( objArray[1] ) );
TernaryMapEntity mapEntity = (TernaryMapEntity) objArray[0];
Assert.assertEquals(
TestTools.makeMap( intEntity1, stringEntity1, intEntity2, stringEntity2 ),
mapEntity.getMap()
);
entity = (TernaryMapEntity) objArray[0];
Assert.assertEquals( ternaryMap.getMap(), entity.getMap() );
}
@Test
@ -251,7 +335,7 @@ public class RemovedObjectQueryTest extends BaseEnversJPAFunctionalTestCase {
M2MIndexedListTargetNotAuditedEntity relationNotAuditedEntity = (M2MIndexedListTargetNotAuditedEntity) objArray[0];
Assert.assertTrue(
TestTools.checkList(
TestTools.checkCollection(
relationNotAuditedEntity.getReferences(),
unversionedEntity1, unversionedEntity2
)
@ -274,6 +358,34 @@ public class RemovedObjectQueryTest extends BaseEnversJPAFunctionalTestCase {
// 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
public void testReferencedOneToManySameRevision() {
List queryResult = getAuditReader().createQuery().forRevisionsOfEntity( SetRefIngEntity.class, false, true )
@ -360,6 +472,34 @@ public class RemovedObjectQueryTest extends BaseEnversJPAFunctionalTestCase {
// 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
public void testOwnedManyToManySameRevision() {
List queryResult = getAuditReader().createQuery().forRevisionsOfEntity( SetOwningEntity.class, false, true )

View File

@ -134,7 +134,7 @@ public class AggregateQuery extends BaseEnversJPAFunctionalTestCase {
.add( AuditEntity.id().between( 2, 3 ) )
.getResultList();
Assert.assertTrue(
TestTools.checkList(
TestTools.checkCollection(
list,
new IntTestEntity( 10, 2 ), new IntTestEntity( 8, 3 ), new IntTestEntity( 52, 2 )
)

View File

@ -311,7 +311,7 @@ public class SimpleQuery extends BaseEnversJPAFunctionalTestCase {
.addProjection( AuditEntity.revisionType() ).add( AuditEntity.id().eq( id1 ) )
.getSingleResult();
Assert.assertTrue( TestTools.checkList( result, site1, site2, site3 ) );
Assert.assertTrue( TestTools.checkCollection( result, site1, site2, site3 ) );
Assert.assertEquals( revisionType, RevisionType.ADD );
}
@ -330,7 +330,7 @@ public class SimpleQuery extends BaseEnversJPAFunctionalTestCase {
.addProjection( AuditEntity.revisionType() ).add( AuditEntity.id().eq( id1 ) )
.getSingleResult();
Assert.assertTrue( TestTools.checkList( result, site1, site2 ) );
Assert.assertTrue( TestTools.checkCollection( result, site1, site2 ) );
Assert.assertEquals( revisionType, RevisionType.MOD );
}
@ -348,7 +348,7 @@ public class SimpleQuery extends BaseEnversJPAFunctionalTestCase {
.addProjection( AuditEntity.revisionType() ).add( AuditEntity.id().eq( id1 ) )
.getSingleResult();
Assert.assertTrue( TestTools.checkList( result, site1 ) );
Assert.assertTrue( TestTools.checkCollection( result, site1 ) );
Assert.assertEquals( revisionType, RevisionType.DEL );
}

View File

@ -91,14 +91,14 @@ public class DefaultTrackingEntitiesTest extends BaseEnversJPAFunctionalTestCase
StrTestEntity ste = new StrTestEntity( "x", steId );
StrIntTestEntity site = new StrIntTestEntity( "y", 1, siteId );
assert TestTools.checkList( getCrossTypeRevisionChangesReader().findEntities( 1 ), ste, site );
assert TestTools.checkCollection( getCrossTypeRevisionChangesReader().findEntities( 1 ), ste, site );
}
@Test
public void testTrackModifiedEntities() {
StrIntTestEntity site = new StrIntTestEntity( "y", 2, siteId );
assert TestTools.checkList( getCrossTypeRevisionChangesReader().findEntities( 2 ), site );
assert TestTools.checkCollection( getCrossTypeRevisionChangesReader().findEntities( 2 ), site );
}
@Test
@ -106,7 +106,7 @@ public class DefaultTrackingEntitiesTest extends BaseEnversJPAFunctionalTestCase
StrTestEntity ste = new StrTestEntity( null, steId );
StrIntTestEntity site = new StrIntTestEntity( null, null, siteId );
assert TestTools.checkList( getCrossTypeRevisionChangesReader().findEntities( 3 ), site, ste );
assert TestTools.checkCollection( getCrossTypeRevisionChangesReader().findEntities( 3 ), site, ste );
}
@Test
@ -120,9 +120,9 @@ public class DefaultTrackingEntitiesTest extends BaseEnversJPAFunctionalTestCase
StrIntTestEntity site = new StrIntTestEntity( "y", 1, siteId );
Map<RevisionType, List<Object>> result = getCrossTypeRevisionChangesReader().findEntitiesGroupByRevisionType( 1 );
assert TestTools.checkList( result.get( RevisionType.ADD ), site, ste );
assert TestTools.checkList( result.get( RevisionType.MOD ) );
assert TestTools.checkList( result.get( RevisionType.DEL ) );
assert TestTools.checkCollection( result.get( RevisionType.ADD ), site, ste );
assert TestTools.checkCollection( result.get( RevisionType.MOD ) );
assert TestTools.checkCollection( result.get( RevisionType.DEL ) );
}
@Test
@ -130,9 +130,9 @@ public class DefaultTrackingEntitiesTest extends BaseEnversJPAFunctionalTestCase
StrIntTestEntity site = new StrIntTestEntity( "y", 2, siteId );
Map<RevisionType, List<Object>> result = getCrossTypeRevisionChangesReader().findEntitiesGroupByRevisionType( 2 );
assert TestTools.checkList( result.get( RevisionType.ADD ) );
assert TestTools.checkList( result.get( RevisionType.MOD ), site );
assert TestTools.checkList( result.get( RevisionType.DEL ) );
assert TestTools.checkCollection( result.get( RevisionType.ADD ) );
assert TestTools.checkCollection( result.get( RevisionType.MOD ), site );
assert TestTools.checkCollection( result.get( RevisionType.DEL ) );
}
@Test
@ -141,9 +141,9 @@ public class DefaultTrackingEntitiesTest extends BaseEnversJPAFunctionalTestCase
StrIntTestEntity site = new StrIntTestEntity( null, null, siteId );
Map<RevisionType, List<Object>> result = getCrossTypeRevisionChangesReader().findEntitiesGroupByRevisionType( 3 );
assert TestTools.checkList( result.get( RevisionType.ADD ) );
assert TestTools.checkList( result.get( RevisionType.MOD ) );
assert TestTools.checkList( result.get( RevisionType.DEL ), site, ste );
assert TestTools.checkCollection( result.get( RevisionType.ADD ) );
assert TestTools.checkCollection( result.get( RevisionType.MOD ) );
assert TestTools.checkCollection( result.get( RevisionType.DEL ), site, ste );
}
@Test
@ -151,7 +151,7 @@ public class DefaultTrackingEntitiesTest extends BaseEnversJPAFunctionalTestCase
StrTestEntity ste = new StrTestEntity( "x", steId );
StrIntTestEntity site = new StrIntTestEntity( "y", 1, siteId );
assert TestTools.checkList(
assert TestTools.checkCollection(
getCrossTypeRevisionChangesReader().findEntities( 1, RevisionType.ADD ),
ste,
site
@ -162,7 +162,10 @@ public class DefaultTrackingEntitiesTest extends BaseEnversJPAFunctionalTestCase
public void testFindChangedEntitiesByRevisionTypeMOD() {
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
@ -170,7 +173,7 @@ public class DefaultTrackingEntitiesTest extends BaseEnversJPAFunctionalTestCase
StrTestEntity ste = new StrTestEntity( null, steId );
StrIntTestEntity site = new StrIntTestEntity( null, null, siteId );
assert TestTools.checkList(
assert TestTools.checkCollection(
getCrossTypeRevisionChangesReader().findEntities( 3, RevisionType.DEL ),
ste,
site

View File

@ -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();
}
}

View File

@ -291,17 +291,17 @@ public class ValidityAuditStrategyRevEndTestCustomRevEnt extends BaseEnversJPAFu
ParentEntity rev4 = getAuditReader().find( ParentEntity.class, p1_id, 4 );
ParentEntity rev5 = getAuditReader().find( ParentEntity.class, p1_id, 5 );
assert TestTools.checkList( rev1.getChildren1() );
assert TestTools.checkList( rev2.getChildren1(), c1_1 );
assert TestTools.checkList( rev3.getChildren1(), c1_1, c1_2 );
assert TestTools.checkList( rev4.getChildren1(), c1_2 );
assert TestTools.checkList( rev5.getChildren1() );
assert TestTools.checkCollection( rev1.getChildren1() );
assert TestTools.checkCollection( rev2.getChildren1(), c1_1 );
assert TestTools.checkCollection( rev3.getChildren1(), c1_1, c1_2 );
assert TestTools.checkCollection( rev4.getChildren1(), c1_2 );
assert TestTools.checkCollection( rev5.getChildren1() );
assert TestTools.checkList( rev1.getChildren2() );
assert TestTools.checkList( rev2.getChildren2() );
assert TestTools.checkList( rev3.getChildren2(), c2_2 );
assert TestTools.checkList( rev4.getChildren2(), c2_2 );
assert TestTools.checkList( rev5.getChildren2(), c2_2 );
assert TestTools.checkCollection( rev1.getChildren2() );
assert TestTools.checkCollection( rev2.getChildren2() );
assert TestTools.checkCollection( rev3.getChildren2(), c2_2 );
assert TestTools.checkCollection( rev4.getChildren2(), c2_2 );
assert TestTools.checkCollection( rev5.getChildren2(), c2_2 );
}
@Test
@ -319,17 +319,17 @@ public class ValidityAuditStrategyRevEndTestCustomRevEnt extends BaseEnversJPAFu
ParentEntity rev4 = getAuditReader().find( ParentEntity.class, p2_id, 4 );
ParentEntity rev5 = getAuditReader().find( ParentEntity.class, p2_id, 5 );
assert TestTools.checkList( rev1.getChildren1() );
assert TestTools.checkList( rev2.getChildren1() );
assert TestTools.checkList( rev3.getChildren1(), c1_1 );
assert TestTools.checkList( rev4.getChildren1(), c1_1 );
assert TestTools.checkList( rev5.getChildren1(), c1_1 );
assert TestTools.checkCollection( rev1.getChildren1() );
assert TestTools.checkCollection( rev2.getChildren1() );
assert TestTools.checkCollection( rev3.getChildren1(), c1_1 );
assert TestTools.checkCollection( rev4.getChildren1(), c1_1 );
assert TestTools.checkCollection( rev5.getChildren1(), c1_1 );
assert TestTools.checkList( rev1.getChildren2() );
assert TestTools.checkList( rev2.getChildren2(), c2_1 );
assert TestTools.checkList( rev3.getChildren2(), c2_1 );
assert TestTools.checkList( rev4.getChildren2(), c2_1, c2_2 );
assert TestTools.checkList( rev5.getChildren2(), c2_1 );
assert TestTools.checkCollection( rev1.getChildren2() );
assert TestTools.checkCollection( rev2.getChildren2(), c2_1 );
assert TestTools.checkCollection( rev3.getChildren2(), c2_1 );
assert TestTools.checkCollection( rev4.getChildren2(), c2_1, c2_2 );
assert TestTools.checkCollection( rev5.getChildren2(), c2_1 );
}
@Test
@ -358,11 +358,11 @@ public class ValidityAuditStrategyRevEndTestCustomRevEnt extends BaseEnversJPAFu
5
);
assert TestTools.checkList( rev1.getParents() );
assert TestTools.checkList( rev2.getParents(), p1 );
assert TestTools.checkList( rev3.getParents(), p1, p2 );
assert TestTools.checkList( rev4.getParents(), p2 );
assert TestTools.checkList( rev5.getParents(), p2 );
assert TestTools.checkCollection( rev1.getParents() );
assert TestTools.checkCollection( rev2.getParents(), p1 );
assert TestTools.checkCollection( rev3.getParents(), p1, p2 );
assert TestTools.checkCollection( rev4.getParents(), p2 );
assert TestTools.checkCollection( rev5.getParents(), p2 );
}
// TODO: this was disabled?
@ -391,11 +391,11 @@ public class ValidityAuditStrategyRevEndTestCustomRevEnt extends BaseEnversJPAFu
5
);
assert TestTools.checkList( rev1.getParents() );
assert TestTools.checkList( rev2.getParents() );
assert TestTools.checkList( rev3.getParents(), p1 );
assert TestTools.checkList( rev4.getParents(), p1 );
assert TestTools.checkList( rev5.getParents() );
assert TestTools.checkCollection( rev1.getParents() );
assert TestTools.checkCollection( rev2.getParents() );
assert TestTools.checkCollection( rev3.getParents(), p1 );
assert TestTools.checkCollection( rev4.getParents(), p1 );
assert TestTools.checkCollection( rev5.getParents() );
}
@Test
@ -423,11 +423,11 @@ public class ValidityAuditStrategyRevEndTestCustomRevEnt extends BaseEnversJPAFu
5
);
assert TestTools.checkList( rev1.getParents() );
assert TestTools.checkList( rev2.getParents(), p2 );
assert TestTools.checkList( rev3.getParents(), p2 );
assert TestTools.checkList( rev4.getParents(), p2 );
assert TestTools.checkList( rev5.getParents(), p2 );
assert TestTools.checkCollection( rev1.getParents() );
assert TestTools.checkCollection( rev2.getParents(), p2 );
assert TestTools.checkCollection( rev3.getParents(), p2 );
assert TestTools.checkCollection( rev4.getParents(), p2 );
assert TestTools.checkCollection( rev5.getParents(), p2 );
}
@Test
@ -456,11 +456,11 @@ public class ValidityAuditStrategyRevEndTestCustomRevEnt extends BaseEnversJPAFu
5
);
assert TestTools.checkList( rev1.getParents() );
assert TestTools.checkList( rev2.getParents() );
assert TestTools.checkList( rev3.getParents(), p1 );
assert TestTools.checkList( rev4.getParents(), p1, p2 );
assert TestTools.checkList( rev5.getParents(), p1 );
assert TestTools.checkCollection( rev1.getParents() );
assert TestTools.checkCollection( rev2.getParents() );
assert TestTools.checkCollection( rev3.getParents(), p1 );
assert TestTools.checkCollection( rev4.getParents(), p1, p2 );
assert TestTools.checkCollection( rev5.getParents(), p1 );
}
private List<Map<String, Object>> getRevisions(

View File

@ -289,17 +289,17 @@ public class ValidityAuditStrategyRevEndTsTest extends BaseEnversJPAFunctionalTe
ParentEntity rev4 = getAuditReader().find( ParentEntity.class, p1_id, 4 );
ParentEntity rev5 = getAuditReader().find( ParentEntity.class, p1_id, 5 );
assert TestTools.checkList( rev1.getChildren1() );
assert TestTools.checkList( rev2.getChildren1(), c1_1 );
assert TestTools.checkList( rev3.getChildren1(), c1_1, c1_2 );
assert TestTools.checkList( rev4.getChildren1(), c1_2 );
assert TestTools.checkList( rev5.getChildren1() );
assert TestTools.checkCollection( rev1.getChildren1() );
assert TestTools.checkCollection( rev2.getChildren1(), c1_1 );
assert TestTools.checkCollection( rev3.getChildren1(), c1_1, c1_2 );
assert TestTools.checkCollection( rev4.getChildren1(), c1_2 );
assert TestTools.checkCollection( rev5.getChildren1() );
assert TestTools.checkList( rev1.getChildren2() );
assert TestTools.checkList( rev2.getChildren2() );
assert TestTools.checkList( rev3.getChildren2(), c2_2 );
assert TestTools.checkList( rev4.getChildren2(), c2_2 );
assert TestTools.checkList( rev5.getChildren2(), c2_2 );
assert TestTools.checkCollection( rev1.getChildren2() );
assert TestTools.checkCollection( rev2.getChildren2() );
assert TestTools.checkCollection( rev3.getChildren2(), c2_2 );
assert TestTools.checkCollection( rev4.getChildren2(), c2_2 );
assert TestTools.checkCollection( rev5.getChildren2(), c2_2 );
}
@Test
@ -317,17 +317,17 @@ public class ValidityAuditStrategyRevEndTsTest extends BaseEnversJPAFunctionalTe
ParentEntity rev4 = getAuditReader().find( ParentEntity.class, p2_id, 4 );
ParentEntity rev5 = getAuditReader().find( ParentEntity.class, p2_id, 5 );
assert TestTools.checkList( rev1.getChildren1() );
assert TestTools.checkList( rev2.getChildren1() );
assert TestTools.checkList( rev3.getChildren1(), c1_1 );
assert TestTools.checkList( rev4.getChildren1(), c1_1 );
assert TestTools.checkList( rev5.getChildren1(), c1_1 );
assert TestTools.checkCollection( rev1.getChildren1() );
assert TestTools.checkCollection( rev2.getChildren1() );
assert TestTools.checkCollection( rev3.getChildren1(), c1_1 );
assert TestTools.checkCollection( rev4.getChildren1(), c1_1 );
assert TestTools.checkCollection( rev5.getChildren1(), c1_1 );
assert TestTools.checkList( rev1.getChildren2() );
assert TestTools.checkList( rev2.getChildren2(), c2_1 );
assert TestTools.checkList( rev3.getChildren2(), c2_1 );
assert TestTools.checkList( rev4.getChildren2(), c2_1, c2_2 );
assert TestTools.checkList( rev5.getChildren2(), c2_1 );
assert TestTools.checkCollection( rev1.getChildren2() );
assert TestTools.checkCollection( rev2.getChildren2(), c2_1 );
assert TestTools.checkCollection( rev3.getChildren2(), c2_1 );
assert TestTools.checkCollection( rev4.getChildren2(), c2_1, c2_2 );
assert TestTools.checkCollection( rev5.getChildren2(), c2_1 );
}
@Test
@ -356,11 +356,11 @@ public class ValidityAuditStrategyRevEndTsTest extends BaseEnversJPAFunctionalTe
5
);
assert TestTools.checkList( rev1.getParents() );
assert TestTools.checkList( rev2.getParents(), p1 );
assert TestTools.checkList( rev3.getParents(), p1, p2 );
assert TestTools.checkList( rev4.getParents(), p2 );
assert TestTools.checkList( rev5.getParents(), p2 );
assert TestTools.checkCollection( rev1.getParents() );
assert TestTools.checkCollection( rev2.getParents(), p1 );
assert TestTools.checkCollection( rev3.getParents(), p1, p2 );
assert TestTools.checkCollection( rev4.getParents(), p2 );
assert TestTools.checkCollection( rev5.getParents(), p2 );
}
// TODO: this was disabled?
@ -389,11 +389,11 @@ public class ValidityAuditStrategyRevEndTsTest extends BaseEnversJPAFunctionalTe
5
);
assert TestTools.checkList( rev1.getParents() );
assert TestTools.checkList( rev2.getParents() );
assert TestTools.checkList( rev3.getParents(), p1 );
assert TestTools.checkList( rev4.getParents(), p1 );
assert TestTools.checkList( rev5.getParents() );
assert TestTools.checkCollection( rev1.getParents() );
assert TestTools.checkCollection( rev2.getParents() );
assert TestTools.checkCollection( rev3.getParents(), p1 );
assert TestTools.checkCollection( rev4.getParents(), p1 );
assert TestTools.checkCollection( rev5.getParents() );
}
@Test
@ -421,11 +421,11 @@ public class ValidityAuditStrategyRevEndTsTest extends BaseEnversJPAFunctionalTe
5
);
assert TestTools.checkList( rev1.getParents() );
assert TestTools.checkList( rev2.getParents(), p2 );
assert TestTools.checkList( rev3.getParents(), p2 );
assert TestTools.checkList( rev4.getParents(), p2 );
assert TestTools.checkList( rev5.getParents(), p2 );
assert TestTools.checkCollection( rev1.getParents() );
assert TestTools.checkCollection( rev2.getParents(), p2 );
assert TestTools.checkCollection( rev3.getParents(), p2 );
assert TestTools.checkCollection( rev4.getParents(), p2 );
assert TestTools.checkCollection( rev5.getParents(), p2 );
}
@Test
@ -454,11 +454,11 @@ public class ValidityAuditStrategyRevEndTsTest extends BaseEnversJPAFunctionalTe
5
);
assert TestTools.checkList( rev1.getParents() );
assert TestTools.checkList( rev2.getParents() );
assert TestTools.checkList( rev3.getParents(), p1 );
assert TestTools.checkList( rev4.getParents(), p1, p2 );
assert TestTools.checkList( rev5.getParents(), p1 );
assert TestTools.checkCollection( rev1.getParents() );
assert TestTools.checkCollection( rev2.getParents() );
assert TestTools.checkCollection( rev3.getParents(), p1 );
assert TestTools.checkCollection( rev4.getParents(), p1, p2 );
assert TestTools.checkCollection( rev5.getParents(), p1 );
}
private List<Map<String, Object>> getRevisions(

View File

@ -25,6 +25,7 @@ package org.hibernate.envers.test.tools;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
@ -63,7 +64,7 @@ public class TestTools {
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 ) {
return false;
}

View File

@ -35,12 +35,10 @@ dependencies {
// Local copies of all jars needed fur the OSGi runtime.
osgiRuntime( "org.jboss.arquillian.osgi:arquillian-osgi-bundle:1.0.3.Final" )
osgiRuntime( "org.ops4j.pax.url:pax-url-wrap:1.5.2" )
// 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( libraries.jpa )
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.transaction:jboss-transaction-api_1.2_spec:1.0.0.Alpha1" )
osgiRuntime( libraries.jta )
osgiRuntime( "commons-collections:commons-collections:3.2.1" )
osgiRuntime( "commons-pool:commons-pool:1.6" )
osgiRuntime( "commons-dbcp:commons-dbcp:1.4" )
@ -93,7 +91,7 @@ task copyBnd(type: Copy) {
task runBnd(type: JavaExec){
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) {

View File

@ -35,6 +35,7 @@ import org.hibernate.jpa.HibernatePersistenceProvider;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.FrameworkUtil;
import org.osgi.framework.ServiceRegistration;
/**
* This BundleActivator provides three different uses of Hibernate in OSGi
@ -59,6 +60,10 @@ import org.osgi.framework.FrameworkUtil;
*/
@SuppressWarnings("UnusedDeclaration")
public class HibernateBundleActivator implements BundleActivator {
private ServiceRegistration<?> persistenceProviderService;
private ServiceRegistration<?> sessionFactoryService;
@Override
@SuppressWarnings("unchecked")
public void start(BundleContext context) throws Exception {
@ -75,12 +80,12 @@ public class HibernateBundleActivator implements BundleActivator {
final Dictionary properties = new Hashtable();
// In order to support existing persistence.xml files, register using the legacy provider name.
properties.put( "javax.persistence.provider", HibernatePersistenceProvider.class.getName() );
context.registerService(
persistenceProviderService = context.registerService(
PersistenceProvider.class.getName(),
new OsgiPersistenceProviderService( osgiClassLoader, osgiJtaPlatform, context ),
properties
);
context.registerService(
sessionFactoryService = context.registerService(
SessionFactory.class.getName(),
new OsgiSessionFactoryService( osgiClassLoader, osgiJtaPlatform, context ),
new Hashtable()
@ -89,6 +94,11 @@ public class HibernateBundleActivator implements BundleActivator {
@Override
public void stop(BundleContext context) throws Exception {
// Nothing else to do?
persistenceProviderService.unregister();
persistenceProviderService = null;
sessionFactoryService.unregister();
sessionFactoryService = null;
ClassLoaderHelper.overridenClassLoader = null;
}
}

View File

@ -18,13 +18,17 @@ package org.hibernate.osgi.test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.fail;
import java.io.InputStream;
import org.hibernate.osgi.OsgiPersistenceProviderService;
import org.hibernate.osgi.OsgiSessionFactoryService;
import org.hibernate.osgi.test.result.OsgiTestResults;
import org.jboss.arquillian.container.test.api.Deployment;
import org.jboss.arquillian.junit.Arquillian;
import org.jboss.arquillian.junit.InSequence;
import org.jboss.arquillian.test.api.ArquillianResource;
import org.jboss.osgi.metadata.OSGiManifestBuilder;
import org.jboss.shrinkwrap.api.ShrinkWrap;
@ -94,6 +98,8 @@ public class OsgiTestCase {
builder.addBundleSymbolicName( archive.getName() );
builder.addBundleManifestVersion( 2 );
builder.addImportPackages( OsgiTestResults.class );
// needed primarily to test service cleanup in #testStop
builder.addImportPackages( OsgiSessionFactoryService.class );
return builder.openStream();
}
} );
@ -107,19 +113,16 @@ public class OsgiTestCase {
* @throws Exception
*/
@Test
@InSequence(1)
public void testClientBundle() throws Exception {
assertNotNull( "BundleContext injected", context );
assertEquals( "System Bundle ID", 0, context.getBundle().getBundleId() );
testHibernateBundle( "org.hibernate.core" );
testHibernateBundle( "org.hibernate.entitymanager" );
commonTests();
final Bundle testClientBundle = findHibernateBundle( "testClientBundle" );
assertNotNull( "The test client bundle was not found!", testClientBundle );
testClientBundle.start();
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 );
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) {
for ( Bundle bundle : context.getBundles() ) {
if ( bundle.getSymbolicName().equals( symbolicName ) ) {
@ -136,10 +169,10 @@ public class OsgiTestCase {
return null;
}
private void testHibernateBundle(String symbolicName) {
private void testHibernateBundle(String symbolicName, int state) {
final Bundle bundle = findHibernateBundle( symbolicName );
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() );
}
}

View File

@ -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

View File

@ -14,11 +14,9 @@ felix.log.level=4
felix.auto.install.1=\
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=\
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/cdi-api-1.1.0.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/h2-1.3.170.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.bundles.ant-1.8.2_2.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