📄 collectiontype.java
字号:
// $Id: CollectionType.java 9562 2006-03-07 14:24:13Z steve.ebersole@jboss.com $
package org.hibernate.type;
import java.io.Serializable;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.dom4j.Element;
import org.dom4j.Node;
import org.hibernate.EntityMode;
import org.hibernate.Hibernate;
import org.hibernate.HibernateException;
import org.hibernate.MappingException;
import org.hibernate.collection.PersistentCollection;
import org.hibernate.engine.CollectionKey;
import org.hibernate.engine.EntityEntry;
import org.hibernate.engine.Mapping;
import org.hibernate.engine.PersistenceContext;
import org.hibernate.engine.SessionFactoryImplementor;
import org.hibernate.engine.SessionImplementor;
import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.persister.collection.QueryableCollection;
import org.hibernate.persister.entity.Joinable;
import org.hibernate.proxy.HibernateProxy;
import org.hibernate.proxy.LazyInitializer;
import org.hibernate.util.ArrayHelper;
import org.hibernate.util.MarkerObject;
/**
* A type that handles Hibernate <tt>PersistentCollection</tt>s (including arrays).
*
* @author Gavin King
*/
public abstract class CollectionType extends AbstractType implements AssociationType {
private static final Object NOT_NULL_COLLECTION = new MarkerObject( "NOT NULL COLLECTION" );
public static final Object UNFETCHED_COLLECTION = new MarkerObject( "UNFETCHED COLLECTION" );
private final String role;
private final String foreignKeyPropertyName;
private final boolean isEmbeddedInXML;
public CollectionType(String role, String foreignKeyPropertyName, boolean isEmbeddedInXML) {
this.role = role;
this.foreignKeyPropertyName = foreignKeyPropertyName;
this.isEmbeddedInXML = isEmbeddedInXML;
}
public boolean isEmbeddedInXML() {
return isEmbeddedInXML;
}
public String getRole() {
return role;
}
public Object indexOf(Object collection, Object element) {
throw new UnsupportedOperationException( "generic collections don't have indexes" );
}
public boolean contains(Object collection, Object childObject, SessionImplementor session) {
// we do not have to worry about queued additions to uninitialized
// collections, since they can only occur for inverse collections!
Iterator elems = getElementsIterator( collection, session );
while ( elems.hasNext() ) {
Object element = elems.next();
// worrying about proxies is perhaps a little bit of overkill here...
if ( element instanceof HibernateProxy ) {
LazyInitializer li = ( (HibernateProxy) element ).getHibernateLazyInitializer();
if ( !li.isUninitialized() ) element = li.getImplementation();
}
if ( element == childObject ) return true;
}
return false;
}
public boolean isCollectionType() {
return true;
}
public final boolean isEqual(Object x, Object y, EntityMode entityMode) {
return x == y
|| ( x instanceof PersistentCollection && ( (PersistentCollection) x ).isWrapper( y ) )
|| ( y instanceof PersistentCollection && ( (PersistentCollection) y ).isWrapper( x ) );
}
public int compare(Object x, Object y, EntityMode entityMode) {
return 0; // collections cannot be compared
}
public int getHashCode(Object x, EntityMode entityMode) {
throw new UnsupportedOperationException( "cannot perform lookups on collections" );
}
/**
* Instantiate an uninitialized collection wrapper or holder. Callers MUST add the holder to the
* persistence context!
*/
public abstract PersistentCollection instantiate(SessionImplementor session,
CollectionPersister persister, Serializable key) throws HibernateException;
public Object nullSafeGet(ResultSet rs, String name, SessionImplementor session, Object owner)
throws HibernateException, SQLException {
return nullSafeGet( rs, new String[] { name }, session, owner );
}
public Object nullSafeGet(ResultSet rs, String[] name, SessionImplementor session, Object owner)
throws HibernateException, SQLException {
return resolve( null, session, owner );
}
public final void nullSafeSet(PreparedStatement st, Object value, int index, boolean[] settable,
SessionImplementor session) throws HibernateException, SQLException {
//NOOP
}
public void nullSafeSet(PreparedStatement st, Object value, int index,
SessionImplementor session) throws HibernateException, SQLException {
}
public int[] sqlTypes(Mapping session) throws MappingException {
return ArrayHelper.EMPTY_INT_ARRAY;
}
public int getColumnSpan(Mapping session) throws MappingException {
return 0;
}
public String toLoggableString(Object value, SessionFactoryImplementor factory)
throws HibernateException {
if ( value == null ) return "null";
if ( Hibernate.isInitialized( value ) ) {
if ( getReturnedClass().isInstance(value) ) {
List list = new ArrayList();
Type elemType = getElementType( factory );
Iterator iter = getElementsIterator( value );
while ( iter.hasNext() ) {
list.add( elemType.toLoggableString( iter.next(), factory ) );
}
return list.toString();
}
else {
// for DOM4J "collections" only
return ( (Element) value ).asXML(); //TODO: it would be better if this was done at the higher level by Printer
}
}
else {
return "<uninitialized>";
}
}
public Object deepCopy(Object value, EntityMode entityMode, SessionFactoryImplementor factory)
throws HibernateException {
return value;
}
public String getName() {
return getReturnedClass().getName() + '(' + getRole() + ')';
}
/**
* Get an iterator over the element set of the collection, which may not yet be wrapped
*/
public Iterator getElementsIterator(Object collection, SessionImplementor session) {
if ( session.getEntityMode()==EntityMode.DOM4J ) {
final SessionFactoryImplementor factory = session.getFactory();
final CollectionPersister persister = factory.getCollectionPersister( getRole() );
final Type elementType = persister.getElementType();
List elements = ( (Element) collection ).elements( persister.getElementNodeName() );
ArrayList results = new ArrayList();
for ( int i=0; i<elements.size(); i++ ) {
Element value = (Element) elements.get(i);
results.add( elementType.fromXMLNode( value, factory ) );
}
return results.iterator();
}
else {
return getElementsIterator(collection);
}
}
/**
* Get an iterator over the element set of the collection in POJO mode
*/
protected Iterator getElementsIterator(Object collection) {
return ( (Collection) collection ).iterator();
}
public boolean isMutable() {
return false;
}
public Serializable disassemble(Object value, SessionImplementor session, Object owner)
throws HibernateException {
//remember the uk value
//This solution would allow us to eliminate the owner arg to disassemble(), but
//what if the collection was null, and then later had elements added? seems unsafe
//session.getPersistenceContext().getCollectionEntry( (PersistentCollection) value ).getKey();
final Serializable key = getKeyOfOwner(owner, session);
if (key==null) {
return null;
}
else {
return getPersister(session)
.getKeyType()
.disassemble( key, session, owner );
}
}
public Object assemble(Serializable cached, SessionImplementor session, Object owner)
throws HibernateException {
//we must use the "remembered" uk value, since it is
//not available from the EntityEntry during assembly
if (cached==null) {
return null;
}
else {
final Serializable key = (Serializable) getPersister(session)
.getKeyType()
.assemble( cached, session, owner);
return resolveKey( key, session, owner );
}
}
/**
* Is the owning entity versioned?
*/
private boolean isOwnerVersioned(SessionImplementor session) throws MappingException {
return getPersister( session )
.getOwnerEntityPersister()
.isVersioned();
}
private CollectionPersister getPersister(SessionImplementor session) {
return session.getFactory()
.getCollectionPersister( role );
}
public boolean isDirty(Object old, Object current, SessionImplementor session)
throws HibernateException {
// collections don't dirty an unversioned parent entity
// TODO: I don't really like this implementation; it would be better if
// this was handled by searchForDirtyCollections()
return isOwnerVersioned( session ) && super.isDirty( old, current, session );
// return false;
}
public boolean isDirty(Object old, Object current, boolean[] checkable, SessionImplementor session)
throws HibernateException {
return isDirty(old, current, session);
}
/**
* Wrap the naked collection instance in a wrapper, or instantiate a holder. Callers MUST add
* the holder to the persistence context!
*/
public abstract PersistentCollection wrap(SessionImplementor session, Object collection);
/**
* Note: return true because this type is castable to <tt>AssociationType</tt>. Not because
* all collections are associations.
*/
public boolean isAssociationType() {
return true;
}
public ForeignKeyDirection getForeignKeyDirection() {
return ForeignKeyDirection.FOREIGN_KEY_TO_PARENT;
}
/**
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -