org.babyfish.hibernate.collection.spi.persistence.AbstractBasePersistence 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.spi.persistence;
import java.io.Serializable;
import java.util.Collection;
import java.util.Map;
import java.util.Set;
import org.babyfish.collection.ArrayList;
import org.babyfish.collection.HashSet;
import org.babyfish.collection.ReferenceEqualityComparator;
import org.babyfish.collection.XCollection;
import org.babyfish.hibernate.collection.spi.PersistentCollection;
import org.babyfish.lang.Arguments;
import org.babyfish.lang.IllegalProgramException;
import org.babyfish.util.LazyResource;
import org.hibernate.HibernateException;
import org.hibernate.engine.internal.ForeignKeys;
import org.hibernate.engine.spi.CollectionEntry;
import org.hibernate.engine.spi.EntityEntry;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.engine.spi.Status;
import org.hibernate.engine.spi.TypedValue;
import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.pretty.MessageHelper;
import org.hibernate.type.Type;
/**
* @author Tao Chen
*/
public abstract class AbstractBasePersistence implements PersistentCollection {
private static final long serialVersionUID = 5060512525878325032L;
private static final LazyResource LAZY_RESOURCE = LazyResource.of(Resource.class);
private Object owner;
private Serializable key;
private String role;
private Serializable storedSnapshot;
private boolean dirty;
AbstractBasePersistence() {
if (this instanceof Collection> || this instanceof Map, ?>) {
throw new IllegalProgramException(
"BasePersistence can not be collection");
}
}
protected final void setInitialized() {
this.setInitializing(false);
this.setInitialized(true);
}
protected abstract void setInitialized(boolean initialized);
protected abstract void setInitializing(boolean initializing);
public final boolean isConnectedToSession() {
SessionImplementor session = this.getSession();
return
session != null &&
session.isOpen() &&
session.getPersistenceContext().containsCollection(this.getWrapperPersistentCollection());
}
protected abstract SessionImplementor getSession();
protected abstract void setSession(SessionImplementor session);
@Override
public Object getOwner() {
return this.owner;
}
@Override
public void setOwner(Object owner) {
this.owner = owner;
}
@Override
public boolean unsetSession(SessionImplementor currentSession) {
if (currentSession==this.getSession()) {
this.setSession(null);
return true;
}
else {
return false;
}
}
@Override
public final boolean setCurrentSession(SessionImplementor session)
throws HibernateException {
if (session == this.getSession()) {
return false;
} else {
if (this.isConnectedToSession()) {
CollectionEntry ce = session.getPersistenceContext().getCollectionEntry(this.getWrapperPersistentCollection());
if (ce == null) {
throw new HibernateException(
"Illegal attempt to associate a collection with two open sessions");
}
else {
throw new HibernateException(
"Illegal attempt to associate a collection with two open sessions: " +
MessageHelper.collectionInfoString(
ce.getLoadedPersister(),
ce.getLoadedKey(),
session.getFactory()));
}
}
else {
this.setSession(session);
return true;
}
}
}
@Override
public Serializable getKey() {
return this.key;
}
@Override
public boolean isUnreferenced() {
return this.role == null;
}
@Override
public String getRole() {
return this.role;
}
@Override
public String getNonNullRole() {
String role = this.role;
if (role == null) {
throw new IllegalStateException(LAZY_RESOURCE.get().roleHasNotBeenInitialized(this.getClass()));
}
return role;
}
@Override
public Serializable getStoredSnapshot() {
return this.storedSnapshot;
}
@Override
public void setSnapshot(Serializable key, String role, Serializable snapshot) {
if (this.role != null && role != null && !this.role.equals(role)) {
Arguments.mustBeEqualToOther("role", role, "this.role", this.role);
}
this.key = key;
this.role = role;
this.storedSnapshot = snapshot;
}
protected final Serializable getSnapshot() {
return this.getSession().getPersistenceContext().getSnapshot(this.getWrapperPersistentCollection());
}
@Override
public boolean isDirty() {
return this.dirty;
}
@Override
public void clearDirty() {
this.dirty = false;
}
@Override
public void dirty() {
this.dirty = true;
}
@Override
public void preInsert(CollectionPersister persister)
throws HibernateException {
}
@Override
public void afterRowInsert(CollectionPersister persister, Object entry,int i)
throws HibernateException {
}
@Override
public void postAction() {
this.clearDirty();
}
protected static Collection getOrphans(
XCollection oldElements,
XCollection currentElements,
String entityName,
SessionImplementor session) throws HibernateException {
// short-circuit(s)
if (currentElements.isEmpty()) {
return oldElements; // no new elements, the old list contains only Orphans
}
if ( oldElements.size()==0) {
return oldElements; // no old elements, so no Orphans neither
}
final EntityPersister entityPersister = session.getFactory().getEntityPersister( entityName );
final Type idType = entityPersister.getIdentifierType();
// create the collection holding the Orphans
Collection res = new ArrayList(oldElements.unifiedComparator());
// collect EntityIdentifier(s) of the *current* elements - add them into a HashSet for fast access
Set currentIds = new HashSet();
Set currentSaving = new HashSet(ReferenceEqualityComparator.getInstance());
for (E current : currentElements) {
if (current != null && ForeignKeys.isNotTransient( entityName, current, null, session)) {
EntityEntry ee = session.getPersistenceContext().getEntry( current );
if (ee != null && ee.getStatus() == Status.SAVING) {
currentSaving.add( current );
}
else {
Serializable currentId = ForeignKeys.getEntityIdentifierIfNotUnsaved(
entityName,
current,
session
);
currentIds.add( new TypedValue(idType, currentId));
}
}
}
// iterate over the *old* list
for (E old : oldElements ) {
if ( !currentSaving.contains( old ) ) {
Serializable oldId = ForeignKeys.getEntityIdentifierIfNotUnsaved( entityName, old, session );
if (!currentIds.contains( new TypedValue(idType, oldId))) {
res.add( old );
}
}
}
return res;
}
@Override
public final Object getIdentifier(Object entry, int i) {
throw new UnsupportedOperationException();
}
@Override
public final boolean needsRecreate(CollectionPersister persister) {
return false;
}
@Deprecated
@Override
public final Object getValue() {
throw new UnsupportedOperationException();
}
/*
* Very important point 2:
* Copy the source code from Hibernate
* if Hibernate's source code use "this" to be the arguments of other modules,
* please replace it to this.getWrapper()
*/
protected final PersistentCollection getWrapperPersistentCollection() {
PersistentCollection wrapper = this.onGetWrapperPersistentCollection();
if (wrapper == null) {
throw new IllegalProgramException(
LAZY_RESOURCE.get().methodCanNotReturnNull(
"onGetWrapperPersistentCollection", this.getClass()
)
);
}
if (wrapper == this) {
throw new IllegalProgramException(
LAZY_RESOURCE.get().methodCanNotReturnThis(
"onGetWrapperPersistentCollection", this.getClass()
)
);
}
return wrapper;
}
protected abstract PersistentCollection onGetWrapperPersistentCollection();
private interface Resource {
String methodCanNotReturnNull(String methodName, Class> thisType);
String methodCanNotReturnThis(String methodName, Class> thisType);
String roleHasNotBeenInitialized(Class> thisType);
}
}