diff --git a/gradle/libraries.gradle b/gradle/libraries.gradle index 5e60a40d6a..7baeb8374c 100644 --- a/gradle/libraries.gradle +++ b/gradle/libraries.gradle @@ -26,7 +26,7 @@ ext { weldVersion = '3.0.0.Final' javassistVersion = '3.24.0-GA' - byteBuddyVersion = '1.10.2' + byteBuddyVersion = '1.10.7' agroalVersion = '1.7' diff --git a/hibernate-core/src/main/java/org/hibernate/action/internal/EntityDeleteAction.java b/hibernate-core/src/main/java/org/hibernate/action/internal/EntityDeleteAction.java index 0fd8284f76..2ca93217dd 100644 --- a/hibernate-core/src/main/java/org/hibernate/action/internal/EntityDeleteAction.java +++ b/hibernate-core/src/main/java/org/hibernate/action/internal/EntityDeleteAction.java @@ -66,6 +66,30 @@ public class EntityDeleteAction extends EntityAction { ); } + public Object getVersion() { + return version; + } + + public boolean isCascadeDeleteEnabled() { + return isCascadeDeleteEnabled; + } + + public Object[] getState() { + return state; + } + + protected Object[] getNaturalIdValues() { + return naturalIdValues; + } + + protected SoftLock getLock() { + return lock; + } + + protected void setLock(SoftLock lock) { + this.lock = lock; + } + @Override public void execute() throws HibernateException { final Object id = getId(); @@ -125,7 +149,7 @@ public class EntityDeleteAction extends EntityAction { } } - private boolean preDelete() { + protected boolean preDelete() { boolean veto = false; final EventListenerGroup listenerGroup = listenerGroup( EventType.PRE_DELETE ); if ( listenerGroup.isEmpty() ) { @@ -138,7 +162,7 @@ public class EntityDeleteAction extends EntityAction { return veto; } - private void postDelete() { + protected void postDelete() { final EventListenerGroup listenerGroup = listenerGroup( EventType.POST_DELETE ); if ( listenerGroup.isEmpty() ) { return; @@ -155,7 +179,7 @@ public class EntityDeleteAction extends EntityAction { } } - private void postCommitDelete(boolean success) { + protected void postCommitDelete(boolean success) { final EventListenerGroup listenerGroup = listenerGroup( EventType.POST_COMMIT_DELETE ); if ( listenerGroup.isEmpty() ) { return; diff --git a/hibernate-core/src/main/java/org/hibernate/action/internal/EntityIdentityInsertAction.java b/hibernate-core/src/main/java/org/hibernate/action/internal/EntityIdentityInsertAction.java index 2fec3fc6cb..847faf866b 100644 --- a/hibernate-core/src/main/java/org/hibernate/action/internal/EntityIdentityInsertAction.java +++ b/hibernate-core/src/main/java/org/hibernate/action/internal/EntityIdentityInsertAction.java @@ -27,7 +27,7 @@ import org.hibernate.stat.spi.StatisticsImplementor; * * @see EntityInsertAction */ -public final class EntityIdentityInsertAction extends AbstractEntityInsertAction { +public class EntityIdentityInsertAction extends AbstractEntityInsertAction { private final boolean isDelayed; private final EntityKey delayedEntityKey; @@ -139,7 +139,7 @@ public final class EntityIdentityInsertAction extends AbstractEntityInsertAction postCommitInsert( success ); } - private void postInsert() { + protected void postInsert() { final EventSource eventSource = eventSource(); if ( isDelayed ) { eventSource.getPersistenceContextInternal().replaceDelayedEntityIdentityInsertKeys( delayedEntityKey, generatedId ); @@ -161,7 +161,7 @@ public final class EntityIdentityInsertAction extends AbstractEntityInsertAction } } - private void postCommitInsert(boolean success) { + protected void postCommitInsert(boolean success) { final EventListenerGroup listenerGroup = listenerGroup( EventType.POST_COMMIT_INSERT ); if ( listenerGroup.isEmpty() ) { return; @@ -189,7 +189,7 @@ public final class EntityIdentityInsertAction extends AbstractEntityInsertAction } } - private boolean preInsert() { + protected boolean preInsert() { final EventListenerGroup listenerGroup = listenerGroup( EventType.PRE_INSERT ); if ( listenerGroup.isEmpty() ) { // NO_VETO @@ -212,6 +212,10 @@ public final class EntityIdentityInsertAction extends AbstractEntityInsertAction return generatedId; } + protected void setGeneratedId(Serializable generatedId) { + this.generatedId = generatedId; + } + /** * Access to the delayed entity key * @@ -235,11 +239,15 @@ public final class EntityIdentityInsertAction extends AbstractEntityInsertAction return entityKey != null ? entityKey : delayedEntityKey; } + protected void setEntityKey(EntityKey entityKey) { + this.entityKey = entityKey; + } + private static DelayedPostInsertIdentifier generateDelayedPostInsertIdentifier() { return new DelayedPostInsertIdentifier(); } - private EntityKey generateDelayedEntityKey() { + protected EntityKey generateDelayedEntityKey() { if ( !isDelayed ) { throw new AssertionFailure( "cannot request delayed entity-key for early-insert post-insert-id generation" ); } diff --git a/hibernate-core/src/main/java/org/hibernate/action/internal/EntityInsertAction.java b/hibernate-core/src/main/java/org/hibernate/action/internal/EntityInsertAction.java index 8beeb092bf..052d23f135 100644 --- a/hibernate-core/src/main/java/org/hibernate/action/internal/EntityInsertAction.java +++ b/hibernate-core/src/main/java/org/hibernate/action/internal/EntityInsertAction.java @@ -33,7 +33,7 @@ import org.hibernate.stat.spi.StatisticsImplementor; * * @see EntityIdentityInsertAction */ -public final class EntityInsertAction extends AbstractEntityInsertAction { +public class EntityInsertAction extends AbstractEntityInsertAction { private Object version; private Object cacheEntry; @@ -59,6 +59,22 @@ public final class EntityInsertAction extends AbstractEntityInsertAction { this.version = version; } + public Object getVersion() { + return version; + } + + public void setVersion(Object version) { + this.version = version; + } + + protected Object getCacheEntry() { + return cacheEntry; + } + + protected void setCacheEntry(Object cacheEntry) { + this.cacheEntry = cacheEntry; + } + @Override public boolean isEarlyInsert() { return false; @@ -140,7 +156,7 @@ public final class EntityInsertAction extends AbstractEntityInsertAction { markExecuted(); } - private boolean cacheInsert(EntityPersister persister, Object ck) { + protected boolean cacheInsert(EntityPersister persister, Object ck) { SharedSessionContractImplementor session = getSession(); try { session.getEventListenerManager().cachePutStart(); @@ -151,7 +167,7 @@ public final class EntityInsertAction extends AbstractEntityInsertAction { } } - private void postInsert() { + protected void postInsert() { final EventListenerGroup listenerGroup = listenerGroup( EventType.POST_INSERT ); if ( listenerGroup.isEmpty() ) { return; @@ -168,7 +184,7 @@ public final class EntityInsertAction extends AbstractEntityInsertAction { } } - private void postCommitInsert(boolean success) { + protected void postCommitInsert(boolean success) { final EventListenerGroup listenerGroup = listenerGroup( EventType.POST_COMMIT_INSERT ); if ( listenerGroup.isEmpty() ) { return; @@ -196,7 +212,7 @@ public final class EntityInsertAction extends AbstractEntityInsertAction { } } - private boolean preInsert() { + protected boolean preInsert() { boolean veto = false; final EventListenerGroup listenerGroup = listenerGroup( EventType.PRE_INSERT ); @@ -230,7 +246,7 @@ public final class EntityInsertAction extends AbstractEntityInsertAction { postCommitInsert( success ); } - private boolean cacheAfterInsert(EntityDataAccess cache, Object ck) { + protected boolean cacheAfterInsert(EntityDataAccess cache, Object ck) { SharedSessionContractImplementor session = getSession(); final SessionEventListenerManager eventListenerManager = session.getEventListenerManager(); try { @@ -253,8 +269,8 @@ public final class EntityInsertAction extends AbstractEntityInsertAction { return false; } - - private boolean isCachePutEnabled(EntityPersister persister, SharedSessionContractImplementor session) { + + protected boolean isCachePutEnabled(EntityPersister persister, SharedSessionContractImplementor session) { return persister.canWriteToCache() && !persister.isCacheInvalidationRequired() && session.getCacheMode().isPutEnabled(); diff --git a/hibernate-core/src/main/java/org/hibernate/action/internal/EntityUpdateAction.java b/hibernate-core/src/main/java/org/hibernate/action/internal/EntityUpdateAction.java index 0c978fc9dd..3d6f8c9dbf 100644 --- a/hibernate-core/src/main/java/org/hibernate/action/internal/EntityUpdateAction.java +++ b/hibernate-core/src/main/java/org/hibernate/action/internal/EntityUpdateAction.java @@ -37,7 +37,7 @@ import org.hibernate.type.TypeHelper; /** * The action for performing entity updates. */ -public final class EntityUpdateAction extends EntityAction { +public class EntityUpdateAction extends EntityAction { private final Object[] state; private final Object[] previousState; private final Object previousVersion; @@ -110,6 +110,58 @@ public final class EntityUpdateAction extends EntityAction { return persistenceContext.getNaturalIdSnapshot( id, persister ); } + public Object[] getState() { + return state; + } + + public Object[] getPreviousState() { + return previousState; + } + + public Object getPreviousVersion() { + return previousVersion; + } + + public Object getNextVersion() { + return nextVersion; + } + + public void setNextVersion(Object nextVersion) { + this.nextVersion = nextVersion; + } + + public int[] getDirtyFields() { + return dirtyFields; + } + + public boolean hasDirtyCollection() { + return hasDirtyCollection; + } + + public Object getRowId() { + return rowId; + } + + public Object[] getPreviousNaturalIdValues() { + return previousNaturalIdValues; + } + + protected Object getCacheEntry() { + return cacheEntry; + } + + protected void setCacheEntry(Object cacheEntry) { + this.cacheEntry = cacheEntry; + } + + protected SoftLock getLock() { + return lock; + } + + protected void setLock(SoftLock lock) { + this.lock = lock; + } + @Override public void execute() throws HibernateException { final Object id = getId(); @@ -221,7 +273,7 @@ public final class EntityUpdateAction extends EntityAction { } } - private boolean cacheUpdate(EntityPersister persister, Object previousVersion, Object ck) { + protected boolean cacheUpdate(EntityPersister persister, Object previousVersion, Object ck) { final SharedSessionContractImplementor session = getSession(); try { session.getEventListenerManager().cachePutStart(); @@ -232,7 +284,7 @@ public final class EntityUpdateAction extends EntityAction { } } - private boolean preUpdate() { + protected boolean preUpdate() { boolean veto = false; final EventListenerGroup listenerGroup = listenerGroup( EventType.PRE_UPDATE ); if ( listenerGroup.isEmpty() ) { @@ -252,7 +304,7 @@ public final class EntityUpdateAction extends EntityAction { return veto; } - private void postUpdate() { + protected void postUpdate() { final EventListenerGroup listenerGroup = listenerGroup( EventType.POST_UPDATE ); if ( listenerGroup.isEmpty() ) { return; @@ -271,7 +323,7 @@ public final class EntityUpdateAction extends EntityAction { } } - private void postCommitUpdate(boolean success) { + protected void postCommitUpdate(boolean success) { final EventListenerGroup listenerGroup = listenerGroup( EventType.POST_COMMIT_UPDATE ); if ( listenerGroup.isEmpty() ) { return; @@ -348,7 +400,7 @@ public final class EntityUpdateAction extends EntityAction { postCommitUpdate( success ); } - private boolean cacheAfterUpdate(EntityDataAccess cache, Object ck) { + protected boolean cacheAfterUpdate(EntityDataAccess cache, Object ck) { final SharedSessionContractImplementor session = getSession(); SessionEventListenerManager eventListenerManager = session.getEventListenerManager(); try { diff --git a/hibernate-core/src/main/java/org/hibernate/event/internal/AbstractSaveEventListener.java b/hibernate-core/src/main/java/org/hibernate/event/internal/AbstractSaveEventListener.java index 9f3b74c652..a27a8a2b3a 100644 --- a/hibernate-core/src/main/java/org/hibernate/event/internal/AbstractSaveEventListener.java +++ b/hibernate-core/src/main/java/org/hibernate/event/internal/AbstractSaveEventListener.java @@ -17,7 +17,6 @@ import org.hibernate.action.internal.EntityInsertAction; import org.hibernate.classic.Lifecycle; import org.hibernate.engine.internal.Cascade; import org.hibernate.engine.internal.CascadePoint; -import org.hibernate.engine.internal.ForeignKeys; import org.hibernate.engine.internal.Versioning; import org.hibernate.engine.spi.CascadingAction; import org.hibernate.engine.spi.EntityEntry; @@ -49,10 +48,6 @@ public abstract class AbstractSaveEventListener implements CallbackRegistryConsumer { private static final CoreMessageLogger LOG = CoreLogging.messageLogger( AbstractSaveEventListener.class ); - public enum EntityState { - PERSISTENT, TRANSIENT, DETACHED, DELETED - } - private CallbackRegistry callbackRegistry; public void injectCallbackRegistry(CallbackRegistry callbackRegistry) { @@ -489,60 +484,4 @@ public abstract class AbstractSaveEventListener protected abstract CascadingAction getCascadeAction(); - /** - * Determine whether the entity is persistent, detached, or transient - * - * @param entity The entity to check - * @param entityName The name of the entity - * @param entry The entity's entry in the persistence context - * @param source The originating session. - * - * @return The state. - */ - protected EntityState getEntityState( - Object entity, - String entityName, - EntityEntry entry, //pass this as an argument only to avoid double looking - SessionImplementor source) { - - if ( entry != null ) { // the object is persistent - - //the entity is associated with the session, so check its status - if ( entry.getStatus() != Status.DELETED ) { - // do nothing for persistent instances - if ( LOG.isTraceEnabled() ) { - LOG.tracev( "Persistent instance of: {0}", getLoggableName( entityName, entity ) ); - } - return EntityState.PERSISTENT; - } - // ie. e.status==DELETED - if ( LOG.isTraceEnabled() ) { - LOG.tracev( "Deleted instance of: {0}", getLoggableName( entityName, entity ) ); - } - return EntityState.DELETED; - } - // the object is transient or detached - - // the entity is not associated with the session, so - // try interceptor and unsaved-value - - if ( ForeignKeys.isTransient( entityName, entity, getAssumedUnsaved(), source ) ) { - if ( LOG.isTraceEnabled() ) { - LOG.tracev( "Transient instance of: {0}", getLoggableName( entityName, entity ) ); - } - return EntityState.TRANSIENT; - } - if ( LOG.isTraceEnabled() ) { - LOG.tracev( "Detached instance of: {0}", getLoggableName( entityName, entity ) ); - } - return EntityState.DETACHED; - } - - protected String getLoggableName(String entityName, Object entity) { - return entityName == null ? entity.getClass().getName() : entityName; - } - - protected Boolean getAssumedUnsaved() { - return null; - } } diff --git a/hibernate-core/src/main/java/org/hibernate/event/internal/AbstractVisitor.java b/hibernate-core/src/main/java/org/hibernate/event/internal/AbstractVisitor.java index 85ff7ba815..b6a1190fdb 100644 --- a/hibernate-core/src/main/java/org/hibernate/event/internal/AbstractVisitor.java +++ b/hibernate-core/src/main/java/org/hibernate/event/internal/AbstractVisitor.java @@ -121,7 +121,7 @@ public abstract class AbstractVisitor { * @param persister * @throws HibernateException */ - void process(Object object, EntityPersister persister) + public void process(Object object, EntityPersister persister) throws HibernateException { processEntityPropertyValues( persister.getPropertyValues( object ), diff --git a/hibernate-core/src/main/java/org/hibernate/event/internal/DefaultDeleteEventListener.java b/hibernate-core/src/main/java/org/hibernate/event/internal/DefaultDeleteEventListener.java index e2559afbc4..52b75524f7 100644 --- a/hibernate-core/src/main/java/org/hibernate/event/internal/DefaultDeleteEventListener.java +++ b/hibernate-core/src/main/java/org/hibernate/event/internal/DefaultDeleteEventListener.java @@ -145,13 +145,7 @@ public class DefaultDeleteEventListener implements DeleteEventListener, Callback version = entityEntry.getVersion(); } - /*if ( !persister.isMutable() ) { - throw new HibernateException( - "attempted to delete an object of immutable class: " + - MessageHelper.infoString(persister) - ); - }*/ - + callbackRegistry.preRemove( entity ); if ( invokeDeleteLifecycle( source, entity, persister ) ) { return; } @@ -338,8 +332,6 @@ public class DefaultDeleteEventListener implements DeleteEventListener, Callback } protected boolean invokeDeleteLifecycle(EventSource session, Object entity, EntityPersister persister) { - callbackRegistry.preRemove( entity ); - if ( persister.implementsLifecycle() ) { LOG.debug( "Calling onDelete()" ); if ( ( (Lifecycle) entity ).onDelete( session ) ) { diff --git a/hibernate-core/src/main/java/org/hibernate/event/internal/DefaultMergeEventListener.java b/hibernate-core/src/main/java/org/hibernate/event/internal/DefaultMergeEventListener.java index 5a74f7e6d6..dc5acdb37c 100644 --- a/hibernate-core/src/main/java/org/hibernate/event/internal/DefaultMergeEventListener.java +++ b/hibernate-core/src/main/java/org/hibernate/event/internal/DefaultMergeEventListener.java @@ -165,7 +165,7 @@ public class DefaultMergeEventListener extends AbstractSaveEventListener impleme } if ( entityState == null ) { - entityState = getEntityState( entity, event.getEntityName(), entry, source ); + entityState = EntityState.getEntityState( entity, event.getEntityName(), entry, source, false ); } switch ( entityState ) { @@ -182,7 +182,7 @@ public class DefaultMergeEventListener extends AbstractSaveEventListener impleme throw new ObjectDeletedException( "deleted instance passed to merge", null, - getLoggableName( event.getEntityName(), entity ) + EventUtil.getLoggableName( event.getEntityName(), entity ) ); } } @@ -537,11 +537,6 @@ public class DefaultMergeEventListener extends AbstractSaveEventListener impleme return CascadingActions.MERGE; } - @Override - protected Boolean getAssumedUnsaved() { - return Boolean.FALSE; - } - /** * Cascade behavior is redefined by this subclass, disable superclass behavior */ diff --git a/hibernate-core/src/main/java/org/hibernate/event/internal/DefaultPersistEventListener.java b/hibernate-core/src/main/java/org/hibernate/event/internal/DefaultPersistEventListener.java index f1a2c01d7d..a82b95aabf 100755 --- a/hibernate-core/src/main/java/org/hibernate/event/internal/DefaultPersistEventListener.java +++ b/hibernate-core/src/main/java/org/hibernate/event/internal/DefaultPersistEventListener.java @@ -6,7 +6,6 @@ */ package org.hibernate.event.internal; -import java.io.Serializable; import java.util.IdentityHashMap; import java.util.Map; @@ -24,7 +23,6 @@ import org.hibernate.event.spi.PersistEventListener; import org.hibernate.id.ForeignGenerator; import org.hibernate.internal.CoreLogging; import org.hibernate.internal.CoreMessageLogger; -import org.hibernate.jpa.event.spi.CallbackRegistry; import org.hibernate.jpa.event.spi.CallbackRegistryConsumer; import org.hibernate.persister.entity.EntityPersister; import org.hibernate.pretty.MessageHelper; @@ -47,11 +45,6 @@ public class DefaultPersistEventListener return CascadingActions.PERSIST; } - @Override - protected Boolean getAssumedUnsaved() { - return Boolean.TRUE; - } - /** * Handle the given create event. * @@ -99,7 +92,7 @@ public class DefaultPersistEventListener } final EntityEntry entityEntry = source.getPersistenceContextInternal().getEntry( entity ); - EntityState entityState = getEntityState( entity, entityName, entityEntry, source ); + EntityState entityState = EntityState.getEntityState( entity, entityName, entityEntry, source, true ); if ( entityState == EntityState.DETACHED ) { // JPA 2, in its version of a "foreign generated", allows the id attribute value // to be manually set by the user, even though this manual value is irrelevant. @@ -116,7 +109,7 @@ public class DefaultPersistEventListener LOG.debug( "Resetting entity id attribute to null for foreign generator" ); } persister.setIdentifier( entity, null, source ); - entityState = getEntityState( entity, entityName, entityEntry, source ); + entityState = EntityState.getEntityState( entity, entityName, entityEntry, source, true ); } } @@ -124,7 +117,7 @@ public class DefaultPersistEventListener case DETACHED: { throw new PersistentObjectException( "detached entity passed to persist: " + - getLoggableName( event.getEntityName(), entity ) + EventUtil.getLoggableName( event.getEntityName(), entity ) ); } case PERSISTENT: { @@ -146,7 +139,7 @@ public class DefaultPersistEventListener throw new ObjectDeletedException( "deleted entity passed to persist", null, - getLoggableName( event.getEntityName(), entity ) + EventUtil.getLoggableName( event.getEntityName(), entity ) ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/event/internal/DefaultPostLoadEventListener.java b/hibernate-core/src/main/java/org/hibernate/event/internal/DefaultPostLoadEventListener.java index f7a91367bd..528a9a6ddc 100644 --- a/hibernate-core/src/main/java/org/hibernate/event/internal/DefaultPostLoadEventListener.java +++ b/hibernate-core/src/main/java/org/hibernate/event/internal/DefaultPostLoadEventListener.java @@ -69,10 +69,14 @@ public class DefaultPostLoadEventListener implements PostLoadEventListener, Call session.getActionQueue().registerProcess( verifyVersion ); } + invokeLoadLifecycle(event, session); + + } + + protected void invokeLoadLifecycle(PostLoadEvent event, EventSource session) { if ( event.getPersister().implementsLifecycle() ) { //log.debug( "calling onLoad()" ); ( (Lifecycle) event.getEntity() ).onLoad( session, (Serializable) event.getId() ); } - } } diff --git a/hibernate-core/src/main/java/org/hibernate/event/internal/DefaultSaveOrUpdateEventListener.java b/hibernate-core/src/main/java/org/hibernate/event/internal/DefaultSaveOrUpdateEventListener.java index 05073eb20b..0d2a23ab1a 100644 --- a/hibernate-core/src/main/java/org/hibernate/event/internal/DefaultSaveOrUpdateEventListener.java +++ b/hibernate-core/src/main/java/org/hibernate/event/internal/DefaultSaveOrUpdateEventListener.java @@ -80,11 +80,12 @@ public class DefaultSaveOrUpdateEventListener extends AbstractSaveEventListener } protected Object performSaveOrUpdate(SaveOrUpdateEvent event) { - EntityState entityState = getEntityState( + EntityState entityState = EntityState.getEntityState( event.getEntity(), event.getEntityName(), event.getEntry(), - event.getSession() + event.getSession(), + null ); switch ( entityState ) { diff --git a/hibernate-core/src/main/java/org/hibernate/event/internal/DirtyCollectionSearchVisitor.java b/hibernate-core/src/main/java/org/hibernate/event/internal/DirtyCollectionSearchVisitor.java index 1fce73d5fe..79fbf5a9a3 100644 --- a/hibernate-core/src/main/java/org/hibernate/event/internal/DirtyCollectionSearchVisitor.java +++ b/hibernate-core/src/main/java/org/hibernate/event/internal/DirtyCollectionSearchVisitor.java @@ -25,12 +25,12 @@ public class DirtyCollectionSearchVisitor extends AbstractVisitor { private boolean dirty; private boolean[] propertyVersionability; - DirtyCollectionSearchVisitor(EventSource session, boolean[] propertyVersionability) { + public DirtyCollectionSearchVisitor(EventSource session, boolean[] propertyVersionability) { super( session ); this.propertyVersionability = propertyVersionability; } - boolean wasDirtyCollectionFound() { + public boolean wasDirtyCollectionFound() { return dirty; } diff --git a/hibernate-core/src/main/java/org/hibernate/event/internal/EntityState.java b/hibernate-core/src/main/java/org/hibernate/event/internal/EntityState.java new file mode 100644 index 0000000000..a0f537827f --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/event/internal/EntityState.java @@ -0,0 +1,71 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or . + */ +package org.hibernate.event.internal; + +import org.hibernate.engine.internal.ForeignKeys; +import org.hibernate.engine.spi.EntityEntry; +import org.hibernate.engine.spi.SessionImplementor; +import org.hibernate.engine.spi.Status; +import org.hibernate.internal.CoreLogging; +import org.hibernate.internal.CoreMessageLogger; + +public enum EntityState { + PERSISTENT, TRANSIENT, DETACHED, DELETED; + + static final CoreMessageLogger LOG = CoreLogging.messageLogger( EntityState.class ); + + /** + * Determine whether the entity is persistent, detached, or transient + * + * @param entity The entity to check + * @param entityName The name of the entity + * @param entry The entity's entry in the persistence context + * @param source The originating session. + * + * @return The state. + */ + public static EntityState getEntityState( + Object entity, + String entityName, + EntityEntry entry, //pass this as an argument only to avoid double looking + SessionImplementor source, + Boolean assumedUnsaved) { + + if ( entry != null ) { // the object is persistent + + //the entity is associated with the session, so check its status + if ( entry.getStatus() != Status.DELETED ) { + // do nothing for persistent instances + if ( LOG.isTraceEnabled() ) { + LOG.tracev( "Persistent instance of: {0}", EventUtil.getLoggableName( entityName, entity ) ); + } + return PERSISTENT; + } + // ie. e.status==DELETED + if ( LOG.isTraceEnabled() ) { + LOG.tracev( "Deleted instance of: {0}", EventUtil.getLoggableName( entityName, entity ) ); + } + return DELETED; + } + // the object is transient or detached + + // the entity is not associated with the session, so + // try interceptor and unsaved-value + + if ( ForeignKeys.isTransient( entityName, entity, assumedUnsaved, source ) ) { + if ( LOG.isTraceEnabled() ) { + LOG.tracev( "Transient instance of: {0}", EventUtil.getLoggableName( entityName, entity ) ); + } + return TRANSIENT; + } + if ( LOG.isTraceEnabled() ) { + LOG.tracev( "Detached instance of: {0}", EventUtil.getLoggableName( entityName, entity ) ); + } + return DETACHED; + } + +} diff --git a/hibernate-core/src/main/java/org/hibernate/event/internal/EventUtil.java b/hibernate-core/src/main/java/org/hibernate/event/internal/EventUtil.java new file mode 100644 index 0000000000..3ea7b26d2a --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/event/internal/EventUtil.java @@ -0,0 +1,13 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or . + */ +package org.hibernate.event.internal; + +public class EventUtil { + public static String getLoggableName(String entityName, Object entity) { + return entityName == null ? entity.getClass().getName() : entityName; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/event/internal/EvictVisitor.java b/hibernate-core/src/main/java/org/hibernate/event/internal/EvictVisitor.java index 9e1347d6d1..c506a5a216 100644 --- a/hibernate-core/src/main/java/org/hibernate/event/internal/EvictVisitor.java +++ b/hibernate-core/src/main/java/org/hibernate/event/internal/EvictVisitor.java @@ -30,7 +30,7 @@ public class EvictVisitor extends AbstractVisitor { private Object owner; - EvictVisitor(EventSource session, Object owner) { + public EvictVisitor(EventSource session, Object owner) { super(session); this.owner = owner; } diff --git a/hibernate-core/src/main/java/org/hibernate/event/internal/FlushVisitor.java b/hibernate-core/src/main/java/org/hibernate/event/internal/FlushVisitor.java index a3d8987182..947d3de574 100644 --- a/hibernate-core/src/main/java/org/hibernate/event/internal/FlushVisitor.java +++ b/hibernate-core/src/main/java/org/hibernate/event/internal/FlushVisitor.java @@ -23,7 +23,7 @@ import org.hibernate.type.CollectionType; public class FlushVisitor extends AbstractVisitor { private Object owner; - FlushVisitor(EventSource session, Object owner) { + public FlushVisitor(EventSource session, Object owner) { super(session); this.owner = owner; } diff --git a/hibernate-core/src/main/java/org/hibernate/event/internal/MergeContext.java b/hibernate-core/src/main/java/org/hibernate/event/internal/MergeContext.java index 3f334dcd52..dfbecc414e 100644 --- a/hibernate-core/src/main/java/org/hibernate/event/internal/MergeContext.java +++ b/hibernate-core/src/main/java/org/hibernate/event/internal/MergeContext.java @@ -77,7 +77,7 @@ import org.jboss.logging.Logger; * * @author Gail Badner */ -class MergeContext implements Map { +public class MergeContext implements Map { private static final Logger LOG = Logger.getLogger( MergeContext.class ); private final EventSource session; @@ -101,7 +101,7 @@ class MergeContext implements Map { // key is a merge entity; // value is a flag indicating if the merge entity is currently in the merge process. - MergeContext(EventSource session, EntityCopyObserver entityCopyObserver){ + public MergeContext(EventSource session, EntityCopyObserver entityCopyObserver){ this.session = session; this.entityCopyObserver = entityCopyObserver; } @@ -226,7 +226,7 @@ class MergeContext implements Map { * managed entity associated with mergeEntity * @throws IllegalStateException if internal cross-references are out of sync, */ - /* package-private */ Object put(Object mergeEntity, Object managedEntity, boolean isOperatedOn) { + public Object put(Object mergeEntity, Object managedEntity, boolean isOperatedOn) { if ( mergeEntity == null || managedEntity == null ) { throw new NullPointerException( "null merge and managed entities are not supported by " + getClass().getName() ); } @@ -347,7 +347,7 @@ class MergeContext implements Map { * @throws NullPointerException if mergeEntity is null * @throws IllegalStateException if this MergeContext does not contain a a cross-reference for mergeEntity */ - /* package-private */ void setOperatedOn(Object mergeEntity, boolean isOperatedOn) { + public void setOperatedOn(Object mergeEntity, boolean isOperatedOn) { if ( mergeEntity == null ) { throw new NullPointerException( "null entities are not supported by " + getClass().getName() ); } diff --git a/hibernate-core/src/main/java/org/hibernate/event/internal/OnReplicateVisitor.java b/hibernate-core/src/main/java/org/hibernate/event/internal/OnReplicateVisitor.java index ad19f57f78..82499cc0cd 100644 --- a/hibernate-core/src/main/java/org/hibernate/event/internal/OnReplicateVisitor.java +++ b/hibernate-core/src/main/java/org/hibernate/event/internal/OnReplicateVisitor.java @@ -28,7 +28,7 @@ public class OnReplicateVisitor extends ReattachVisitor { private boolean isUpdate; - OnReplicateVisitor(EventSource session, Object key, Object owner, boolean isUpdate) { + public OnReplicateVisitor(EventSource session, Object key, Object owner, boolean isUpdate) { super( session, key, owner ); this.isUpdate = isUpdate; } diff --git a/hibernate-core/src/main/java/org/hibernate/event/internal/OnUpdateVisitor.java b/hibernate-core/src/main/java/org/hibernate/event/internal/OnUpdateVisitor.java index 80f00a72c7..219aeebb88 100644 --- a/hibernate-core/src/main/java/org/hibernate/event/internal/OnUpdateVisitor.java +++ b/hibernate-core/src/main/java/org/hibernate/event/internal/OnUpdateVisitor.java @@ -24,7 +24,7 @@ import org.hibernate.type.CollectionType; */ public class OnUpdateVisitor extends ReattachVisitor { - OnUpdateVisitor(EventSource session, Object key, Object owner) { + public OnUpdateVisitor(EventSource session, Object key, Object owner) { super( session, key, owner ); } diff --git a/hibernate-core/src/main/java/org/hibernate/event/internal/ProxyVisitor.java b/hibernate-core/src/main/java/org/hibernate/event/internal/ProxyVisitor.java index 499412b7a1..aed9ecdf9c 100644 --- a/hibernate-core/src/main/java/org/hibernate/event/internal/ProxyVisitor.java +++ b/hibernate-core/src/main/java/org/hibernate/event/internal/ProxyVisitor.java @@ -19,7 +19,6 @@ import org.hibernate.type.EntityType; */ public abstract class ProxyVisitor extends AbstractVisitor { - public ProxyVisitor(EventSource session) { super(session); } diff --git a/hibernate-core/src/main/java/org/hibernate/event/internal/WrapVisitor.java b/hibernate-core/src/main/java/org/hibernate/event/internal/WrapVisitor.java index df3769e588..bc665b5737 100644 --- a/hibernate-core/src/main/java/org/hibernate/event/internal/WrapVisitor.java +++ b/hibernate-core/src/main/java/org/hibernate/event/internal/WrapVisitor.java @@ -40,11 +40,11 @@ public class WrapVisitor extends ProxyVisitor { this.id = id; } - boolean isSubstitutionRequired() { + public boolean isSubstitutionRequired() { return substitute; } - WrapVisitor(EventSource session) { + public WrapVisitor(EventSource session) { super( session ); } @@ -150,7 +150,7 @@ public class WrapVisitor extends ProxyVisitor { } @Override - void process(Object object, EntityPersister persister) throws HibernateException { + public void process(Object object, EntityPersister persister) throws HibernateException { final Object[] values = persister.getPropertyValues( object ); final Type[] types = persister.getPropertyTypes(); processEntityPropertyValues( values, types ); diff --git a/hibernate-core/src/main/java/org/hibernate/graph/internal/AttributeNodeImpl.java b/hibernate-core/src/main/java/org/hibernate/graph/internal/AttributeNodeImpl.java index 02aecd58ed..da82b86676 100644 --- a/hibernate-core/src/main/java/org/hibernate/graph/internal/AttributeNodeImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/graph/internal/AttributeNodeImpl.java @@ -160,7 +160,7 @@ public class AttributeNodeImpl final SubGraphImplementor previous = subGraphMap.put( subType, (SubGraphImplementor) subGraph ); if ( previous != null ) { - log.debugf( "Adding sub-graph [%s] over-wrote existing [%]", subGraph, previous ); + log.debugf( "Adding sub-graph [%s] over-wrote existing [%s]", subGraph, previous ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/internal/AbstractSharedSessionContract.java b/hibernate-core/src/main/java/org/hibernate/internal/AbstractSharedSessionContract.java index 2197be372e..2c6175cacd 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/AbstractSharedSessionContract.java +++ b/hibernate-core/src/main/java/org/hibernate/internal/AbstractSharedSessionContract.java @@ -51,6 +51,7 @@ import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.engine.transaction.internal.TransactionImpl; import org.hibernate.engine.transaction.spi.TransactionImplementor; import org.hibernate.id.uuid.StandardRandomStrategy; +import org.hibernate.jpa.QueryHints; import org.hibernate.jpa.internal.util.FlushModeTypeHelper; import org.hibernate.persister.entity.EntityPersister; import org.hibernate.procedure.ProcedureCall; diff --git a/hibernate-core/src/main/java/org/hibernate/internal/SessionFactoryImpl.java b/hibernate-core/src/main/java/org/hibernate/internal/SessionFactoryImpl.java index ff4eb2937e..feebf2ca86 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/SessionFactoryImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/internal/SessionFactoryImpl.java @@ -156,7 +156,7 @@ import org.jboss.logging.Logger; * @author Steve Ebersole * @author Chris Cranford */ -public final class SessionFactoryImpl implements SessionFactoryImplementor { +public class SessionFactoryImpl implements SessionFactoryImplementor { private static final CoreMessageLogger LOG = CoreLogging.messageLogger( SessionFactoryImpl.class ); private final String name; @@ -1081,7 +1081,7 @@ public final class SessionFactoryImpl implements SessionFactoryImplementor { return null; } - static class SessionBuilderImpl implements SessionBuilderImplementor, SessionCreationOptions { + public static class SessionBuilderImpl implements SessionBuilderImplementor, SessionCreationOptions { private static final Logger log = CoreLogging.logger( SessionBuilderImpl.class ); private final SessionFactoryImpl sessionFactory; @@ -1105,7 +1105,7 @@ public final class SessionFactoryImpl implements SessionFactoryImplementor { //todo : expose setting private SessionOwnerBehavior sessionOwnerBehavior = SessionOwnerBehavior.LEGACY_NATIVE; - SessionBuilderImpl(SessionFactoryImpl sessionFactory) { + public SessionBuilderImpl(SessionFactoryImpl sessionFactory) { this.sessionFactory = sessionFactory; // set up default builder values... diff --git a/hibernate-core/src/main/java/org/hibernate/internal/SessionImpl.java b/hibernate-core/src/main/java/org/hibernate/internal/SessionImpl.java index e760dc4889..eff61efc05 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/SessionImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/internal/SessionImpl.java @@ -164,7 +164,7 @@ import static org.hibernate.cfg.AvailableSettings.JPA_SHARED_CACHE_STORE_MODE; * @author Chris Cranford * @author Sanne Grinovero */ -public final class SessionImpl +public class SessionImpl extends AbstractSessionImpl implements SessionImplementor, EventSource { private static final EntityManagerMessageLogger log = HEMLogging.messageLogger( SessionImpl.class ); @@ -532,13 +532,13 @@ public final class SessionImpl } } - private void checkNoUnresolvedActionsBeforeOperation() { + protected void checkNoUnresolvedActionsBeforeOperation() { if ( persistenceContext.getCascadeLevel() == 0 && actionQueue.hasUnresolvedEntityInsertActions() ) { throw new IllegalStateException( "There are delayed insert actions before operation as cascade level 0." ); } } - private void checkNoUnresolvedActionsAfterOperation() { + protected void checkNoUnresolvedActionsAfterOperation() { if ( persistenceContext.getCascadeLevel() == 0 ) { actionQueue.checkNoUnresolvedActionsAfterOperation(); } @@ -2815,7 +2815,7 @@ public final class SessionImpl } } - private CacheMode determineAppropriateLocalCacheMode(Map localProperties) { + protected CacheMode determineAppropriateLocalCacheMode(Map localProperties) { CacheRetrieveMode retrieveMode = null; CacheStoreMode storeMode = null; if ( localProperties != null ) { diff --git a/hibernate-core/src/main/java/org/hibernate/mapping/Column.java b/hibernate-core/src/main/java/org/hibernate/mapping/Column.java index a6aef3f89f..c8c238944e 100644 --- a/hibernate-core/src/main/java/org/hibernate/mapping/Column.java +++ b/hibernate-core/src/main/java/org/hibernate/mapping/Column.java @@ -113,7 +113,7 @@ public class Column implements Selectable, Serializable, Cloneable { final int lastLetter = StringHelper.lastIndexOfLetter( name ); final String suffix = AliasConstantsHelper.get( uniqueInteger ); - String alias = name; + String alias = name.toLowerCase( Locale.ROOT ); if ( lastLetter == -1 ) { alias = "column"; } diff --git a/hibernate-core/src/main/java/org/hibernate/persister/collection/AbstractCollectionPersister.java b/hibernate-core/src/main/java/org/hibernate/persister/collection/AbstractCollectionPersister.java index 5f91c1b3b4..dedb604846 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/collection/AbstractCollectionPersister.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/collection/AbstractCollectionPersister.java @@ -95,6 +95,9 @@ import org.hibernate.persister.walking.spi.CompositionDefinition; import org.hibernate.persister.walking.spi.EntityDefinition; import org.hibernate.pretty.MessageHelper; import org.hibernate.sql.Alias; +import org.hibernate.sql.Insert; +import org.hibernate.sql.Update; +import org.hibernate.sql.Delete; import org.hibernate.sql.SelectFragment; import org.hibernate.sql.SimpleSelect; import org.hibernate.sql.Template; @@ -2429,4 +2432,16 @@ public abstract class AbstractCollectionPersister public CollectionSemantics getCollectionSemantics() { return collectionSemantics; } + + protected Insert createInsert() { + return new Insert( getFactory().getJdbcServices().getDialect() ); + } + + protected Update createUpdate() { + return new Update( getFactory().getJdbcServices().getDialect() ); + } + + protected Delete createDelete() { + return new Delete(); + } } diff --git a/hibernate-core/src/main/java/org/hibernate/persister/collection/BasicCollectionPersister.java b/hibernate-core/src/main/java/org/hibernate/persister/collection/BasicCollectionPersister.java index f1b8acde24..5445f369fe 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/collection/BasicCollectionPersister.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/collection/BasicCollectionPersister.java @@ -66,8 +66,7 @@ public class BasicCollectionPersister extends AbstractCollectionPersister { */ @Override protected String generateDeleteString() { - final Delete delete = new Delete() - .setTableName( qualifiedTableName ) + final Delete delete = createDelete().setTableName( qualifiedTableName ) .addPrimaryKeyColumns( keyColumnNames ); if ( hasWhere ) { @@ -86,8 +85,7 @@ public class BasicCollectionPersister extends AbstractCollectionPersister { */ @Override protected String generateInsertRowString() { - final Insert insert = new Insert( getDialect() ) - .setTableName( qualifiedTableName ) + final Insert insert = createInsert().setTableName( qualifiedTableName ) .addColumns( keyColumnNames ); if ( hasIdentifier ) { @@ -114,8 +112,7 @@ public class BasicCollectionPersister extends AbstractCollectionPersister { */ @Override protected String generateUpdateRowString() { - final Update update = new Update( getDialect() ) - .setTableName( qualifiedTableName ); + final Update update = createUpdate().setTableName( qualifiedTableName ); //if ( !elementIsFormula ) { update.addColumns( elementColumnNames, elementColumnIsSettable, elementColumnWriters ); @@ -149,7 +146,7 @@ public class BasicCollectionPersister extends AbstractCollectionPersister { */ @Override protected String generateDeleteRowString() { - final Delete delete = new Delete().setTableName( qualifiedTableName ); + final Delete delete = createDelete().setTableName( qualifiedTableName ); if ( hasIdentifier ) { delete.addPrimaryKeyColumns( new String[] {identifierColumnName} ); diff --git a/hibernate-core/src/main/java/org/hibernate/persister/collection/OneToManyPersister.java b/hibernate-core/src/main/java/org/hibernate/persister/collection/OneToManyPersister.java index 7622b80a00..8b6d62078c 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/collection/OneToManyPersister.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/collection/OneToManyPersister.java @@ -72,10 +72,8 @@ public class OneToManyPersister extends AbstractCollectionPersister { */ @Override protected String generateDeleteString() { - final Update update = new Update( getDialect() ) - .setTableName( qualifiedTableName ) - .addColumns( keyColumnNames, "null" ) - .addPrimaryKeyColumns( keyColumnNames ); + final Update update = createUpdate().setTableName( qualifiedTableName ) + .addColumns( keyColumnNames, "null" ); if ( hasIndex && !indexContainsFormula ) { for ( int i = 0 ; i < indexColumnNames.length ; i++ ) { @@ -85,6 +83,8 @@ public class OneToManyPersister extends AbstractCollectionPersister { } } + update.addPrimaryKeyColumns( keyColumnNames ); + if ( hasWhere ) { update.setWhere( sqlWhereString ); } @@ -101,8 +101,7 @@ public class OneToManyPersister extends AbstractCollectionPersister { */ @Override protected String generateInsertRowString() { - final Update update = new Update( getDialect() ) - .setTableName( qualifiedTableName ) + final Update update = createUpdate().setTableName( qualifiedTableName ) .addColumns( keyColumnNames ); if ( hasIndex && !indexContainsFormula ) { @@ -128,11 +127,8 @@ public class OneToManyPersister extends AbstractCollectionPersister { */ @Override protected String generateUpdateRowString() { - final Update update = new Update( getDialect() ).setTableName( qualifiedTableName ); - update.addPrimaryKeyColumns( elementColumnNames, elementColumnIsSettable, elementColumnWriters ); - if ( hasIdentifier ) { - update.addPrimaryKeyColumns( new String[] {identifierColumnName} ); - } + final Update update = createUpdate().setTableName( qualifiedTableName ); + if ( hasIndex && !indexContainsFormula ) { for ( int i = 0 ; i < indexColumnNames.length ; i++ ) { if ( indexColumnIsSettable[i] ) { @@ -141,6 +137,12 @@ public class OneToManyPersister extends AbstractCollectionPersister { } } + update.addPrimaryKeyColumns( elementColumnNames, elementColumnIsSettable, elementColumnWriters ); + + if ( hasIdentifier ) { + update.addPrimaryKeyColumns( new String[] {identifierColumnName} ); + } + return update.toStatementString(); } @@ -150,8 +152,7 @@ public class OneToManyPersister extends AbstractCollectionPersister { */ @Override protected String generateDeleteRowString() { - final Update update = new Update( getDialect() ) - .setTableName( qualifiedTableName ) + final Update update = createUpdate().setTableName( qualifiedTableName ) .addColumns( keyColumnNames, "null" ); if ( hasIndex && !indexContainsFormula ) { diff --git a/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java b/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java index 13ae4ec824..b8441d153d 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java @@ -410,15 +410,15 @@ public abstract class AbstractEntityPersister public abstract int getSubclassTableSpan(); - protected abstract int getTableSpan(); + public abstract int getTableSpan(); - protected abstract boolean isTableCascadeDeleteEnabled(int j); + public abstract boolean isTableCascadeDeleteEnabled(int j); - protected abstract String getTableName(int j); + public abstract String getTableName(int j); - protected abstract String[] getKeyColumns(int j); + public abstract String[] getKeyColumns(int j); - protected abstract boolean isPropertyOfTable(int property, int j); + public abstract boolean isPropertyOfTable(int property, int j); protected abstract int[] getPropertyTableNumbersInSelect(); @@ -449,19 +449,19 @@ public abstract class AbstractEntityPersister } } - protected String getDiscriminatorAlias() { + public String getDiscriminatorAlias() { return DISCRIMINATOR_ALIAS; } - protected String getDiscriminatorFormulaTemplate() { + public String getDiscriminatorFormulaTemplate() { return null; } - protected boolean isInverseTable(int j) { + public boolean isInverseTable(int j) { return false; } - protected boolean isNullableTable(int j) { + public boolean isNullableTable(int j) { return false; } @@ -485,7 +485,7 @@ public abstract class AbstractEntityPersister return rootTableKeyColumnNames; } - protected String[] getSQLUpdateByRowIdStrings() { + public String[] getSQLUpdateByRowIdStrings() { if ( sqlUpdateByRowIdString == null ) { throw new AssertionFailure( "no update by row id" ); } @@ -495,7 +495,7 @@ public abstract class AbstractEntityPersister return result; } - protected String[] getSQLLazyUpdateByRowIdStrings() { + public String[] getSQLLazyUpdateByRowIdStrings() { if ( sqlLazyUpdateByRowIdString == null ) { throw new AssertionFailure( "no update by row id" ); } @@ -505,52 +505,64 @@ public abstract class AbstractEntityPersister return result; } - protected String getSQLSnapshotSelectString() { + public String getSQLSnapshotSelectString() { return sqlSnapshotSelectString; } - protected String getSQLLazySelectString(String fetchGroup) { + public String getSQLLazySelectString(String fetchGroup) { return sqlLazySelectStringsByFetchGroup.get( fetchGroup ); } - protected String[] getSQLDeleteStrings() { + public String[] getSQLDeleteStrings() { return sqlDeleteStrings; } - protected String[] getSQLInsertStrings() { + public String[] getSQLInsertStrings() { return sqlInsertStrings; } - protected String[] getSQLUpdateStrings() { + public String[] getSQLUpdateStrings() { return sqlUpdateStrings; } - protected String[] getSQLLazyUpdateStrings() { + public String[] getSQLLazyUpdateStrings() { return sqlLazyUpdateStrings; } + public ExecuteUpdateResultCheckStyle[] getInsertResultCheckStyles() { + return insertResultCheckStyles; + } + + public ExecuteUpdateResultCheckStyle[] getUpdateResultCheckStyles() { + return updateResultCheckStyles; + } + + public ExecuteUpdateResultCheckStyle[] getDeleteResultCheckStyles() { + return deleteResultCheckStyles; + } + /** * The query that inserts a row, letting the database generate an id * * @return The IDENTITY-based insertion query. */ - protected String getSQLIdentityInsertString() { + public String getSQLIdentityInsertString() { return sqlIdentityInsertString; } - protected String getVersionSelectString() { + public String getVersionSelectString() { return sqlVersionSelectString; } - protected boolean isInsertCallable(int j) { + public boolean isInsertCallable(int j) { return insertCallable[j]; } - protected boolean isUpdateCallable(int j) { + public boolean isUpdateCallable(int j) { return updateCallable[j]; } - protected boolean isDeleteCallable(int j) { + public boolean isDeleteCallable(int j) { return deleteCallable[j]; } @@ -577,7 +589,7 @@ public abstract class AbstractEntityPersister * * @return Array of booleans indicating which table require updating. */ - protected boolean[] getTableUpdateNeeded(final int[] dirtyProperties, boolean hasDirtyCollection) { + public boolean[] getTableUpdateNeeded(final int[] dirtyProperties, boolean hasDirtyCollection) { if ( dirtyProperties == null ) { return getTableHasColumns(); // for objects that came in via update() @@ -611,15 +623,15 @@ public abstract class AbstractEntityPersister return rowIdName != null; } - protected boolean[][] getPropertyColumnUpdateable() { + public boolean[][] getPropertyColumnUpdateable() { return propertyColumnUpdateable; } - protected boolean[][] getPropertyColumnInsertable() { + public boolean[][] getPropertyColumnInsertable() { return propertyColumnInsertable; } - protected boolean[] getPropertySelectable() { + public boolean[] getPropertySelectable() { return propertySelectable; } @@ -1719,11 +1731,11 @@ public abstract class AbstractEntityPersister return rootTableKeyColumnReaderTemplates; } - protected int getIdentifierColumnSpan() { + public int getIdentifierColumnSpan() { return identifierColumnSpan; } - protected String[] getIdentifierAliases() { + public String[] getIdentifierAliases() { return identifierAliases; } @@ -1731,7 +1743,7 @@ public abstract class AbstractEntityPersister return versionColumnName; } - protected String getVersionedTableName() { + public String getVersionedTableName() { return getTableName( 0 ); } @@ -1864,7 +1876,7 @@ public abstract class AbstractEntityPersister /** * Generate the SQL that selects the version number by id */ - protected String generateSelectVersionString() { + public String generateSelectVersionString() { SimpleSelect select = new SimpleSelect( getFactory().getDialect() ) .setTableName( getVersionedTableName() ); if ( isVersioned() ) { @@ -1883,11 +1895,11 @@ public abstract class AbstractEntityPersister return propertyUniqueness; } - protected String generateInsertGeneratedValuesSelectString() { + public String generateInsertGeneratedValuesSelectString() { return generateGeneratedValuesSelectString( GenerationTiming.INSERT ); } - protected String generateUpdateGeneratedValuesSelectString() { + public String generateUpdateGeneratedValuesSelectString() { return generateGeneratedValuesSelectString( GenerationTiming.ALWAYS ); } @@ -1969,7 +1981,7 @@ public abstract class AbstractEntityPersister return frag.toFragmentString(); } - protected String generateSnapshotSelectString() { + public String generateSnapshotSelectString() { //TODO: should we use SELECT .. FOR UPDATE? @@ -2065,8 +2077,7 @@ public abstract class AbstractEntityPersister } private String generateVersionIncrementUpdateString() { - Update update = new Update( getFactory().getDialect() ); - update.setTableName( getTableName( 0 ) ); + Update update = createUpdate().setTableName( getTableName( 0 ) ); if ( getFactory().getSessionFactoryOptions().isCommentsEnabled() ) { update.setComment( "forced version increment" ); } @@ -2345,11 +2356,11 @@ public abstract class AbstractEntityPersister return propertyColumnWriters[i]; } - protected int getPropertyColumnSpan(int i) { + public int getPropertyColumnSpan(int i) { return propertyColumnSpans[i]; } - protected boolean hasFormulaProperties() { + public boolean hasFormulaProperties() { return hasFormulaProperties; } @@ -2709,28 +2720,20 @@ public abstract class AbstractEntityPersister return true; } - protected String generateUpdateString(boolean[] includeProperty, int j, boolean useRowId) { + public String generateUpdateString(boolean[] includeProperty, int j, boolean useRowId) { return generateUpdateString( includeProperty, j, null, useRowId ); } /** * Generate the SQL that updates a row by id (and version) */ - protected String generateUpdateString( + public String generateUpdateString( final boolean[] includeProperty, final int j, final Object[] oldFields, final boolean useRowId) { - Update update = new Update( getFactory().getDialect() ).setTableName( getTableName( j ) ); - - // select the correct row by either pk or rowid - if ( useRowId ) { - update.addPrimaryKeyColumns( new String[] {rowIdName} ); //TODO: eventually, rowIdName[j] - } - else { - update.addPrimaryKeyColumns( getKeyColumns( j ) ); - } + Update update = createUpdate().setTableName( getTableName( j ) ); boolean hasColumns = false; for ( int i = 0; i < entityMetamodel.getPropertySpan(); i++ ) { @@ -2759,6 +2762,14 @@ public abstract class AbstractEntityPersister } } + // select the correct row by either pk or rowid + if ( useRowId ) { + update.addPrimaryKeyColumns( new String[] {rowIdName} ); //TODO: eventually, rowIdName[j] + } + else { + update.addPrimaryKeyColumns( getKeyColumns( j ) ); + } + if ( j == 0 && isVersioned() && entityMetamodel.getOptimisticLockStyle() == OptimisticLockStyle.VERSION ) { // this is the root (versioned) table, and we are using version-based // optimistic locking; if we are not updating the version, also don't @@ -2810,29 +2821,28 @@ public abstract class AbstractEntityPersister return hasColumns ? update.toStatementString() : null; } - protected final boolean checkVersion(final boolean[] includeProperty) { + public final boolean checkVersion(final boolean[] includeProperty) { return includeProperty[getVersionProperty()] || entityMetamodel.isVersionGenerated(); } - protected String generateInsertString(boolean[] includeProperty, int j) { + public String generateInsertString(boolean[] includeProperty, int j) { return generateInsertString( false, includeProperty, j ); } - protected String generateInsertString(boolean identityInsert, boolean[] includeProperty) { + public String generateInsertString(boolean identityInsert, boolean[] includeProperty) { return generateInsertString( identityInsert, includeProperty, 0 ); } /** * Generate the SQL that inserts a row */ - protected String generateInsertString(boolean identityInsert, boolean[] includeProperty, int j) { + public String generateInsertString(boolean identityInsert, boolean[] includeProperty, int j) { // todo : remove the identityInsert param and variations; // identity-insert strings are now generated from generateIdentityInsertString() - Insert insert = new Insert( getFactory().getDialect() ) - .setTableName( getTableName( j ) ); + Insert insert = createInsert().setTableName( getTableName( j ) ); // add normal properties for ( int i = 0; i < entityMetamodel.getPropertySpan(); i++ ) { @@ -2925,7 +2935,7 @@ public abstract class AbstractEntityPersister * * @return The insert SQL statement string */ - protected String generateIdentityInsertString(boolean[] includeProperty) { + public String generateIdentityInsertString(boolean[] includeProperty) { Insert insert = identityDelegate.prepareIdentifierGeneratingInsert(); insert.setTableName( getTableName( 0 ) ); @@ -2992,9 +3002,8 @@ public abstract class AbstractEntityPersister /** * Generate the SQL that deletes a row by id (and version) */ - protected String generateDeleteString(int j) { - final Delete delete = new Delete() - .setTableName( getTableName( j ) ) + public String generateDeleteString(int j) { + final Delete delete = createDelete().setTableName( getTableName( j ) ) .addPrimaryKeyColumns( getKeyColumns( j ) ); if ( j == 0 ) { delete.setVersionColumnName( getVersionColumnName() ); @@ -3005,7 +3014,7 @@ public abstract class AbstractEntityPersister return delete.toStatementString(); } - protected int dehydrate( + public int dehydrate( Serializable id, Object[] fields, boolean[] includeProperty, @@ -3020,7 +3029,7 @@ public abstract class AbstractEntityPersister /** * Marshall the fields of a persistent instance to a prepared statement */ - protected int dehydrate( + public int dehydrate( final Object id, final Object[] fields, final Object rowId, @@ -3201,11 +3210,11 @@ public abstract class AbstractEntityPersister } } - protected boolean useInsertSelectIdentity() { + public boolean useInsertSelectIdentity() { return !useGetGeneratedKeys() && getFactory().getDialect().getIdentityColumnSupport().supportsInsertSelectIdentity(); } - protected boolean useGetGeneratedKeys() { + public boolean useGetGeneratedKeys() { return getFactory().getSessionFactoryOptions().isGetGeneratedKeysEnabled(); } @@ -3219,7 +3228,7 @@ public abstract class AbstractEntityPersister * This form is used for PostInsertIdentifierGenerator-style ids (IDENTITY, * select, etc). */ - protected Serializable insert( + public Serializable insert( final Object[] fields, final boolean[] notNull, String sql, @@ -3272,7 +3281,7 @@ public abstract class AbstractEntityPersister * This for is used for all non-root tables as well as the root table * in cases where the identifier value is known before the insert occurs. */ - protected void insert( + public void insert( final Object id, final Object[] fields, final boolean[] notNull, @@ -3375,7 +3384,7 @@ public abstract class AbstractEntityPersister /** * Perform an SQL UPDATE or SQL INSERT */ - protected void updateOrInsert( + public void updateOrInsert( final Object id, final Object[] fields, final Object[] oldFields, @@ -3429,7 +3438,7 @@ public abstract class AbstractEntityPersister private BasicBatchKey updateBatchKey; - protected boolean update( + public boolean update( final Object id, final Object[] fields, final Object[] oldFields, @@ -3577,7 +3586,7 @@ public abstract class AbstractEntityPersister /** * Perform an SQL DELETE */ - protected void delete( + public void delete( final Object id, final Object version, final int j, @@ -3934,8 +3943,7 @@ public abstract class AbstractEntityPersister int span = getTableSpan(); String[] deleteStrings = new String[span]; for ( int j = span - 1; j >= 0; j-- ) { - Delete delete = new Delete() - .setTableName( getTableName( j ) ) + Delete delete = createDelete().setTableName( getTableName( j ) ) .addPrimaryKeyColumns( getKeyColumns( j ) ); if ( getFactory().getSessionFactoryOptions().isCommentsEnabled() ) { delete.setComment( "delete " + getEntityName() + " [" + j + "]" ); @@ -4539,7 +4547,7 @@ public abstract class AbstractEntityPersister && filterHelper.isAffectedBy( loadQueryInfluencers.getEnabledFilters() ); } - protected final boolean isAllNull(Object[] array, int tableNumber) { + public final boolean isAllNull(Object[] array, int tableNumber) { for ( int i = 0; i < array.length; i++ ) { if ( isPropertyOfTable( i, tableNumber ) && array[i] != null ) { return false; @@ -4556,7 +4564,7 @@ public abstract class AbstractEntityPersister * Transform the array of property indexes to an array of booleans, * true when the property is dirty */ - protected final boolean[] getPropertiesToUpdate(final int[] dirtyProperties, final boolean hasDirtyCollection) { + public final boolean[] getPropertiesToUpdate(final int[] dirtyProperties, final boolean hasDirtyCollection) { final boolean[] propsToUpdate = new boolean[entityMetamodel.getPropertySpan()]; final boolean[] updateability = getPropertyUpdateability(); //no need to check laziness, dirty checking handles that for ( int j = 0; j < dirtyProperties.length; j++ ) { @@ -4580,7 +4588,7 @@ public abstract class AbstractEntityPersister * Transform the array of property indexes to an array of booleans, * true when the property is insertable and non-null */ - protected boolean[] getPropertiesToInsert(Object[] fields) { + public boolean[] getPropertiesToInsert(Object[] fields) { boolean[] notNull = new boolean[fields.length]; boolean[] insertable = getPropertyInsertability(); for ( int i = 0; i < fields.length; i++ ) { @@ -4654,7 +4662,7 @@ public abstract class AbstractEntityPersister * Which properties appear in the SQL update? * (Initialized, updateable ones!) */ - protected boolean[] getPropertyUpdateability(Object entity) { + public boolean[] getPropertyUpdateability(Object entity) { return hasUninitializedLazyProperties( entity ) ? getNonLazyPropertyUpdateability() : getPropertyUpdateability(); @@ -4891,7 +4899,7 @@ public abstract class AbstractEntityPersister return entityMetamodel.isMutable(); } - protected final boolean isModifiableEntity(EntityEntry entry) { + public final boolean isModifiableEntity(EntityEntry entry) { return ( entry == null ? isMutable() : entry.isModifiableEntity() ); } @@ -4936,7 +4944,7 @@ public abstract class AbstractEntityPersister return entityMetamodel.isDynamicInsert(); } - protected boolean hasEmbeddedCompositeIdentifier() { + public boolean hasEmbeddedCompositeIdentifier() { return entityMetamodel.getIdentifierProperty().isEmbedded(); } @@ -5298,7 +5306,7 @@ public abstract class AbstractEntityPersister return false; } - protected int getPropertySpan() { + public int getPropertySpan() { return entityMetamodel.getPropertySpan(); } @@ -6553,4 +6561,16 @@ public abstract class AbstractEntityPersister // } // }; } + + protected Insert createInsert() { + return new Insert( getFactory().getJdbcServices().getDialect() ); + } + + protected Update createUpdate() { + return new Update( getFactory().getJdbcServices().getDialect() ); + } + + protected Delete createDelete() { + return new Delete(); + } } diff --git a/hibernate-core/src/main/java/org/hibernate/persister/entity/JoinedSubclassEntityPersister.java b/hibernate-core/src/main/java/org/hibernate/persister/entity/JoinedSubclassEntityPersister.java index 450924a525..94f9baa20c 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/entity/JoinedSubclassEntityPersister.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/entity/JoinedSubclassEntityPersister.java @@ -788,12 +788,12 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister { } @Override - protected boolean isNullableTable(int j) { + public boolean isNullableTable(int j) { return isNullableTable[j]; } @Override - protected boolean isInverseTable(int j) { + public boolean isInverseTable(int j) { return isInverseTable[j]; } @@ -851,7 +851,7 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister { return getDiscriminatorColumnName(); } - protected String getDiscriminatorAlias() { + public String getDiscriminatorAlias() { return discriminatorAlias; } @@ -871,19 +871,19 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister { } - protected String getTableName(int j) { + public String getTableName(int j) { return naturalOrderTableNames[j]; } - protected String[] getKeyColumns(int j) { + public String[] getKeyColumns(int j) { return naturalOrderTableKeyColumns[j]; } - protected boolean isTableCascadeDeleteEnabled(int j) { + public boolean isTableCascadeDeleteEnabled(int j) { return naturalOrderCascadeDeleteEnabled[j]; } - protected boolean isPropertyOfTable(int property, int j) { + public boolean isPropertyOfTable(int property, int j) { return naturalOrderPropertyTableNumbers[property] == j; } @@ -980,14 +980,14 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister { } @Override - public String filterFragment(String alias) { + protected String filterFragment(String alias) { return hasWhere() ? " and " + getSQLWhereString( generateFilterConditionAlias( alias ) ) : ""; } @Override - public String filterFragment(String alias, Set treatAsDeclarations) { + protected String filterFragment(String alias, Set treatAsDeclarations) { return filterFragment( alias ); } diff --git a/hibernate-core/src/main/java/org/hibernate/persister/entity/SingleTableEntityPersister.java b/hibernate-core/src/main/java/org/hibernate/persister/entity/SingleTableEntityPersister.java index d75311bd9c..de1caf71be 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/entity/SingleTableEntityPersister.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/entity/SingleTableEntityPersister.java @@ -465,7 +465,7 @@ public class SingleTableEntityPersister extends AbstractEntityPersister { } } - protected boolean isInverseTable(int j) { + public boolean isInverseTable(int j) { return isInverseTable[j]; } @@ -485,11 +485,11 @@ public class SingleTableEntityPersister extends AbstractEntityPersister { return discriminatorColumnReaderTemplate; } - protected String getDiscriminatorAlias() { + public String getDiscriminatorAlias() { return discriminatorAlias; } - protected String getDiscriminatorFormulaTemplate() { + public String getDiscriminatorFormulaTemplate() { return discriminatorFormulaTemplate; } @@ -540,19 +540,19 @@ public class SingleTableEntityPersister extends AbstractEntityPersister { return discriminatorFormula; } - protected String getTableName(int j) { + public String getTableName(int j) { return qualifiedTableNames[j]; } - protected String[] getKeyColumns(int j) { + public String[] getKeyColumns(int j) { return keyColumnNames[j]; } - protected boolean isTableCascadeDeleteEnabled(int j) { + public boolean isTableCascadeDeleteEnabled(int j) { return cascadeDeleteEnabled[j]; } - protected boolean isPropertyOfTable(int property, int j) { + public boolean isPropertyOfTable(int property, int j) { return propertyTableNumbers[property] == j; } @@ -567,7 +567,7 @@ public class SingleTableEntityPersister extends AbstractEntityPersister { } @Override - public String filterFragment(String alias) throws MappingException { + protected String filterFragment(String alias) throws MappingException { String result = discriminatorFilterFragment( alias ); if ( hasWhere() ) { result += " and " + getSQLWhereString( alias ); @@ -593,7 +593,7 @@ public class SingleTableEntityPersister extends AbstractEntityPersister { } @Override - public String filterFragment(String alias, Set treatAsDeclarations) { + protected String filterFragment(String alias, Set treatAsDeclarations) { String result = discriminatorFilterFragment( alias, treatAsDeclarations ); if ( hasWhere() ) { result += " and " + getSQLWhereString( alias ); @@ -825,7 +825,7 @@ public class SingleTableEntityPersister extends AbstractEntityPersister { return subclassTableIsLazyClosure[j]; } - protected boolean isNullableTable(int j) { + public boolean isNullableTable(int j) { return isNullableTable[j]; } diff --git a/hibernate-core/src/main/java/org/hibernate/persister/entity/UnionSubclassEntityPersister.java b/hibernate-core/src/main/java/org/hibernate/persister/entity/UnionSubclassEntityPersister.java index 83663311c9..650190ea04 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/entity/UnionSubclassEntityPersister.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/entity/UnionSubclassEntityPersister.java @@ -308,22 +308,22 @@ public class UnionSubclassEntityPersister extends AbstractEntityPersister { } @Override - protected String getTableName(int j) { + public String getTableName(int j) { return tableName; } @Override - protected String[] getKeyColumns(int j) { + public String[] getKeyColumns(int j) { return getIdentifierColumnNames(); } @Override - protected boolean isTableCascadeDeleteEnabled(int j) { + public boolean isTableCascadeDeleteEnabled(int j) { return false; } @Override - protected boolean isPropertyOfTable(int property, int j) { + public boolean isPropertyOfTable(int property, int j) { return true; } @@ -335,7 +335,7 @@ public class UnionSubclassEntityPersister extends AbstractEntityPersister { } @Override - public String filterFragment(String name) { + protected String filterFragment(String name) { return hasWhere() ? " and " + getSQLWhereString( name ) : ""; diff --git a/hibernate-core/src/main/java/org/hibernate/sql/Delete.java b/hibernate-core/src/main/java/org/hibernate/sql/Delete.java index a6badc0305..cd5affb8f3 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/Delete.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/Delete.java @@ -16,13 +16,13 @@ import java.util.Map; */ public class Delete { - private String tableName; - private String versionColumnName; - private String where; + protected String tableName; + protected String versionColumnName; + protected String where; + protected String comment; + + protected Map primaryKeyColumns = new LinkedHashMap<>(); - private Map primaryKeyColumns = new LinkedHashMap(); - - private String comment; public Delete setComment(String comment) { this.comment = comment; return this; @@ -43,9 +43,9 @@ public class Delete { buf.append( " where " ); } boolean conditionsAppended = false; - Iterator iter = primaryKeyColumns.entrySet().iterator(); + Iterator> iter = primaryKeyColumns.entrySet().iterator(); while ( iter.hasNext() ) { - Map.Entry e = (Map.Entry) iter.next(); + Map.Entry e = iter.next(); buf.append( e.getKey() ).append( '=' ).append( e.getValue() ); if ( iter.hasNext() ) { buf.append( " and " ); diff --git a/hibernate-core/src/main/java/org/hibernate/sql/InFragment.java b/hibernate-core/src/main/java/org/hibernate/sql/InFragment.java index 3237c53204..3e15777220 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/InFragment.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/InFragment.java @@ -25,8 +25,8 @@ public class InFragment { public static final String NULL = "null"; public static final String NOT_NULL = "not null"; - private String columnName; - private List values = new ArrayList(); + protected String columnName; + protected List values = new ArrayList(); /** * @param value an SQL literal, NULL, or NOT_NULL diff --git a/hibernate-core/src/main/java/org/hibernate/sql/Insert.java b/hibernate-core/src/main/java/org/hibernate/sql/Insert.java index 25b2d7d276..93083a90e1 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/Insert.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/Insert.java @@ -19,10 +19,13 @@ import org.hibernate.type.LiteralType; * @author Gavin King */ public class Insert { + + protected String tableName; + protected String comment; + + protected Map columns = new LinkedHashMap<>(); + private Dialect dialect; - private String tableName; - private String comment; - private Map columns = new LinkedHashMap(); public Insert(Dialect dialect) { this.dialect = dialect; @@ -111,7 +114,7 @@ public class Insert { } else { buf.append(" ("); - Iterator iter = columns.keySet().iterator(); + Iterator iter = columns.keySet().iterator(); while ( iter.hasNext() ) { buf.append( iter.next() ); if ( iter.hasNext() ) { diff --git a/hibernate-core/src/main/java/org/hibernate/sql/InsertSelect.java b/hibernate-core/src/main/java/org/hibernate/sql/InsertSelect.java index 6bdf5f91d3..ec4bab87df 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/InsertSelect.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/InsertSelect.java @@ -21,10 +21,13 @@ import org.hibernate.dialect.Dialect; */ @Deprecated public class InsertSelect { - private String tableName; - private String comment; - private List columnNames = new ArrayList(); - private Select select; + + protected String tableName; + protected String comment; + + protected List columnNames = new ArrayList<>(); + + protected Select select; public InsertSelect(Dialect dialect) { //This is no longer used. Deprecate & remove? @@ -73,7 +76,7 @@ public class InsertSelect { buf.append( "insert into " ).append( tableName ); if ( !columnNames.isEmpty() ) { buf.append( " (" ); - Iterator itr = columnNames.iterator(); + Iterator itr = columnNames.iterator(); while ( itr.hasNext() ) { buf.append( itr.next() ); if ( itr.hasNext() ) { diff --git a/hibernate-core/src/main/java/org/hibernate/sql/Select.java b/hibernate-core/src/main/java/org/hibernate/sql/Select.java index e8b0aa4f3f..30a516dfb8 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/Select.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/Select.java @@ -17,15 +17,17 @@ import org.hibernate.internal.util.StringHelper; */ public class Select { - private String selectClause; - private String fromClause; - private String outerJoinsAfterFrom; - private String whereClause; - private String outerJoinsAfterWhere; - private String orderByClause; - private String groupByClause; - private String comment; - private LockOptions lockOptions = new LockOptions(); + protected String selectClause; + protected String fromClause; + protected String outerJoinsAfterFrom; + protected String whereClause; + protected String outerJoinsAfterWhere; + protected String orderByClause; + protected String groupByClause; + protected String comment; + + protected LockOptions lockOptions = new LockOptions(); + public final Dialect dialect; private int guesstimatedBufferSize = 20; diff --git a/hibernate-core/src/main/java/org/hibernate/sql/SimpleSelect.java b/hibernate-core/src/main/java/org/hibernate/sql/SimpleSelect.java index f27f407b2c..46f96b71cd 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/SimpleSelect.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/SimpleSelect.java @@ -31,15 +31,18 @@ public class SimpleSelect { //private static final Alias DEFAULT_ALIAS = new Alias(10, null); - private String tableName; - private String orderBy; - private Dialect dialect; - private LockOptions lockOptions = new LockOptions( LockMode.READ ); - private String comment; + protected String tableName; + protected String orderBy; + protected String comment; + + protected List columns = new ArrayList(); + protected Map aliases = new HashMap(); + protected List whereTokens = new ArrayList(); + + protected LockOptions lockOptions = new LockOptions( LockMode.READ ); + + private Dialect dialect; - private List columns = new ArrayList(); - private Map aliases = new HashMap(); - private List whereTokens = new ArrayList(); public SimpleSelect addColumns(String[] columnNames, String[] columnAliases) { for ( int i = 0; i < columnNames.length; i++ ) { diff --git a/hibernate-core/src/main/java/org/hibernate/sql/Update.java b/hibernate-core/src/main/java/org/hibernate/sql/Update.java index 93611d73a4..7b9a3fdae8 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/Update.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/Update.java @@ -19,15 +19,15 @@ import org.hibernate.type.LiteralType; */ public class Update { - private String tableName; - private String versionColumnName; - private String where; - private String assignments; - private String comment; + protected String tableName; + protected String versionColumnName; + protected String where; + protected String assignments; + protected String comment; - private Map primaryKeyColumns = new LinkedHashMap(); - private Map columns = new LinkedHashMap(); - private Map whereColumns = new LinkedHashMap(); + protected Map primaryKeyColumns = new LinkedHashMap<>(); + protected Map columns = new LinkedHashMap<>(); + protected Map whereColumns = new LinkedHashMap<>(); private Dialect dialect; @@ -170,9 +170,9 @@ public class Update { } buf.append( "update " ).append( tableName ).append( " set " ); boolean assignmentsAppended = false; - Iterator iter = columns.entrySet().iterator(); + Iterator> iter = columns.entrySet().iterator(); while ( iter.hasNext() ) { - Map.Entry e = (Map.Entry) iter.next(); + Map.Entry e = iter.next(); buf.append( e.getKey() ).append( '=' ).append( e.getValue() ); if ( iter.hasNext() ) { buf.append( ", " ); @@ -192,7 +192,7 @@ public class Update { } iter = primaryKeyColumns.entrySet().iterator(); while ( iter.hasNext() ) { - Map.Entry e = (Map.Entry) iter.next(); + Map.Entry e = iter.next(); buf.append( e.getKey() ).append( '=' ).append( e.getValue() ); if ( iter.hasNext() ) { buf.append( " and " ); @@ -208,7 +208,7 @@ public class Update { } iter = whereColumns.entrySet().iterator(); while ( iter.hasNext() ) { - final Map.Entry e = (Map.Entry) iter.next(); + final Map.Entry e = iter.next(); if ( conditionsAppended ) { buf.append( " and " ); } diff --git a/hibernate-core/src/test/java/org/hibernate/test/distinct/SelectDistinctHqlTest.java b/hibernate-core/src/test/java/org/hibernate/test/distinct/SelectDistinctHqlTest.java index df13035c24..77ff5c5d17 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/distinct/SelectDistinctHqlTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/distinct/SelectDistinctHqlTest.java @@ -14,6 +14,9 @@ import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.ManyToOne; import javax.persistence.OneToMany; +import javax.persistence.NamedQueries; +import javax.persistence.NamedQuery; +import javax.persistence.QueryHint; import org.hibernate.boot.SessionFactoryBuilder; import org.hibernate.jpa.QueryHints; @@ -34,6 +37,9 @@ import static org.junit.Assert.assertTrue; @TestForIssue( jiraKey = "HHH-10965" ) public class SelectDistinctHqlTest extends BaseNonConfigCoreFunctionalTestCase { + private static final String DISTINCT_PASSES_THROUGH_TRUE_NAMED_QUERY = "distinctPassesThroughTrue"; + private static final String DISTINCT_PASSES_THROUGH_FALSE_NAMED_QUERY = "distinctPassesThroughFalse"; + private static final String DISTINCT_PASSES_THROUGH_NOT_SPECIFIED_NAMED_QUERY = "distinctPassesThroughNotSpecified"; private SQLStatementInterceptor sqlStatementInterceptor; @Override @@ -137,7 +143,65 @@ public class SelectDistinctHqlTest extends BaseNonConfigCoreFunctionalTestCase { }); } + @Test + @TestForIssue(jiraKey = "HHH-13780") + public void testNamedQueryDistinctPassThroughTrue() { + doInHibernate( this::sessionFactory, session -> { + sqlStatementInterceptor.getSqlQueries().clear(); + List persons = session.createNamedQuery( DISTINCT_PASSES_THROUGH_TRUE_NAMED_QUERY, Person.class ) + .setMaxResults( 5 ) + .getResultList(); + assertEquals( 1, persons.size() ); + String sqlQuery = sqlStatementInterceptor.getSqlQueries().getLast(); + assertTrue( sqlQuery.contains( " distinct " ) ); + } ); + } + + @Test + @TestForIssue(jiraKey = "HHH-13780") + public void testNamedQueryDistinctPassThroughTrueWhenNotSpecified() { + doInHibernate( this::sessionFactory, session -> { + sqlStatementInterceptor.getSqlQueries().clear(); + List persons = + session.createNamedQuery( DISTINCT_PASSES_THROUGH_NOT_SPECIFIED_NAMED_QUERY, Person.class ) + .setMaxResults( 5 ) + .getResultList(); + assertEquals( 1, persons.size() ); + String sqlQuery = sqlStatementInterceptor.getSqlQueries().getLast(); + assertTrue( sqlQuery.contains( " distinct " ) ); + } ); + } + + @Test + @TestForIssue(jiraKey = "HHH-13780") + public void testNamedQueryDistinctPassThroughFalse() { + doInHibernate( this::sessionFactory, session -> { + sqlStatementInterceptor.getSqlQueries().clear(); + List persons = + session.createNamedQuery( DISTINCT_PASSES_THROUGH_FALSE_NAMED_QUERY, Person.class ) + .setMaxResults( 5 ) + .getResultList(); + assertEquals( 1, persons.size() ); + String sqlQuery = sqlStatementInterceptor.getSqlQueries().getLast(); + assertFalse( sqlQuery.contains( " distinct " ) ); + } ); + } + @Entity(name = "Person") + @NamedQueries({ + @NamedQuery(name = DISTINCT_PASSES_THROUGH_TRUE_NAMED_QUERY, + query = "select distinct p from Person p left join fetch p.phones", + hints = { + @QueryHint(name = QueryHints.HINT_PASS_DISTINCT_THROUGH, value = "true") + }), + @NamedQuery(name = DISTINCT_PASSES_THROUGH_FALSE_NAMED_QUERY, + query = "select distinct p from Person p left join fetch p.phones", + hints = { + @QueryHint(name = QueryHints.HINT_PASS_DISTINCT_THROUGH, value = "false") + }), + @NamedQuery(name = DISTINCT_PASSES_THROUGH_NOT_SPECIFIED_NAMED_QUERY, + query = "select distinct p from Person p left join fetch p.phones") + }) public static class Person { @Id diff --git a/hibernate-core/src/test/java/org/hibernate/test/hql/NaturalIdDereferenceTest.java b/hibernate-core/src/test/java/org/hibernate/test/hql/NaturalIdDereferenceTest.java index b279cccd8f..a3455af970 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/hql/NaturalIdDereferenceTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/hql/NaturalIdDereferenceTest.java @@ -11,6 +11,7 @@ import org.hibernate.NotYetImplementedFor6Exception; import org.hibernate.annotations.NaturalId; import org.hibernate.query.Query; +import org.hibernate.testing.TestForIssue; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import org.junit.Before; import org.junit.Test; @@ -21,10 +22,13 @@ import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.JoinColumn; +import javax.persistence.JoinTable; import javax.persistence.ManyToOne; +import javax.persistence.OneToMany; import javax.persistence.Table; import java.util.Collections; import java.util.List; +import java.util.Set; import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate; import static org.junit.Assert.assertEquals; @@ -239,6 +243,16 @@ public class NaturalIdDereferenceTest extends BaseCoreFunctionalTestCase { } ); } + @Test + @TestForIssue(jiraKey = "HHH-13752") + public void deleteWithNaturalIdBasedJoinTable() { + doInHibernate( this::sessionFactory, session -> { + Query query = session.createQuery( + "DELETE FROM Book b WHERE 1=0" ); + query.executeUpdate(); + } ); + } + private int getSQLJoinCount(Query query) { String sqlQuery = getSQLQuery( query ).toLowerCase(); @@ -317,6 +331,14 @@ public class NaturalIdDereferenceTest extends BaseCoreFunctionalTestCase { @Column(name = "isbn", unique = true) private String isbn; + @OneToMany + @JoinTable( + name = "similar_books", + joinColumns = @JoinColumn(name = "base_isbn", referencedColumnName = "isbn"), + inverseJoinColumns = @JoinColumn(name = "ref_isbn", referencedColumnName = "isbn_ref") + ) + private Set similarBooks; + } @Entity(name = "BookRef") diff --git a/hibernate-osgi/src/test/java/org/hibernate/osgi/test/OsgiIntegrationTest.java b/hibernate-osgi/src/test/java/org/hibernate/osgi/test/OsgiIntegrationTest.java index 40710e731f..4e64ea2e25 100644 --- a/hibernate-osgi/src/test/java/org/hibernate/osgi/test/OsgiIntegrationTest.java +++ b/hibernate-osgi/src/test/java/org/hibernate/osgi/test/OsgiIntegrationTest.java @@ -80,6 +80,8 @@ import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.logLevel; public class OsgiIntegrationTest { private static final boolean DEBUG = false; + private static final String jbossPublicRepository = "https://repository.jboss.org/nexus/content/groups/public-jboss/"; + private static final String mavenCentralRepository = "https://repo.maven.apache.org/maven2/"; // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Prepare the Karaf container @@ -108,10 +110,15 @@ public class OsgiIntegrationTest { ) ) .useDeployFolder( false ), - editConfigurationFileExtend( + editConfigurationFilePut( // Erase the defaults: Maven Central uses HTTP by default, but HTTPS is required now. "etc/org.ops4j.pax.url.mvn.cfg", "org.ops4j.pax.url.mvn.repositories", - "https://repository.jboss.org/nexus/content/groups/public/" + mavenCentralRepository + + "@id=central" + + ", " + + jbossPublicRepository + + "@id=jboss-public-repository" + + "https://repository.jboss.org/nexus/content/groups/public/" ), configureConsole().ignoreLocalConsole().ignoreRemoteShell(), when( debug ).useOptions( keepRuntimeFolder() ),