finally kill of Lifecycle after all these years

This commit is contained in:
Gavin King 2024-12-13 00:30:04 +01:00
parent 2a03f97b73
commit 1b1dfaecd0
20 changed files with 32 additions and 448 deletions

View File

@ -5,8 +5,7 @@
package org.hibernate;
/**
* Intended to be thrown from {@link org.hibernate.classic.Lifecycle}
* and {@link Interceptor} callbacks.
* Intended to be thrown from {@link Interceptor} callbacks.
*
* @implNote This is a legacy exception type from back in the day before
* Hibernate moved to an unchecked exception strategy.

View File

@ -54,7 +54,6 @@ import org.hibernate.type.Type;
*
* @author Gavin King
*/
@SuppressWarnings("unused")
public interface Interceptor {
/**
* Called just before an object is initialized. The interceptor may change the {@code state}, which will

View File

@ -1,125 +0,0 @@
/*
* SPDX-License-Identifier: LGPL-2.1-or-later
* Copyright Red Hat Inc. and Hibernate Authors
*/
package org.hibernate.classic;
import org.hibernate.CallbackException;
import org.hibernate.Session;
import java.io.Serializable;
/**
* Provides callbacks from the {@code Session} to the persistent object.
* Persistent classes <b>may</b> implement this interface but they are not
* required to.
* <ul>
* <li><b>onSave:</b> called just before the object is saved
* <li><b>onUpdate:</b> called just before an object is updated,
* ie. when {@code Session.update()} is called
* <li><b>onDelete:</b> called just before an object is deleted
* <b>onLoad:</b> called just after an object is loaded
* </ul>
* <p>
* {@code onLoad()} may be used to initialize transient properties of the
* object from its persistent state. It may <b>not</b> be used to load
* dependent objects since the {@code Session} interface may not be
* invoked from inside this method.
* <p>
* A further intended usage of {@code onLoad()}, {@code onSave()} and
* {@code onUpdate()} is to store a reference to the {@code Session}
* for later use.
* <p>
* If {@code onSave()}, {@code onUpdate()} or {@code onDelete()} return
* {@code VETO}, the operation is silently vetoed. If a
* {@code CallbackException} is thrown, the operation is vetoed and the
* exception is passed back to the application.
* <p>
* Note that {@code onSave()} is called after an identifier is assigned
* to the object, except when identity column key generation is used.
*
* @see CallbackException
* @see jakarta.persistence.EntityListeners
* @see jakarta.persistence.PrePersist
* @see jakarta.persistence.PreRemove
* @see jakarta.persistence.PreUpdate
* @see jakarta.persistence.PostLoad
* @see jakarta.persistence.PostPersist
* @see jakarta.persistence.PostRemove
* @see jakarta.persistence.PostUpdate
*
* @author Gavin King
*/
public interface Lifecycle {
/**
* Return value to veto the action (true)
*/
boolean VETO = true;
/**
* Return value to accept the action (false)
*/
boolean NO_VETO = false;
/**
* Called when an entity is saved.
* @param s the session
* @return true to veto save
* @throws CallbackException Indicates a problem happened during callback
*/
default boolean onSave(Session s) throws CallbackException {
return NO_VETO;
}
/**
* Called when an entity is passed to {@code Session.update()}.
* This method is <em>not</em> called every time the object's
* state is persisted during a flush.
* @param s the session
* @return true to veto update
* @throws CallbackException Indicates a problem happened during callback
*/
default boolean onUpdate(Session s) throws CallbackException {
return NO_VETO;
}
/**
* Called when an entity is deleted.
* @param s the session
* @return true to veto delete
* @throws CallbackException Indicates a problem happened during callback
*/
default boolean onDelete(Session s) throws CallbackException {
return NO_VETO;
}
/**
* Called after an entity is loaded. <em>It is illegal to
* access the {@code Session} from inside this method.</em>
* However, the object may keep a reference to the session
* for later use.
*
* @param s the session
* @param id the identifier
*/
default void onLoad(Session s, Object id) {
if (id==null || id instanceof Serializable) {
onLoad(s, (Serializable) id);
}
}
/**
* Called after an entity is loaded. <em>It is illegal to
* access the {@code Session} from inside this method.</em>
* However, the object may keep a reference to the session
* for later use.
*
* @param s the session
* @param id the identifier
*
* @deprecated use {@link #onLoad(Session, Object)}
*/
@Deprecated(since = "6.0")
default void onLoad(Session s, Serializable id) {}
}

View File

@ -1,12 +0,0 @@
/*
* 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 http://www.gnu.org/licenses/lgpl-2.1.html
*/
/**
* This package historically provided backward-compatibility
* with Hibernate 2.1 APIs which were deprecated in Hibernate 3.
*/
package org.hibernate.classic;

View File

@ -11,7 +11,6 @@ import org.hibernate.NonUniqueObjectException;
import org.hibernate.action.internal.AbstractEntityInsertAction;
import org.hibernate.action.internal.EntityIdentityInsertAction;
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.spi.CascadingAction;
@ -215,13 +214,8 @@ public abstract class AbstractSaveEventListener<C> implements CallbackRegistryCo
}
final EntityKey key = useIdentityColumn ? null : entityKey( id, persister, source );
if ( invokeSaveLifecycle( entity, persister, source ) ) {
return id;
}
else {
return performSaveOrReplicate( entity, key, persister, useIdentityColumn, context, source, delayIdentityInserts );
}
}
private static EntityKey entityKey(Object id, EntityPersister persister, EventSource source) {
final EntityKey key = source.generateEntityKey( id, persister );
@ -241,19 +235,6 @@ public abstract class AbstractSaveEventListener<C> implements CallbackRegistryCo
return key;
}
protected boolean invokeSaveLifecycle(Object entity, EntityPersister persister, EventSource source) {
// Sub-insertions should occur before containing insertion so
// Try to do the callback now
if ( persister.implementsLifecycle() ) {
LOG.debug( "Calling onSave()" );
if ( ((Lifecycle) entity).onSave( source ) ) {
LOG.debug( "Insertion vetoed by onSave()" );
return true;
}
}
return false;
}
/**
* Performs all the actual work needed to save an entity (well to get the save moved to
* the execution queue).

View File

@ -14,7 +14,6 @@ import org.hibernate.action.internal.EntityDeleteAction;
import org.hibernate.action.internal.OrphanRemovalAction;
import org.hibernate.bytecode.enhance.spi.LazyPropertyInitializer;
import org.hibernate.bytecode.spi.BytecodeEnhancementMetadata;
import org.hibernate.classic.Lifecycle;
import org.hibernate.engine.internal.Cascade;
import org.hibernate.engine.internal.CascadePoint;
import org.hibernate.engine.internal.ForeignKeys;
@ -271,8 +270,7 @@ public class DefaultDeleteEventListener implements DeleteEventListener, Callback
Object id,
Object version,
EntityEntry entityEntry) {
callbackRegistry.preRemove(entity);
if ( !invokeDeleteLifecycle( source, entity, persister ) ) {
callbackRegistry.preRemove( entity );
deleteEntity(
source,
entity,
@ -286,14 +284,12 @@ public class DefaultDeleteEventListener implements DeleteEventListener, Callback
persister.resetIdentifier( entity, id, version, source );
}
}
}
/**
* Can we delete the row represented by the proxy without loading the entity?
*/
private boolean canBeDeletedWithoutLoading(EventSource source, EntityPersister persister) {
return source.getInterceptor() == EmptyInterceptor.INSTANCE
&& !persister.implementsLifecycle()
&& !persister.hasSubclasses() //TODO: should be unnecessary, using EntityPersister.getSubclassPropertyTypeClosure(), etc
&& !persister.hasCascadeDelete()
&& !persister.hasNaturalIdentifier()
@ -488,17 +484,6 @@ public class DefaultDeleteEventListener implements DeleteEventListener, Callback
return deletedState;
}
protected boolean invokeDeleteLifecycle(EventSource session, Object entity, EntityPersister persister) {
if ( persister.implementsLifecycle() ) {
LOG.debug( "Calling onDelete()" );
if ( ( (Lifecycle) entity ).onDelete( session ) ) {
LOG.debug( "Deletion vetoed by onDelete()" );
return true;
}
}
return false;
}
protected void cascadeBeforeDelete(
EventSource session,
EntityPersister persister,

View File

@ -10,7 +10,6 @@ import org.hibernate.HibernateException;
import org.hibernate.LockMode;
import org.hibernate.action.internal.EntityIncrementVersionProcess;
import org.hibernate.action.internal.EntityVerifyVersionProcess;
import org.hibernate.classic.Lifecycle;
import org.hibernate.engine.spi.EntityEntry;
import org.hibernate.event.spi.EventSource;
import org.hibernate.event.spi.PostLoadEvent;
@ -20,11 +19,7 @@ import org.hibernate.jpa.event.spi.CallbackRegistryConsumer;
import org.hibernate.persister.entity.EntityPersister;
/**
* We do two things here:
* <ul>
* <li>Call {@link Lifecycle} interface if necessary</li>
* <li>Perform needed {@link EntityEntry#getLockMode()} related processing</li>
* </ul>
* Performs needed {@link EntityEntry#getLockMode()}-related processing.
*
* @author Gavin King
* @author Steve Ebersole
@ -72,13 +67,5 @@ public class DefaultPostLoadEventListener implements PostLoadEventListener, Call
+ "] not supported for non-versioned entities [" + persister.getEntityName() + "]");
}
}
invokeLoadLifecycle( event, session );
}
protected void invokeLoadLifecycle(PostLoadEvent event, EventSource session) {
if ( event.getPersister().implementsLifecycle() ) {
( (Lifecycle) event.getEntity() ).onLoad( session, event.getId() );
}
}
}

View File

@ -16,7 +16,6 @@ import org.hibernate.boot.registry.selector.spi.StrategySelector;
import org.hibernate.bytecode.spi.BytecodeProvider;
import org.hibernate.bytecode.spi.ReflectionOptimizer;
import org.hibernate.bytecode.spi.ReflectionOptimizer.InstantiationOptimizer;
import org.hibernate.classic.Lifecycle;
import org.hibernate.internal.CoreLogging;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.internal.util.ReflectHelper;
@ -59,7 +58,6 @@ public class EntityRepresentationStrategyPojoStandard implements EntityRepresent
private final JavaType<?> proxyJtd;
private final boolean isBytecodeEnhanced;
private final boolean lifecycleImplementor;
private final ReflectionOptimizer reflectionOptimizer;
private final ProxyFactory proxyFactory;
@ -89,7 +87,6 @@ public class EntityRepresentationStrategyPojoStandard implements EntityRepresent
this.proxyJtd = null;
}
this.lifecycleImplementor = Lifecycle.class.isAssignableFrom( mappedJavaType );
this.isBytecodeEnhanced = isPersistentAttributeInterceptableType( mappedJavaType );
final Property identifierProperty = bootDescriptor.getIdentifierProperty();
@ -389,11 +386,6 @@ public class EntityRepresentationStrategyPojoStandard implements EntityRepresent
return proxyFactory;
}
@Override
public boolean isLifecycleImplementor() {
return lifecycleImplementor;
}
@Override
public boolean isBytecodeEnhanced() {
return isBytecodeEnhanced;

View File

@ -27,10 +27,6 @@ public interface EntityRepresentationStrategy extends ManagedTypeRepresentationS
*/
ProxyFactory getProxyFactory();
default boolean isLifecycleImplementor() {
return false;
}
default boolean isBytecodeEnhanced() {
return false;
}

View File

@ -40,7 +40,6 @@ import org.hibernate.cache.spi.entry.ReferenceCacheEntryImpl;
import org.hibernate.cache.spi.entry.StandardCacheEntryImpl;
import org.hibernate.cache.spi.entry.StructuredCacheEntry;
import org.hibernate.cache.spi.entry.UnstructuredCacheEntry;
import org.hibernate.classic.Lifecycle;
import org.hibernate.collection.spi.PersistentCollection;
import org.hibernate.dialect.Dialect;
import org.hibernate.dialect.lock.LockingStrategy;
@ -464,8 +463,6 @@ public abstract class AbstractEntityPersister
*/
private final EntityPropertyMapping propertyMapping;
private final boolean implementsLifecycle;
private List<UniqueKeyEntry> uniqueKeyEntries = null; //lazily initialized
private ConcurrentHashMap<String,SingleIdArrayLoadPlan> nonLazyPropertyLoadPlansByName;
@ -523,7 +520,6 @@ public abstract class AbstractEntityPersister
javaType = representationStrategy.getLoadJavaType();
assert javaType != null;
this.implementsLifecycle = Lifecycle.class.isAssignableFrom( javaType.getJavaTypeClass() );
concreteProxy = entityMetamodel.isPolymorphic()
&& ( getBytecodeEnhancementMetadata().isEnhancedForLazyLoading() || hasProxy() )
@ -4181,11 +4177,6 @@ public abstract class AbstractEntityPersister
return this.getMappedJavaType().getJavaTypeClass();
}
@Override
public boolean implementsLifecycle() {
return this.implementsLifecycle;
}
@Override
public Class<?> getConcreteProxyClass() {
final JavaType<?> proxyJavaType = getRepresentationStrategy().getProxyJavaType();

View File

@ -537,8 +537,7 @@ public interface EntityPersister extends EntityMappingType, EntityMutationTarget
JdbcValueBiConsumer<X, Y> valueConsumer,
SharedSessionContractImplementor session) {
int span = 0;
if ( domainValue instanceof Object[] ) {
final Object[] values = (Object[]) domainValue;
if ( domainValue instanceof Object[] values ) {
for ( int i = 0; i < getNumberOfAttributeMappings(); i++ ) {
final AttributeMapping attributeMapping = getAttributeMapping( i );
span += attributeMapping.breakDownJdbcValues( values[ i ], offset + span, x, y, valueConsumer, session );
@ -1078,11 +1077,6 @@ public interface EntityPersister extends EntityMappingType, EntityMutationTarget
*/
Class<?> getMappedClass();
/**
* Does the class implement the {@link org.hibernate.classic.Lifecycle} interface?
*/
boolean implementsLifecycle();
/**
* Get the proxy interface that instances of <em>this</em> concrete class will be
* cast to (optional operation).

View File

@ -617,11 +617,6 @@ public class GoofyPersisterClassProvider implements PersisterClassResolver {
return null;
}
@Override
public boolean implementsLifecycle() {
return false;
}
@Override
public Class<?> getConcreteProxyClass() {
return null;

View File

@ -639,11 +639,6 @@ public class PersisterClassProviderTest {
return null;
}
@Override
public boolean implementsLifecycle() {
return false;
}
@Override
public Class getConcreteProxyClass() {
return null;

View File

@ -284,11 +284,6 @@ public class CustomPersister implements EntityPersister {
public void processUpdateGeneratedProperties(Object id, Object entity, Object[] state, GeneratedValues generatedValues, SharedSessionContractImplementor session) {
}
@Override
public boolean implementsLifecycle() {
return false;
}
@Override
public Class<?> getConcreteProxyClass() {
return Custom.class;

View File

@ -9,11 +9,13 @@ import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
import jakarta.persistence.PostLoad;
import jakarta.persistence.PrePersist;
import jakarta.persistence.PreRemove;
import jakarta.persistence.PreUpdate;
import org.hibernate.CallbackException;
import org.hibernate.Session;
import org.hibernate.classic.Lifecycle;
public class Foo implements Lifecycle, FooProxy, Serializable {
public class Foo implements FooProxy, Serializable {
private static int count=0;
@ -89,7 +91,8 @@ public class Foo implements Lifecycle, FooProxy, Serializable {
this.x=x;
}
public boolean onSave(Session db) throws CallbackException {
@PrePersist
public void onSave() throws CallbackException {
_string = "a string";
_date = new Date(123);
_timestamp = new Date( System.currentTimeMillis() );
@ -114,17 +117,6 @@ public class Foo implements Lifecycle, FooProxy, Serializable {
dependent = new Fee();
dependent.setFi( "belongs to foo # " + getKey() );
theLocale = Locale.getDefault();
return NO_VETO;
}
public boolean onDelete(Session db) throws CallbackException {
return NO_VETO;
}
public boolean onUpdate(Session db) throws CallbackException {
return NO_VETO;
}
public void onLoad(Session db, Object id) {
}
public String getKey() {

View File

@ -4,20 +4,13 @@
*/
package org.hibernate.orm.test.legacy;
import java.io.Serializable;
import java.sql.SQLException;
import java.util.Calendar;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import org.hibernate.CallbackException;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.classic.Lifecycle;
public class Fum implements Lifecycle, Serializable {
public class Fum implements Serializable {
private String fum;
private FumCompositeID id;
private Fum fo;
@ -30,7 +23,7 @@ public class Fum implements Lifecycle, Serializable {
private MapComponent mapComponent = new MapComponent();
public Fum() {}
public Fum(FumCompositeID id) throws SQLException, HibernateException {
public Fum(FumCompositeID id) {
this.id = id;
friends = new HashSet();
FumCompositeID fid = new FumCompositeID();
@ -76,45 +69,6 @@ public class Fum implements Lifecycle, Serializable {
this.friends = friends;
}
public boolean onDelete(Session s) throws CallbackException {
if (friends==null) return false;
try {
Iterator iter = friends.iterator();
while ( iter.hasNext() ) {
s.remove( iter.next() );
}
}
catch (Exception e) {
throw new CallbackException(e);
}
return false;
}
public void onLoad(Session s, Object id) {
}
public boolean onSave(Session s) throws CallbackException {
if (friends==null) return false;
try {
Iterator iter = friends.iterator();
while ( iter.hasNext() ) {
s.persist( iter.next() );
}
}
catch (Exception e) {
throw new CallbackException(e);
}
return false;
}
public boolean onUpdate(Session s) throws CallbackException {
return false;
}
public Calendar getLastUpdated() {
return lastUpdated;
}

View File

@ -9,11 +9,10 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import jakarta.persistence.PrePersist;
import org.hibernate.CallbackException;
import org.hibernate.Session;
import org.hibernate.classic.Lifecycle;
public class Glarch extends Super implements GlarchProxy, Lifecycle, Named, Serializable {
public class Glarch extends Super implements GlarchProxy, Named, Serializable {
private int version;
private GlarchProxy next;
@ -97,34 +96,14 @@ public class Glarch extends Super implements GlarchProxy, Lifecycle, Named, Seri
this.proxySet = proxySet;
}
public boolean onDelete(Session s) throws CallbackException {
return NO_VETO;
}
public void onLoad(Session s, Object id) {
if ( ! ( ( (String) id ).length()==32 ) ) throw new RuntimeException("id problem");
}
public boolean onSave(Session s) throws CallbackException {
@PrePersist
public void onSave() throws CallbackException {
dynaBean = new HashMap();
dynaBean.put("foo", "foo");
dynaBean.put("bar", new Integer(66));
immutable="never changes!";
return NO_VETO;
}
public boolean onUpdate(Session s) throws CallbackException {
return NO_VETO;
}
/*public Currency getCurrency() {
return currency;
}
public void setCurrency(Currency currency) {
this.currency = currency;
}*/
/**
* Returns the dynaBean.
* @return DynaBean

View File

@ -7,12 +7,11 @@ import java.sql.SQLException;
import java.util.List;
import java.util.Set;
import org.hibernate.CallbackException;
import jakarta.persistence.PostLoad;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.classic.Lifecycle;
public class Qux implements Lifecycle {
public class Qux {
boolean created;
boolean deleted;
@ -35,31 +34,7 @@ public class Qux implements Lifecycle {
stuff=s;
}
public boolean onSave(Session session) throws CallbackException {
created=true;
try {
foo = new Foo();
session.persist(foo);
}
catch (Exception e) {
throw new CallbackException(e);
}
foo.setString("child of a qux");
return NO_VETO;
}
public boolean onDelete(Session session) throws CallbackException {
deleted=true;
try {
session.remove(foo);
}
catch (Exception e) {
throw new CallbackException(e);
}
//if (child!=null) session.remove(child);
return NO_VETO;
}
@PostLoad
public void onLoad(Session session, Object id) {
loaded=true;
this.session=session;
@ -157,10 +132,6 @@ public class Qux implements Lifecycle {
this.childKey = childKey;
}
public boolean onUpdate(Session s) throws CallbackException {
return NO_VETO;
}
protected void finalize() { }
public Holder getHolder() {

View File

@ -1,63 +0,0 @@
/*
* SPDX-License-Identifier: LGPL-2.1-or-later
* Copyright Red Hat Inc. and Hibernate Authors
*/
package org.hibernate.orm.test.legacy;
import org.hibernate.CallbackException;
import org.hibernate.Session;
import org.hibernate.classic.Lifecycle;
public class Vetoer implements Lifecycle {
private String id;
private String name;
private String[] strings;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String[] getStrings() {
return strings;
}
public void setStrings(String[] strings) {
this.strings = strings;
}
boolean onSaveCalled;
boolean onUpdateCalled;
boolean onDeleteCalled;
public boolean onSave(Session s) throws CallbackException {
boolean result = !onSaveCalled;
onSaveCalled = true;
return result;
}
public boolean onUpdate(Session s) throws CallbackException {
boolean result = !onUpdateCalled;
onUpdateCalled = true;
return result;
}
public boolean onDelete(Session s) throws CallbackException {
boolean result = !onDeleteCalled;
onDeleteCalled = true;
return result;
}
public void onLoad(Session s, Object id) {}
}

View File

@ -1,21 +0,0 @@
<?xml version="1.0"?>
<!--
~ 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 <http://www.gnu.org/licenses/lgpl-2.1.html>.
-->
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping default-lazy="false">
<class name="org.hibernate.orm.test.legacy.Vetoer">
<id name="id" type="string" column="id_" length="32">
<generator class="uuid.hex"/>
</id>
<property name="name"/>
<property name="strings"/>
</class>
</hibernate-mapping>