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

时间:2012-05-24 14:46:53

标签: hibernate hibernate-annotations

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

这是该实体的相关部分。

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>();

    ...
}

异常

Caused by: org.hibernate.MappingException: Repeated column in mapping for entity: com.casenet.domain.configuration.screen.OptionValue column: option_value_set_id (should be mapped with insert="false" update="false")
    at org.hibernate.mapping.PersistentClass.checkColumnDuplication(PersistentClass.java:670)
    at org.hibernate.mapping.PersistentClass.checkPropertyColumnDuplication(PersistentClass.java:692)
    at org.hibernate.mapping.PersistentClass.checkColumnDuplication(PersistentClass.java:714)
    at org.hibernate.mapping.PersistentClass.validate(PersistentClass.java:468)
    at org.hibernate.mapping.RootClass.validate(RootClass.java:215)
    at org.hibernate.cfg.Configuration.validate(Configuration.java:1135)
    at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1320)
    at org.hibernate.cfg.AnnotationConfiguration.buildSessionFactory(AnnotationConfiguration.java:867)
    at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:669)
    ... 137 more

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

2 个答案:

答案 0 :(得分: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;
}

答案 1 :(得分:0)

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

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