• Hibernate映射


    数据库表中存在的关系在hibernate为各实体之间的关系。

    实体之间有三种关系:

      一对多:一个用户,生成多个订单,每一个订单只能属于一个用户

        建表原则:在多的一方创建一个字段,作为外键,指向一的一方的主键.

      多对多:一个学生可以选择多门课程,一个课程可以被多个学生选择.

        建表原则:创建第三张表,中间表至少有两个字段,分别作为外键指向多对多双方主键.

      一对一(特殊.最少):一个公司只能有一个注册地址,一个注册地址,只能被一个公司使用.(否则将两个表建到一个表.)

       建表原则:

        唯一外键:一对一的双方,假设一方是多的关系.需要在多的一方创建一个字段,作为外键.指向一的一方的主键.但是在外键添加一个unique.

        主键对应: 一对一的双方,通过主键进行关联.

    Hibernate中一对多的配置:

    第一步:创建两个实体:

    客户实体:

     1 public class Customer {
     2     private Integer cid;
     3     private String cname;
     4     // 一个客户有多个订单.
     5     private Set<Order> orders = new HashSet<Order>();
     6     public Integer getCid() {
     7         return cid;
     8     }
     9     public void setCid(Integer cid) {
    10         this.cid = cid;
    11     }
    12     public String getCname() {
    13         return cname;
    14     }
    15     public void setCname(String cname) {
    16         this.cname = cname;
    17     }
    18     public Set<Order> getOrders() {
    19         return orders;
    20     }
    21     public void setOrders(Set<Order> orders) {
    22         this.orders = orders;
    23     }
    24     
    25 }

    订单实体:

     1 public class Order {
     2     private Integer oid;
     3     private String addr;
     4     // 订单属于某一个客户.放置一个客户的对象.
     5     private Customer customer;
     6     public Integer getOid() {
     7         return oid;
     8     }
     9     public void setOid(Integer oid) {
    10         this.oid = oid;
    11     }
    12     public String getAddr() {
    13         return addr;
    14     }
    15     public void setAddr(String addr) {
    16         this.addr = addr;
    17     }
    18     public Customer getCustomer() {
    19         return customer;
    20     }
    21     public void setCustomer(Customer customer) {
    22         this.customer = customer;
    23     }
    24     
    25 }

    第二步:建立映射:

    Customer.hbm.xml

     1 <hibernate-mapping>
     2     <class name="cn.itcast.hibernate3.demo2.Customer" table="customer">
     3         <!-- 配置唯一标识 -->
     4         <id name="cid" column="cid">
     5             <generator class="native"/>
     6         </id>
     7         <!-- 配置普通属性 -->
     8         <property name="cname" column="cname" length="20"/>
     9         
    10         <!-- 建立映射 -->
    11         <!-- 配置一个集合 <set>的name Customer对象中的关联对象的属性名称. -->
    12         <set name="orders">
    13             <!-- <key>标签中column:用来描述一对多多的一方的外键的名称. -->
    14             <key column="cno"></key>
    15             <!-- 配置一个<one-to-many>标签中class属性:订单的类的全路径 -->
    16             <one-to-many class="cn.itcast.hibernate3.demo2.Order"/>
    17         </set>
    18     </class>
    19 </hibernate-mapping>

    Order.hbm.xml

     1 <hibernate-mapping>
     2     <class name="cn.itcast.hibernate3.demo2.Order" table="orders">
     3         <!-- 配置唯一标识  -->
     4         <id name="oid" column="oid">
     5             <generator class="native"/>
     6         </id>
     7         <!-- 配置普通属性 -->
     8         <property name="addr" column="addr" length="50"/>
     9         <!-- 配置映射 -->
    10         <!-- 
    11         <many-to-one>标签
    12             name     :关联对象的属性的名称.
    13             column    :表中的外键名称.
    14             class    :关联对象类的全路径
    15         -->
    16         <many-to-one name="customer" column="cno" class="cn.itcast.hibernate3.demo2.Customer"/>
    17     </class>
    18 </hibernate-mapping>

    第三步:将映射放到核心配置文件中,完成。

    测试:

     1 @Test
     2 // 向客户表插入一个客户,在订单表中插入两个订单.
     3 public void demo1(){
     4     Session session = HibernateUtils.openSession();
     5     Transaction tx = session.beginTransaction();
     6     
     7     // 定义一个客户:
     8     Customer customer = new Customer();
     9     customer.setCname("老汤姆");
    10     
    11     // 定义两个订单:
    12     Order order1 = new Order();
    13     order1.setAddr("吉尼斯");
    14     
    15     Order order2 = new Order();
    16     order2.setAddr("西西里");
    17     
    18     // 建立关系:
    19     order1.setCustomer(customer);
    20     order2.setCustomer(customer);
    21     
    22     customer.getOrders().add(order1);
    23     customer.getOrders().add(order2);
    24     
    25     session.save(customer);
    26     session.save(order1);
    27     session.save(order2);
    28     
    29     tx.commit();
    30     session.close();

    ~成功

    但是,这样保存数据太麻烦,在hibernate中存在级联保存:操作当前对象的时候,关联的对象也会被保存

    只需在Customer.hbm.xml中set中加入<set name="orders" cascade="save-update">

     1 @Test
     2 // 保存客户级联订单.
     3 // <set>集合是客户的关联订单对象的集合.所以在<set>上配置一个属性:cascade="save-update"
     4 public void demo3(){
     5     Session session = HibernateUtils.openSession();
     6     Transaction tx = session.beginTransaction();
     7     
     8     // 定义客户:
     9     Customer customer = new Customer();
    10     customer.setCname("老汤姆");
    11     
    12     // 定义订单:
    13     Order order = new Order();
    14     order.setAddr("吉尼斯");
    15     order.setCustomer(customer);
    16     
    17     customer.getOrders().add(order);
    18     
    19     // 保存的时候只保存一方:
    20     session.save(customer);
    21     
    22     tx.commit();
    23     session.close();
    24 }

    当然,hibernate中不止一种级联

    none			:不使用级联
    dave-update		:保存或更新的时候级联
    delete			:删除的时候级联
    all			:除了孤儿删除以外的所有级联.
    delete-orphan	        :孤儿删除(孤子删除).
    * 仅限于一对多.只有一对多时候,才有父子存在.认为一的一方是父亲,多的一方是子方.
    * 当一个客户与某个订单解除了关系.将外键置为null.订单没有了所属客户,相当于一个孩子没有了父亲.将这种记录就删除了.
    all-delete-orphan	:包含了孤儿删除的所有的级联.
    

    另外,hibernate中多表之间由于外键存在双向维护,导致产生多余的sql语句,同样在Customer.hbm.xml中<set name="orders" cascade="save-update" inverse="true">

    当inverse=true时,就是告诉Customer放弃对外键的维护权。

    Hibernate中多对多的配置和一对多差不多,只是在各自的实体类中都存在对方的实体类集合,另外xml中如下:

    Course.hbm.xml

     1 <hibernate-mapping>
     2     <class name="cn.itcast.hibernate3.demo3.Course" table="course">
     3         <!-- 配置唯一标识 -->
     4         <id name="cid" column="cid">
     5             <generator class="native"/>
     6         </id>
     7         <!-- 配置普通属性 -->
     8         <property name="cname" column="cname" length="20"/>
     9         <!-- 配置与学生关联映射 -->
    10         <!-- <set>中name:对应当前类中的学生的集合的名称  table:中间表的名称-->
    11         <set name="students" table="stu_cour" inverse="true">
    12             <!-- <key>中column:当前类在中间表中外键 -->
    13             <key column="cno"></key>
    14             <!-- <many-to-many>中class:另一方的类全路径. column:另一方在中间表中外键名称 -->
    15             <many-to-many class="cn.itcast.hibernate3.demo3.Student" column="sno"/>
    16         </set>
    17     </class>
    18 </hibernate-mapping>

    Student.hbm.xml

     1 <hibernate-mapping>
     2     <class name="cn.itcast.hibernate3.demo3.Student" table="student">
     3         <!-- 配置唯一标识 -->
     4         <id name="sid" column="sid">
     5             <generator class="native"/>
     6         </id>
     7         <!-- 配置普通属性 -->
     8         <property name="sname" column="sname" length="20"/>
     9         
    10         <!-- 配置关联映射 -->
    11         <!-- <set>标签 name:对应学生中的课程集合的名称   table:中间表名称. -->
    12         <set name="courses" table="stu_cour" cascade="save-update,delete">
    13             <!-- <key>中column写 当前类在中间表的外键.-->
    14             <key column="sno"></key>
    15             <!-- <many-to-many>中class:另一方类的全路径. column:另一方在中间表中外键名称-->
    16             <many-to-many class="cn.itcast.hibernate3.demo3.Course" column="cno"/>
    17         </set>
    18     </class>
    19 </hibernate-mapping>

    另外,对应多对多中数据的删除,建议采用remove来删除数据

     1 @Test
     2 // 多对多的学生退选.
     3 public void demo4(){
     4     Session session = HibernateUtils.openSession();
     5     Transaction tx = session.beginTransaction();
     6     
     7     // 查询一号学生
     8     Student student = (Student) session.get(Student.class, 1);
     9     Course course = (Course) session.get(Course.class, 2);
    10     student.getCourses().remove(course);
    11     
    12     tx.commit();
    13     session.close();
    14 }
  • 相关阅读:
    mui实现分页上拉加载更多 下拉刷新数据的简单实现 移动端下拉上拉
    滑动时候警告:Unable to preventDefault inside passive event listener
    vue-cli3 一直运行 /sockjs-node/info?t= 解决方案
    css设置不允许复制文本内容
    SDK manager打不开解决办法
    Android Studio 于夜神模拟器进行连接
    从零开始学 Java
    从零开始学 Java
    从零开始学 Java
    从零开始学 Java
  • 原文地址:https://www.cnblogs.com/lesliehe/p/8021988.html
Copyright © 2020-2023  润新知