Hibernate级联操作代码实现(一对多、多对多关系)(二)

目录

1、⼀对多关系

客户和订单:

代码实现:

1、Customer实体类和Customer.hbm.xml文件:

 2、Orders实体类和Orders.hbm.xml文件:

3、hibernate.cfg.xml文件:(实体关系映射⽂件注册到 Hibernate 的配置⽂件中。)

4、使⽤ Hibernate API 完成数据操作

2、多对多关系

学⽣选课:

代码实现:

1、Account实体类和Account.hbm.xml文件:

2、Course实体类和Course.hbm.xml文件:

3、hibernate.cfg.xml文件:(实体关系映射⽂件注册到 Hibernate 的配置⽂件中。)

4、使⽤ Hibernate API 完成数据操作


1、⼀对多关系

客户和订单:

每个客户可以购买多个产品,⽣成多个订单,但是⼀个订单只能属于⼀个客户,所以客户是⼀,订单是多。

数据库中⼀的⼀⽅是主表,多的⼀⽅时候从表,通过主外键关系来维护。

代码实现:

1、Customer实体类和Customer.hbm.xml文件:

//Customer实体类
@Getter
@Setter
public class Customer {
    private Integer id;
    private String  name;
    private Set<Orders> orders;  //一个customer对应多个order

    @Override
    public String toString() {
        return "Customer{" +
                "id=" + id +
                ", name='" + name + '\'' +
                '}';
    }
}


#Customer.hbm.xml文件:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping> <!--文件名的hbm就是hibernate-mapping 的缩写,在这里面完成类和表的映射-->

    <!-- class 就是指类,name就是指类名 table 就是指对应的表名,表customer里面有id和name两个字段-->
    <class name="com.southwind.entity.Customer" table="customer">
       <!-- 主键映射 name指的是实体类里面的属性:id   type指的是id属性的类型-->
        <id name="id" type="java.lang.Integer">
            <!--column是字段,指的是对应类里面id的表里面的名称-->
            <column name="id"></column>
            <!--这个是配置主键自增的方式,identity的意思就是自增-->
            <generator class="identity"></generator>
        </id>
        <!-- 下面继续配置类里面的其他信息,name   type指的是name属性的类型-->
        <property name="name" type="java.lang.String">
            <!--column是字段,指的是对应类里面name的表里面的名称-->
            <column name="name"></column>
        </property>

        <!-- 下面继续配置类里面的其他信息,因为是set集合,就直接用set配,table是orders.   private Set<Orders> orders;-->
        <set name="orders" table="orders" lazy="extra">
            <!-- key是外键,column是字段,指的是表里面的外键名称-->
            <key column="cid"></key>
            <!-- 怎么去映射这个东西,这里面one-to-many 指的是一对多的关系     private Set<Orders> orders;
                  class表示是这里面的类从哪里来的,创建orders对象把它装到set集合里面-->
            <one-to-many class="com.southwind.entity.Orders"></one-to-many>
        </set>
<!--        set 标签来配置实体类中的集合属性 orsers-->
<!--        name 实体类属性名-->
<!--        table 表名-->
<!--        key 外键-->
<!--        one-to-many 与集合泛型的实体类对应-->

    </class>

</hibernate-mapping>


<!--hibernate-mapping 属性
package:给 class 节点对应的实体类统⼀设置包名,此处设置包名,class 的 name 属性就可以
省略包名
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD
3.0//EN"
 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.southwind.entity">
 <class name="Course" table="t_course">
 <id name="id" type="java.lang.Integer">
 <column name="id"></column>
 ....


-->

 2、Orders实体类和Orders.hbm.xml文件:

//Orders实体类
@Data
public class Orders {
    private Integer id;
    private String name;
    private Customer customer; //一个订单对应一个客户
}

#Orders.hbm.xml文件:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping> <!--文件名的hbm就是hibernate-mapping 的缩写,在这里面完成类和表的映射-->

    <!-- class 就是指类,name就是指类名 table 就是指对应的表名,表customer里面有id和name两个字段-->
    <class name="com.southwind.entity.Orders" table="orders">
       <!-- 主键映射 name指的是实体类里面的属性:id   type指的是id属性的类型-->
        <id name="id" type="java.lang.Integer">
            <!--column是字段,指的是对应类里面id的表里面的名称-->
            <column name="id"></column>
            <!--这个是配置主键自增的方式,identity的意思就是自增-->
            <generator class="identity"></generator>
        </id>
        <!-- 下面继续配置类里面的其他信息,name   type指的是name属性的类型-->
        <property name="name" type="java.lang.String">
            <!--column是字段,指的是对应类里面name的表里面的名称-->
            <column name="name"></column>
        </property>

<!--        many-to-one 配置实体类对应的对象属性-->
<!--        name 属性名-->
<!--        class 属性对应的类-->
<!--        column 外键-->
        <many-to-one name="customer" class="com.southwind.entity.Customer" column="cid"></many-to-one>

    </class>

</hibernate-mapping>

3、hibernate.cfg.xml文件:(实体关系映射⽂件注册到 Hibernate 的配置⽂件中。)

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<!--    核⼼配置:session-factory-->
<!--    SessionFactory:针对单个数据库映射经过编译的内存镜像⽂件,将数据库转换为⼀个 Java 可以识别的镜像⽂件。-->
<!--    构建 SessionFactory ⾮常耗费资源,所以通常⼀个⼯程只需要创建⼀个 SessionFactory。-->
    <session-factory>
        <!-- datasource 数据源配置 -->
        <property name="connection.username">root</property>
        <property name="connection.password">123456</property>
        <property name="connection.driver_class">com.mysql.cj.jdbc.Driver</property>
        <property name="connection.url">jdbc:mysql://localhost:3306/test?useUnicode=true&amp;characterEncoding=utf8&amp;serverTimezone=GMT</property>
<!--?useUnicode=true&amp;characterEncoding=utf8&amp;serverTimezone=GMT" />-->

        <!-- C3P0 连接池 -->
        <property name="hibernate.c3p0.acquire_increment">10</property>    <!-- 每次不够的话就会增加的数量-->
        <property name="hibernate.c3p0.idle_test_period">10000</property>  <!--释放资源时间的设置,s为单位-->
        <property name="hibernate.c3p0.timeout">5000</property>            <!-- 超时时间-->
        <property name="hibernate.c3p0.max_size">30</property>             <!-- 最大连接数-->
        <property name="hibernate.c3p0.min_size">5</property>              <!-- 最小连接数-->
        <property name="hibernate.c3p0.max_statements">10</property>       <!-- 最大线程数数-->
        <!-- 数据库⽅⾔ oracle或mysql-->
        <property name="dialect">org.hibernate.dialect.MySQLDialect</property>
        <!-- 打印SQL语句,固定写法 -->
        <property name="show_sql">true</property>
        <!-- 格式化SQL语句,固定写法 -->
        <property name="format_sql">true</property>
        <!-- 是否⾃动⽣成数据表-->
        <property name="hibernate.hbm2ddl.auto">update</property>
        <!-- create:每次加载hibernate时都会删除上一次的生成的表,然后根据你的model类再重新来生成新表,
                     哪怕两次没有任何改变也要这样执行,这就是导致数据库表数据丢失的一个重要原因。
             create-drop :每次加载hibernate时根据model类生成表,但是sessionFactory一关闭,表就自动删除。
             update:最常用的属性,第一次加载hibernate时根据model类会自动建立起表的结构(前提是先建立好数据库),
                     以后加载hibernate时根据 model类自动更新表结构,即使表结构改变了但表中的行仍然存在不会删除以前的行。
                     要注意的是当部署到服务器后,表结构是不会被马上建立起来的,是要等 应用第一次运行起来后才会。
             validate :每次加载hibernate时,验证创建数据库表结构,只会和数据库中的表进行比较,不会创建新表,但是会插入新值。
             -->

        <!-- 注册实体关系映射文件 -->
        <mapping resource="com/southwind/entity/People.hbm.xml"></mapping>
        <mapping resource="com/southwind/entity/Customer.hbm.xml"></mapping>
        <mapping resource="com/southwind/entity/Orders.hbm.xml"></mapping>
<!--        <mapping resource="com/southwind/entity/Account.hbm.xml"></mapping>-->
<!--        <mapping resource="com/southwind/entity/Course.hbm.xml"></mapping>-->

    </session-factory>
</hibernate-configuration>

4、使⽤ Hibernate API 完成数据操作

package com.southwind.test;

import com.southwind.entity.Customer;
import com.southwind.entity.Orders;
import com.southwind.entity.People;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

public class Test2 {
    public static void main(String[] args) {

        //创建Configuration,即配置类对象 默认的是去读hibernate.cfg.xml,
        // 不然你就在下面一行最后面这样写:.configure("hibernate.xml");,这个可以自己在resources下面定义文件名是什么
//        Configuration configuration = new Configuration().configure();
//        System.out.println("configuration = " + configuration);


        //创建Configuration,即配置类对象 默认的是去读hibernate.cfg.xml,
        // 不然你就在下面一行最后面这样写:.configure("hibernate.xml");,这个可以自己在resources下面定义文件名是什么
        Configuration configuration = new Configuration().configure();
        //获取SessionFactory
        SessionFactory sessionFactory = configuration.buildSessionFactory();
        //获取Session
        Session session = sessionFactory.openSession();

        //创建 Customer
        Customer customer = new Customer();
        customer.setName("张三");

        //创建 Orders
        Orders orders = new Orders();
        orders.setName("订单1");

        //建立关联关系
        orders.setCustomer(customer);

        //保存
        session.save(customer);
        session.save(orders);

        //提交事务
        session.beginTransaction().commit();

        //关闭session
        session.close();
    }
}

2、多对多关系

学⽣选课:

⼀⻔课程可以被多个学⽣选择,⼀个学⽣可以选择多⻔课程,学⽣是多,课程也是多。
数据库中是通过两个⼀对多关系来维护的,学⽣和课程都是主表,额外增加⼀张中间表作为从表,两张 主表和中间表都是⼀对多关系。

 

代码实现:

1、Account实体类和Account.hbm.xml文件:

//Account实体类:
@Getter
@Setter
public class Account {
    private Integer id;
    private String name;
    private Set<Course> courses; //一个学生对应多个课程

    @Override
    public String toString() {
        return "Account{" +
                "id=" + id +
                ", name='" + name + '\'' +
                '}';
    }
}

#Account.hbm.xml文件:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping> <!--文件名的hbm就是hibernate-mapping 的缩写,在这里面完成类和表的映射-->

    <!-- class 就是指类,name就是指类名 table 就是指对应的表名,表customer里面有id和name两个字段-->
    <class name="com.southwind.entity.Account" table="account">
       <!-- 主键映射 name指的是实体类里面的属性:id   type指的是id属性的类型-->
        <id name="id" type="java.lang.Integer">
            <!--column是字段,指的是对应类里面id的表里面的名称-->
            <column name="id"></column>
            <!--这个是配置主键自增的方式,identity的意思就是自增-->
            <generator class="identity"></generator>
        </id>
        <!-- 下面继续配置类里面的其他信息,name   type指的是name属性的类型-->
        <property name="name" type="java.lang.String">
            <!--column是字段,指的是对应类里面name的表里面的名称-->
            <column name="name"></column>
        </property>

        <!-- 下面继续配置类里面的其他信息,因为是set集合,就直接用set配,private Set<Course> courses; //一个学生对应多个课程-->
        <!--这里要特别注意,多对多关系的话,这里的table是中间表,account_course-->
        <set name="courses" table="account_course" >
            <!-- key是外键,column是字段,指的是表里面的外键名称-->
            <key column="aid"></key>
            <!-- 怎么去映射这个东西,这里面many-to-many 指的是多对多的关系     private Set<Orders> orders;
                  class表示是这里面的类从哪里来的,创建Course对象把它装到set集合里面-->
            <!-- 注意这里是要加上column="cid",即course在中间标的外键名称-->
            <many-to-many class="com.southwind.entity.Course" column="cid"></many-to-many>
        </set>

    </class>

</hibernate-mapping>

2、Course实体类和Course.hbm.xml文件:

//Course实体类:
@Getter
@Setter
public class Course {
    private Integer id;
    private String name;
    private Set<Account> accounts; //一个课程对应多个学生

    @Override
    public String toString() {
        return "Course{" +
                "id=" + id +
                ", name='" + name + '\'' +
                '}';
    }
}

#Course.hbm.xml文件:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping> <!--文件名的hbm就是hibernate-mapping 的缩写,在这里面完成类和表的映射-->

    <!-- class 就是指类,name就是指类名 table 就是指对应的表名,表customer里面有id和name两个字段-->
    <class name="com.southwind.entity.Course" table="course">
       <!-- 主键映射 name指的是实体类里面的属性:id   type指的是id属性的类型-->
        <id name="id" type="java.lang.Integer">
            <!--column是字段,指的是对应类里面id的表里面的名称-->
            <column name="id"></column>
            <!--这个是配置主键自增的方式,identity的意思就是自增-->
            <generator class="identity"></generator>
        </id>
        <!-- 下面继续配置类里面的其他信息,name   type指的是name属性的类型-->
        <property name="name" type="java.lang.String">
            <!--column是字段,指的是对应类里面name的表里面的名称-->
            <column name="name"></column>
        </property>

        <!-- 下面继续配置类里面的其他信息,因为是set集合,就直接用set配,private Set<Account> accounts; //一个课程对应多个学生-->
        <!--这里要特别注意,多对多关系的话,这里的table是中间表,account_course-->
        <set name="accounts" table="account_course" >
            <!-- key是外键,column是字段,指的是表里面的外键名称-->
            <key column="cid"></key>
            <!-- 怎么去映射这个东西,这里面many-to-many 指的是多对多的关系     private Set<Orders> orders;
                  class表示是这里面的类从哪里来的,创建Course对象把它装到set集合里面-->
            <!-- 注意这里是要加上column="cid",即course在中间标的外键名称-->
            <many-to-many class="com.southwind.entity.Account" column="aid"></many-to-many>
        </set>
<!--        name 实体类对应的集合属性名-->
<!--        table 中间表名-->
<!--        key 外键-->
<!--        many-to-many 与集合泛型的实体类对应-->
<!--        column 属性与中间表的外键字段名对应-->

    </class>

</hibernate-mapping>

3、hibernate.cfg.xml文件:(实体关系映射⽂件注册到 Hibernate 的配置⽂件中。)

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<!--    核⼼配置:session-factory-->
<!--    SessionFactory:针对单个数据库映射经过编译的内存镜像⽂件,将数据库转换为⼀个 Java 可以识别的镜像⽂件。-->
<!--    构建 SessionFactory ⾮常耗费资源,所以通常⼀个⼯程只需要创建⼀个 SessionFactory。-->
    <session-factory>
        <!-- datasource 数据源配置 -->
        <property name="connection.username">root</property>
        <property name="connection.password">123456</property>
        <property name="connection.driver_class">com.mysql.cj.jdbc.Driver</property>
        <property name="connection.url">jdbc:mysql://localhost:3306/test?useUnicode=true&amp;characterEncoding=utf8&amp;serverTimezone=GMT</property>
<!--?useUnicode=true&amp;characterEncoding=utf8&amp;serverTimezone=GMT" />-->

        <!-- C3P0 连接池 -->
        <property name="hibernate.c3p0.acquire_increment">10</property>    <!-- 每次不够的话就会增加的数量-->
        <property name="hibernate.c3p0.idle_test_period">10000</property>  <!--释放资源时间的设置,s为单位-->
        <property name="hibernate.c3p0.timeout">5000</property>            <!-- 超时时间-->
        <property name="hibernate.c3p0.max_size">30</property>             <!-- 最大连接数-->
        <property name="hibernate.c3p0.min_size">5</property>              <!-- 最小连接数-->
        <property name="hibernate.c3p0.max_statements">10</property>       <!-- 最大线程数数-->
        <!-- 数据库⽅⾔ oracle或mysql-->
        <property name="dialect">org.hibernate.dialect.MySQLDialect</property>
        <!-- 打印SQL语句,固定写法 -->
        <property name="show_sql">true</property>
        <!-- 格式化SQL语句,固定写法 -->
        <property name="format_sql">true</property>
        <!-- 是否⾃动⽣成数据表-->
        <property name="hibernate.hbm2ddl.auto">update</property>
        <!-- create:每次加载hibernate时都会删除上一次的生成的表,然后根据你的model类再重新来生成新表,
                     哪怕两次没有任何改变也要这样执行,这就是导致数据库表数据丢失的一个重要原因。
             create-drop :每次加载hibernate时根据model类生成表,但是sessionFactory一关闭,表就自动删除。
             update:最常用的属性,第一次加载hibernate时根据model类会自动建立起表的结构(前提是先建立好数据库),
                     以后加载hibernate时根据 model类自动更新表结构,即使表结构改变了但表中的行仍然存在不会删除以前的行。
                     要注意的是当部署到服务器后,表结构是不会被马上建立起来的,是要等 应用第一次运行起来后才会。
             validate :每次加载hibernate时,验证创建数据库表结构,只会和数据库中的表进行比较,不会创建新表,但是会插入新值。
             -->

        <!-- 注册实体关系映射文件 -->
        <mapping resource="com/southwind/entity/People.hbm.xml"></mapping>
        <mapping resource="com/southwind/entity/Customer.hbm.xml"></mapping>
        <mapping resource="com/southwind/entity/Orders.hbm.xml"></mapping>
        <mapping resource="com/southwind/entity/Account.hbm.xml"></mapping>
        <mapping resource="com/southwind/entity/Course.hbm.xml"></mapping>

    </session-factory>
</hibernate-configuration>

4、使⽤ Hibernate API 完成数据操作

package com.southwind.test;

import com.southwind.entity.Account;
import com.southwind.entity.Course;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

import java.util.HashSet;
import java.util.Set;

public class Test3 {
    public static void main(String[] args) {
        //创建 Configuration
        Configuration configuration = new Configuration().configure();
        //获取 SessionFactory
        SessionFactory sessionFactory = configuration.buildSessionFactory();
        //获取 Session
        Session session = sessionFactory.openSession();
        //创建 Course
        Course course = new Course();
        course.setName("Java");
       //创建 Account
        Account account = new Account();
        account.setName("张三");

        //建立关联关系
        Set<Course> courses = new HashSet<>();
        courses.add(course);
        //建立关联关系
        account.setCourses(courses);

        //保存
        session.save(course);
        session.save(account);
       //提交事务
        session.beginTransaction().commit();
        //关闭session
        session.close();
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

91科技

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值