Hibernate--一对多/多对一

Posted 耍流氓的兔兔

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Hibernate--一对多/多对一相关的知识,希望对你有一定的参考价值。

 

一对多关联(多对一):

    一对多关联映射:
        在多的一端添加一个外键指向一的一端,它维护的关系是一指向多
    多对一关联映射:
        咋多的一端加入一个外键指向一的一端,它维护的关系是多指向一

  在配置文件中添加:    在一一端使用
<set><key></key><one-to-many></one-to-many></set>    <key>指定的外键字段必须和<many-to-one>指定的外键字段一致    在多一端使用<many-to-one>
       在有外键的一端设置many-to-one

数据库中customer表和order表的关系:

创建实体类:

public class Customer {

    private Integer id;
    private String name;
    private Character gender;
    private Integer age;
    private String level;

    //一对多
    private Set<Order> orders = new HashSet<Order>();
    
    public Customer() {
        super();
        
    }

  getters and setters }
public class Order {

    private Integer id;
    private String orderno;
    private String productName;
    
    //多对一
    private Customer customer;

    public Order() {
        super();
        // TODO Auto-generated constructor stub
    }

  getters and setters }

 创建映射文件:

<hibernate-mapping>
    <class name="com.roxy.hibernate.pojo.Customer" table="t_customer">
    
        <id name="id" column="c_id">
            <generator class="native"></generator>
        </id>
        
        <property name="name" column="c_name" not-null="true"></property>
        <property name="gender" column="c_gender" length="1"></property>
        <property name="age" column="c_age"></property>
        <property name="level" column="c_level" length="20"></property>
        
        <set name="orders">
            <key column="customer_id"></key>
            <one-to-many class="com.roxy.hibernate.pojo.Order"/>
        </set>
    </class>
</hibernate-mapping>
<hibernate-mapping package="com.roxy.hibernate.pojo">

    <!-- 类和表的映射 -->
    <class name="Order" table="t_order">
        <id name="id" column="id">
            <generator class="native"></generator>
        </id>
        <!-- 其他属性映射 -->
        <property name="orderno" column="orderno" length="20"></property>
        <property name="productName" column="product_name" length="100"></property>

        <!-- 多对一 -->
        <many-to-one name="customer" class="Customer" column="customer_id" />
    
    </class>
</hibernate-mapping>   

 创建配置文件:

        <!-- mapping文件 -->
        <mapping resource="com/roxy/hibernate/pojo/Customer.hbm.xml"/>
        <mapping resource="com/roxy/hibernate/pojo/Order.hbm.xml"/>

 查看并分析SQL语句:

Hibernate: 
       alter table t_order 
       add constraint FKesy3n2gc3fa0s3trrk3tvyv9a 
       foreign key (customer_id) 
       references t_customer (c_id)

----- hibernate首先为t_order和t_customer添加外键关联
Hibernate: insert into t_customer (c_name, c_gender, c_age, c_level) values (
?, ?, ?, ?)

----- 向t_customer中插入数据(session.save(cust);)
Hibernate: insert into t_order (orderno, product_name, customer_id) values (
?, ?, ?)

----- 向t_order中插入数据(session.save(o1);)
----- 此时customer_id为null

Hibernate: insert into t_order (orderno, product_name, customer_id) values (
?, ?, ?)

-----
向t_order中插入数据(session.save(o2);)
----- 此时customer_id为null

Hibernate: update t_order set customer_id
=? where id=?

-----
维护两个表之间的关系,hibernate更新t_customer数据
Hibernate: update t_order set customer_id=? where id=?
----- 维护两个表之间的关系,hibernate更新t_customer数据

 多对多级联:


    双向一对多关联就是多对多关联
    自动生成一个关联表放置两个表的外键,即联合主键

   <!-- 多对多映射 -->
     <!-- table:中间表名 -->
         <set name="users" table="t_user_role" cascade="save-update">
             <!-- 当前方在中间表的外键 -->
             <key column="role_id"/>
             <!-- column:对方在中间表的外键 -->
             <many-to-many class="User" column="user_id"/>
         </set>

数据库中user表和role表的关系:

创建实体类:

public class User {

    private Integer id;
    private String name;
    
    //关联角色
    private Set<Role> roles = new HashSet<Role>();

    public User() {
        super();
        // TODO Auto-generated constructor stub
    }
}
public class Role {

    private Integer id;
    private String name;

    //关联用户
    private Set<User> users = new HashSet<User>();

    public Role() {
        super();
        // TODO Auto-generated constructor stub
    }
}

创建映射文件:

User:

<set name="roles" table="t_user_role" > <!-- 当前方在中间表的外键 --> <key column="user_id"/> <!-- column:对方在中间表的外键 --> <many-to-many class="Role" column="role_id"/> </set>
 Role:

<set name="users" table="t_user_role" > <!-- 当前方在中间表的外键 --> <key column="role_id"/> <!-- column:对方在中间表的外键 --> <many-to-many class="User" column="user_id"/> </set>

创建配置文件:

        <mapping resource="com/roxy/hibernate/pojo/User.hbm.xml" />
        <mapping resource="com/roxy/hibernate/pojo/Role.hbm.xml" />

查看并分析SQL语句:

Hibernate: 
    insert
    into
        t_user
        (name)
    values
        (?)
Hibernate:
    insert
    into
        t_role
        (name)
    values
        (?)
Hibernate:
    insert
    into
        t_user_role
        (user_id, role_id)
    values
        (?, ?)
Hibernate:
    insert
    into
        t_user_role
        (role_id, user_id)
    values
        (?, ?)

----- 虽然在test中只保存了user,但是在两个表的映射文件中都对彼此的关联关系进行维护,体现在SQL语句上就是执行了两次t_user_role的插入操作,这就导致了重复插入,报告联合主键重复的异常

 解决方法:

  1 既然两个表同时维护关联导致异常,那么只要一个表放弃维护即可,使用inverse:

<set name="users" table="t_user_role" inverse="true">

  2 在一个表中设置关联保存,在执行test的时候只对此表进行save操作:

<set name="users" table="t_user_role" cascade="save-update">

 

以上是关于Hibernate--一对多/多对一的主要内容,如果未能解决你的问题,请参考以下文章

优化Hibernate所鼓励的7大措施

优化Hibernate所鼓励的7大措施

优化Hibernate所鼓励的7大措施:

优化Hibernate所鼓励的7大措施:

hibernate中配置单向多对一关联,和双向一对多

利用hibernate实现数据库对象关联(多对一对多一对多对多)