Hibernate---数据表于java类映射

一对多关联关系

在 UML 中, 关联是有方向的.

  • 以 Customer 和 Order 为例: 一个用户能发出多个订单, 而一个订单只能属于一个客户. 从 Order 到 Customer 的关联是多对一关联; 而从 Customer 到 Order 是一对多关联

  • 单向关联
    在这里插入图片描述在这里插入图片描述

  • 双向关联
    在这里插入图片描述

  • 单向 n-1

  • 单向 n-1 关联只需从 n 的一端可以访问 1 的一端

  • 域模型: 从 Order 到 Customer 的多对一单向关联需要在Order 类中定义一个 Customer 属性, 而在 Customer 类中无需定义存放 Order 对象的集合属性
    在这里插入图片描述

  • 关系数据模型:ORDERS 表中的 CUSTOMER_ID 参照 CUSTOMER 表的主键
    在这里插入图片描述

  • 显然无法直接用 property 映射 customer 属性

  • Hibernate 使用 元素来映射多对一关联关系

  • many-to-one节点属性
    在这里插入图片描述

  • 示例:描述多对一的关系
  1. 编写Customer类,描述顾客,表示1的一端
public class Customer {
    private Integer id;
    private String name;
    //getter和setter方法
    //toString方法
}
  • 配置Customer.hbm.xml文件
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<!--定义对象关系映射,package设置类所在的包名称-->
<hibernate-mapping package="mao.shu.vo.n21" >
<class name="Customer" table="CUSTOMER">
    <id name="customerId" type="java.lang.Integer">
        <column name="CUSTOMER_ID"/>
        <generator class="native"/>
    </id>

    <property name="customerName" type="java.lang.String">
        <column name="CUSTOMER_NAME"/>
    </property>
</class>


</hibernate-mapping>
  1. 编写Orders程序类,该类描述多的一方,在类属性中需要有一个Customer类的引用
public class Orders {
    private Integer oid;
    private String orderName;
    private Customer customer;
	//getter和setter方法
	//toString方法   
}
  • 编写 Order.hbm.xml文件
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<!--定义对象关系映射,package设置类所在的包名称-->
<hibernate-mapping package="mao.shu.vo.n21" >
<class name="mao.shu.vo.n21.Orders" table="ORDERS">
    <id name="oid" type="java.lang.Integer">
        <column name="O_ID"/>
        <generator class="native"/>
    </id>

    <property name="orderName" type="java.lang.String">
        <column name="ORDER_NAME"/>
    </property>

    <many-to-one name="customer" class="Customer" column="CUSTOMER_ID"></many-to-one>
</class>


</hibernate-mapping>
  • 在设置字段的时候,需要注意字段名称不要与数据库中的关键字重复
  • 在hibernate.cfg.xml文件中配置这两个映射文件
<mapping resource="mao/shu/vo/Customer.hbm.xml"/>
<mapping resource="mao/shu/vo/Order.hbm.xml"/>
  • 测试多对一的增删改查方法
  • 保存
    @Test
    public void testSave(){
        Customer customer = new Customer();
        customer.setCustomerName("xiemaoshu");

        Orders order = new Orders();
        order.setOrderName("cc");
        order.setCustomer(customer);

        this.session.save(customer);
        this.session.save(order);
    }
  • 正常情况

在这里插入图片描述

  • 如果先保存order ,在插入customer 的一段会多执行一些update语句,这是因为如果先插入 多的一段的时候,无法确定customer 的一段的外键值,所以只有当customer 的一段插入之后才能够获取到一的一端的id值,然后才能够更新n的一端的id值
  • 当先保存order时多执行了一条更新语句

在这里插入图片描述

  • 查询
    @Test
    public void testSelect(){
        Orders orders = (Orders) this.session.get(Orders.class,1);

        Customer customer = (Customer) this.session.get(Customer.class,orders.getCustomer().getCustomerId());
        System.out.println(customer);
    }

在这里插入图片描述

  • 默认情况下不会查询关联一端的对象

  • 在需要使用到关联的对象时,才发送对应的sql语句.

  • 在查询时,如果session被关闭了,则无法加载关联对象,可能会出现懒加载异常.

  • 在查询时,默认情况下 关联的对象为代理对象,还未完全加载.

  • 更新方法

   @Test
    public void testUpdate(){
        Orders orders = (Orders) this.session.get(Orders.class,1);
        // this.session.close();
        orders.setOrderName("测试修改");
        this.session.update(orders);
    }

在这里插入图片描述

  • 删除方法
    @Test
    public void testDelete(){
        Orders orders = new Orders();
        orders.setOid(1);
        this.session.delete(orders);
    }

在这里插入图片描述

  • 在不设定级联关系的情况下,不能够直接删除被关联的数据表中的数据,也就是Customer表,因为此时Order表中的有一个 CUSTOMER_ID 的字段与Customer表中的主键成外键关联关系.
  • 所以只能够先删除 "Orders"表中的数据再删除 Customer表中的数据

双向一对多关系映射

  • 一个客户可以拥有多个订单,可以在描述客户端java类之中使用一个Set集合来描述订单的关系.
  • 这个Set集合需要先进行初始化,否则Hibernate在映射关系的时候可能会出现空指针异常,
  • 域模型:从 Order 到 Customer 的多对一双向关联需要在Order 类中定义一个 Customer 属性, 而在 Customer 类中需定义存放 Order 对象的集合属性
    在这里插入图片描述
  • 关系数据模型:ORDERS 表中的 CUSTOMER_ID 参照 CUSTOMER 表的主键
    在这里插入图片描述
  • 示例:创建Customer程序类
public class Customer {
    private Integer customerId;
    private String customerName;
    private Set<Orders> ordersSet = new HashSet<Orders>();
    //getter和setter方法
    //toString()方法
}
  • 修改Customer.hbm.xml文件
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<!--定义对象关系映射,package设置类所在的包名称-->
<hibernate-mapping package="mao.shu.vo.bothway" >
<class name="Customer" table="CUSTOMER">
    <id name="customerId" type="java.lang.Integer">
        <column name="CUSTOMER_ID"/>
        <generator class="native"/>
    </id>

    <property name="customerName" type="java.lang.String">
        <column name="CUSTOMER_NAME"/>
    </property>

    <!--映射一对多的关系,
    set标签描述一对多的关系,
    set标签的name表示一对多的属性
    set标签的table描述数据库中关联的表名称
    key标签描述外键关联的字段
    one-to-many标签描述关联的类-->
    <set name="ordersSet">
        <key column="CUSTOMER_ID"></key>
        <one-to-many class="Orders"/>
    </set>
</class>


</hibernate-mapping>
  • 创建Orders程序类
public class Orders {
    private Integer oid;
    private String orderName;
    private Customer customer;
    //setter和getter()方法
    //toString()方法
}
  • Orders.hbm.xml文件
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<!--定义对象关系映射,package设置类所在的包名称-->
<hibernate-mapping package="mao.shu.vo.bothway" >
<class name="Orders" table="ORDERS">
    <id name="oid" type="java.lang.Integer">
        <column name="O_ID"/>
        <generator class="native"/>
    </id>

    <property name="orderName" type="java.lang.String">
        <column name="ORDER_NAME"/>
    </property>

    <many-to-one name="customer" class="Customer" column="CUSTOMER_ID"></many-to-one>
</class>


</hibernate-mapping>
  • 在hibernate.cfg.xml文件之中定义两个映射文件
<mapping resource="mao/shu/vo/bothway/Customer.hbm.xml"/>
<mapping resource="mao/shu/vo/bothway/Orders.hbm.xml"/>
  • 测试保存操作
    @Test
    public void testSave(){
        Customer customer = new Customer();
        customer.setCustomerName("谢茂树");

        Orders orders1 = new Orders();
        orders1.setOrderName("kfc");
        orders1.setCustomer(customer);

        Orders orders2 = new Orders();
        orders2.setOrderName("MCD");
        orders2.setCustomer(customer);

        //进行保存操作
        this.session.save(customer);
        this.session.save(orders1);
        this.session.save(orders2);
    }
  • 通过执行结果可以看到,一共执行了三条"insert"语句.

在这里插入图片描述

  • 如果先保存 Orders对象,在保存Customer对象则会发生什么?
        //进行保存操作
        this.session.save(orders1);
        this.session.save(orders2);
        
        this.session.save(customer);
  • 通过结果可以发现如果先保存Orders对象再保存Customer对象,则会多执行两条update语句,这是因为在保存ORDER数据时,由于与之关联的Customer表中的数据还未保存,所以还没有关联的外键id,所以只有当Customer的数据保存之后需要再次更新外键id字段.
    在这里插入图片描述

  • 测试修改操作

    @Test
    public void testUpdate(){
        Customer customer = (Customer) session.get(Customer.class,1);
        System.out.println(customer);
        System.out.println(customer.getOrdersSet());

        customer.getOrdersSet().iterator().next().setOrderName("测试");
    }

在这里插入图片描述

Set标签的三个属性

  1. inverse
  • <set> 标签的 inverse 属性
  • 在hibernate中通过对 inverse 属性的来决定是由双向关联的哪一方来维护表和表之间的关系. inverse = false 的为主动方,inverse = true 的为被动方, 由主动方负责维护关联关系
  • 在没有设置 inverse=true 的情况下,父子两边都维护父子
    关系
  • 在 1-n 关系中,将 n 方设为主控方将有助于性能改善(如果要国家元首记住全国人民的名字,不是太可能,但要让全国人民知道国家元首,就容易的多)
  • 在 1-N 关系中,若将 1 方设为主控方
    • 会额外多出 update 语句。
    • 插入数据时无法同时插入外键列,因而无法为外键列添加非空约束
  • 修改Customer.hbm.xml文件,将Set集合设置为主动方
 <set name="ordersSet"  table="ORDERS" inverse="true">
  1. cascade:设置级联操作
    • 开发的时候不建议设定该属性.建议使用手工的方式来处理.
  • 在对象 – 关系映射文件中, 用于映射持久化类之间关联关系的元素, , 和 都有一个 cascade 属性, 它用于指定如何操纵与当前对象关联的其他对象.
    在这里插入图片描述
  • 示例:修改Customer.hbm.xml文件,设置Set集合的级联操作
  1. 设置级联更新操作
   <set name="ordersSet"  table="ORDERS" inverse="true" cascade="delete">
  • 测试删除操作
    @Test
    public void testDelete(){
        Customer customer = (Customer) session.get(Customer.class,1);
        this.session.delete(customer);
    }
  • 此时只删除了一条customer数据,但却将order表中的另外两条数据也删除了.

在这里插入图片描述

  1. order-by :在数据库中对集合排序

<set> 元素有一个 order-by 属性, 如果设置了该属性, 当 Hibernate 通过 select 语句到数据库中检索集合对象时, 利用 order by 子句进行排序
order-by 属性中还可以加入 SQL 函数

  • 示例:设置order-by
<set name="ordersSet"  table="ORDERS" inverse="true" order-by="ORDER_NAME">
  • 测试查询操作
    @Test
    public void testSelect(){
        Customer customer = (Customer) session.get(Customer.class,4);
        Orders orders2 = new Orders();
        orders2.setOrderName("a");

        Orders orders3 = new Orders();
        orders3.setOrderName("b");

        orders2.setCustomer(customer);
        orders3.setCustomer(customer);

        this.session.save(customer);
        this.session.save(orders2);
        this.session.save(orders3);


        Set<Orders> set= customer.getOrdersSet();
        System.out.println(set);
    }
  • 输出的结果,最后输出的集合结果,是按照orderName的值进行排序的

在这里插入图片描述

映射一对一关系

  • 域模型
    在这里插入图片描述在这里插入图片描述
  • 关系数据模型
  1. 按照外键映射
  2. 按照主键映射:
    在这里插入图片描述
  • 基于外键映射的 1-1

  • 对于基于外键的1-1关联,其外键可以存放在任意一边,在需要存放外键一端,增加many-to-one元素。为many-to-one元素增加unique=“true” 属性使其不能够重复,来表示为1-1关联

  • 另一端需要使用one-to-one元素,该元素使用 property-ref 属性指定使用被关联实体主键以外的字段作为关联字段

  • 示例:定义Department类

public class Department {
    private Integer deptno;
    private String dname;
    private Manager manager;
    //getter和setter方法
    //toString方法
}
  • 配置Department.hbm.xml映射文件
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<!--定义对象关系映射,package设置类所在的包名称-->
<hibernate-mapping package="mao.shu.vo.one2one" >


  <class name="Department" table="DEPT">
      <id name="deptno" type="java.lang.Integer">
        <column name="DEPTNO"/>
          <generator class="native"/>
      </id>
      <property name="dname" type="java.lang.String">
          <column name="DNAME"/>
      </property>
      <!--描述外键关联的关系字段
      name表示属性名称
      class=外键字段所属的java类
      column=外键关联字段名称-->
      <many-to-one name="manager" class="Manager" column="MANAGER_ID"
                    unique="true" />
  </class>
</hibernate-mapping>
  • 编写Manager程序类
public class Manager {
    private Integer mid;
    private String manName;
    private Integer age;
    private Department dept;
    //getter和setter方法
    //toString方法
}
  • 编写Manager程序类的映射文件
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<!--定义对象关系映射,package设置类所在的包名称-->
<hibernate-mapping package="mao.shu.vo.one2one" >


  <class name="Manager" table="MANAGER">
      <id name="mid" type="java.lang.Integer">
        <column name="MID"/>
          <generator class="native"/>
      </id>
      <property name="manName" type="java.lang.String">
          <column name="MAN_NAME"/>
      </property>
            <property name="age" type="java.lang.Integer">
          <column name="MAN_AGE"/>
      </property>
      <!--描述一对一关系
      使用name描述属性名称
      使用class描述属性所属的类型
      -->
     <one-to-one name="dept" class="Department" />
  </class>
</hibernate-mapping>
  • 在hibernate.cfg.xm文件中配置映射文件
<mapping resource="mao/shu/vo/one2one/Department.hbm.xml"/>
<mapping resource="mao/shu/vo/one2one/Manager.hbm.xml"/>
  • 测试添加
@Test
 public void testAdd(){
     Manager manager = new Manager();
     manager.setAge(22);
     manager.setManName("xiemaoshu");

     Department department = new Department();
     department.setDname("开发部");

     department.setManager(manager);
     manager.setDept(department);
     this.session.save(manager);
     this.session.save(department);
 }

在这里插入图片描述

  • 测试查询
    @Test
    public void testGet(){
        /*以manager表查询department表*/
        Manager manager = (Manager) this.session.get(Manager.class,1);
        System.out.println(manager.getAge());
        System.out.println(manager.getManName());
        System.out.println(manager.getMid());
        System.out.println(manager.getDept().getClass());


        //以department表查询manager表
        Department department = (Department) this.session.get(Department.class,1);
        System.out.println(department.getDeptno());
        System.out.println(department.getDname());
     System.out.println(department.getManager().getManName());

    }
  • 在查询结果中,可以发现在通过department表查询manager表中的时候,使用了做外链接的方式,但是做外链接的查询方式为"manager0_.MID=department1_.DEPTNO",这显然是不正确的,
  • 这是由于在配置Manager.hbm.xml文件时,少配置了一样属性

在这里插入图片描述

  • 修改Manager.hbm.xml,修改one-to-one标签,添加property-ref属性
  • property-ref属性的作用为:指定关联类的属性名,这个属性将会和本类的主键相对应。如果没有指定,会使用对方关联类的主键
  • 此时Department类中的主键设置为"deptno"如果不设置"property-ref"的属性,就会使用"deptno"于Manager的主键所对应,所以就会出现"manager0_.MID=department1_.DEPTNO"的情况
<one-to-one name="dept" class="Department" property-ref="manager"/>
  • 修改之后,比对正常
  • 如果使用错误的关联类属性与本类主键对应(如:manager.id = department.id),这就会导致查询出来的数据错误

在这里插入图片描述

一对一基于主键关联

  • 基于主键的映射策略:指一端的主键生成器使用 foreign 策略,表明根据”对方”的主键来生成自己的主键,自己并不能独立生成主键. <param> 子元素指定使用当前持久化类的哪个属性作为 “对方”的主键
  • 采用foreign主键生成器策略的一端增加 one-to-one 元素映射关联属性,其one-to-one属性还应增加 constrained=“true” 属性;另一端增加one-to-one元素映射关联属性。
    constrained(约束):指定为当前持久化类对应的数据库表的主键添加一个外键约束,引用被关联的对象(“对方”)所对应的数据库表主键
    在这里插入图片描述
  • 编写Department程序类
package mao.shu.vo.one2one.primary;

public class Department {
    private Integer deptno;
    private String dname;
    private Manager manager;

	//getter和setter方法
}

  • Department.hbm.xml文件
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<!--定义对象关系映射,package设置类所在的包名称-->
<hibernate-mapping package="mao.shu.vo.one2one.primary" >


  <class name="Department" table="DEPT">
      <id name="deptno" type="java.lang.Integer">
        <column name="DEPTNO"/>
          <!--根据关联类生成主键-->
          <generator class="foreign">
              <!--关联类的属性-->
              <param name="property">manager</param>
          </generator>
      </id>
      <property name="dname" type="java.lang.String">
          <column name="DNAME"/>
      </property>
      <!--描述一对一关系-->
    <one-to-one name="manager" class="Manager" constrained="true"/>
  </class>
</hibernate-mapping>
  • 编写Manager程序类
public class Manager {
    private Integer mid;
    private String manName;
    private Integer age;
    private Department dept;
//getter和setter方法

}
  • Manager.hbm.xml文件
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<!--定义对象关系映射,package设置类所在的包名称-->
<hibernate-mapping package="mao.shu.vo.one2one.primary" >


  <class name="Manager" table="MANAGER">
      <id name="mid" type="java.lang.Integer">
        <column name="MID"/>
          <generator class="native"/>
      </id>
      <property name="manName" type="java.lang.String">
          <column name="MAN_NAME"/>
      </property>

      <property name="age" type="java.lang.Integer">
          <column name="MAN_AGE"/>
      </property>
      <!--描述一对一关系
      使用name描述属性名称
      使用class描述属性所属的类型
      -->
     <one-to-one name="dept" class="Department" />
  </class>
</hibernate-mapping>
  • 在hibernate.cfg.xml文件中配置映射文件
<mapping resource="mao/shu/vo/one2one/primary/Manager.hbm.xml"/>
<mapping resource="mao/shu/vo/one2one/primary/Department.hbm.xml"/>
  • 测试增加程序
@Test
public void testAdd(){
    Manager manager = new Manager();
    manager.setManName("谢茂树");
    manager.setAge(22);

    Department department = new Department();
    department.setDname("开发部");

    department.setManager(manager);
    manager.setDept(department);

    this.session.save(manager);
    this.session.save(department);
}

在这里插入图片描述

  • 测试查询
@Test
public void testGet(){
    Manager manager = (Manager) this.session.get(Manager.class,163840);
    System.out.println(manager.getManName());
    System.out.println(manager.getAge());
    System.out.println(manager.getMid());
    System.out.println(manager.getDept().getDeptno());
}
  • 运行结果
    在这里插入图片描述

映射多对多关联关系

  • 单向 n-n
  • 域模型:

在这里插入图片描述

  • 关系数据模型

在这里插入图片描述

实现多对多关系需要有一个中间表.在这里插入图片描述

  • 编写Category程序类
public class Item {
    private Integer cid;
    private String name;
    private Set<Item> itemSet = new HashSet<Item>();
    //setter和getter()方法
}
  • 编写Category映射文件
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<!--定义对象关系映射,package设置类所在的包名称-->
<hibernate-mapping package="mao.shu.vo.manyToMany" >


    <class name="Category" table="CATEGORY">
        <id name="cid" type="java.lang.Integer">
            <column name="C_ID"/>
            <generator class="native"/>
        </id>

        <property name="name" type="java.lang.String">
            <column name="NAME"/>
        </property>

        <!--使用集合描述items集合属性
        使用name描述属性名称
        使用table表示参照的表名称-->
        <set name="itemSet" table="CATEGORY_ITEM">
            <key>
                <!--在CATEGORY_ITEM表中映射的字段为"CID"-->
                <column name="C_ID"/>
            </key>
            <!--使用many-to-many描述多对多关系
            使用class描述集合中对象所属的类型,
            使用column描述映射到CATEGORY_ITEM数据表中的字段名称 -->
            <many-to-many class="Item" column="I_ID"></many-to-many>
        </set>
    </class>
</hibernate-mapping>
  • 编写Item程序类
public class Item {
    private Integer iId;
    private String name;
    private Double price;
    //getter和setter方法
}
  • 编写Item.hbm.xml文件
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<!--定义对象关系映射,package设置类所在的包名称-->
<hibernate-mapping package="mao.shu.vo.manyToMany" >


    <class name="Item" table="Item">
       <id name="iId" type="java.lang.Integer">
           <column name="I_ID"/>
           <generator class="native"/>
       </id>
        <property name="name" type="java.lang.String">
            <column name="NAME"/>
        </property>
        <property name="price" type="java.lang.Double">
            <column name="PRICE"/>
        </property>
    </class>
</hibernate-mapping>
  • 在hibernate.cfg.xml文件之中配置映射路径
<mapping resource="mao/shu/vo/manyToMany/Category.hbm.xml"/>
<mapping resource="mao/shu/vo/manyToMany/Item.hbm.xml"/>
  • 编写测试程序
   @Test
    public void testAdd(){
        Item item1 = new Item();
        item1.setName("衣服");
        item1.setPrice(12340.2);

        Item item2 = new Item();
        item2.setName("iphone5");
        item2.setPrice(456.123);

        Item item3 = new Item();
        item3.setName("照相机");
        item3.setPrice(50000.12);

        Category category = new Category();
        category.setName("分类1");
        category.getItemSet().add(item1);
        category.getItemSet().add(item2);

        Category category2 = new Category();
        category2.setName("分类2");
        category2.getItemSet().add(item3);
        category2.getItemSet().add(item2);

        Category category3 = new Category();
        category3.setName("分类3");
        category3.getItemSet().add(item1);
        category3.getItemSet().add(item2);
        category3.getItemSet().add(item3);


        this.session.save(item1);
        this.session.save(item2);
        this.session.save(item3);
        
        this.session.save(category);
        this.session.save(category2);
        this.session.save(category3);


    }
  • 输出结果

在这里插入图片描述

  • 数据库中存储的数据
  1. category表

在这里插入图片描述
2. category_item表

在这里插入图片描述
3. item表

在这里插入图片描述

多对多双向关联

  • 域模型
  • 在这里插入图片描述

双向 n-n 关联需要两端都使用集合属性
双向n-n关联必须使用连接表
集合属性应增加 key 子元素用以映射外键列, 集合元素里还应增加many-to-many子元素关联实体类
对于双向 n-n 关联, 必须把其中一端的 inverse 设置为 true, 否则两端都维护关联关系可能会造成主键冲突.

  • 在上述的代码基础上,在Item程序类中添加一个Set<Category>集合属性
    private Set<Category> categorySet = new HashSet<Category>();

    public Set<Category> getCategorySet() {
        return categorySet;
    }

    public void setCategorySet(Set<Category> categorySet) {
        this.categorySet = categorySet;
    }

  • 修改Item.hbm.xml文件,添加集合的多对多关系
<set name="categorySet" table="category_item" inverse="true">
   <key>
       <column name="C_ID"/>
   </key>
   <many-to-many class="Category" column="C_ID" ></many-to-many>
</set>
  • 测试代码
   @Test
    public void testAdd(){
        Item item1 = new Item();
        item1.setName("衣服");
        item1.setPrice(12340.2);

        Item item2 = new Item();
        item2.setName("iphone5");
        item2.setPrice(456.123);

        Item item3 = new Item();
        item3.setName("照相机");
        item3.setPrice(50000.12);

        Category category = new Category();
        category.setName("分类1");
        category.getItemSet().add(item1);
        category.getItemSet().add(item2);

        Category category2 = new Category();
        category2.setName("分类2");
        category2.getItemSet().add(item3);
        category2.getItemSet().add(item2);

        Category category3 = new Category();
        category3.setName("分类3");
        category3.getItemSet().add(item1);
        category3.getItemSet().add(item2);
        category3.getItemSet().add(item3);


        this.session.save(item1);
        this.session.save(item2);
        this.session.save(item3);

        this.session.save(category);
        this.session.save(category2);
        this.session.save(category3);


    }
  • 添加成功

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值