0

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

这是实体的相关部分。

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 注释会干扰缓存。我必须在不更改底层数据库架构的情况下解决这个问题。我们在发布周期中为时已晚,无法做任何更激进的事情。

4

2 回答 2

1

Since those collections are eagerly fetched anyway, why don't you simply add a getOptions() method that returns a filtered view (or copy) of 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;
}
于 2012-05-24T15:22:59.200 回答
0

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

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

于 2012-05-24T15:33:25.453 回答