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

标签 java hibernate hql lazy-loading

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

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(仅加载要更新的组件),但它不会更新已更改的组件。

最佳答案

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

来自13.4. DML-style operations chapter :

  • 在 from 子句中只能有一个实体命名。
  • 不能在批量 HQL 查询中指定任何连接,无论是隐式连接还是显式连接。

由于您的集合元素不是实体,因此无法从批量更新中对其进行寻址。从技术上讲,非实体集合元素一般是不可寻址的;具有自然 ID 的元素的索引集合或集合是唯一的异常(exception)。

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

选择单个集合元素 is possible for indexed collection (不是你问题的一部分,但我想根据 KLE 的回答和你的评论对此进行澄清):

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

关于java - 从依赖对象列表中更新一个值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1886925/

相关文章:

java - 如何使用@PersistenceContext 注解的 `properties` 属性?

java - Hibernate hql 查询与 sum() 函数一起使用返回空值

java - HQL 查询抛出 ExecutionException

java - SQL try catch 永远无法捕获(实现超时?)

java - 为什么在比较 Java 中的整数包装器时 128==128 为假但 127==127 为真?

java - 如何用java中的接口(interface)覆盖方法

java - 如何在 Hibernate HQL 中使用 Oracle 的 regexp_like?

java - 将 JLabel 大小/间隙设置为 JCheckBox

java - 错误 : No suitable driver found for jdbc:mysql://localhost:3306/test

java - sqlite 打开数据库 : './sqlite.db' : permission denied