[
http://opensource.atlassian.com/projects/hibernate/browse/HHH-2344?page=c...
]
Sebastian Gooren commented on HHH-2344:
---------------------------------------
I have the same issue on Hibernate 3.2.6GA;
What seems to be happening is this:
- I call remove() on an uninitialized collection
- persistentMap.remove() calls readElementByIndex(), which loads the collection
- persistentMap.remove() then stores the remove action in the operations queue
- the queue is never executed?
This is a normal use-case for me, and I still don't get why I should be required to
call size() (or any other function which initializes the collection) to be able to delete
an item from a persistent collection.
Entities:
- Product:
@Entity
@Table( name = "products" )
public class Product
{
@OneToMany( mappedBy = "pk.product", fetch = FetchType.LAZY, cascade = {
CascadeType.ALL } )
@MapKey( name = "pk.locale" )
@OnDelete( action = OnDeleteAction.CASCADE )
@Cascade( { org.hibernate.annotations.CascadeType.DELETE_ORPHAN } )
@Fetch( FetchMode.SUBSELECT )
private Map<Locale, ProductI18n> localizations = new HashMap<Locale,
ProductI18n>();
public Map<Locale, ProductI18n> getLocalizations()
{
return localizations;
}
}
- ProductI18n:
@Entity
@Table( name = "products_i18n" )
public class ProductI18n
{
@EmbeddedId
private Pkey pk = new Pkey();
private String name;
@Lob
private String description;
protected ProductI18n()
{
}
public ProductI18n( final Product product, final Locale locale )
{
this.pk.product = product;
this.pk.locale = locale;
}
public String getName()
{
return name;
}
public void setName( String name )
{
this.name = name;
}
public String getDescription()
{
return description;
}
public void setDescription( String description )
{
this.description = description;
}
public Product getProduct()
{
return pk.product;
}
public Locale getLocale()
{
return pk.locale;
}
@Embeddable
private static class Pkey implements Serializable
{
@Transient
private static final long serialVersionUID = 1L;
@ManyToOne( optional = false )
@JoinColumn( name = "productid" )
@NotNull
private Product product;
@NotNull
private Locale locale;
@Override
public boolean equals( Object obj )
{
if (obj instanceof Pkey)
{
Pkey other = (Pkey) obj;
return other.product.equals( product ) && other.locale.equals( locale );
}
return false;
}
@Override
public int hashCode()
{
return super.hashCode();
}
}
}
Code:
class Testcase
{
public void setup()
{
Session session = ...
Product p = new Product();
List<ProductI18n> localizations = p.getLocalizations();
ProductI18n en_US = new ProductI18n( p, new Locale("en", "US") );
en_US.setName( "product 1" );
en_US.setDescription( "This is product1" );
localizations.put( en_US.getLocale(), en_US );
ProductI18n nl_NL = new ProductI18n( p, new Locale("nl", "NL") );
nl_NL.setName( "product 1" );
nl_NL.setDescription( "Dit is product 1" );
localizations.put( nl_NL.getLocale(), nl_NL );
session.persist( p );
session.flush();
}
public void test()
{
Session session = ...;
List<Product> products = session.createQuery( "from Product" ).list();
for( Product p : products )
{
p.getLocalizations().remove( new Locale( "nl", "NL" ) );
session.persist( p );
session.flush();
// getLocalizations().size() is still 2, both locally and in the database
}
}
}
Persistent collection queued operation ignored with lazy inverse
one-to-many collection.
----------------------------------------------------------------------------------------
Key: HHH-2344
URL:
http://opensource.atlassian.com/projects/hibernate/browse/HHH-2344
Project: Hibernate Core
Issue Type: Bug
Components: core
Affects Versions: 3.2.1
Environment: Hibernate 3.2.1
Reporter: Sebastien Robert
I load an Object that contains a lazy inverse collection (one-to-many).
Hibernate wrap my collection with a PersistentMap
There is objects in the collection in the database but in my case the PersistentMap is
not yet initialized.
I perform a remove operation on the persistentMap with a known key of one of the
objects.
The map is not initialized (and the relation is an inverse one-to-many) so the map queue
the removeOperation.
I perform a get operation with the same key and the value is still returned.
If we look closer at what happened in the PersistentMap, it's look like this.
//*****
public Object remove(Object key) {
if ( isPutQueueEnabled() ) { // This returned true, the
// map
is not yet
//
initialized
Object old = readElementByIndex( key ); // This method triggered
// an
initialization of the
//
map.
//
Queued operation are
//
processed in the after
//
init method
queueOperation( new Remove( key, old ) ); // The remove operation
//
is queued.
return old;
}
....
//*******
When i perform the get operation on the map the map is now initialized. The get is
processed by the underlying map and the value is returned. The queued operation is
completely ignored.
Currently i fixed my code by performing a containsKey before the remove . The containsKey
initialize the map and then the remove do not queue the operation. But by looking at all
the PersistentCollection it seem that i may have the same problem using put and remove
with other persistentCollection.
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators:
http://opensource.atlassian.com/projects/hibernate/secure/Administrators....
-
For more information on JIRA, see:
http://www.atlassian.com/software/jira