Hibernate操作多对多关系

来源:互联网 发布:游戏服务器编程 编辑:程序博客网 时间:2024/05/22 10:24

多对多业务说明

        本例涉及的数据库表表为PRODUCTS(商品表)SUPPLIERS(提供商表)PRODUCT_SUPPLY(中间表)

        规定:商品可以由多个提供商提供;每个提供商可以提供多种商品。

 

实体间的关联-----ER

        双向多对多:即从Product商品就可知道该商品的供应商有哪些,因为Product类中包含一个供货商集合Set;同理供货商也可知道该供货商有生产哪些商品。

 

怎样将实体多对多关系映射到数据库?

        在运用SSH架构开发Web应用时,总会遇到表之间一对多、多对一、多对多等等的关系,而对于多对多的关系,在操作和性能方面都不太理想,所以多对多的映射使用较少,实际使用中最好转换成一对多的对象模型;hibernate会为我们创建中间关联表,转换成两个一对多。

多对多操作时的中间表

        在关系数据模型中,无法直接表达PRODUCTS表和SUPPLIERS表之间的多对多关系,需要创建一个连接表(也称为中间表、中间关联表)PRODUCT_SUPPLY,它同时参照PRODUCTS表和SUPPLIERS表。

        中间表存储的是ProductSupply之间的关系。

        中间表不需要被程序员直接操作。即没有与中间表对应的POJOhbm文件。它仅被参照表在映射文件中引用。

PRODUCT_SUPPLY表以PRODUCT_NUMSUPPLY_NUM作为联合主键,PRODUCT_NUM作为外键参照PRODUCTS表,SUPPLY_NUM作为外键参照SUPPLIERS表。如下图:

 

定义“商品”和“供货商”实体类

public class Product {

     private String  num;

     private Category category;

     private Set suppliers;

     // Getters & Setters ...

}

public class  Supply{

     private String num;

     private Set products;

     // Getters & Setters ...

}

 

实体类的映射文件

<!Product类映射文件- ->

<class name="Product" table="PRODUCTS">

……

    <many-to-one name="category"

             column="CATEGORY_ID"

                              class="Category"

                              cascade="save-update">

    </many-to-one>

    <set name="suppliers"

            table="PRODUCT_SUPPLY"

            cascade="save-update"

            inverse="true">

            <key column="PRODUCT_NUM"></key>

            <many-to-many column="SUPPLY_NUM"                       class="Supply">

            </many-to-many>

    </set>

</class>

 

<!Supply类映射文件- ->

<class name="Supply" table="SUPPLIERS">

……

    <set name="products"

            table="PRODUCT_SUPPLY"

            cascade="save-update">

            <key column="SUPPLY_NUM"></key>

            <many-to-many column="PRODUCT_NUM"                                              class="Product">

            </many-to-many>

    </set>

</class>

分析:商品Product包含一个供货商集合Set,供货商也包含一个商品集合,就此做了双向关联,多对多关系会产生中间表PRODUCT_SUPPLY,由商品Product和供货商Supply所映射的表做联合主键。

set name="suppliers"

            table="PRODUCT_SUPPLY"

            cascade="save-update"

            inverse="true">

            <key column="PRODUCT_NUM"></key>

            <many-to-many column="SUPPLY_NUM"                       class="Supply">

            </many-to-many>

    </set>

        这是Product的类映射文件,table="PRODUCT_SUPPLY"指明了中间表,cascade="save-update"指明级联关系,inverse="true"指明多对多的关系维护有对方完成。<many-to-many column="SUPPLY_NUM"多对多关系,Product表中的主键在中间表PRODUCT_SUPPLY中作column="SUPPLY_NUM"这一列;class="Supply"表示该集合Set中放的都是Supply这种类型。同理Supply类映射文件也类似。

 

添加提供商示例

录入某商品的提供商信息:该商品由提供商“S0001,S0002”供货。

 

修改操作

任务:修改商品“p0001”的提供商信息,改为仅由“S0003”提供商提供

要求:删除中间表 “p0001”之前与其他提供商的关系,再添加一个新的关系。

仅删除中间表记录

能通过直接操作中间表完成吗?

        中间表不能被直接操作。中间表只是记录参照表之间的关系,并不是真正的实体。所以不能被作为POJO被程序直接操作。

        解决方案:既然中间表记录的是参照表的关系,那么我们在程序中操作参照表,将其之间的从属关系用Java代码解除,再更新即可。

        注意:在本质上,这是修改操作,而不是删除(对象的)操作,所以在本次操作中,cascade=update”足已。只是因为配置在程序运行过程中不能随意修改,所以一般cascade=save-update”。

 

注意: inverse=true”属性,在多对多的任意一方设置。否则会造成数据库插入失败。(重复的主键)

 

多对多的关系有很多,常见的还有用户角色和权限、学生和选课......

下面这是一个完整的实例:使用Hibernate演示学生和课程之间多对多的关系操作

https://github.com/ljheee/StudentORM

1 0
原创粉丝点击