如何在 Hibernate 的 XML 文件中声明一对多映射?
How do I declare a one-to-many Map in Hibernate's XML file?
我正在尝试创建一对多映射关系,但在 Hibernate (4.x) 映射文件中声明它时遇到问题。我只是……想不通。
实体类是这样的,我想在其中使用IPLogEntry#ip
作为映射键(它是不可变的):
class User {
private long id;
private Map<String,IPLogEntry> ipHistory = new HashMap<String,IPLogEntry>();
... other fields;
public void addIPEntry (String ip) {
IPLogEntry e = ipHistory.get(ip);
if (e == null) {
e = new IPLogEntry(this, ip);
ipHistory.put(ip, e);
}
e.doOtherStuff(...);
}
}
class IPLogEntry {
private long id;
private User user;
private String ip;
... other fields;
IPLogEntry (User user, String ip) {
this.user = user;
this.ip = ip;
... init other fields;
}
}
还有像这样的表格:
╔═══════════════════╗ ╔══════════════════════════════════════════════════╗
║ users ║ ║ ip_log ║
╟─────────────┬─────╢ ╟─────────────┬───────────────┬──────────────┬─────╢
║ id (bigint) │ ... ║ ║ id (bigint) │ user (bigint) │ ip (varchar) │ ... ║
╚═════════════╧═════╝ ╚═════════════╧═══════════════╧══════════════╧═════╝
请注意,ip_log.ip
是映射键 和 IPLogEntry#ip
字段值。
在多次挥手之后,我的映射尝试失败了(顺便说一下,我现在不需要级联 delete
支持...别问) :
<class name="d13.dao.User" table="users">
<id name="id"><generator class="native"/></id>
<map name="ipHistory" cascade="save-update,merge">
<key column="user"/>
<map-key column="ip" type="string"/>
<element type="d13.dao.IPLogEntry"/>
</map>
...
</class>
<class name="d13.dao.IPLogEntry" table="ip_log">
<id name="id"><generator class="native"/></id>
<many-to-one name="user" class="d13.dao.User" not-null="true"/>
<property name="ip" not-null="true"/>
...
</class>
这让我在初始化时得到了这个:
Error: creating static hibernate session factoryCould not determine type for:
d13.dao.IPLogEntry,
at table: users_ipHistory,
for columns: [org.hibernate.mapping.Column(elt)]
我认为 IPLogEntry
方面是正确的,我遇到问题的是 User
方面和 map
的用法。
我一直在盯着:
- The Hibernate Manual,但我无法理解
map
、map-key
和 element
。
- This "tutorial",但它使用基本的
String
而不是元素类型的完整对象,而且我实际上无法说出示例代码的用途,因此很难联系起来到.
- This wikibooks page,但它是 JPA 映射而不是 Hibernate。
我不知道该怎么办。所以我知道这是一个基本问题,但是,我应该使用什么映射描述符来完成这项工作?
嗯,基于注释的映射非常简单
@OneToMany(mappedBy = "user", cascade = { PERSIST, MERGE })
@MapKey(name = "ip")
private Map<String, IPLogEntry> ipHistory = new HashMap<>();
我没有XML映射经验,不过应该是:
<class name="d13.dao.User" table="users">
<id name="id">
<generator class="native"/>
</id>
<map name="ipHistory" cascade="save-update,merge" inverse="true">
<key column="user_id"/>
<map-key column="ip" type="string"/>
<one-to-many class="d13.dao.IPLogEntry"/>
</map>
...
</class>
<class name="d13.dao.IPLogEntry" table="ip_log">
<id name="id">
<generator class="native"/>
</id>
<many-to-one name="user" class="d13.dao.User" column="user_id" not-null="true"/>
<property name="ip" not-null="true"/>
...
</class>
见Example 7.29. Bidirectional association with indexed collection
我正在尝试创建一对多映射关系,但在 Hibernate (4.x) 映射文件中声明它时遇到问题。我只是……想不通。
实体类是这样的,我想在其中使用IPLogEntry#ip
作为映射键(它是不可变的):
class User {
private long id;
private Map<String,IPLogEntry> ipHistory = new HashMap<String,IPLogEntry>();
... other fields;
public void addIPEntry (String ip) {
IPLogEntry e = ipHistory.get(ip);
if (e == null) {
e = new IPLogEntry(this, ip);
ipHistory.put(ip, e);
}
e.doOtherStuff(...);
}
}
class IPLogEntry {
private long id;
private User user;
private String ip;
... other fields;
IPLogEntry (User user, String ip) {
this.user = user;
this.ip = ip;
... init other fields;
}
}
还有像这样的表格:
╔═══════════════════╗ ╔══════════════════════════════════════════════════╗
║ users ║ ║ ip_log ║
╟─────────────┬─────╢ ╟─────────────┬───────────────┬──────────────┬─────╢
║ id (bigint) │ ... ║ ║ id (bigint) │ user (bigint) │ ip (varchar) │ ... ║
╚═════════════╧═════╝ ╚═════════════╧═══════════════╧══════════════╧═════╝
请注意,ip_log.ip
是映射键 和 IPLogEntry#ip
字段值。
在多次挥手之后,我的映射尝试失败了(顺便说一下,我现在不需要级联 delete
支持...别问) :
<class name="d13.dao.User" table="users">
<id name="id"><generator class="native"/></id>
<map name="ipHistory" cascade="save-update,merge">
<key column="user"/>
<map-key column="ip" type="string"/>
<element type="d13.dao.IPLogEntry"/>
</map>
...
</class>
<class name="d13.dao.IPLogEntry" table="ip_log">
<id name="id"><generator class="native"/></id>
<many-to-one name="user" class="d13.dao.User" not-null="true"/>
<property name="ip" not-null="true"/>
...
</class>
这让我在初始化时得到了这个:
Error: creating static hibernate session factoryCould not determine type for:
d13.dao.IPLogEntry,
at table: users_ipHistory,
for columns: [org.hibernate.mapping.Column(elt)]
我认为 IPLogEntry
方面是正确的,我遇到问题的是 User
方面和 map
的用法。
我一直在盯着:
- The Hibernate Manual,但我无法理解
map
、map-key
和element
。 - This "tutorial",但它使用基本的
String
而不是元素类型的完整对象,而且我实际上无法说出示例代码的用途,因此很难联系起来到. - This wikibooks page,但它是 JPA 映射而不是 Hibernate。
我不知道该怎么办。所以我知道这是一个基本问题,但是,我应该使用什么映射描述符来完成这项工作?
嗯,基于注释的映射非常简单
@OneToMany(mappedBy = "user", cascade = { PERSIST, MERGE })
@MapKey(name = "ip")
private Map<String, IPLogEntry> ipHistory = new HashMap<>();
我没有XML映射经验,不过应该是:
<class name="d13.dao.User" table="users">
<id name="id">
<generator class="native"/>
</id>
<map name="ipHistory" cascade="save-update,merge" inverse="true">
<key column="user_id"/>
<map-key column="ip" type="string"/>
<one-to-many class="d13.dao.IPLogEntry"/>
</map>
...
</class>
<class name="d13.dao.IPLogEntry" table="ip_log">
<id name="id">
<generator class="native"/>
</id>
<many-to-one name="user" class="d13.dao.User" column="user_id" not-null="true"/>
<property name="ip" not-null="true"/>
...
</class>
见Example 7.29. Bidirectional association with indexed collection