Hibernate:如何让两个集合字段指向相同的对象

Posted

技术标签:

【中文标题】Hibernate:如何让两个集合字段指向相同的对象【英文标题】:Hibernate: how to have two collection fields pointing to same objects 【发布时间】:2012-05-24 14:46:53 【问题描述】:

我正在尝试将两个有序集合一对多字段映射到相同的值。这些字段具有不同的过滤要求。因此,一个字段将包含从另一个字段中过滤掉的项目。

这是实体的相关部分。

public class OptionValueSet extends ConfigurationDomainObject 
    ...

    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
    @JoinColumn(name = OPTION_VALUE_SET_ID_COLUMN, nullable = false)
    @IndexColumn(name = "option_index", nullable = false)
    @Where(clause = OBSOLETE_FILTER)
    private final List<OptionValue> allOptions = new java.util.ArrayList<OptionValue>();

    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
    @JoinColumn(name = OPTION_VALUE_SET_ID_COLUMN, nullable = false, insertable = false, updatable = false)
    @IndexColumn(name = "option_index", nullable = false)
    @Where(clause = OBSOLETE_FILTER + " AND disabled = '0'")
    @Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
    @Immutable
    private final List<OptionValue> options = new java.util.ArrayList<OptionValue>();

    ...

还有例外

原因:org.hibernate.MappingException:实体映射中的重复列:com.casenet.domain.configuration.screen.OptionValue 列:option_value_set_id(应使用 insert="false" update="false" 映射) 在 org.hibernate.mapping.PersistentClass.checkColumnDuplication(PersistentClass.java:670) 在 org.hibernate.mapping.PersistentClass.checkPropertyColumnDuplication(PersistentClass.java:692) 在 org.hibernate.mapping.PersistentClass.checkColumnDuplication(PersistentClass.java:714) 在 org.hibernate.mapping.PersistentClass.validate(PersistentClass.java:468) 在 org.hibernate.mapping.RootClass.validate(RootClass.java:215) 在 org.hibernate.cfg.Configuration.validate(Configuration.java:1135) 在 org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1320) 在 org.hibernate.cfg.AnnotationConfiguration.buildSessionFactory(AnnotationConfiguration.java:867) 在 org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:669) ... 137 更多

出于好奇,我正在解开两个使用相同休眠字段的用例。目前,过滤器在一个中打开以隐藏禁用的选项值,在另一个中打开以编辑它们。但是,@Filter 注释会干扰缓存。我必须在不更改底层数据库架构的情况下解决这个问题。我们在发布周期中为时已晚,无法做任何更激进的事情。

【问题讨论】:

【参考方案1】:

既然这些集合无论如何都被急切地获取,为什么不简单地添加一个 getOptions() 方法来返回allOptions 的过滤视图(或副本)?

public List<OptionValue> getOptions() 
    List<OptionValue> result = new ArrayList<OptionValue>(allOptions.size());
    for (OptionValue o : allOptions) 
        if (!o.isDisabled()) 
            result.add(o);
        
    
    return result;

【讨论】:

我遇到了一个类似的问题,我正在尝试创建三个单独的列表,每个列表在 Spring Hibernate 应用程序中具有相同对象类型的不同过滤器。你有一点时间帮我找出解决方案吗?问题出在这个链接:***.com/questions/20292152/…【参考方案2】:

在 hibernate 的概念中,您已经两次映射了同一个字段(在这种情况下是一个子列表;如果您将一个简单的属性映射两次,您将得到相同的错误消息)。 Hibernate 无法处理它,因为在更新或插入之后状态可能无效(如果两次映射的对象在 Java 代码中获得不同的更新值,hibernate 应该做什么?)。

如果两个字段之一仅用于读取,您可以映射一个字段两次。对于简单属性,错误消息已经告诉您如何操作 (insert="false" update="false")。对于您的子列表,您可能还必须将cascade 设置为none 作为只读属性。

【讨论】:

以上是关于Hibernate:如何让两个集合字段指向相同的对象的主要内容,如果未能解决你的问题,请参考以下文章

如何避免两个不同的线程从DB中读取相同的行(Hibernate和Oracle 10g)

如何在同一个数据库表上映射两个 JPA 或 Hibernate 实体

Hibernate CriteriaBuilder - 如何匹配具有相同字段的所有元素,其中 id 相同

是否将Lazily提取的对象附加到Hibernate会话(由Hibernate支持的Spring Data)?

hibernate用HQL查询集合属性

Hibernate映射