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