org.hibernate.collection.PersistentIdentifierBag Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of hibernate Show documentation
Show all versions of hibernate Show documentation
Relational Persistence for Java
//$Id: PersistentIdentifierBag.java 10739 2006-11-06 22:00:41Z [email protected] $
package org.hibernate.collection;
import java.io.Serializable;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import org.hibernate.EntityMode;
import org.hibernate.HibernateException;
import org.hibernate.loader.CollectionAliases;
import org.hibernate.engine.SessionImplementor;
import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.type.Type;
/**
* An IdentifierBag implements "bag" semantics more efficiently than
* a regular Bag by adding a synthetic identifier column to the
* table. This identifier is unique for all rows in the table, allowing very
* efficient updates and deletes. The value of the identifier is never exposed
* to the application.
*
* IdentifierBags may not be used for a many-to-one association.
* Furthermore, there is no reason to use inverse="true".
*
* @author Gavin King
*/
public class PersistentIdentifierBag extends AbstractPersistentCollection implements List {
protected List values; //element
protected Map identifiers; //index -> id
public PersistentIdentifierBag(SessionImplementor session) {
super(session);
}
public PersistentIdentifierBag() {} //needed for SOAP libraries, etc
public PersistentIdentifierBag(SessionImplementor session, Collection coll) {
super(session);
if (coll instanceof List) {
values = (List) coll;
}
else {
values = new ArrayList();
Iterator iter = coll.iterator();
while ( iter.hasNext() ) {
values.add( iter.next() );
}
}
setInitialized();
setDirectlyAccessible(true);
identifiers = new HashMap();
}
public void initializeFromCache(CollectionPersister persister, Serializable disassembled, Object owner)
throws HibernateException {
Serializable[] array = (Serializable[]) disassembled;
int size = array.length;
beforeInitialize( persister, size );
for ( int i = 0; i < size; i+=2 ) {
identifiers.put(
new Integer(i/2),
persister.getIdentifierType().assemble( array[i], getSession(), owner )
);
values.add( persister.getElementType().assemble( array[i+1], getSession(), owner ) );
}
}
public Object getIdentifier(Object entry, int i) {
return identifiers.get( new Integer(i) );
}
public boolean isWrapper(Object collection) {
return values==collection;
}
public boolean add(Object o) {
write();
values.add(o);
return true;
}
public void clear() {
initialize( true );
if ( ! values.isEmpty() || ! identifiers.isEmpty() ) {
values.clear();
identifiers.clear();
dirty();
}
}
public boolean contains(Object o) {
read();
return values.contains(o);
}
public boolean containsAll(Collection c) {
read();
return values.containsAll(c);
}
public boolean isEmpty() {
return readSize() ? getCachedSize()==0 : values.isEmpty();
}
public Iterator iterator() {
read();
return new IteratorProxy( values.iterator() );
}
public boolean remove(Object o) {
initialize( true );
int index = values.indexOf(o);
if (index>=0) {
beforeRemove(index);
values.remove(index);
dirty();
return true;
}
else {
return false;
}
}
public boolean removeAll(Collection c) {
if ( c.size() > 0 ) {
boolean result = false;
Iterator iter = c.iterator();
while ( iter.hasNext() ) {
if ( remove( iter.next() ) ) result=true;
}
return result;
}
else {
return false;
}
}
public boolean retainAll(Collection c) {
initialize( true );
if ( values.retainAll( c ) ) {
dirty();
return true;
}
else {
return false;
}
}
public int size() {
return readSize() ? getCachedSize() : values.size();
}
public Object[] toArray() {
read();
return values.toArray();
}
public Object[] toArray(Object[] a) {
read();
return values.toArray(a);
}
public void beforeInitialize(CollectionPersister persister, int anticipatedSize) {
identifiers = anticipatedSize <= 0 ? new HashMap() : new HashMap( anticipatedSize + 1 + (int)( anticipatedSize * .75f ), .75f );
values = anticipatedSize <= 0 ? new ArrayList() : new ArrayList( anticipatedSize );
}
public Serializable disassemble(CollectionPersister persister)
throws HibernateException {
Serializable[] result = new Serializable[ values.size() * 2 ];
int i=0;
for (int j=0; j< values.size(); j++) {
Object value = values.get(j);
result[i++] = persister.getIdentifierType().disassemble( identifiers.get( new Integer(j) ), getSession(), null );
result[i++] = persister.getElementType().disassemble( value, getSession(), null );
}
return result;
}
public boolean empty() {
return values.isEmpty();
}
public Iterator entries(CollectionPersister persister) {
return values.iterator();
}
public boolean entryExists(Object entry, int i) {
return entry!=null;
}
public boolean equalsSnapshot(CollectionPersister persister) throws HibernateException {
Type elementType = persister.getElementType();
Map snap = (Map) getSnapshot();
if ( snap.size()!= values.size() ) return false;
for ( int i=0; i 0 ) {
Iterator iter = c.iterator();
while ( iter.hasNext() ) {
add( index++, iter.next() );
}
return true;
}
else {
return false;
}
}
public Object get(int index) {
read();
return values.get(index);
}
public int indexOf(Object o) {
read();
return values.indexOf(o);
}
public int lastIndexOf(Object o) {
read();
return values.lastIndexOf(o);
}
public ListIterator listIterator() {
read();
return new ListIteratorProxy( values.listIterator() );
}
public ListIterator listIterator(int index) {
read();
return new ListIteratorProxy( values.listIterator(index) );
}
private void beforeRemove(int index) {
Object removedId = identifiers.get( new Integer(index) );
int last = values.size()-1;
for ( int i=index; i 0 ) {
write();
return values.addAll(c);
}
else {
return false;
}
}
public void afterRowInsert(
CollectionPersister persister,
Object entry,
int i)
throws HibernateException {
//TODO: if we are using identity columns, fetch the identifier
}
}