如何在Hibernate的XML文件中声明一对多Map?

时间:2017-06-22 15:13:49

标签: java hibernate orm hibernate-4.x

我正在尝试创建一对多的Map关系,但我在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支持......不要问):< / p>

<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,但我无法绕过mapmap-keyelement
  • This "tutorial",但是对于元素类型使用基本的String而不是完整的对象,而且我实际上无法告诉示例代码的用途,因此很难与之相关。
  • This wikibooks page,但它的JPA映射不是Hibernate。

我无法弄清楚该怎么做。所以我知道这是一个基本问题,但是,我应该使用什么映射描述符来使其工作?

1 个答案:

答案 0 :(得分:1)

嗯,基于注释的映射非常简单

@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