使用联接表的 JPA 一对多单向关系
我想评估现有项目的 JPA。数据库模型和 java 类存在,并且当前通过自行生成的代码进行映射。数据库模型和 java 类并不完美地结合在一起 - 但自定义映射工作得很好。尽管如此,JPA 的总体使用似乎还是值得一试。
如您所见,我是 JPA 新手,必须使用 xml 配置进行工作。目前,我正在使用连接表处理一对多单向关系(请不要在这里讨论这个场景)。
A (one - relationship owner) <-> AB (JoinTable) <-> B (many)
这些表看起来像这样,
A
--
ID
BREF
...
B
--
ID
...
AB
--
A_BREF (foreign key to a reference column in A which is NOT the id)
B_ID
我想为 A 类定义一个单向一对多关系,
class A {
private List<B> bs;
}
并这样做:
<one-to-many name="bs">
<join-table name="ab">
<join-column name="a_bref">
<referenced-column-name name="bref" />
</join-column>
<inverse-join-column name="b_id">
<referenced-column-name name="id" />
</inverse-join-column>
</join-table>
</one-to-many>
虽然这不会强制出现错误,但它不起作用。问题是连接表不适用于 A 的 ID 列。选择“B”实体的查询使用 A.ID
列值而不是 A.BREF
列值来选择实体。
(如何)我可以使这个映射工作(我使用 eclipselink 2.2.0)?
感谢您的任何建议!
编辑:
查看@SJuan76答案中提供的链接后,我稍微修改了我的映射,
<one-to-many name="bs">
<join-table name="ab">
<join-column name="a_bref" referenced-column-name="bref" />
<inverse-join-column name="b_id" referenced-column-name="id" />
</join-table>
</one-to-many>
这现在会导致以下错误(使用 eclipselink 2.1.0 和 2.2.0 进行测试)
eclipselink 2.1.0
异常描述:参数 查询选择中的名称 [bref] 标准不匹配任何参数 查询中定义的名称。
eclipselink 2.2.0
异常描述:参考 映射到的列名称 [bref] 元素 [field bs] 不 对应于有效字段 映射参考。
顺便说一句 - 如果我从定义中删除 referenced-column-name="bref"
,我会得到与 referenced-column-name="id"
相同的异常在 inverse-join-column 元素上。所以我怀疑我是否正确理解了referenced-column-name
。我用它来指定与连接表相关的表的数据库列名称。这是正确的吗?
解决方案:
我的 szenario 中的最后一个错误是我没有在我的类中定义 BREF 字段
class A {
private long bref; // missing !
private List<B> bs;
}
该类的 orm.xml
映射文件中
<basic name="bref">
<column name="bref" />
</basic>
,并且在我不知道的 我必须在映射类中的某个位置定义使用的联接映射 referenced-column-name
属性(因为我也没有联接表本身或 name
属性的join-column/inverse-join-column 映射到一个类或类成员。)
此外,检查案例问题的提示对我很有帮助。我现在觉得指定映射非常冗长,因为我用小写值覆盖了所有默认(大写)映射。由于我的数据库不区分大小写,如果需要特殊映射来使用默认值,我将使用大写表示法。
所有人+1!
I would like to evaluate JPA on an existing project. The database model and the java classes exists and are currently mapped via self generated code. The database model and the java classes do not fit ideally together - but the custom mapping works well. Nevertheless the usage of JPA in general seems worth a try.
As you see I am new to JPA and have to do the work with xml configuration. Currently I am working on a one-to-many unidirectional relationship using a join table (please do not discuss this szenario here).
A (one - relationship owner) <-> AB (JoinTable) <-> B (many)
The tables look like this
A
--
ID
BREF
...
B
--
ID
...
AB
--
A_BREF (foreign key to a reference column in A which is NOT the id)
B_ID
I would like to define a unidirectional one-to-many relationship for class A.
class A {
private List<B> bs;
}
and did it like this:
<one-to-many name="bs">
<join-table name="ab">
<join-column name="a_bref">
<referenced-column-name name="bref" />
</join-column>
<inverse-join-column name="b_id">
<referenced-column-name name="id" />
</inverse-join-column>
</join-table>
</one-to-many>
Althoug this does not force an error it is not working. The problem is that the join table does not work on the ID column of A. The query to select the "B" entities works with the A.ID
column value instead of the A.BREF
column value to select the entities.
(How) can I make this mapping work (I use eclipselink 2.2.0)?
Thanks for any suggestion!
EDIT:
After looking at a link provided in @SJuan76 answer I slightly modified my mapping to
<one-to-many name="bs">
<join-table name="ab">
<join-column name="a_bref" referenced-column-name="bref" />
<inverse-join-column name="b_id" referenced-column-name="id" />
</join-table>
</one-to-many>
This now causes the following errors (tested with eclipselink 2.1.0 and 2.2.0)
eclipselink 2.1.0
Exception Description: The parameter
name [bref] in the query's selection
criteria does not match any parameter
name defined in the query.
eclipselink 2.2.0
Exception Description: The reference
column name [bref] mapped on the
element [field bs] does not
correspond to a valid field on the
mapping reference.
By the way - if I remove the referenced-column-name="bref"
from the definition I get the same exception for the referenced-column-name="id"
on the inverse-join-column element. So I doubt that I have understood referenced-column-name
correct. I used it to specify the database column name of the tables which are related to the join table. Is this correct?
SOLUTION:
The final error in my szenario was that I did not have the BREF field definied in my class
class A {
private long bref; // missing !
private List<B> bs;
}
and in my orm.xml
mapping file for this class
<basic name="bref">
<column name="bref" />
</basic>
I was not aware that I have to define the used join mapping referenced-column-name
attributes somewhere in my mapping classes (as I also did not have the join-table itself or the name
attributes of join-column/inverse-join-column mapped to a class or class members.)
Also the tip to check the case issue was helpful for me. I feel now quite to verbose in specifying my mapping as I overwrite all default (uppercase) mappings with lowercase values. As my database is not case sensitive I will use upper case notation if special mapping is needed to go with the default.
+1 for all!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您可以尝试将字段定义为“BREF”,或者在属性映射上定义它时使用相同的大小写,或者您可以尝试将 eclipselink.jpa.uppercase-column-names 持久性属性设置为 true。当引用列名称=“bref”被删除时,这可能是“id”的问题,因为实体中的字段可能默认为“ID”。
Can you try defining the field as "BREF" or the same exact case used if you defined it on the attribute mapping, or you can try setting the eclipselink.jpa.uppercase-column-names persistence property to true. This is likely the issue with "id" when referenced-column-name="bref" is removed, since it is likely the field in the entity defaults to "ID".
一般来说,JPA 要求外键/连接列引用实体的主键/Id。但是,这应该适用于 EclipseLink,因此请包含正在生成的 SQL,如果错误,请记录错误。
A的Id是怎么定义的,是只有ID还是ID加BREF?
您可以使用 DescriptorCustomizer 自定义关系的 ManyToManyMapping 并设置正确的外键字段名称。
In general JPA requires that the foreign keys/join columns reference the primary key/Id of the Entity. But, this should work with EclipseLink, so please include the SQL that is being generated, and if it is wrong, please log a bug.
How is the Id of A defined, is it just ID or ID and BREF?
You can use a DescriptorCustomizer to customize the ManyToManyMapping for the relationship and set the correct foreign key field name.