代码之家  ›  专栏  ›  技术社区  ›  Thomas Jung

从依赖对象列表中更新一个值

  •  3
  • Thomas Jung  · 技术社区  · 15 年前

    给定一个包含组件列表的实体:

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

    配置:

    <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>
    

    是否可以使用hql语句更新列表中的一个组件,如

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

    那不管用?

    或者,是否可以通过第一次访问的方式配置组件列表的延迟加载:

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

    不加载整个列表?

    编辑: 这个 lazy="extra" 配置确实适用于select(仅加载要更新的组件),但它不会更新已更改的组件。

    1 回复  |  直到 15 年前
        1
  •  1
  •   ChssPly76    15 年前

    不能通过hql更新单个集合元素。

    13.4. DML-style operations chapter :

    • 在FROM子句中只能有一个名为的实体。
    • 不能在批量HQL查询中指定隐式或显式联接。

    由于集合元素不是实体,因此无法从批量更新中对其进行寻址。从技术上讲,一般来说,非实体集合元素是不可寻址的;索引集合或集合中只有具有自然ID的元素是例外。

    虽然有可能 lazy-load collection elements few at a time (尽管在这种情况下,它并没有真正意义,除非您提前知道您将只查看第n个元素,因为批大小在运行时不容易更改),但它不会有帮助,因为当您尝试更新它时,仍然会加载整个集合。

    选择单个集合元素 is possible for indexed collection (不是你问题的一部分,但我想根据克莱的回答和你的评论来澄清这一点):

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