简体   繁体   中英

Hibernate simultaneous many-to-many and many-to-one mapping

I have a question about the creation of database schemes by Hibernate.

In our project we have users and groups. Groups have exactly one owner and can have multiple members. A user can be owner and member of multiple groups.

We came up with the following Hibernate mapping:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
    "-//Hibernate/Hibernate Mapping DTD//EN"
    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="model.User" table="ProductUser">
    <id name="id" column="userId">
        <generator class="native"/>
    </id>
    <property name="email"/>
    <property name="firstName"/>
    <property name="lastName"/>

    <set name="ownedUserGroups" table="UserGroup" inverse="true">
        <key column="userId"/>
        <one-to-many class="model.UserGroup"/>
    </set>

    <set name="userGroups" table="Members" inverse="false" lazy="true" fetch="select">
        <key column="userId"/>
        <many-to-many column="userGroupId" class="model.UserGroup"/>
    </set>
</class>

<class name="model.UserGroup" table="UserGroup">
    <id name="id" column="userGroupId">
        <generator class="native"/>
    </id>
    <property name="name"/>

    <many-to-one name="owner" class="model.User" column="owner_UserId"/>

    <set name="members" table="Members" inverse="true" lazy="true" fetch="select">
        <key column="userGroupId"/>
        <many-to-many column="userId" class="model.User"/>
    </set>

</class>
</hibernate-mapping>

The database scheme Hibernate creates for us looks the following: Database scheme created by Hibernate

Can somebody explain why usergroup has the userid as a foreign key? (As you can see in the image)

For the sake of completeness, here is the code for User and UserGroup:

public class User {
    private int id;
    private String firstName;
    private String lastName;
    private String email;
    private Set<UserGroup> ownedUserGroups;
    private Set<UserGroup> userGroups;

    public User() {
        this.ownedUserGroups = new HashSet<>();
        this.userGroups = new HashSet<>();
    }

    public User(String firstName, String lastName, String email) {
        this();
        this.firstName = firstName;
        this.lastName = lastName;
        this.email = email;
    }
    // getters and setters
}

public class UserGroup {
    private int id;
    private String name;
    private User owner;
    private Set<User> members;

    public UserGroup() {
        this.members = new HashSet<>();
    }

    public UserGroup(String name, User owner, HashSet<User> members) {
        this.name = name;
        this.owner = owner;
        this.members = members;
    }
    // getters and setters
}

Ok. The problem is with your many-to-one-mapping. What your doing is your trying to set ownedUserGroups to all the groups where the userId equals the id of the current user. However you need to look for all groups where the owner_UserId equals the id of your user. Basically you just need to replace userId with owner_UserId. Your final mapping file should look like this:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
    "-//Hibernate/Hibernate Mapping DTD//EN"
    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="model.User" table="ProductUser">
    <id name="id" column="userId">
        <generator class="native"/>
    </id>
    <property name="email"/>
    <property name="firstName"/>
    <property name="lastName"/>

    <set name="ownedUserGroups" table="UserGroup" inverse="true">
        <key column="owner_userid"/> <!-- CHANGED -->
        <one-to-many class="model.UserGroup"/>
    </set>

    <set name="userGroups" table="Members" inverse="false" lazy="true" fetch="select">
        <key column="userId"/>
        <many-to-many column="userGroupId" class="model.UserGroup"/>
    </set>
</class>

<class name="model.UserGroup" table="UserGroup">
    <id name="id" column="userGroupId">
        <generator class="native"/>
    </id>
    <property name="name"/>

    <many-to-one name="owner" class="model.User" column="owner_UserId"/>

    <set name="members" table="Members" inverse="true" lazy="true" fetch="select">
        <key column="userGroupId"/>
        <many-to-many column="userId" class="model.User"/>
    </set>

</class>
</hibernate-mapping>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM