views:

122

answers:

1

Given an entity with a list of components:

class Entity{
    Long id;
    String name;
    List<Component> components = new ArrayList<Component>();
}
class Component{ Object value; }

Configuration:

<hibernate-mapping>
    <class name="Entity" table="entity">
        <id name="id" access="field" column="id"/>
        <property name="name" access="field" unique="true"/>

        <list name="components" access="field" table="COMPONENTS" lazy="true">
            <key column="id"/>
            <list-index column="idx"/>
            <composite-element class="Component">
                <property name="value" access="field"/>
            </composite-element>
        </list>
    </class>
</hibernate-mapping>

Is it possible to update one component from the list with HQL statement like

update Entity e set e.components[:index].value = :value where e.name = :name

that does not work?

Alternatively, is it possible to configure lazy loading of the list of components in a way that the first access:

entity.components.get(0).value = "..";

does not load the whole list?

Edit: The lazy="extra" configuration does work for select (loads only the component to update), but it will not update the changed component.

+1  A: 

You can't update a single collection element via HQL.

From the 13.4. DML-style operations chapter:

  • There can only be a single entity named in the from-clause.
  • No joins, either implicit or explicit, can be specified in a bulk HQL query.

Since your collection element is not an entity, it's not addressable from within bulk update. Technically speaking, non-entity collection elements are not addressable in general; indexed collections or sets with elements having natural ids being the only exceptions.

While it is possible to lazy-load collection elements few at a time (though it doesn't really make sense in this case unless you know ahead of time that you'll only be looking at Nth element since batch size is not easily changeable at runtime), it's not going to help because entire collection will be loaded anyway when you try to update it.

Selecting a single collection element is possible for indexed collection (not part of your question, but I wanted to clarify on this based on KLE answer and your comments):

select c
  from Entity e join e.components c
 where index(c) = :index
ChssPly76