下面列出了怎么用org.hibernate.persister.entity.EntityPersister的API类实例代码及写法,或者点击链接到github查看源代码。
private EntityReferenceAliases createCollectionElementAliases(
CollectionPersister collectionPersister,
String tableAlias,
String elementQuerySpaceUid) {
if ( !collectionPersister.getElementType().isEntityType() ) {
return null;
}
else {
final EntityType entityElementType = (EntityType) collectionPersister.getElementType();
return generateEntityReferenceAliases(
elementQuerySpaceUid,
tableAlias,
(EntityPersister) entityElementType.getAssociatedJoinable( sessionFactory() )
);
}
}
protected void cascadeBeforeDelete(
EventSource session,
EntityPersister persister,
Object entity,
EntityEntry entityEntry,
Set transientEntities) throws HibernateException {
CacheMode cacheMode = session.getCacheMode();
session.setCacheMode( CacheMode.GET );
session.getPersistenceContext().incrementCascadeLevel();
try {
// cascade-delete to collections BEFORE the collection owner is deleted
new Cascade( CascadingAction.DELETE, Cascade.AFTER_INSERT_BEFORE_DELETE, session )
.cascade( persister, entity, transientEntities );
}
finally {
session.getPersistenceContext().decrementCascadeLevel();
session.setCacheMode( cacheMode );
}
}
/**
* Generate an info message string relating to a particular entity,.
*
* @param persister The persister for the entity
* @param id The entity id value
* @param identifierType The entity identifier type mapping
* @param factory The session factory
* @return An info string, in the form [FooBar#1]
*/
public static String infoString(
EntityPersister persister,
Object id,
Type identifierType,
SessionFactoryImplementor factory) {
StringBuilder s = new StringBuilder();
s.append( '[' );
if( persister == null ) {
s.append( "<null EntityPersister>" );
}
else {
s.append( persister.getEntityName() );
}
s.append( '#' );
if ( id == null ) {
s.append( "<null>" );
}
else {
s.append( identifierType.toLoggableString( id, factory ) );
}
s.append( ']' );
return s.toString();
}
private CompletionStage<Void> entityIsDeleted(PersistEvent event, IdentitySet createCache) {
final EventSource source = event.getSession();
final Object entity = source.getPersistenceContextInternal().unproxy( event.getObject() );
final EntityPersister persister = source.getEntityPersister( event.getEntityName(), entity );
if ( LOG.isTraceEnabled() ) {
LOG.tracef(
"un-scheduling entity deletion [%s]",
MessageHelper.infoString(
persister,
persister.getIdentifier( entity, source ),
source.getFactory()
)
);
}
if ( createCache.add( entity ) ) {
return justCascade( createCache, source, entity, persister );
}
return CompletionStages.nullFuture();
}
protected void doEvict(
final Object object,
final EntityKey key,
final EntityPersister persister,
final EventSource session) throws HibernateException {
if ( log.isTraceEnabled() ) {
log.trace( "evicting " + MessageHelper.infoString(persister) );
}
// remove all collections for the entity from the session-level cache
if ( persister.hasCollections() ) {
new EvictVisitor( session ).process( object, persister );
}
new Cascade( CascadingAction.EVICT, Cascade.AFTER_EVICT, session )
.cascade( persister, object );
}
private Object[] getValues(Object entity, EntityEntry entry, boolean mightBeDirty, SessionImplementor session) {
final Object[] loadedState = entry.getLoadedState();
final Status status = entry.getStatus();
final EntityPersister persister = entry.getPersister();
final Object[] values;
if ( status == Status.DELETED ) {
//grab its state saved at deletion
values = entry.getDeletedState();
}
else if ( !mightBeDirty && loadedState != null ) {
values = loadedState;
}
else {
checkId( entity, persister, entry.getId(), session );
// grab its current state
values = persister.getPropertyValues( entity );
checkNaturalId( persister, entry, values, loadedState, session );
}
return values;
}
/**
* Find all non-nullable references to entities that have not yet
* been inserted in the database, where the foreign key
* is a reference to an unsaved transient entity. .
*
* @param entityName - the entity name
* @param entity - the entity instance
* @param values - insertable properties of the object (including backrefs),
* possibly with substitutions
* @param isEarlyInsert - true if the entity needs to be executed as soon as possible
* (e.g., to generate an ID)
* @param session - the session
*
* @return the transient unsaved entity dependencies that are non-nullable,
* or null if there are none.
*/
public static NonNullableTransientDependencies findNonNullableTransientEntities(
String entityName,
Object entity,
Object[] values,
boolean isEarlyInsert,
SharedSessionContractImplementor session) {
final Nullifier nullifier = new Nullifier( entity, false, isEarlyInsert, session );
final EntityPersister persister = session.getEntityPersister( entityName, entity );
final String[] propertyNames = persister.getPropertyNames();
final Type[] types = persister.getPropertyTypes();
final boolean[] nullability = persister.getPropertyNullability();
final NonNullableTransientDependencies nonNullableTransientEntities = new NonNullableTransientDependencies();
for ( int i = 0; i < types.length; i++ ) {
collectNonNullableTransientEntities(
nullifier,
values[i],
propertyNames[i],
types[i],
nullability[i],
session,
nonNullableTransientEntities
);
}
return nonNullableTransientEntities.isEmpty() ? null : nonNullableTransientEntities;
}
/**
* Performs the process of loading an entity from the configured
* underlying datasource.
*
* @param event The load event
* @param persister The persister for the entity being requested for load
*
* @return The object loaded from the datasource, or null if not found.
*/
protected CompletionStage<Object> loadFromDatasource(
final LoadEvent event,
final EntityPersister persister) {
CompletionStage<Object> entity =
( (ReactiveEntityPersister) persister).reactiveLoad(
event.getEntityId(),
event.getInstanceToLoad(),
event.getLockOptions(),
event.getSession()
);
final StatisticsImplementor statistics = event.getSession().getFactory().getStatistics();
if ( event.isAssociationFetch() && statistics.isStatisticsEnabled() ) {
statistics.fetchEntity( event.getEntityClassName() );
}
return entity;
}
/**
* We encountered a delete request on a transient instance.
* <p>
* This is a deviation from historical Hibernate (pre-3.2) behavior to
* align with the JPA spec, which states that transient entities can be
* passed to remove operation in which case cascades still need to be
* performed.
*
* @param session The session which is the source of the event
* @param entity The entity being delete processed
* @param cascadeDeleteEnabled Is cascading of deletes enabled
* @param persister The entity persister
* @param transientEntities A cache of already visited transient entities
* (to avoid infinite recursion).
*/
protected CompletionStage<Void> deleteTransientEntity(
EventSource session,
Object entity,
boolean cascadeDeleteEnabled,
EntityPersister persister,
IdentitySet transientEntities) {
LOG.handlingTransientEntity();
if ( transientEntities.contains( entity ) ) {
LOG.trace( "Already handled transient entity; skipping" );
return CompletionStages.nullFuture();
}
transientEntities.add( entity );
return cascadeBeforeDelete( session, persister, entity, null, transientEntities )
.thenCompose( v -> cascadeAfterDelete( session, persister, entity, transientEntities ) );
}
/**
* Handles the calls needed to perform pre-save cascades for the given entity.
*
* @param source The session from whcih the save event originated.
* @param persister The entity's persister instance.
* @param entity The entity to be saved.
* @param anything Generally cascade-specific data
*/
protected void cascadeBeforeSave(
EventSource source,
EntityPersister persister,
Object entity,
Object anything) {
// cascade-save to many-to-one BEFORE the parent is saved
source.getPersistenceContext().incrementCascadeLevel();
try {
new Cascade( getCascadeAction(), Cascade.BEFORE_INSERT_AFTER_DELETE, source )
.cascade( persister, entity, anything );
}
finally {
source.getPersistenceContext().decrementCascadeLevel();
}
}
private void removeLocalization(EntityPersister persister, Object entity) {
if (entity instanceof DomainObject<?>) {
DomainObject<?> obj = (DomainObject<?>) entity;
List<LocalizedObjectTypes> objType = obj.getLocalizedObjectTypes();
if (objType.size() > 0) {
long key = obj.getKey();
final StatelessSession session = persister.getFactory()
.openStatelessSession();
Transaction tx = session.beginTransaction();
org.hibernate.Query query = session
.createQuery("DELETE FROM LocalizedResource WHERE objectKey = :objectKey AND objectType IN (:objectType)");
query.setParameter("objectKey", Long.valueOf(key));
query.setParameterList("objectType", objType);
query.executeUpdate();
tx.commit();
session.close();
}
}
}
public void applyTreatAsDeclarations(Set<String> treatAsDeclarations) {
if ( treatAsDeclarations != null && !treatAsDeclarations.isEmpty() ) {
if ( this.treatAsDeclarations == null ) {
this.treatAsDeclarations = new HashSet<String>();
}
for ( String treatAsSubclassName : treatAsDeclarations ) {
try {
EntityPersister subclassPersister = fromElement.getSessionFactoryHelper().requireClassPersister(
treatAsSubclassName
);
this.treatAsDeclarations.add( subclassPersister.getEntityName() );
}
catch (SemanticException e) {
throw new QueryException( "Unable to locate persister for subclass named in TREAT-AS : " + treatAsSubclassName );
}
}
if ( joinSequence != null ) {
joinSequence.applyTreatAsDeclarations( this.treatAsDeclarations );
}
}
}
protected void copyValues(
final EntityPersister persister,
final Object entity,
final Object target,
final SessionImplementor source,
final Map copyCache
) {
final Object[] copiedValues = TypeFactory.replace(
persister.getPropertyValues( entity, source.getEntityMode() ),
persister.getPropertyValues( target, source.getEntityMode() ),
persister.getPropertyTypes(),
source,
target,
copyCache
);
persister.setPropertyValues( target, copiedValues, source.getEntityMode() );
}
private boolean isFoundInParent(
String property,
Object childEntity,
EntityPersister persister,
CollectionPersister collectionPersister,
Object potentialParent
) {
Object collection = persister.getPropertyValue(
potentialParent,
property,
session.getEntityMode()
);
return collection!=null && Hibernate.isInitialized(collection) &&
collectionPersister.getCollectionType()
.contains(collection, childEntity, session);
}
protected final Object getIdentifier(Object value, SharedSessionContractImplementor session) throws HibernateException {
if ( isReferenceToPrimaryKey() || uniqueKeyPropertyName == null ) {
return ForeignKeys.getEntityIdentifierIfNotUnsaved(
getAssociatedEntityName(),
value,
session
); //tolerates nulls
}
else if ( value == null ) {
return null;
}
else {
EntityPersister entityPersister = getAssociatedEntityPersister( session.getFactory() );
Object propertyValue = entityPersister.getPropertyValue( value, uniqueKeyPropertyName );
// We now have the value of the property-ref we reference. However,
// we need to dig a little deeper, as that property might also be
// an entity type, in which case we need to resolve its identitifier
Type type = entityPersister.getPropertyType( uniqueKeyPropertyName );
if ( type.isEntityType() ) {
propertyValue = ( (EntityType) type ).getIdentifier( propertyValue, session );
}
return propertyValue;
}
}
/**
* Determine the id to use for updating.
*
* @param entity The entity.
* @param persister The entity persister
* @param requestedId The requested identifier
* @param entityMode The entity mode.
*
* @return The id.
*
* @throws TransientObjectException If the entity is considered transient.
*/
protected Serializable getUpdateId(
Object entity,
EntityPersister persister,
Serializable requestedId,
EntityMode entityMode) {
// use the id assigned to the instance
Serializable id = persister.getIdentifier( entity, entityMode );
if ( id == null ) {
// assume this is a newly instantiated transient object
// which should be saved rather than updated
throw new TransientObjectException(
"The given object has a null identifier: " +
persister.getEntityName()
);
}
else {
return id;
}
}
public void initializeEntity(
FromClause fromClause,
String className,
EntityPersister persister,
EntityType type,
String classAlias,
String tableAlias) {
doInitialize( fromClause, tableAlias, className, classAlias, persister, type );
this.sequence = fromClause.nextFromElementCounter();
initialized = true;
}
private void synchronizeHibernateState(EntityPersister persister, Object[] state, Map<String, Object> modifiedProperties) {
EntityMetamodel entityMetamodel = persister.getEntityMetamodel();
for(Map.Entry<String,Object> entry : modifiedProperties.entrySet()) {
Integer index = entityMetamodel.getPropertyIndexOrNull(entry.getKey());
if(index != null) {
state[index] = entry.getValue();
}
}
}
private SQLLoadable getSQLLoadable(String entityName) throws MappingException {
EntityPersister persister = factory.getEntityPersister( entityName );
if ( !(persister instanceof SQLLoadable) ) {
throw new MappingException( "class persister is not SQLLoadable: " + entityName );
}
return (SQLLoadable) persister;
}
/**
* Attempts to locate the entity in the session-level cache.
* <p/>
* If allowed to return nulls, then if the entity happens to be found in
* the session cache, we check the entity type for proper handling
* of entity hierarchies.
* <p/>
* If checkDeleted was set to true, then if the entity is found in the
* session-level cache, it's current status within the session cache
* is checked to see if it has previously been scheduled for deletion.
*
* @param event The load event
* @param keyToLoad The EntityKey representing the entity to be loaded.
* @param options The load options.
* @return The entity from the session-level cache, or null.
* @throws HibernateException Generally indicates problems applying a lock-mode.
*/
protected Object loadFromSessionCache(
final LoadEvent event,
final EntityKey keyToLoad,
final LoadEventListener.LoadType options) throws HibernateException {
SessionImplementor session = event.getSession();
Object old = session.getEntityUsingInterceptor( keyToLoad );
if ( old != null ) {
// this object was already loaded
EntityEntry oldEntry = session.getPersistenceContext().getEntry( old );
if ( options.isCheckDeleted() ) {
Status status = oldEntry.getStatus();
if ( status == Status.DELETED || status == Status.GONE ) {
return REMOVED_ENTITY_MARKER;
}
}
if ( options.isAllowNulls() ) {
EntityPersister persister = event.getSession().getFactory().getEntityPersister( event.getEntityClassName() );
if ( ! persister.isInstance( old, event.getSession().getEntityMode() ) ) {
return INCONSISTENT_RTN_CLASS_MARKER;
}
}
upgradeLock( old, oldEntry, event.getLockMode(), session );
}
return old;
}
/**
* Is this instance, which we know is not persistent, actually transient?
* If <tt>assumed</tt> is non-null, don't hit the database to make the
* determination, instead assume that value; the client code must be
* prepared to "recover" in the case that this assumed result is incorrect.
*/
public static boolean isTransient(String entityName, Object entity, Boolean assumed, SessionImplementor session)
throws HibernateException {
if (entity==LazyPropertyInitializer.UNFETCHED_PROPERTY) {
// an unfetched association can only point to
// an entity that already exists in the db
return false;
}
// let the interceptor inspect the instance to decide
Boolean isUnsaved = session.getInterceptor().isTransient(entity);
if (isUnsaved!=null) return isUnsaved.booleanValue();
// let the persister inspect the instance to decide
EntityPersister persister = session.getEntityPersister(entityName, entity);
isUnsaved = persister.isTransient(entity, session);
if (isUnsaved!=null) return isUnsaved.booleanValue();
// we use the assumed value, if there is one, to avoid hitting
// the database
if (assumed!=null) return assumed.booleanValue();
// hit the database, after checking the session cache for a snapshot
Object[] snapshot = session.getPersistenceContext()
.getDatabaseSnapshot( persister.getIdentifier( entity, session.getEntityMode() ), persister );
return snapshot==null;
}
/**
* Construct a unique identifier for an entity class instance
*/
public EntityKey(Serializable id, EntityPersister persister, EntityMode entityMode) {
if ( id == null ) {
throw new AssertionFailure( "null identifier" );
}
this.identifier = id;
this.entityMode = entityMode;
this.rootEntityName = persister.getRootEntityName();
this.entityName = persister.getEntityName();
this.identifierType = persister.getIdentifierType();
this.isBatchLoadable = persister.isBatchLoadable();
this.factory = persister.getFactory();
hashCode = generateHashCode(); //cache the hashcode
}
public PostDeleteEvent(
Object entity,
Serializable id,
Object[] deletedState,
EntityPersister persister,
EventSource source
) {
super(source);
this.entity = entity;
this.id = id;
this.persister = persister;
this.deletedState = deletedState;
}
private CompletionStage<Void> checkIdClass(
final EntityPersister persister,
final LoadEvent event,
final LoadEventListener.LoadType loadType,
final Class<?> idClass) {
// we may have the kooky jpa requirement of allowing find-by-id where
// "id" is the "simple pk value" of a dependent objects parent. This
// is part of its generally goofy "derived identity" "feature"
final IdentifierProperty identifierProperty = persister.getEntityMetamodel().getIdentifierProperty();
if ( identifierProperty.isEmbedded() ) {
final EmbeddedComponentType dependentIdType = (EmbeddedComponentType) identifierProperty.getType();
if ( dependentIdType.getSubtypes().length == 1 ) {
final Type singleSubType = dependentIdType.getSubtypes()[0];
if ( singleSubType.isEntityType() ) {
final EntityType dependentParentType = (EntityType) singleSubType;
final SessionFactoryImplementor factory = event.getSession().getFactory();
final Type dependentParentIdType = dependentParentType.getIdentifierOrUniqueKeyType( factory );
if ( dependentParentIdType.getReturnedClass().isInstance( event.getEntityId() ) ) {
// yep that's what we have...
return loadByDerivedIdentitySimplePkValue( event, loadType, persister,
dependentIdType, factory.getMetamodel().entityPersister( dependentParentType.getAssociatedEntityName() )
);
}
}
}
}
throw new TypeMismatchException(
"Provided id of the wrong type for class " + persister.getEntityName() + ". Expected: " + idClass + ", got " + event.getEntityId().getClass() );
}
private FromElement createAndAddFromElement(
String className,
String classAlias,
EntityPersister entityPersister,
EntityType type,
String tableAlias) {
if ( !( entityPersister instanceof Joinable ) ) {
throw new IllegalArgumentException( "EntityPersister " + entityPersister + " does not implement Joinable!" );
}
FromElement element = createFromElement( entityPersister );
initializeAndAddFromElement( element, className, classAlias, entityPersister, type, tableAlias );
return element;
}
private void markInterceptorDirty(Object entity, EntityPersister persister, EventSource source) {
if ( FieldInterceptionHelper.isInstrumented( entity ) ) {
FieldInterceptor interceptor = FieldInterceptionHelper.injectFieldInterceptor(
entity,
persister.getEntityName(),
null,
source
);
interceptor.dirty();
}
}
public void testNormalBoundary() {
EntityPersister persister = sfi().getEntityPersister( Entity.class.getName() );
assertClassAssignability( TableGenerator.class, persister.getIdentifierGenerator().getClass() );
TableGenerator generator = ( TableGenerator ) persister.getIdentifierGenerator();
int count = 5;
Entity[] entities = new Entity[count];
Session s = openSession();
s.beginTransaction();
for ( int i = 0; i < count; i++ ) {
entities[i] = new Entity( "" + ( i + 1 ) );
s.save( entities[i] );
long expectedId = i + 1;
assertEquals( expectedId, entities[i].getId().longValue() );
assertEquals( expectedId, generator.getTableAccessCount() );
assertEquals( expectedId, generator.getOptimizer().getLastSourceValue() );
}
s.getTransaction().commit();
s.beginTransaction();
for ( int i = 0; i < count; i++ ) {
assertEquals( i + 1, entities[i].getId().intValue() );
s.delete( entities[i] );
}
s.getTransaction().commit();
s.close();
}
public EntityInsertAction(
Serializable id,
Object[] state,
Object instance,
Object version,
EntityPersister persister,
SessionImplementor session) throws HibernateException {
super( session, id, instance, persister );
this.state = state;
this.version = version;
}
/**
* If the user specified an id, assign it to the instance and use that,
* otherwise use the id already assigned to the instance
*/
protected Serializable getUpdateId(
Object entity,
EntityPersister persister,
Serializable requestedId,
SessionImplementor session) throws HibernateException {
if ( requestedId == null ) {
return super.getUpdateId( entity, persister, requestedId, session );
}
else {
persister.setIdentifier( entity, requestedId, session );
return requestedId;
}
}
public PostInsertEvent(
Object entity,
Serializable id,
Object[] state,
EntityPersister persister,
EventSource source
) {
super(source);
this.entity = entity;
this.id = id;
this.state = state;
this.persister = persister;
}