`
xuehongliang
  • 浏览: 95341 次
  • 性别: Icon_minigender_1
  • 来自: 辽宁
社区版块
存档分类
最新评论

多对多示例

阅读更多

假設現在有User與Server兩個類別,一個User可以被授權使用多台Server,而在Server上也記錄授權使用它的使用者,就User與Server兩者而言即使多對多的關係。

在程式設計時,基本上是不建議直接在User與Server之間建立多對多關係,這會使得User與Server相互依賴,通常會透過一個中介類別來維護兩者之間的多對多關係,避免兩者的相互依賴。

如果一定要直接建立User與Server之間的多對多關係,Hibernate也是支援的,基本上只要您瞭解之前介紹的幾個實體映射,建立多對多關聯在配置上並不困難。

先看一下我們設計的User與Server類別:

java 代码
  1. package onlyfun.caterpillar;    
  2.   
  3. import java.util.*;    
  4.   
  5. public class User {    
  6.     private long id;    
  7.     private String name;    
  8.     private Set servers = new HashSet();    
  9.        
  10.     public long getId() {    
  11.         return id;    
  12.     }    
  13.     public void setId(long id) {    
  14.         this.id = id;    
  15.     }    
  16.     public String getName() {    
  17.         return name;    
  18.     }    
  19.     public void setName(String name) {    
  20.         this.name = name;    
  21.     }    
  22.     public Set getServers() {    
  23.         return servers;    
  24.     }    
  25.          
  26.     public void setServers(Set servers) {    
  27.         this.servers = servers;    
  28.     }         
  29. }    
java 代码
  1. package onlyfun.caterpillar;    
  2.   
  3. import java.util.*;    
  4.   
  5. public class Server {    
  6.    private long id;    
  7.    private String address;    
  8.    private Set users = new HashSet();    
  9.        
  10.    public long getId() {    
  11.        return id;    
  12.    }    
  13.    public void setId(long id) {    
  14.        this.id = id;    
  15.    }       
  16.    public String getAddress() {    
  17.        return address;    
  18.    }    
  19.    public void setAddress(String address) {    
  20.        this.address = address;    
  21.    }    
  22.    public Set getUsers() {    
  23.          return users;    
  24.    }    
  25.    public void setUsers(Set users) {    
  26.        this.users = users;    
  27.    }    
  28. }   

這邊各使用HashSet來保存彼此的關係,在多對多關係映射上,我們可以建立單向或雙向關係,這邊直接介紹雙向關係映射,並藉由設定inverse="true",將關係的維護交由其中一方來維護,這麼作的結果,在原始碼的撰寫上,也比較符合Java的物件關係維護,也就是雙方都要設置至對方的參考。

首先來看看User.hbm.xml:

xml 代码
  1. <?xml version="1.0"?>    
  2. <!DOCTYPE hibernate-mapping    
  3.     PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN"    
  4.     "http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">    
  5.   
  6. <hibernate-mapping>    
  7.   
  8.     <class name="onlyfun.caterpillar.User" table="USER">    
  9.   
  10.         <id name="id" column="USER_ID" unsaved-value="0">    
  11.             <generator class="increment"/>    
  12.         </id>    
  13.   
  14.         <property name="name">    
  15.             <column name="NAME" length="16" not-null="true"/>    
  16.         </property>    
  17.          
  18.         <set name="servers"    
  19.              table="USER_SERVER"    
  20.              cascade="save-update">    
  21.                  
  22.             <key column="USER_ID"/>    
  23.             <many-to-many class="onlyfun.caterpillar.Server"    
  24.                           column="SERVER_ID"/>               
  25.         </set>    
  26.                              
  27.     </class>    
  28.   
  29. </hibernate-mapping>   

在資料庫中,資料表之間的多對多關係是透過一個中介的資料表來完成,例如在這個例子中,USER資料表與USER_SERVER資料表是一對多,而USER_SERVER對SERVER是多對一,從而完成USER至SERVER的多對多關係,在USER_SERVER資料表中,將會有USER_ID與SERVER_ID共同作為主鍵,USER_ID作為一個至USER的外鍵參考,而SERVER_ID作為一個至SERVER的外鍵參考。

來看看Server.hbm.xml映射文件:

xml 代码
  1. <?xml version="1.0"?>    
  2. <!DOCTYPE hibernate-mapping    
  3.     PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN"    
  4.     "http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">    
  5.   
  6. <hibernate-mapping>    
  7.   
  8.     <class name="onlyfun.caterpillar.Server" table="SERVER">    
  9.   
  10.         <id name="id" column="SERVER_ID" unsaved-value="0">    
  11.             <generator class="increment"/>    
  12.         </id>    
  13.   
  14.         <property name="address" type="string"/>    
  15.            
  16.         <set name="users"    
  17.              table="USER_SERVER"    
  18.              inverse="true"    
  19.              cascade="save-update">    
  20.                  
  21.              <key column="SERVER_ID"/>    
  22.              <many-to-many class="onlyfun.caterpillar.User"    
  23.                            column="USER_ID"/>    
  24.         </set>    
  25.     </class>    
  26.   
  27. </hibernate-mapping>   

設置上與User.hbm.xml是類似的,只是增加了inverse="true",表示將關係的維護交由另一端,注意我們在User與Server的cascade都是設置為save-update,在多對多的關係中,all、delete等cascade是沒有意義的,因為多對多中,並不能因為父物件被刪除,而造成被包括的子物件被刪除,因為可能還有其它的父物件參考至這個子物件。

我們使用下面這個程式來測試:

java 代码
  1. import onlyfun.caterpillar.*;    
  2. import net.sf.hibernate.*;    
  3. import net.sf.hibernate.cfg.*;    
  4.   
  5. public class HibernateTest {    
  6.     public static void main(String[] args) throws HibernateException {    
  7.         SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();    
  8.            
  9.         Server server1 = new Server();    
  10.         server1.setAddress("PC-219");    
  11.         Server server2 = new Server();    
  12.         server2.setAddress("PC-220");    
  13.         Server server3 = new Server();    
  14.         server3.setAddress("PC-221");    
  15.            
  16.         User user1 = new User();    
  17.         user1.setName("caterpillar");    
  18.         User user2 = new User();    
  19.         user2.setName("momor");    
  20.            
  21.         user1.getServers().add(server1);    
  22.         user1.getServers().add(server2);    
  23.         user1.getServers().add(server3);    
  24.         server1.getUsers().add(user1);    
  25.         server2.getUsers().add(user1);    
  26.         server3.getUsers().add(user1);    
  27.            
  28.         user2.getServers().add(server1);    
  29.         user2.getServers().add(server3);    
  30.         server1.getUsers().add(user2);    
  31.         server3.getUsers().add(user2);    
  32.            
  33.         Session session = sessionFactory.openSession();    
  34.         Transaction tx= session.beginTransaction();    
  35.         session.save(user1);    
  36.         session.save(user2);    
  37.   
  38.         tx.commit();    
  39.         session.close();    
  40.   
  41.         sessionFactory.close();    
  42.     }    
  43. }    

注意由於設定了inverse="true",所以必須分別設定User與Server之間的相互參考,來看看實際上資料庫中是如何儲存的:

select * FROM USER

+---------+-------------+
| USER_ID | NAME |
+---------+-------------+
|       1 | caterpillar   |
|       2 | momor        |
+---------+-------------+

select * FROM USER_SERVER

+-----------------+--------------+
| SERVER_ID | USER_ID |
+-----------------+--------------+
|                     1 |                 1 |
|                     2 |                 1 |
|                     3 |                 1 |
|                     1 |                 2 |
|                     2 |                 2 |
+-----------------+--------------+

select * FROM SERVER

+-----------------+------------+
| SERVER_ID | address |
+-----------------+------------+
|                     1 |  PC-219  |
|                     2 |  PC-221  |
|                     3 |  PC-220  |
+-----------------+-------------+

分享到:
评论

相关推荐

    多示例多标签代码

    标题提到的"多示例多标签代码"表明,这是一个用MATLAB实现的程序,它结合了多示例学习和多标签学习的特性,用于处理复杂的分类任务。MATLAB是一个强大的编程环境,特别适合于数值计算和数据处理,因此它是实现这种...

    多示例学习内容

    此外,文章提到了多示例学习的一些应用领域,比如在生物信息学、环境科学和计算机视觉中,通过多示例学习对数据进行分类和分析。在这些应用中,数据点以一种自然的方式组织成包,而多示例学习提供了一种处理此类数据...

    注册程序示例示例示例示例示例

    注册程序示例示例示例示例示例

    多线程示例源码工程文件

    这是一个多线程的示例工程,非常适合新手学习! 这是一个多线程的示例工程,非常适合新手学习! 这是一个多线程的示例工程,非常适合新手学习! 这是一个多线程的示例工程,非常适合新手学习! 这是一个多线程的示例...

    Silverlight示例

    Silverlight示例Silverlight示例Silverlight示例Silverlight示例Silverlight示例Silverlight示例Silverlight示例Silverlight示例Silverlight示例Silverlight示例Silverlight示例Silverlight示例

    VB winsock服务端连接多个客户端示例

    本示例着重讲解如何利用Winsock控件设计一个服务端程序,能够同时处理多个客户端的连接请求。下面将详细阐述相关知识点。 1. **Winsock控件介绍** Winsock控件是VB中的一个标准控件,它提供了一个简单的接口,允许...

    wpf示例wpf示例wpf示例wpf示例wpf示例wpf示例wpf示例

    wpf示例wpf示例wpf示例wpf示例wpf示例wpf示例wpf示例wpf示例wpf示例wpf示例wpf示例wpf示例wpf示例wpf示例wpf示例wpf示例wpf示例wpf示例wpf示例wpf示例wpf示例wpf示例wpf示例wpf示例wpf示例wpf示例wpf示例wpf示例wpf...

    精典java程序示例

    6. **多线程**:Java内置了对多线程的支持,可以创建Thread对象或实现Runnable接口。示例会展示如何启动、同步和管理线程,以及理解并发编程的基本概念。 7. **Swing与GUI**:对于桌面应用开发,Java的Swing库提供...

    google 示例 google 示例google 示例

    "google 示例google 示例google 示例google 示例"的描述虽然重复,但我们可以从中推测,这些示例可能涵盖了多个使用场景,可能是为了帮助开发者更好地理解和应用Google的技术。这可能包括搜索API、地图API、身份验证...

    LayUI框架示例整合

    这个“LayUI框架示例整合”是为初学者提供的一份实践教程,旨在帮助小白快速上手LayUI,掌握其基本用法和常见功能。 LayUI的核心思想是模块化,它将页面元素如表格、表单、按钮、弹窗等封装成独立的模块,开发者...

    C#开发经典示例

    示例中可能会包含如何创建和使用类、接口以及实现多态性的示例。 3. **异常处理**:C#中的try-catch-finally结构用于处理运行时错误。理解何时和如何使用这些语句是编写健壮代码的关键。 4. **LINQ(Language ...

    论文研究-基于聚类与分类结合的多示例预测算法.pdf

    针对训练包不含标签的无监督多示例问题,提出了聚类与分类结合的多示例预测算法。利用多示例聚类算法完成无监督多示例学习的聚类任务,并根据聚类结果将各个簇中的每个包转换成相应的k维特征向量。在标准多示例预测...

    netty示例NIO示例

    myeclipse开发通信示例,框架netty,代码本人写的,而且已测试通过,先运行NettyService,再运行NettyClient即可看到效果。nio示例也有,原理一样,运行先后顺序同netty.

    Brinson多期归因计算示例

    针对基金业绩归因常用的brinson模型,多期归因的公式随处可见,但具体计算步骤网上不多见

    qt插件开发完整工程示例

    qt插件开发完整工程示例qt插件开发完整工程示例qt插件开发完整工程示例qt插件开发完整工程示例qt插件开发完整工程示例qt插件开发完整工程示例qt插件开发完整工程示例qt插件开发完整工程示例qt插件开发完整工程示例qt...

    Spring boot 示例 官方 Demo

    spring-boot-mybatis-mulidatasource:springboot+mybatis多数据源最简解决方案 spring-boot-mybatis-annotation-mulidatasource:springboot+mybatis(注解版)多数据源最简解决方案 spring-boot-thymeleaf:simple...

    openlayers3 简单示例

    openlayers 3 示例代码 demo.html:基本的地图展示示例 - map-animation.html:地图动画效果示例 - map-zoom.html:地图基本缩放操作示例 - map-controls.html:地图控件显示的操作示例 - map-geojson.html: 加载...

    表格识别示例代码表格识别示例代码

    表格识别示例代码表格识别示例代码表格识别示例代码表格识别示例代码表格识别示例代码表格识别示例代码表格识别示例代码表格识别示例代码表格识别示例代码表格识别示例代码表格识别示例代码表格识别示例代码表格识别...

Global site tag (gtag.js) - Google Analytics