![](/img/trans.png)
[英]why One-To-Many association cannot be Bidirectional and it should just be Unidirectional?
[英]Hibernate One-To-Many Unidirectional on an existing DB
您好Stack Overflow专家,我需要您的专业知识:
我正在尝试在现有数据库上使用休眠模式。 当前,我正在尝试加载一个User对象和一个UserData对象列表。
在数据库中,(简化的)布局是
| User | | UserData |
---------------- -----------------------------------
uid | username | | uid | parentuid | field | value |
因此,每个User对象都与其中UserData.parentuid = User.uid的所有UserData对象匹配。
我的用户类映射文件
<class name="com.agetor.commons.security.User" table="ac_users">
<id name="uid" column="uid" type="long" >
<!--<generator class="native"/>-->
</id>
<property name="username" column="username" />
<list name="fieldData" cascade="all">
<key column="parentuid" not-null="true" />
<index column="parentuid" />
<one-to-many class="com.agetor.commons.fields.FieldData"/>
</list>
</class>
Mu UserData映射文件
<class name="com.agetor.commons.fields.FieldData" table="ac_userdef_data">
<id name="uid" column="uid" type="long" >
<!--<generator class="native"/> -->
</id>
<!--<property name="parentuid" column="parentuid" /> -->
<property name="fieldname" column="fieldname" />
<property name="value" column="value" />
</class>
到目前为止,我已经尝试了许多不同的配置,并且所有这些配置都有不同程度的故障。 粘贴在这里的代码不起作用。
<list-index />
我希望有人能够提供帮助。
当您定义一对多和多对一时,这不使它成为双向的吗? 当前的工作模型是Unidirectional,UserData没有对User的引用。 您的建议失败,因为Hibernate在UserData上找不到User的get或set方法。
是否暗示此代码使用User.uid作为键并将其与UserData.parentuid列进行匹配? 还是在其他地方指定了这个事实?
<list name="fieldData" inverse="true">
<key column="parentuid" not-null="true" />
<one-to-many class="com.agetor.commons.fields.FieldData"/>
</list>
我仍在学习Hibernate,并通过我可以找到的文档和示例进行工作。
试试这个(干码):
<class name="com.agetor.commons.security.User" table="ac_users">
<id name="uid" column="uid" type="long" >
<!--<generator class="native"/>-->
</id>
<property name="username" column="username" />
<list name="fieldData" inverse="true">
<key column="parentuid" not-null="true" />
<one-to-many class="com.agetor.commons.fields.FieldData"/>
</list>
</class>
<class name="com.agetor.commons.fields.FieldData" table="ac_userdef_data">
<id name="uid" column="uid" type="long" >
<!--<generator class="native"/> -->
</id>
<many-to-one name="user" class="com.agetor.commons.security.User" fetch="join">
<column name="parentuid" not-null="true"/>
</many-to-one>
<property name="fieldname" column="fieldname" />
<property name="value" column="value" />
</class>
如果可行,请尝试添加索引并层叠我遗漏的内容。
干杯,
米奇
我认为您已经接近了,但是List可能不是您想要在新User类中使用的数据结构。 列表表示子元素的顺序,表似乎没有这些元素。 如果您有一个像列表这样的索引集合,则数据必须有一个单独的列来提供索引,因此出现“映射中的重复列”问题。
我使用的经验法则是-每个映射都应为要映射的类的每个成员包括一个条目。 因此,例如,您的User类应该为其FieldData集合提供一个条目,但您的FieldData映射不需要为父代条目,因为该列不会映射到FieldData类的元素-它只是用于放置FieldData在父对象的集合中。
如果User对象确实确实包含FieldData的有序集合,请改用set。 另一方面,我认为您更可能希望使用“字段”名称作为索引来代替FieldData的映射。 然后,FieldData类不需要映射“字段”列,也不需要将其作为成员,它仅具有值(以及该表中的任何其他字段-当然,如果实际上只有一列向左映射,您可能最终会得到字符串到字符串的映射。
这是关于此问题的最新进展。 此配置可以成功从数据库加载。 保存无效。 我决定改为更改数据库设计,因此在我放弃此方法之前,将其发布在这里以供他人参考。
<class name="com.agetor.commons.security.User" table="ac_users">
<id name="uid" column="uid" type="long" >
<generator class="increment"/>
</id>
<property name="deleted" column="deleted" />
<property name="username" column="username" />
<property name="password" column="passwd" />
<property name="disabled" column="disabled" />
<property name="lockout" column="lockout" />
<property name="expires" column="expires" />
<bag name="fieldData" lazy="extra">
<key column="parentuid" not-null="true" />
<one-to-many class="com.agetor.commons.fields.FieldData"/>
</bag>
<bag name="groups" table="ac_group_rel" access="field" lazy="extra">
<key column="useruid"/>
<many-to-many column="groupuid" class="com.agetor.commons.security.Group"/>
</bag>
<join table="ac_userdef_data" optional="true" fetch="join">
<subselect>
select
*
from
ac_userdef_data data
where
data.objectname = 'user' and
data.fieldname = 'firstname'
</subselect>
<key column="parentuid" />
<property name="firstname" formula="(select data.value from ac_userdef_data data where data.fieldname = 'firstname' and data.uid = uid)"/>
</join>
<join table="ac_userdef_data" optional="true" fetch="join">
<subselect>
select
*
from
ac_userdef_data data
where
data.objectname = 'user' and
data.fieldname = 'lastname'
</subselect>
<key column="parentuid" />
<property name="lastname" formula="(select data.value from ac_userdef_data data where data.fieldname = 'lastname' and data.uid = uid)"/>
</join>
</class>
->
<list name="fieldData" cascade="all">
<key column="uid" not-null="true" />
<index column="parentuid" />
<one-to-many class="com.agetor.commons.fields.FieldData"/>
</list>
试试这个,我只是将键coloumn更改为uid的parentuid(最好在休眠映射中使用set)
欢呼,Nagendra Prasad ..
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.