org.babyfish.hibernate.collection.PersistentMAOrderedSet Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of babyfish-hibernate Show documentation
Show all versions of babyfish-hibernate Show documentation
The hibernate enhancement project of BabyFish.
The newest version!
/*
* BabyFish, Object Model Framework for Java and JPA.
* https://github.com/babyfish-ct/babyfish
*
* Copyright (c) 2008-2015, Tao Chen
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* Please visit "http://opensource.org/licenses/LGPL-3.0" to know more.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*/
package org.babyfish.hibernate.collection;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Collection;
import java.util.Iterator;
import org.babyfish.association.AssociatedEndpoint;
import org.babyfish.collection.MAOrderedSet;
import org.babyfish.collection.MASet;
import org.babyfish.collection.UnifiedComparator;
import org.babyfish.collection.XCollection;
import org.babyfish.collection.XMap;
import org.babyfish.collection.event.ElementEvent;
import org.babyfish.collection.spi.laziness.AbstractLazyMAOrderedSet;
import org.babyfish.collection.spi.laziness.DummyReadingResultRef;
import org.babyfish.collection.spi.laziness.LazyBehaviorProcessor;
import org.babyfish.collection.spi.laziness.QueuedOperationType;
import org.babyfish.collection.spi.wrapper.WrapperAware;
import org.babyfish.hibernate.collection.spi.PersistentCollection;
import org.babyfish.hibernate.collection.spi.persistence.SetBasePersistence;
import org.babyfish.hibernate.model.metadata.HibernateMetadatas;
import org.babyfish.lang.Ref;
import org.babyfish.persistence.model.metadata.JPAAssociationProperty;
import org.babyfish.persistence.model.metadata.LazyBehavior;
import org.babyfish.util.LazyResource;
import org.hibernate.HibernateException;
import org.hibernate.LazyInitializationException;
import org.hibernate.engine.spi.CollectionEntry;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.loader.CollectionAliases;
import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.type.Type;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* @author Tao Chen
*/
public class PersistentMAOrderedSet
extends AbstractLazyMAOrderedSet
implements PersistentCollection, Serializable{
private static final long serialVersionUID = -6449898442600402473L;
private static final LazyResource LAZY_COMMON_RESOURCE = LazyResource.of(CommonResource.class);
private static final Logger LOGGER = LoggerFactory.getLogger(PersistentMAOrderedSet.class);
private transient AssociatedEndpoint, E> wrapperEndpoint;
public PersistentMAOrderedSet(String role, SessionImplementor session, MAOrderedSet base) {
super(null);
RootData rootData = this.>getRootData();
SetBasePersistence basePersistence = rootData.basePersistence;
basePersistence.setSnapshot(null, role, null);
basePersistence.setCurrentSession(session);
this.replace(base);
rootData.setDirectlyAccessible();
}
@Override
protected RootData createRootData() {
return new RootData();
}
@Override
protected void onModified(ElementEvent e) throws Throwable {
this.dirty();
}
protected final AssociatedEndpoint, E> getWrapperEndpoint() {
return this.wrapperEndpoint;
}
@SuppressWarnings("unchecked")
@WrapperAware
void setWrapper(XCollection wrapper) {
AssociatedEndpoint, E> oldWrapper = this.wrapperEndpoint;
if (oldWrapper != wrapper) {
if (wrapper instanceof AssociatedEndpoint, ?>) {
this.wrapperEndpoint = (AssociatedEndpoint, E>)wrapper;
} else {
this.wrapperEndpoint = null;
}
}
}
@Override
public E getElement(Object entry) {
return this.>getRootData().basePersistence.getElement(entry);
}
@Override
public Iterator entries(CollectionPersister persister) {
return this.>getRootData().basePersistence.entries(persister);
}
@Override
public E readFrom(ResultSet rs, CollectionPersister persister,
CollectionAliases descriptor, Object owner)
throws HibernateException, SQLException {
return this.>getRootData().basePersistence.readFrom(rs, persister, descriptor, owner);
}
@Override
public Iterator> getDeletes(CollectionPersister persister,
boolean indexIsFormula) throws HibernateException {
return this.>getRootData().basePersistence.getDeletes(persister, indexIsFormula);
}
@Override
public Collection getOrphans(Serializable snapshot, String entityName)
throws HibernateException {
return this.>getRootData().basePersistence.getOrphans(snapshot, entityName);
}
@Override
public Iterator queuedAdditionIterator() {
return this.>getRootData().basePersistence.queuedAdditionIterator();
}
@Override
public Collection getQueuedOrphans(String entityName) {
return this.>getRootData().basePersistence.getQueuedOrphans(entityName);
}
@Override
public Object getOwner() {
return this.>getRootData().basePersistence.getOwner();
}
@Override
public void setOwner(Object entity) {
this.>getRootData().basePersistence.setOwner(entity);
}
@Override
public boolean empty() {
return this.>getRootData().basePersistence.empty();
}
@Override
public void setSnapshot(Serializable key, String role, Serializable snapshot) {
this.>getRootData().basePersistence.setSnapshot(key, role, snapshot);
}
@Override
public void postAction() {
this.>getRootData().basePersistence.postAction();
}
@Override
public Object getValue() {
return this;
}
@Override
public void beginRead() {
this.>getRootData().basePersistence.beginRead();
}
@Override
public boolean endRead() {
return this.>getRootData().basePersistence.endRead();
}
@Override
public boolean afterInitialize() {
return this.>getRootData().basePersistence.afterInitialize();
}
@Override
public boolean isDirectlyAccessible() {
return this.>getRootData().basePersistence.isDirectlyAccessible();
}
@Override
public boolean unsetSession(SessionImplementor currentSession) {
return this.>getRootData().basePersistence.unsetSession(currentSession);
}
@Override
public boolean setCurrentSession(SessionImplementor session)
throws HibernateException {
return this.>getRootData().basePersistence.setCurrentSession(session);
}
@Override
public void initializeFromCache(CollectionPersister persister,
Serializable disassembled, Object owner) throws HibernateException {
this.>getRootData().basePersistence.initializeFromCache(persister, disassembled, owner);
}
@Override
public Object getIdentifier(Object entry, int i) {
return this.>getRootData().basePersistence.getIdentifier(entry, i);
}
@Override
public Object getIndex(Object entry, int i, CollectionPersister persister) {
throw new UnsupportedOperationException();
}
@Override
public Object getSnapshotElement(Object entry, int i) {
throw new UnsupportedOperationException();
}
@Override
public void beforeInitialize(CollectionPersister persister,
int anticipatedSize) {
this.>getRootData().basePersistence.beforeInitialize(persister, anticipatedSize);
}
@Override
public boolean equalsSnapshot(CollectionPersister persister)
throws HibernateException {
return this.>getRootData().basePersistence.equalsSnapshot(persister);
}
@Override
public boolean isSnapshotEmpty(Serializable snapshot) {
return this.>getRootData().basePersistence.isSnapshotEmpty(snapshot);
}
@Override
public Serializable disassemble(CollectionPersister persister)
throws HibernateException {
return this.>getRootData().basePersistence.disassemble(persister);
}
@Override
public boolean needsRecreate(CollectionPersister persister) {
return this.>getRootData().basePersistence.needsRecreate(persister);
}
@Override
public Serializable getSnapshot(CollectionPersister persister)
throws HibernateException {
return this.>getRootData().basePersistence.getSnapshot(persister);
}
@Override
public void forceInitialization() throws HibernateException {
this.>getRootData().basePersistence.forceInitialization();
}
@Override
public boolean entryExists(Object entry, int i) {
return this.>getRootData().basePersistence.entryExists(entry, i);
}
@Override
public boolean needsInserting(Object entry, int i, Type elemType)
throws HibernateException {
return this.>getRootData().basePersistence.needsInserting(entry, i, elemType);
}
@Override
public boolean needsUpdating(Object entry, int i, Type elemType)
throws HibernateException {
return this.>getRootData().basePersistence.needsUpdating(entry, i, elemType);
}
@Override
public boolean isRowUpdatePossible() {
return this.>getRootData().basePersistence.isRowUpdatePossible();
}
@Override
public boolean isWrapper(Object collection) {
return this.>getRootData().basePersistence.isWrapper(collection);
}
@Override
public boolean wasInitialized() {
return this.>getRootData().basePersistence.wasInitialized();
}
@Override
public boolean hasQueuedOperations() {
return this.>getRootData().basePersistence.hasQueuedOperations();
}
@Override
public Serializable getKey() {
return this.>getRootData().basePersistence.getKey();
}
@Override
public String getRole() {
return this.>getRootData().basePersistence.getRole();
}
@Override
public String getNonNullRole() {
return this.>getRootData().basePersistence.getNonNullRole();
}
@Override
public boolean isUnreferenced() {
return this.>getRootData().basePersistence.isUnreferenced();
}
@Override
public boolean isDirty() {
return this.>getRootData().basePersistence.isDirty();
}
@Override
public void clearDirty() {
this.>getRootData().basePersistence.clearDirty();
}
@Override
public Serializable getStoredSnapshot() {
return this.>getRootData().basePersistence.getStoredSnapshot();
}
@Override
public void dirty() {
this.>getRootData().basePersistence.dirty();
}
@Override
public void preInsert(CollectionPersister persister)
throws HibernateException {
this.>getRootData().basePersistence.preInsert(persister);
}
@Override
public void afterRowInsert(CollectionPersister persister, Object entry,
int i) throws HibernateException {
this.>getRootData().basePersistence.afterRowInsert(persister, entry, i);
}
private void writeObject(ObjectOutputStream out) throws IOException {
this.writeState(out);
}
private void readObject(ObjectInputStream in) throws ClassNotFoundException, IOException {
this.readState(in);
}
protected static class RootData extends AbstractLazyMAOrderedSet.RootData {
private static final long serialVersionUID = 2878573738768806181L;
private boolean loaded;
private SetBasePersistence basePersistence;
private transient boolean loading;
private transient SessionImplementor session;
private transient JPAAssociationProperty jpaAssociationProperty;
private transient boolean directlyAccessible;
public RootData() {
}
protected void onInitialize() {
this.basePersistence = new SetBasePersistence() {
private static final long serialVersionUID = 8607658837550099941L;
@Override
public void forceInitialization() throws HibernateException {
RootData.this.load();
}
@Override
protected void setBase(MASet base) {
RootData.this.setBase((MAOrderedSet)base);
}
@Override
protected MAOrderedSet getBase() {
return RootData.this.getBase();
}
@Override
protected UnifiedComparator super E> unifiedComparator() {
return RootData.this.unifiedComparator();
}
@Override
public boolean hasQueuedOperations() {
return RootData.this.hasQueuedOperations();
}
@Override
protected XMap getQueuedOperations() {
return RootData.this.getQueuedOperations();
}
@Override
protected void performQueuedOperations() {
RootData.this.performQueuedOperations();
}
@Override
protected PersistentCollection onGetWrapperPersistentCollection() {
return RootData.this.>getRootWrapper();
}
@Override
public boolean isDirectlyAccessible() {
return RootData.this.directlyAccessible;
}
@Override
public boolean wasInitialized() {
return RootData.this.loaded;
}
@Override
protected void setInitialized(boolean initialized) {
RootData.this.loaded = initialized;
}
@Override
protected void setInitializing(boolean initializing) {
RootData.this.loading = initializing;
}
@Override
protected SessionImplementor getSession() {
return RootData.this.session;
}
@Override
protected void setSession(SessionImplementor session) {
RootData.this.session = session;
}
};
}
public final SetBasePersistence getBasePersistence() {
return this.basePersistence;
}
public final JPAAssociationProperty getJPAAssociationProperty() {
JPAAssociationProperty jpaAssociationProperty = this.jpaAssociationProperty;
if (jpaAssociationProperty == null) {
String role = this.basePersistence.getNonNullRole();
this.jpaAssociationProperty = jpaAssociationProperty = HibernateMetadatas.ofRole(role);
}
return jpaAssociationProperty;
}
@Override
public final boolean isLoaded() {
return this.loaded;
}
@Override
public final boolean isLoading() {
return this.loading;
}
@Override
public final boolean isLoadable() {
return this.basePersistence.isConnectedToSession();
}
@Override
protected final void setLoaded(boolean loaded) {
this.loaded = loaded;
}
@Override
protected final void setLoading(boolean loading) {
this.loading = loading;
}
protected final void setDirectlyAccessible() {
MAOrderedSet base = this.getBase(true);
if (base != null) {
this.directlyAccessible = true;
this.loading = false;
this.loaded = true;
}
}
@Override
protected void onLoad() {
SessionImplementor session = this.session;
if (session==null) {
throw new LazyInitializationException(
LAZY_COMMON_RESOURCE.get().rootTypeRetainNoSession(this.getClass(), SessionImplementor.class)
);
}
if (!session.isConnected()) {
throw new LazyInitializationException(
LAZY_COMMON_RESOURCE.get().rootTypeRetainDisconnectedSession(this.getClass(), SessionImplementor.class)
);
}
session.initializeCollection(this.>getRootWrapper(), false);
}
@SuppressWarnings("unchecked")
@Override
protected UnifiedComparator super E> getDefaultUnifiedComparator() {
return this.basePersistence.getRole() == null ?
null :
(UnifiedComparator super E>)
this.getJPAAssociationProperty().getCollectionUnifiedComparator();
}
@Override
protected boolean onGetVisionallyReadable(QueuedOperationType nullOrOperationType) {
if (nullOrOperationType != null) {
return this.jpaAssociationProperty.isInverse();
}
return super.onGetVisionallyReadable(nullOrOperationType);
}
@Override
protected int onGetVisionalSize() {
SessionImplementor session = this.session;
CollectionEntry ce =
session
.getPersistenceContext()
.getCollectionEntry(this.>getRootWrapper());
CollectionPersister persister = ce.getLoadedPersister();
if (!persister.isInverse()) {
return -1;
}
if (session != null && this.hasQueuedOperations()) {
session.flush();
}
return persister.getSize(ce.getLoadedKey(), session);
}
@Override
protected Ref onVisionallyRead(E element, QueuedOperationType nullOrQueuedOperationType) {
if (nullOrQueuedOperationType != null) {
AssociatedEndpoint, E> endpoint =
this
.>getRootWrapper()
.getWrapperEndpoint();
if (endpoint != null) {
AssociatedEndpoint, ?> oppositeEndpoint = endpoint.getOppositeEndpoint(element);
if (oppositeEndpoint.isSuspended()) {
LOGGER.info(
"The visioanllyRead(" +
QueuedOperationType.class.getSimpleName() +
'.' +
nullOrQueuedOperationType.name() +
") of the collection whose role is \"" +
this.>getRootWrapper().getRole() +
"\" return a dummy value immediately without the real data checking " +
"because the opposite endpoint wrapper is supspended(" +
"the current endpoint is not modified by the programer).");
return new DummyReadingResultRef(nullOrQueuedOperationType == QueuedOperationType.ATTACH ? null : element);
}
}
}
SessionImplementor session = this.session;
if (session != null && this.hasQueuedOperations()) {
session.flush();
}
return this.basePersistence.visionallyRead(element);
}
@Override
protected LazyBehaviorProcessor createLazyBehaviorProcessor() {
LazyBehavior lazyBehavior = this.getJPAAssociationProperty().getLazyBehavior();
if (lazyBehavior == null) {
return LazyBehaviorProcessor.of(16, 2);
}
return LazyBehaviorProcessor.of(lazyBehavior.rowLimit(), lazyBehavior.countLimit());
}
}
}