HHH-952 : subqueries with joins using DetatchedCriteria
git-svn-id: https://svn.jboss.org/repos/hibernate/core/branches/Branch_3_2@14209 1b8cb986-b30d-0410-93ca-fae66ebed9b2
This commit is contained in:
parent
012bf08a0d
commit
dbfcafa8bf
|
@ -21,7 +21,11 @@ public final class CollectionRecreateAction extends CollectionAction {
|
|||
}
|
||||
|
||||
public void execute() throws HibernateException {
|
||||
final PersistentCollection collection = getCollection();
|
||||
final boolean stats = getSession().getFactory().getStatistics().isStatisticsEnabled();
|
||||
long startTime = 0;
|
||||
if ( stats ) startTime = System.currentTimeMillis();
|
||||
|
||||
final PersistentCollection collection = getCollection();
|
||||
|
||||
getPersister().recreate( collection, getKey(), getSession() );
|
||||
|
||||
|
@ -31,9 +35,9 @@ public final class CollectionRecreateAction extends CollectionAction {
|
|||
|
||||
evict();
|
||||
|
||||
if ( getSession().getFactory().getStatistics().isStatisticsEnabled() ) {
|
||||
if ( stats ) {
|
||||
getSession().getFactory().getStatisticsImplementor()
|
||||
.recreateCollection( getPersister().getRole() );
|
||||
.recreateCollection( getPersister().getRole(), System.currentTimeMillis() - startTime);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -25,7 +25,11 @@ public final class CollectionRemoveAction extends CollectionAction {
|
|||
}
|
||||
|
||||
public void execute() throws HibernateException {
|
||||
if ( !emptySnapshot ) getPersister().remove( getKey(), getSession() );
|
||||
final boolean stats = getSession().getFactory().getStatistics().isStatisticsEnabled();
|
||||
long startTime = 0;
|
||||
if ( stats ) startTime = System.currentTimeMillis();
|
||||
|
||||
if ( !emptySnapshot ) getPersister().remove( getKey(), getSession() );
|
||||
|
||||
final PersistentCollection collection = getCollection();
|
||||
if (collection!=null) {
|
||||
|
@ -36,9 +40,9 @@ public final class CollectionRemoveAction extends CollectionAction {
|
|||
|
||||
evict();
|
||||
|
||||
if ( getSession().getFactory().getStatistics().isStatisticsEnabled() ) {
|
||||
if ( stats ) {
|
||||
getSession().getFactory().getStatisticsImplementor()
|
||||
.removeCollection( getPersister().getRole() );
|
||||
.removeCollection( getPersister().getRole(), System.currentTimeMillis() - startTime);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -32,6 +32,9 @@ public final class CollectionUpdateAction extends CollectionAction {
|
|||
final CollectionPersister persister = getPersister();
|
||||
final PersistentCollection collection = getCollection();
|
||||
boolean affectedByFilters = persister.isAffectedByEnabledFilters(session);
|
||||
final boolean stats = session.getFactory().getStatistics().isStatisticsEnabled();
|
||||
long startTime = 0;
|
||||
if ( stats ) startTime = System.currentTimeMillis();
|
||||
|
||||
if ( !collection.wasInitialized() ) {
|
||||
if ( !collection.hasQueuedOperations() ) throw new AssertionFailure( "no queued adds" );
|
||||
|
@ -62,9 +65,9 @@ public final class CollectionUpdateAction extends CollectionAction {
|
|||
|
||||
evict();
|
||||
|
||||
if ( getSession().getFactory().getStatistics().isStatisticsEnabled() ) {
|
||||
if ( stats ) {
|
||||
getSession().getFactory().getStatisticsImplementor().
|
||||
updateCollection( getPersister().getRole() );
|
||||
updateCollection( getPersister().getRole(), System.currentTimeMillis() - startTime);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -44,6 +44,9 @@ public final class EntityDeleteAction extends EntityAction {
|
|||
EntityPersister persister = getPersister();
|
||||
SessionImplementor session = getSession();
|
||||
Object instance = getInstance();
|
||||
final boolean stats = session.getFactory().getStatistics().isStatisticsEnabled();
|
||||
long startTime = 0;
|
||||
if ( stats ) startTime = System.currentTimeMillis();
|
||||
|
||||
boolean veto = preDelete();
|
||||
|
||||
|
@ -93,9 +96,9 @@ public final class EntityDeleteAction extends EntityAction {
|
|||
|
||||
postDelete();
|
||||
|
||||
if ( getSession().getFactory().getStatistics().isStatisticsEnabled() && !veto ) {
|
||||
if ( stats && !veto ) {
|
||||
getSession().getFactory().getStatisticsImplementor()
|
||||
.deleteEntity( getPersister().getEntityName() );
|
||||
.deleteEntity( getPersister().getEntityName(), System.currentTimeMillis() - startTime);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -38,7 +38,10 @@ public final class EntityIdentityInsertAction extends EntityAction {
|
|||
final EntityPersister persister = getPersister();
|
||||
final SessionImplementor session = getSession();
|
||||
final Object instance = getInstance();
|
||||
|
||||
final boolean stats = session.getFactory().getStatistics().isStatisticsEnabled();
|
||||
long startTime = 0;
|
||||
if ( stats ) startTime = System.currentTimeMillis();
|
||||
|
||||
boolean veto = preInsert();
|
||||
|
||||
// Don't need to lock the cache here, since if someone
|
||||
|
@ -65,9 +68,9 @@ public final class EntityIdentityInsertAction extends EntityAction {
|
|||
|
||||
postInsert();
|
||||
|
||||
if ( session.getFactory().getStatistics().isStatisticsEnabled() && !veto ) {
|
||||
if ( stats && !veto ) {
|
||||
session.getFactory().getStatisticsImplementor()
|
||||
.insertEntity( getPersister().getEntityName() );
|
||||
.insertEntity( getPersister().getEntityName(), System.currentTimeMillis() - startTime);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -46,6 +46,10 @@ public final class EntityInsertAction extends EntityAction {
|
|||
Object instance = getInstance();
|
||||
Serializable id = getId();
|
||||
|
||||
final boolean stats = session.getFactory().getStatistics().isStatisticsEnabled();
|
||||
long startTime = 0;
|
||||
if ( stats ) startTime = System.currentTimeMillis();
|
||||
|
||||
boolean veto = preInsert();
|
||||
|
||||
// Don't need to lock the cache here, since if someone
|
||||
|
@ -96,7 +100,7 @@ public final class EntityInsertAction extends EntityAction {
|
|||
// boolean put = persister.getCache().insert(ck, cacheEntry);
|
||||
boolean put = persister.getCache().insert( ck, cacheEntry, version );
|
||||
|
||||
if ( put && factory.getStatistics().isStatisticsEnabled() ) {
|
||||
if ( put && stats ) {
|
||||
factory.getStatisticsImplementor()
|
||||
.secondLevelCachePut( getPersister().getCache().getRegionName() );
|
||||
}
|
||||
|
@ -105,9 +109,9 @@ public final class EntityInsertAction extends EntityAction {
|
|||
|
||||
postInsert();
|
||||
|
||||
if ( factory.getStatistics().isStatisticsEnabled() && !veto ) {
|
||||
if ( stats && !veto ) {
|
||||
factory.getStatisticsImplementor()
|
||||
.insertEntity( getPersister().getEntityName() );
|
||||
.insertEntity( getPersister().getEntityName(), System.currentTimeMillis() - startTime);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -65,7 +65,11 @@ public final class EntityUpdateAction extends EntityAction {
|
|||
boolean veto = preUpdate();
|
||||
|
||||
final SessionFactoryImplementor factory = getSession().getFactory();
|
||||
Object previousVersion = this.previousVersion;
|
||||
final boolean stats = factory.getStatistics().isStatisticsEnabled();
|
||||
long startTime = 0;
|
||||
if ( stats ) startTime = System.currentTimeMillis();
|
||||
|
||||
Object previousVersion = this.previousVersion;
|
||||
if ( persister.isVersionPropertyGenerated() ) {
|
||||
// we need to grab the version value from the entity, otherwise
|
||||
// we have issues with generated-version entities that may have
|
||||
|
@ -158,9 +162,9 @@ public final class EntityUpdateAction extends EntityAction {
|
|||
|
||||
postUpdate();
|
||||
|
||||
if ( factory.getStatistics().isStatisticsEnabled() && !veto ) {
|
||||
if ( stats && !veto ) {
|
||||
factory.getStatisticsImplementor()
|
||||
.updateEntity( getPersister().getEntityName() );
|
||||
.updateEntity( getPersister().getEntityName(), System.currentTimeMillis() - startTime);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1997,7 +1997,7 @@ public final class HbmBinder {
|
|||
Iterator iter = subnode.elementIterator( "param" );
|
||||
while ( iter.hasNext() ) {
|
||||
Element childNode = (Element) iter.next();
|
||||
params.setProperty( childNode.attributeValue( "name" ), childNode.getText() );
|
||||
params.setProperty( childNode.attributeValue( "name" ), childNode.getTextTrim() );
|
||||
}
|
||||
|
||||
model.setIdentifierGeneratorProperties( params );
|
||||
|
|
|
@ -1,17 +1,18 @@
|
|||
//$Id$
|
||||
package org.hibernate.criterion;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
import org.hibernate.Criteria;
|
||||
import org.hibernate.EntityMode;
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.engine.QueryParameters;
|
||||
import org.hibernate.engine.SessionFactoryImplementor;
|
||||
import org.hibernate.engine.SessionImplementor;
|
||||
import org.hibernate.engine.TypedValue;
|
||||
import org.hibernate.impl.CriteriaImpl;
|
||||
import org.hibernate.loader.criteria.CriteriaJoinWalker;
|
||||
import org.hibernate.loader.criteria.CriteriaQueryTranslator;
|
||||
import org.hibernate.persister.entity.OuterJoinLoadable;
|
||||
import org.hibernate.sql.Select;
|
||||
import org.hibernate.type.Type;
|
||||
|
||||
/**
|
||||
|
@ -24,7 +25,8 @@ public abstract class SubqueryExpression implements Criterion {
|
|||
private String op;
|
||||
private QueryParameters params;
|
||||
private Type[] types;
|
||||
|
||||
private CriteriaQueryTranslator innerQuery;
|
||||
|
||||
protected Type[] getTypes() {
|
||||
return types;
|
||||
}
|
||||
|
@ -39,34 +41,23 @@ public abstract class SubqueryExpression implements Criterion {
|
|||
|
||||
public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery)
|
||||
throws HibernateException {
|
||||
|
||||
final SessionImplementor session = ( (CriteriaImpl) criteria ).getSession(); //ugly!
|
||||
final SessionFactoryImplementor factory = session.getFactory();
|
||||
|
||||
|
||||
final SessionFactoryImplementor factory = criteriaQuery.getFactory();
|
||||
final OuterJoinLoadable persister = (OuterJoinLoadable) factory.getEntityPersister( criteriaImpl.getEntityOrClassName() );
|
||||
CriteriaQueryTranslator innerQuery = new CriteriaQueryTranslator(
|
||||
factory,
|
||||
criteriaImpl,
|
||||
criteriaImpl.getEntityOrClassName(), //implicit polymorphism not supported (would need a union)
|
||||
criteriaQuery.generateSQLAlias(),
|
||||
criteriaQuery
|
||||
);
|
||||
|
||||
params = innerQuery.getQueryParameters(); //TODO: bad lifecycle....
|
||||
types = innerQuery.getProjectedTypes();
|
||||
|
||||
//String filter = persister.filterFragment( innerQuery.getRootSQLALias(), session.getEnabledFilters() );
|
||||
|
||||
String sql = new Select( factory.getDialect() )
|
||||
.setWhereClause( innerQuery.getWhereCondition() )
|
||||
.setGroupByClause( innerQuery.getGroupBy() )
|
||||
.setSelectClause( innerQuery.getSelect() )
|
||||
.setFromClause(
|
||||
persister.fromTableFragment( innerQuery.getRootSQLALias() ) +
|
||||
persister.fromJoinFragment( innerQuery.getRootSQLALias(), true, false )
|
||||
)
|
||||
.toStatementString();
|
||||
|
||||
createAndSetInnerQuery( criteriaQuery, factory );
|
||||
|
||||
CriteriaJoinWalker walker = new CriteriaJoinWalker(
|
||||
persister,
|
||||
innerQuery,
|
||||
factory,
|
||||
criteriaImpl,
|
||||
criteriaImpl.getEntityOrClassName(),
|
||||
new HashMap(),
|
||||
innerQuery.getRootSQLALias());
|
||||
|
||||
String sql = walker.getSQLString();
|
||||
|
||||
final StringBuffer buf = new StringBuffer()
|
||||
.append( toLeftSqlString(criteria, criteriaQuery) );
|
||||
if (op!=null) buf.append(' ').append(op).append(' ');
|
||||
|
@ -77,13 +68,49 @@ public abstract class SubqueryExpression implements Criterion {
|
|||
|
||||
public TypedValue[] getTypedValues(Criteria criteria, CriteriaQuery criteriaQuery)
|
||||
throws HibernateException {
|
||||
Type[] types = params.getPositionalParameterTypes();
|
||||
Object[] values = params.getPositionalParameterValues();
|
||||
TypedValue[] tv = new TypedValue[types.length];
|
||||
for ( int i=0; i<types.length; i++ ) {
|
||||
tv[i] = new TypedValue( types[i], values[i], EntityMode.POJO );
|
||||
//the following two lines were added to ensure that this.params is not null, which
|
||||
//can happen with two-deep nested subqueries
|
||||
SessionFactoryImplementor factory = criteriaQuery.getFactory();
|
||||
createAndSetInnerQuery(criteriaQuery, factory);
|
||||
|
||||
Type[] ppTypes = params.getPositionalParameterTypes();
|
||||
Object[] ppValues = params.getPositionalParameterValues();
|
||||
TypedValue[] tv = new TypedValue[ppTypes.length];
|
||||
for ( int i=0; i<ppTypes.length; i++ ) {
|
||||
tv[i] = new TypedValue( ppTypes[i], ppValues[i], EntityMode.POJO );
|
||||
}
|
||||
return tv;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the inner query used to extract some useful information about
|
||||
* types, since it is needed in both methods.
|
||||
* @param criteriaQuery
|
||||
* @param factory
|
||||
*/
|
||||
private void createAndSetInnerQuery(CriteriaQuery criteriaQuery, final SessionFactoryImplementor factory) {
|
||||
if ( innerQuery == null ) {
|
||||
//with two-deep subqueries, the same alias would get generated for
|
||||
//both using the old method (criteriaQuery.generateSQLAlias()), so
|
||||
//that is now used as a fallback if the main criteria alias isn't set
|
||||
String alias;
|
||||
if ( this.criteriaImpl.getAlias() == null ) {
|
||||
alias = criteriaQuery.generateSQLAlias();
|
||||
}
|
||||
else {
|
||||
alias = this.criteriaImpl.getAlias() + "_";
|
||||
}
|
||||
|
||||
innerQuery = new CriteriaQueryTranslator(
|
||||
factory,
|
||||
criteriaImpl,
|
||||
criteriaImpl.getEntityOrClassName(), //implicit polymorphism not supported (would need a union)
|
||||
alias,
|
||||
criteriaQuery
|
||||
);
|
||||
|
||||
params = innerQuery.getQueryParameters();
|
||||
types = innerQuery.getProjectedTypes();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -357,10 +357,6 @@ public class DB2Dialect extends Dialect {
|
|||
return false;
|
||||
}
|
||||
|
||||
public String getCurrentTimestampSQLFunctionName() {
|
||||
return "sysdate";
|
||||
}
|
||||
|
||||
// Overridden informational metadata ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
public boolean supportsEmptyInList() {
|
||||
|
|
|
@ -121,7 +121,7 @@ public class Oracle8iDialect extends Dialect {
|
|||
registerFunction( "current_time", new NoArgSQLFunction("current_timestamp", Hibernate.TIME, false) );
|
||||
registerFunction( "current_timestamp", new NoArgSQLFunction("current_timestamp", Hibernate.TIMESTAMP, false) );
|
||||
|
||||
registerFunction( "lastday", new StandardSQLFunction("lastday", Hibernate.DATE) );
|
||||
registerFunction( "last_day", new StandardSQLFunction("last_day", Hibernate.DATE) );
|
||||
registerFunction( "sysdate", new NoArgSQLFunction("sysdate", Hibernate.DATE, false) );
|
||||
registerFunction( "systimestamp", new NoArgSQLFunction("systimestamp", Hibernate.TIMESTAMP, false) );
|
||||
registerFunction( "uid", new NoArgSQLFunction("uid", Hibernate.INTEGER, false) );
|
||||
|
|
|
@ -103,7 +103,7 @@ public class Oracle9Dialect extends Dialect {
|
|||
registerFunction( "current_time", new NoArgSQLFunction("current_timestamp", Hibernate.TIME, false) );
|
||||
registerFunction( "current_timestamp", new NoArgSQLFunction("current_timestamp", Hibernate.TIMESTAMP, false) );
|
||||
|
||||
registerFunction( "lastday", new StandardSQLFunction("lastday", Hibernate.DATE) );
|
||||
registerFunction( "last_day", new StandardSQLFunction("last_day", Hibernate.DATE) );
|
||||
registerFunction( "sysdate", new NoArgSQLFunction("sysdate", Hibernate.DATE, false) );
|
||||
registerFunction( "systimestamp", new NoArgSQLFunction("systimestamp", Hibernate.TIMESTAMP, false) );
|
||||
registerFunction( "uid", new NoArgSQLFunction("uid", Hibernate.INTEGER, false) );
|
||||
|
|
|
@ -93,7 +93,11 @@ public final class TwoPhaseLoad {
|
|||
final PostLoadEvent postLoadEvent) throws HibernateException {
|
||||
|
||||
//TODO: Should this be an InitializeEntityEventListener??? (watch out for performance!)
|
||||
|
||||
final SessionFactoryImplementor factory = session.getFactory();
|
||||
final boolean stats = factory.getStatistics().isStatisticsEnabled();
|
||||
long startTime = 0;
|
||||
if ( stats ) startTime = System.currentTimeMillis();
|
||||
|
||||
final PersistenceContext persistenceContext = session.getPersistenceContext();
|
||||
EntityEntry entityEntry = persistenceContext.getEntry(entity);
|
||||
if ( entityEntry == null ) {
|
||||
|
@ -128,7 +132,6 @@ public final class TwoPhaseLoad {
|
|||
|
||||
persister.setPropertyValues( entity, hydratedState, session.getEntityMode() );
|
||||
|
||||
final SessionFactoryImplementor factory = session.getFactory();
|
||||
if ( persister.hasCache() && session.getCacheMode().isPutEnabled() ) {
|
||||
|
||||
if ( log.isDebugEnabled() )
|
||||
|
@ -208,8 +211,8 @@ public final class TwoPhaseLoad {
|
|||
MessageHelper.infoString( persister, id, session.getFactory() )
|
||||
);
|
||||
|
||||
if ( factory.getStatistics().isStatisticsEnabled() ) {
|
||||
factory.getStatisticsImplementor().loadEntity( persister.getEntityName() );
|
||||
if ( stats) {
|
||||
factory.getStatisticsImplementor().loadEntity( persister.getEntityName(), System.currentTimeMillis() - startTime);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -233,6 +233,9 @@ public class CollectionLoadContext {
|
|||
}
|
||||
final SessionImplementor session = getLoadContext().getPersistenceContext().getSession();
|
||||
final EntityMode em = session.getEntityMode();
|
||||
final boolean stats = session.getFactory().getStatistics().isStatisticsEnabled();
|
||||
long startTime = 0;
|
||||
if ( stats ) startTime = System.currentTimeMillis();
|
||||
|
||||
boolean hasNoQueuedAdds = lce.getCollection().endRead(); // warning: can cause a recursive calls! (proxy initialization)
|
||||
|
||||
|
@ -260,8 +263,8 @@ public class CollectionLoadContext {
|
|||
log.debug( "collection fully initialized: " + MessageHelper.collectionInfoString(persister, lce.getKey(), session.getFactory() ) );
|
||||
}
|
||||
|
||||
if ( session.getFactory().getStatistics().isStatisticsEnabled() ) {
|
||||
session.getFactory().getStatisticsImplementor().loadCollection( persister.getRole() );
|
||||
if ( stats ) {
|
||||
session.getFactory().getStatisticsImplementor().loadCollection( persister.getRole(), System.currentTimeMillis() - startTime);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -33,6 +33,9 @@ public class DefaultInitializeCollectionEventListener implements InitializeColle
|
|||
|
||||
PersistentCollection collection = event.getCollection();
|
||||
SessionImplementor source = event.getSession();
|
||||
final boolean stats = source.getFactory().getStatistics().isStatisticsEnabled();
|
||||
long startTime = 0;
|
||||
if ( stats ) startTime = System.currentTimeMillis();
|
||||
|
||||
CollectionEntry ce = source.getPersistenceContext().getCollectionEntry(collection);
|
||||
if (ce==null) throw new HibernateException("collection was evicted");
|
||||
|
@ -60,10 +63,10 @@ public class DefaultInitializeCollectionEventListener implements InitializeColle
|
|||
ce.getLoadedPersister().initialize( ce.getLoadedKey(), source );
|
||||
log.trace("collection initialized");
|
||||
|
||||
if ( source.getFactory().getStatistics().isStatisticsEnabled() ) {
|
||||
if ( stats ) {
|
||||
source.getFactory().getStatisticsImplementor().fetchCollection(
|
||||
ce.getLoadedPersister().getRole()
|
||||
);
|
||||
ce.getLoadedPersister().getRole(),
|
||||
System.currentTimeMillis() - startTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -392,15 +392,19 @@ public class DefaultLoadEventListener extends AbstractLockUpgradeEventListener i
|
|||
final EntityKey keyToLoad,
|
||||
final LoadEventListener.LoadType options) throws HibernateException {
|
||||
final SessionImplementor source = event.getSession();
|
||||
Object entity = persister.load(
|
||||
final boolean stats = source.getFactory().getStatistics().isStatisticsEnabled();
|
||||
long startTime = 0;
|
||||
if ( stats ) startTime = System.currentTimeMillis();
|
||||
|
||||
Object entity = persister.load(
|
||||
event.getEntityId(),
|
||||
event.getInstanceToLoad(),
|
||||
event.getLockMode(),
|
||||
source
|
||||
);
|
||||
|
||||
if ( event.isAssociationFetch() && source.getFactory().getStatistics().isStatisticsEnabled() ) {
|
||||
source.getFactory().getStatisticsImplementor().fetchEntity( event.getEntityClassName() );
|
||||
if ( event.isAssociationFetch() && stats) {
|
||||
source.getFactory().getStatisticsImplementor().fetchEntity( event.getEntityClassName(), System.currentTimeMillis() - startTime);
|
||||
}
|
||||
|
||||
return entity;
|
||||
|
|
|
@ -336,7 +336,8 @@ public class DotNode extends FromReferenceNode implements DisplayableNode, Selec
|
|||
joinIsNeeded = generateJoin && !isReferenceToPrimaryKey( parentAsDotNode.propertyName, entityType );
|
||||
}
|
||||
else if ( ! getWalker().isSelectStatement() ) {
|
||||
joinIsNeeded = false;
|
||||
// in non-select queries, the only time we should need to join is if we are in a subquery from clause
|
||||
joinIsNeeded = getWalker().getCurrentStatementType() == SqlTokenTypes.SELECT && getWalker().isInFrom();
|
||||
}
|
||||
else if ( REGRESSION_STYLE_JOIN_SUPPRESSION ) {
|
||||
// this is the regression style determination which matches the logic of the classic translator
|
||||
|
|
|
@ -120,7 +120,7 @@ public class OptimizerFactory {
|
|||
}
|
||||
}
|
||||
|
||||
public Serializable generate(AccessCallback callback) {
|
||||
public synchronized Serializable generate(AccessCallback callback) {
|
||||
if ( lastSourceValue < 0 ) {
|
||||
lastSourceValue = callback.getNextValue();
|
||||
while ( lastSourceValue <= 0 ) {
|
||||
|
@ -168,7 +168,7 @@ public class OptimizerFactory {
|
|||
}
|
||||
}
|
||||
|
||||
public Serializable generate(AccessCallback callback) {
|
||||
public synchronized Serializable generate(AccessCallback callback) {
|
||||
if ( hiValue < 0 ) {
|
||||
value = callback.getNextValue();
|
||||
if ( value < 1 ) {
|
||||
|
|
|
@ -314,4 +314,14 @@ public class StatisticsService implements StatisticsServiceMBean {
|
|||
public String getQueryExecutionMaxTimeQueryString() {
|
||||
return stats.getQueryExecutionMaxTimeQueryString();
|
||||
}
|
||||
|
||||
public void setOperationThreshold(long threshold) {
|
||||
stats.setOperationThreshold(threshold);
|
||||
}
|
||||
|
||||
public long getOperationThreshold() {
|
||||
return stats.getOperationThreshold();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -26,12 +26,16 @@ import org.hibernate.util.CollectionHelper;
|
|||
public abstract class AbstractEntityJoinWalker extends JoinWalker {
|
||||
|
||||
private final OuterJoinLoadable persister;
|
||||
private String alias;
|
||||
private final String alias;
|
||||
|
||||
public AbstractEntityJoinWalker(OuterJoinLoadable persister, SessionFactoryImplementor factory, Map enabledFilters) {
|
||||
this( persister, factory, enabledFilters, null );
|
||||
}
|
||||
|
||||
public AbstractEntityJoinWalker(OuterJoinLoadable persister, SessionFactoryImplementor factory, Map enabledFilters, String alias) {
|
||||
super( factory, enabledFilters );
|
||||
this.persister = persister;
|
||||
alias = generateRootAlias( persister.getEntityName() );
|
||||
this.alias = ( alias == null ) ? generateRootAlias( persister.getEntityName() ) : alias;
|
||||
}
|
||||
|
||||
protected final void initAll(
|
||||
|
@ -39,9 +43,7 @@ public abstract class AbstractEntityJoinWalker extends JoinWalker {
|
|||
final String orderByString,
|
||||
final LockMode lockMode)
|
||||
throws MappingException {
|
||||
|
||||
walkEntityTree( persister, getAlias() );
|
||||
|
||||
List allAssociations = new ArrayList();
|
||||
allAssociations.addAll(associations);
|
||||
allAssociations.add( new OuterJoinableAssociation(
|
||||
|
|
|
@ -8,7 +8,6 @@ import java.util.Set;
|
|||
|
||||
import org.hibernate.Criteria;
|
||||
import org.hibernate.FetchMode;
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.LockMode;
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.engine.CascadeStyle;
|
||||
|
@ -18,7 +17,6 @@ import org.hibernate.loader.AbstractEntityJoinWalker;
|
|||
import org.hibernate.persister.entity.Joinable;
|
||||
import org.hibernate.persister.entity.OuterJoinLoadable;
|
||||
import org.hibernate.persister.entity.Queryable;
|
||||
import org.hibernate.sql.JoinFragment;
|
||||
import org.hibernate.type.AssociationType;
|
||||
import org.hibernate.type.Type;
|
||||
import org.hibernate.type.TypeFactory;
|
||||
|
@ -57,9 +55,19 @@ public class CriteriaJoinWalker extends AbstractEntityJoinWalker {
|
|||
final SessionFactoryImplementor factory,
|
||||
final CriteriaImpl criteria,
|
||||
final String rootEntityName,
|
||||
final Map enabledFilters)
|
||||
throws HibernateException {
|
||||
super(persister, factory, enabledFilters);
|
||||
final Map enabledFilters) {
|
||||
this(persister, translator, factory, criteria, rootEntityName, enabledFilters, null);
|
||||
}
|
||||
|
||||
public CriteriaJoinWalker(
|
||||
final OuterJoinLoadable persister,
|
||||
final CriteriaQueryTranslator translator,
|
||||
final SessionFactoryImplementor factory,
|
||||
final CriteriaImpl criteria,
|
||||
final String rootEntityName,
|
||||
final Map enabledFilters,
|
||||
final String alias) {
|
||||
super(persister, factory, enabledFilters, alias);
|
||||
|
||||
this.translator = translator;
|
||||
|
||||
|
|
|
@ -208,4 +208,17 @@ public interface Statistics {
|
|||
* that occurred
|
||||
*/
|
||||
public long getOptimisticFailureCount();
|
||||
|
||||
/**
|
||||
* Set the operationThreshold to a value greater than zero to enable logging of long running operations.
|
||||
* @param threshold (milliseconds)
|
||||
*/
|
||||
public void setOperationThreshold(long threshold);
|
||||
|
||||
/**
|
||||
*
|
||||
* @return Operationthreshold, if greater than zero, operations that exceed the level will be logged.
|
||||
*/
|
||||
public long getOperationThreshold();
|
||||
|
||||
}
|
|
@ -46,8 +46,11 @@ public class StatisticsImpl implements Statistics, StatisticsImplementor {
|
|||
private long secondLevelCacheHitCount;
|
||||
private long secondLevelCacheMissCount;
|
||||
private long secondLevelCachePutCount;
|
||||
|
||||
private long queryExecutionCount;
|
||||
|
||||
private long operationThreshold = 0; // log operations that take longer than this value (in milliseconds)
|
||||
// We don't log anything if operationThreshold == 0
|
||||
|
||||
private long queryExecutionCount;
|
||||
private long queryExecutionMaxTime;
|
||||
private String queryExecutionMaxTimeQueryString;
|
||||
private long queryCacheHitCount;
|
||||
|
@ -68,7 +71,20 @@ public class StatisticsImpl implements Statistics, StatisticsImplementor {
|
|||
/** entity statistics per query string (HQL or SQL) */
|
||||
private final Map queryStatistics = new HashMap();
|
||||
|
||||
public StatisticsImpl() {
|
||||
static final String OPERATION_LOAD = "load ";
|
||||
static final String OPERATION_FETCH = "fetch ";
|
||||
static final String OPERATION_UPDATE = "update ";
|
||||
static final String OPERATION_INSERT = "insert ";
|
||||
static final String OPERATION_DELETE = "delete ";
|
||||
static final String OPERATION_LOADCOLLECTION = "loadCollection ";
|
||||
static final String OPERATION_FETCHCOLLECTION = "fetchCollection ";
|
||||
static final String OPERATION_UPDATECOLLECTION = "updateCollection ";
|
||||
static final String OPERATION_RECREATECOLLECTION = "recreateCollection ";
|
||||
static final String OPERATION_REMOVECOLLECTION = "removeCollection ";
|
||||
static final String OPERATION_EXECUTEQUERY = "executeQuery ";
|
||||
static final String OPERATION_ENDTRANSACTION = "endTransaction ";
|
||||
|
||||
public StatisticsImpl() {
|
||||
clear();
|
||||
}
|
||||
|
||||
|
@ -140,16 +156,43 @@ public class StatisticsImpl implements Statistics, StatisticsImplementor {
|
|||
public synchronized void connect() {
|
||||
connectCount++;
|
||||
}
|
||||
|
||||
public synchronized void loadEntity(String entityName) {
|
||||
entityLoadCount++;
|
||||
getEntityStatistics(entityName).loadCount++;
|
||||
}
|
||||
|
||||
public synchronized void fetchEntity(String entityName) {
|
||||
entityFetchCount++;
|
||||
getEntityStatistics(entityName).fetchCount++;
|
||||
}
|
||||
public synchronized void setOperationThreshold(long threshold) {
|
||||
operationThreshold = threshold;
|
||||
}
|
||||
|
||||
public synchronized long getOperationThreshold() {
|
||||
return operationThreshold;
|
||||
}
|
||||
|
||||
private void logOperation(String operation, String entityName, long time) {
|
||||
if(entityName != null)
|
||||
log.info(operation+entityName + " " + time + "ms");
|
||||
else
|
||||
log.info(operation); // just log that the event occurred
|
||||
|
||||
}
|
||||
|
||||
|
||||
public void loadEntity(String entityName, long time) {
|
||||
synchronized(this) {
|
||||
entityLoadCount++;
|
||||
getEntityStatistics(entityName).loadCount++;
|
||||
}
|
||||
if(operationThreshold > 0 && operationThreshold < time) {
|
||||
logOperation(OPERATION_LOAD,entityName, time);
|
||||
}
|
||||
}
|
||||
|
||||
public void fetchEntity(String entityName, long time) {
|
||||
synchronized(this) {
|
||||
entityFetchCount++;
|
||||
getEntityStatistics(entityName).fetchCount++;
|
||||
}
|
||||
if(operationThreshold > 0 && operationThreshold < time) {
|
||||
logOperation(OPERATION_FETCH,entityName, time);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* find entity statistics per name
|
||||
|
@ -165,26 +208,41 @@ public class StatisticsImpl implements Statistics, StatisticsImplementor {
|
|||
}
|
||||
return es;
|
||||
}
|
||||
|
||||
public synchronized void updateEntity(String entityName) {
|
||||
entityUpdateCount++;
|
||||
EntityStatistics es = getEntityStatistics(entityName);
|
||||
es.updateCount++;
|
||||
}
|
||||
|
||||
public synchronized void insertEntity(String entityName) {
|
||||
entityInsertCount++;
|
||||
EntityStatistics es = getEntityStatistics(entityName);
|
||||
es.insertCount++;
|
||||
}
|
||||
public void updateEntity(String entityName, long time) {
|
||||
synchronized(this) {
|
||||
entityUpdateCount++;
|
||||
EntityStatistics es = getEntityStatistics(entityName);
|
||||
es.updateCount++;
|
||||
}
|
||||
if(operationThreshold > 0 && operationThreshold < time) {
|
||||
logOperation(OPERATION_UPDATE,entityName, time);
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void deleteEntity(String entityName) {
|
||||
entityDeleteCount++;
|
||||
EntityStatistics es = getEntityStatistics(entityName);
|
||||
es.deleteCount++;
|
||||
}
|
||||
public void insertEntity(String entityName, long time) {
|
||||
synchronized(this) {
|
||||
entityInsertCount++;
|
||||
EntityStatistics es = getEntityStatistics(entityName);
|
||||
es.insertCount++;
|
||||
}
|
||||
if(operationThreshold > 0 && operationThreshold < time) {
|
||||
logOperation(OPERATION_INSERT,entityName, time);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
public void deleteEntity(String entityName, long time) {
|
||||
synchronized(this) {
|
||||
entityDeleteCount++;
|
||||
EntityStatistics es = getEntityStatistics(entityName);
|
||||
es.deleteCount++;
|
||||
}
|
||||
if(operationThreshold > 0 && operationThreshold < time) {
|
||||
logOperation(OPERATION_DELETE,entityName, time);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get collection statistics per role
|
||||
*
|
||||
* @param role collection role
|
||||
|
@ -199,30 +257,55 @@ public class StatisticsImpl implements Statistics, StatisticsImplementor {
|
|||
return cs;
|
||||
}
|
||||
|
||||
public synchronized void loadCollection(String role) {
|
||||
collectionLoadCount++;
|
||||
getCollectionStatistics(role).loadCount++;
|
||||
}
|
||||
public void loadCollection(String role, long time) {
|
||||
synchronized(this) {
|
||||
collectionLoadCount++;
|
||||
getCollectionStatistics(role).loadCount++;
|
||||
}
|
||||
if(operationThreshold > 0 && operationThreshold < time) {
|
||||
logOperation(OPERATION_LOADCOLLECTION,role, time);
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void fetchCollection(String role) {
|
||||
collectionFetchCount++;
|
||||
getCollectionStatistics(role).fetchCount++;
|
||||
}
|
||||
public void fetchCollection(String role, long time) {
|
||||
synchronized(this) {
|
||||
collectionFetchCount++;
|
||||
getCollectionStatistics(role).fetchCount++;
|
||||
}
|
||||
if(operationThreshold > 0 && operationThreshold < time) {
|
||||
logOperation(OPERATION_FETCHCOLLECTION,role, time);
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void updateCollection(String role) {
|
||||
collectionUpdateCount++;
|
||||
getCollectionStatistics(role).updateCount++;
|
||||
}
|
||||
public void updateCollection(String role, long time) {
|
||||
synchronized(this) {
|
||||
collectionUpdateCount++;
|
||||
getCollectionStatistics(role).updateCount++;
|
||||
}
|
||||
if(operationThreshold > 0 && operationThreshold < time) {
|
||||
logOperation(OPERATION_UPDATECOLLECTION,role, time);
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void recreateCollection(String role) {
|
||||
collectionRecreateCount++;
|
||||
getCollectionStatistics(role).recreateCount++;
|
||||
}
|
||||
public void recreateCollection(String role, long time) {
|
||||
synchronized(this) {
|
||||
collectionRecreateCount++;
|
||||
getCollectionStatistics(role).recreateCount++;
|
||||
}
|
||||
if(operationThreshold > 0 && operationThreshold < time) {
|
||||
logOperation(OPERATION_RECREATECOLLECTION,role, time);
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void removeCollection(String role) {
|
||||
collectionRemoveCount++;
|
||||
getCollectionStatistics(role).removeCount++;
|
||||
}
|
||||
public void removeCollection(String role, long time) {
|
||||
synchronized(this) {
|
||||
collectionRemoveCount++;
|
||||
getCollectionStatistics(role).removeCount++;
|
||||
}
|
||||
if(operationThreshold > 0 && operationThreshold < time) {
|
||||
logOperation(OPERATION_REMOVECOLLECTION,role, time);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Second level cache statistics per region
|
||||
|
@ -257,17 +340,23 @@ public class StatisticsImpl implements Statistics, StatisticsImplementor {
|
|||
getSecondLevelCacheStatistics(regionName).missCount++;
|
||||
}
|
||||
|
||||
public synchronized void queryExecuted(String hql, int rows, long time) {
|
||||
queryExecutionCount++;
|
||||
if (queryExecutionMaxTime<time) {
|
||||
queryExecutionMaxTime=time;
|
||||
queryExecutionMaxTimeQueryString = hql;
|
||||
}
|
||||
if (hql!=null) {
|
||||
QueryStatistics qs = getQueryStatistics(hql);
|
||||
qs.executed(rows, time);
|
||||
}
|
||||
}
|
||||
|
||||
public void queryExecuted(String hql, int rows, long time) {
|
||||
synchronized(this) {
|
||||
queryExecutionCount++;
|
||||
if (queryExecutionMaxTime<time) {
|
||||
queryExecutionMaxTime=time;
|
||||
queryExecutionMaxTimeQueryString = hql;
|
||||
}
|
||||
if (hql!=null) {
|
||||
QueryStatistics qs = getQueryStatistics(hql);
|
||||
qs.executed(rows, time);
|
||||
}
|
||||
}
|
||||
if(operationThreshold > 0 && operationThreshold < time) {
|
||||
logOperation(OPERATION_EXECUTEQUERY,hql, time);
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void queryCacheHit(String hql, String regionName) {
|
||||
queryCacheHitCount++;
|
||||
|
@ -556,10 +645,17 @@ public class StatisticsImpl implements Statistics, StatisticsImplementor {
|
|||
}
|
||||
}
|
||||
|
||||
public void endTransaction(boolean success) {
|
||||
transactionCount++;
|
||||
if (success) commitedTransactionCount++;
|
||||
}
|
||||
public void endTransaction(boolean success) {
|
||||
synchronized(this) {
|
||||
transactionCount++;
|
||||
if (success) commitedTransactionCount++;
|
||||
}
|
||||
// The end transaction message can get too verbose (output log fills up with just end tx messages)
|
||||
//if(operationThreshold > 0) { // show endTransaction operations if we are logging operations that exceed a threshold.
|
||||
// logOperation(OPERATION_ENDTRANSACTION,null, 0);
|
||||
//}
|
||||
|
||||
}
|
||||
|
||||
public long getSuccessfulTransactionCount() {
|
||||
return commitedTransactionCount;
|
||||
|
|
|
@ -11,16 +11,16 @@ public interface StatisticsImplementor {
|
|||
public void closeSession();
|
||||
public void flush();
|
||||
public void connect();
|
||||
public void loadEntity(String entityName);
|
||||
public void fetchEntity(String entityName);
|
||||
public void updateEntity(String entityName);
|
||||
public void insertEntity(String entityName);
|
||||
public void deleteEntity(String entityName);
|
||||
public void loadCollection(String role);
|
||||
public void fetchCollection(String role);
|
||||
public void updateCollection(String role);
|
||||
public void recreateCollection(String role);
|
||||
public void removeCollection(String role);
|
||||
public void loadEntity(String entityName, long time);
|
||||
public void fetchEntity(String entityName, long time);
|
||||
public void updateEntity(String entityName, long time);
|
||||
public void insertEntity(String entityName, long time);
|
||||
public void deleteEntity(String entityName, long time);
|
||||
public void loadCollection(String role, long time);
|
||||
public void fetchCollection(String role, long time);
|
||||
public void updateCollection(String role, long time);
|
||||
public void recreateCollection(String role, long time);
|
||||
public void removeCollection(String role, long time);
|
||||
public void secondLevelCachePut(String regionName);
|
||||
public void secondLevelCacheHit(String regionName);
|
||||
public void secondLevelCacheMiss(String regionName);
|
||||
|
|
|
@ -16,7 +16,6 @@ import org.hibernate.cfg.Configuration;
|
|||
import org.hibernate.cfg.Environment;
|
||||
import org.hibernate.criterion.DetachedCriteria;
|
||||
import org.hibernate.criterion.Example;
|
||||
import org.hibernate.criterion.Expression;
|
||||
import org.hibernate.criterion.MatchMode;
|
||||
import org.hibernate.criterion.Order;
|
||||
import org.hibernate.criterion.Projection;
|
||||
|
@ -154,8 +153,8 @@ public class CriteriaQueryTest extends FunctionalTestCase {
|
|||
.list();
|
||||
|
||||
session.createCriteria(Student.class)
|
||||
.add( Property.forName("name").eqAll(dc) )
|
||||
.list();
|
||||
.add( Property.forName("name").eqAll(dc) )
|
||||
.list();
|
||||
|
||||
session.createCriteria(Student.class)
|
||||
.add( Subqueries.in("Gavin King", dc) )
|
||||
|
@ -169,8 +168,7 @@ public class CriteriaQueryTest extends FunctionalTestCase {
|
|||
.add( Subqueries.eq("Gavin King", dc2) )
|
||||
.list();
|
||||
|
||||
//TODO: join in subselect: HHH-952
|
||||
/*DetachedCriteria dc3 = DetachedCriteria.forClass(Student.class, "st")
|
||||
DetachedCriteria dc3 = DetachedCriteria.forClass(Student.class, "st")
|
||||
.createCriteria("enrolments")
|
||||
.createCriteria("course")
|
||||
.add( Property.forName("description").eq("Hibernate Training") )
|
||||
|
@ -178,7 +176,7 @@ public class CriteriaQueryTest extends FunctionalTestCase {
|
|||
|
||||
session.createCriteria(Enrolment.class, "e")
|
||||
.add( Subqueries.eq("Gavin King", dc3) )
|
||||
.list();*/
|
||||
.list();
|
||||
|
||||
session.delete(enrolment2);
|
||||
session.delete(gavin);
|
||||
|
@ -398,8 +396,8 @@ public class CriteriaQueryTest extends FunctionalTestCase {
|
|||
.add( Projections.property("studentNumber"), "stNumber" )
|
||||
.add( Projections.property("courseCode"), "cCode" ) )
|
||||
)
|
||||
.add( Expression.gt( "studentNumber", new Long(665) ) )
|
||||
.add( Expression.lt( "studentNumber", new Long(668) ) )
|
||||
.add( Restrictions.gt( "studentNumber", new Long(665) ) )
|
||||
.add( Restrictions.lt( "studentNumber", new Long(668) ) )
|
||||
.addOrder( Order.asc("stNumber") )
|
||||
.setResultTransformer(Criteria.ALIAS_TO_ENTITY_MAP)
|
||||
.list();
|
||||
|
|
|
@ -10,7 +10,9 @@ import junit.framework.Test;
|
|||
import org.hibernate.Hibernate;
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.Transaction;
|
||||
import org.hibernate.proxy.HibernateProxy;
|
||||
import org.hibernate.criterion.Property;
|
||||
import org.hibernate.criterion.Restrictions;
|
||||
import org.hibernate.junit.functional.FunctionalTestCase;
|
||||
import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
|
||||
|
||||
|
@ -171,6 +173,82 @@ public class DiscriminatorTest extends FunctionalTestCase {
|
|||
s.close();
|
||||
}
|
||||
|
||||
public void testLoadSuperclassProxyPolymorphicAccess() {
|
||||
Session s = openSession();
|
||||
s.beginTransaction();
|
||||
Employee e = new Employee();
|
||||
e.setName( "Steve" );
|
||||
e.setSex( 'M' );
|
||||
e.setTitle( "grand poobah" );
|
||||
s.save( e );
|
||||
s.getTransaction().commit();
|
||||
s.close();
|
||||
|
||||
s = openSession();
|
||||
s.beginTransaction();
|
||||
// load the superclass proxy.
|
||||
Person pLoad = ( Person ) s.load( Person.class, new Long( e.getId() ) );
|
||||
assertTrue( pLoad instanceof HibernateProxy);
|
||||
Person pGet = ( Person ) s.get( Person.class, new Long( e.getId() ));
|
||||
Person pQuery = ( Person ) s.createQuery( "from Person where id = :id" )
|
||||
.setLong( "id", e.getId() )
|
||||
.uniqueResult();
|
||||
Person pCriteria = ( Person ) s.createCriteria( Person.class )
|
||||
.add( Restrictions.idEq( new Long( e.getId() ) ) )
|
||||
.uniqueResult();
|
||||
// assert that executing the queries polymorphically returns the same proxy
|
||||
assertSame( pLoad, pGet );
|
||||
assertSame( pLoad, pQuery );
|
||||
assertSame( pLoad, pCriteria );
|
||||
|
||||
// assert that the proxy is not an instance of Employee
|
||||
assertFalse( pLoad instanceof Employee );
|
||||
|
||||
s.getTransaction().commit();
|
||||
s.close();
|
||||
|
||||
s = openSession();
|
||||
s.beginTransaction();
|
||||
s.delete( e );
|
||||
s.getTransaction().commit();
|
||||
s.close();
|
||||
}
|
||||
|
||||
public void testLoadSuperclassProxyEvictPolymorphicAccess() {
|
||||
Session s = openSession();
|
||||
s.beginTransaction();
|
||||
Employee e = new Employee();
|
||||
e.setName( "Steve" );
|
||||
e.setSex( 'M' );
|
||||
e.setTitle( "grand poobah" );
|
||||
s.save( e );
|
||||
s.getTransaction().commit();
|
||||
s.close();
|
||||
|
||||
s = openSession();
|
||||
s.beginTransaction();
|
||||
// load the superclass proxy.
|
||||
Person pLoad = ( Person ) s.load( Person.class, new Long( e.getId() ) );
|
||||
assertTrue( pLoad instanceof HibernateProxy);
|
||||
// evict the proxy
|
||||
s.evict( pLoad );
|
||||
Employee pGet = ( Employee ) s.get( Person.class, new Long( e.getId() ));
|
||||
Employee pQuery = ( Employee ) s.createQuery( "from Person where id = :id" )
|
||||
.setLong( "id", e.getId() )
|
||||
.uniqueResult();
|
||||
Employee pCriteria = ( Employee ) s.createCriteria( Person.class )
|
||||
.add( Restrictions.idEq( new Long( e.getId() ) ) )
|
||||
.uniqueResult();
|
||||
// assert that executing the queries polymorphically returns the same Employee instance
|
||||
assertSame( pGet, pQuery );
|
||||
assertSame( pGet, pCriteria );
|
||||
s.getTransaction().commit();
|
||||
s.close();
|
||||
|
||||
s = openSession();
|
||||
s.beginTransaction();
|
||||
s.delete( e );
|
||||
s.getTransaction().commit();
|
||||
s.close();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -451,6 +451,17 @@ public class BulkManipulationTest extends FunctionalTestCase {
|
|||
s.close();
|
||||
}
|
||||
|
||||
public void testInsertWithSelectListUsingJoins() {
|
||||
// this is just checking parsing and syntax...
|
||||
Session s = openSession();
|
||||
s.beginTransaction();
|
||||
s.createQuery( "insert into Animal (description, bodyWeight) select h.description, h.bodyWeight from Human h where h.mother.mother is not null" ).executeUpdate();
|
||||
s.createQuery( "delete from Animal" ).executeUpdate();
|
||||
s.getTransaction().commit();
|
||||
s.close();
|
||||
}
|
||||
|
||||
|
||||
// UPDATES ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
public void testIncorrectSyntax() {
|
||||
|
|
|
@ -8,11 +8,12 @@ import java.util.List;
|
|||
import junit.framework.Test;
|
||||
|
||||
import org.hibernate.Hibernate;
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.Transaction;
|
||||
import org.hibernate.NonUniqueObjectException;
|
||||
import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.StaleObjectStateException;
|
||||
import org.hibernate.Transaction;
|
||||
import org.hibernate.criterion.Projections;
|
||||
import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
|
||||
|
||||
/**
|
||||
* @author Gavin King
|
||||
|
@ -27,6 +28,39 @@ public class MergeTest extends AbstractOperationTestCase {
|
|||
return new FunctionalTestClassTestSuite( MergeTest.class );
|
||||
}
|
||||
|
||||
public void testMergeStaleVersionFails() throws Exception {
|
||||
Session s = openSession();
|
||||
s.beginTransaction();
|
||||
VersionedEntity entity = new VersionedEntity( "entity", "entity" );
|
||||
s.persist( entity );
|
||||
s.getTransaction().commit();
|
||||
s.close();
|
||||
|
||||
// make the detached 'entity' reference stale...
|
||||
s = openSession();
|
||||
s.beginTransaction();
|
||||
VersionedEntity entity2 = ( VersionedEntity ) s.get( VersionedEntity.class, entity.getId() );
|
||||
entity2.setName( "entity-name" );
|
||||
s.getTransaction().commit();
|
||||
s.close();
|
||||
|
||||
// now try to reattch it
|
||||
s = openSession();
|
||||
s.beginTransaction();
|
||||
try {
|
||||
s.merge( entity );
|
||||
s.getTransaction().commit();
|
||||
fail( "was expecting staleness error" );
|
||||
}
|
||||
catch ( StaleObjectStateException expected ) {
|
||||
// expected outcome...
|
||||
}
|
||||
finally {
|
||||
s.getTransaction().rollback();
|
||||
s.close();
|
||||
}
|
||||
}
|
||||
|
||||
public void testMergeBidiPrimayKeyOneToOne() throws Exception {
|
||||
Session s = openSession();
|
||||
s.beginTransaction();
|
||||
|
@ -121,7 +155,7 @@ public class MergeTest extends AbstractOperationTestCase {
|
|||
assertInsertCount( 0 );
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
cleanup();
|
||||
// cleanup();
|
||||
}
|
||||
|
||||
public void testNoExtraUpdatesOnMergeWithCollection() throws Exception {
|
||||
|
@ -162,7 +196,7 @@ public class MergeTest extends AbstractOperationTestCase {
|
|||
assertInsertCount( 1 );
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
cleanup();
|
||||
// cleanup();
|
||||
}
|
||||
|
||||
public void testNoExtraUpdatesOnMergeVersioned() throws Exception {
|
||||
|
@ -201,7 +235,7 @@ public class MergeTest extends AbstractOperationTestCase {
|
|||
assertInsertCount( 0 );
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
cleanup();
|
||||
// cleanup();
|
||||
}
|
||||
|
||||
public void testNoExtraUpdatesOnMergeVersionedWithCollection() throws Exception {
|
||||
|
@ -245,7 +279,7 @@ public class MergeTest extends AbstractOperationTestCase {
|
|||
assertInsertCount( 1 );
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
cleanup();
|
||||
// cleanup();
|
||||
}
|
||||
|
||||
public void testPersistThenMergeInSameTxnWithVersion() {
|
||||
|
@ -267,7 +301,7 @@ public class MergeTest extends AbstractOperationTestCase {
|
|||
tx.commit();
|
||||
s.close();
|
||||
|
||||
cleanup();
|
||||
// cleanup();
|
||||
}
|
||||
|
||||
public void testPersistThenMergeInSameTxnWithTimestamp() {
|
||||
|
@ -289,7 +323,7 @@ public class MergeTest extends AbstractOperationTestCase {
|
|||
tx.commit();
|
||||
s.close();
|
||||
|
||||
cleanup();
|
||||
// cleanup();
|
||||
}
|
||||
|
||||
public void testMergeDeepTree() {
|
||||
|
@ -447,7 +481,7 @@ public class MergeTest extends AbstractOperationTestCase {
|
|||
assertInsertCount(1);
|
||||
assertUpdateCount(2);
|
||||
|
||||
cleanup();
|
||||
// cleanup();
|
||||
}
|
||||
|
||||
public void testMergeTreeWithGeneratedId() {
|
||||
|
@ -482,7 +516,7 @@ public class MergeTest extends AbstractOperationTestCase {
|
|||
assertInsertCount(1);
|
||||
assertUpdateCount(2);
|
||||
|
||||
cleanup();
|
||||
// cleanup();
|
||||
}
|
||||
|
||||
public void testMergeManaged() {
|
||||
|
@ -524,7 +558,7 @@ public class MergeTest extends AbstractOperationTestCase {
|
|||
|
||||
s.close();
|
||||
|
||||
cleanup();
|
||||
// cleanup();
|
||||
}
|
||||
|
||||
public void testRecursiveMergeTransient() {
|
||||
|
@ -544,7 +578,7 @@ public class MergeTest extends AbstractOperationTestCase {
|
|||
tx.commit();
|
||||
s.close();
|
||||
|
||||
cleanup();
|
||||
// cleanup();
|
||||
}
|
||||
|
||||
public void testDeleteAndMerge() throws Exception {
|
||||
|
@ -567,7 +601,7 @@ public class MergeTest extends AbstractOperationTestCase {
|
|||
s.getTransaction().commit();
|
||||
s.close();
|
||||
|
||||
cleanup();
|
||||
// cleanup();
|
||||
}
|
||||
|
||||
public void testMergeManyToManyWithCollectionDeference() throws Exception {
|
||||
|
@ -610,11 +644,16 @@ public class MergeTest extends AbstractOperationTestCase {
|
|||
tx.commit();
|
||||
s.close();
|
||||
|
||||
// cleanup();
|
||||
}
|
||||
|
||||
protected void cleanupTest() throws Exception {
|
||||
cleanup();
|
||||
super.cleanupTest();
|
||||
}
|
||||
|
||||
private void cleanup() {
|
||||
Session s = openSession();
|
||||
Session s = sfi().openSession();
|
||||
s.beginTransaction();
|
||||
s.createQuery( "delete from NumberedNode where parent is not null" ).executeUpdate();
|
||||
s.createQuery( "delete from NumberedNode" ).executeUpdate();
|
||||
|
|
Loading…
Reference in New Issue