Hibernate总结(二)

在上一篇Hibernate总结(一)简单总结了一级缓存,快照,增删改查的简单使用,这一篇总结两张表的级联操作。

级联涉及到三种情况,many-many,1-many,many-1。

  • 首先是1-many,many-1情况,所以先设置一个情景:客户与订单的关系
//因为太占版面缘故,没有列出get()/set()方法
public class Customer {
    private Integer id;
    private String name;
    private Set<Order> orders = new HashSet<Order>();//1对多
}
public class Order {
    private Integer id;
    private String name;
    private Customer customer;//多对1
}

接下来是hibernate.cfg.xml与两个实体类的配置文件Order.hbm.xml与Customer.hbm.xml,第一个不多说,主要是映射文件的配置

//Customer.hbm.xml
<hibernate-mapping package="king.domain">
    <class name="Customer" table="t_customer">
        <id name="id" column="id">
            <generator class="native"></generator>
        </id>
        <property name="name" column="name"></property>
        <!-- 一对多关系 -->
        <!--         inverse:true 不维护关系,交给拥有外键一方维护       cascade:save-update(级联保存与级联更新),当然还有其它选项,delete(级联删除),all(级联保存,更新,删除),none(默认没有级联)       -->
        <set name="orders" inverse="true" cascade="save-update">
            <key column="cid"></key>      <!-- 在Order表中的外键的名字-->
            <one-to-many class="Order"/>
        </set>
    </class>
</hibernate-mapping>
//Order.hbm.xml
<hibernate-mapping package="king.domain">
    <class name="Order" table="t_order">
        <id name="id" column="id">
            <generator class="native"></generator>
        </id>
        <property name="name" column="name"></property>
        <!-- 多对一关系 -->
        <!-- 含有外键一方维护关系 -->
        <many-to-one name="customer" column="cid" class="Customer"></many-to-one>
    </class>
</hibernate-mapping>

一切准备就绪,开始级联的代码:

因为代码中大量使用了得到连接,关闭连接操作,所以我使用了模板设计模式,在我的文章《Hibernate-模板模式》有讲解

    /**
     * 级联保存:
     * 1.inverse="true",维护关系,最好只有一方维护,而且是拥有外键一方维护
     * 2.cascade="save-update",级联保存与级联更新
     */
    @Test
    public void test0() {
        new SessionTemplate(){
            @Override
            public void fun(Session s) {
                Customer c=new Customer();
                c.setName("King");
                Order o1=new Order();
                o1.setName("炒面");
                Order o2=new Order();
                o2.setName("肉");

                o1.setCustomer(c);//由拥有外键一方维护关系
                o2.setCustomer(c);

                s.save(c);
                s.save(o1);
                s.save(o2);//这样框架只执行了3条SQL语句
            }
        }.execute();
    }
    /**
     * 级联删除:
     * 1.inverse="false"为默认处理方式:把客户的订单的外键修改为null,然后再删除客户
     * 2.inverse="true"若客户不处理,会出错
     */
    @Test
    public void test1() {
        new SessionTemplate(){
            @Override
            public void fun(Session s) {         //这是没有使用级联删除的情况,这时cascade为save-update
                Customer c=(Customer) s.get(Customer.class, 3);
                for(Order o:c.getOrders()){
                    s.delete(o);
                }
                s.delete(c);//此时,inverse="true",所以前面删除了所有客户的订单才能删除客户

          //更改配置文件,cascade为delete,这时就是级联删除
                Customer c=(Customer) s.get(Customer.class, 3);
                s.delete(c);//这时不需要手动删除订单了
            }
        }.execute();
    }
    /**
     * 级联更新   * cascade为save-update 
     */
    @Test
    public void test2() {
        new SessionTemplate(){
            @Override
            public void fun(Session s) {
                Customer c=(Customer) s.get(Customer.class, 2);
                for(Order o:c.getOrders()){
                    o.setName("羊杂汤");//持久态,不需要更新
                }
            }
        }.execute();
    }

查询涉及到了加载策略,所以很复杂,所以将在写在下一篇中。

  • 接下来说many-many的情况,还是先设置一个情景:学生与课程的关系
public class Student {
    private Integer id;
    private String name;
    private Set<Course> courses=new HashSet<>();//多对多
}
public class Course {
    private Integer id;
    private String name;
    private Set<Student> students=new HashSet<>();//多对多
}

接下来是两个实体类与数据库表的映射文件:

//Student.hbm.xml
<hibernate-mapping package="king.domain">
    <class name="Student" table="t_student">
        <id name="id" column="id">
            <generator class="native"></generator>
        </id>
        <property name="name" column="name"></property>
        <!-- 多对多关系,在多对多中,需要双方都设置存储关系的表名 -->
        <set name="courses" cascade="save-update" table="t_selectcourse">
            <key column="sid"></key>
            <many-to-many class="Course" column="cid"></many-to-many>
        </set>
    </class>
</hibernate-mapping>
//Course.hbm.xml
<hibernate-mapping package="king.domain">
    <class name="Course" table="t_course">
        <id name="id" column="id">
            <generator class="native"></generator>
        </id>
        <property name="name" column="name"></property>
        <!-- 多对多关系 -->
        <!-- 维护权反转给对方 -->
        <set name="students" inverse="true" table="t_selectcourse">
            <key column="cid"></key>
            <many-to-many class="Student" column="sid"></many-to-many>
        </set>
    </class>
</hibernate-mapping>

一切准备继续,开始代码工作:

    /**
     * 多对多
     * 级联保存:   * 本来想也写上级联删除与级联更新,但是发现写的代码和我想要实现的结果不同,故没有贴出代码,额...我的意思就是我也不会...挺尴尬...
     */
    @Test
    public void test0() {
        new SessionTemplate(){
            @Override
            public void fun(Session s) {
                Student s1=new Student();
                s1.setName("King");

                Course c1=new Course();
                c1.setName("数学");
                Course c2=new Course();
                c2.setName("英语");

                s1.getCourses().add(c1);//由学生维护关系
                s1.getCourses().add(c2);//由学生维护关系

                s.save(s1);
            }
        }.execute();
    }

增删改查,现在就差“查”没有写出,我将在下一篇总结中写出Hibernate的关于查询的加载策略。

时间: 2024-08-23 12:54:50

Hibernate总结(二)的相关文章

深入浅出Hibernate(二)多对一关系映射

学习Hibernate是为了更方便的操作数据库,在数据库中的关系模型中存在多对一的关系,比如下图所示的员工和部门之间的关系,那么这种关系在Hibernate中如何映射呢?让我用一个小Demo来详细讲解. 建立映射分为以下几步: 1.设计domain对象Department.Employee,代码如下: package cn.itcast.hibernate.domain; public class Department { private int id; private String name;

Hibernate复习(二)主要对象

1.SessionFactory 一个SessionFactory实例对应一个数据存储源,应用从SessionFactory中获得Session实例. SessionFactory有以下特点: –它是线程安全的,这意味着它的同一个实例可以被应用的多个线程共享. –它是重量级的,这意味着不能随意创建或销毁它的实例.如果应用只访问一个数据库,只需要创建一个SessionFactory实例,在应用初始化的时候创建该实 例.如果应用同时访问多个数据库,则需要为每个数据库创建一个单独的SessionFac

Hibernate实例二

Hibernate实例二 一.测试openSession方法和getCurrentSession方法 hebernate中可以通过上述两种方法获取session对象以对数据库进行操作,下面的代码以及注解是对两种方法的辨析 SessionTest.java 1 import java.sql.Connection; 2 import java.sql.SQLException; 3 import java.util.Date; 4 5 import org.hibernate.Session; 6

hibernate(二)annotation第一个示例

一.在数据库中创建teacher表(数据库hibernate) create table teache( id int auto_increment primary key, name varchar(20), title varchar(20) ); 二.创建model 在cn.orlion.hibernate.model下创建实体类Teacher(注意添加注解,一开始只添加了@Id,然后抛出异常,后来又加上了@GeneratedValue(strategy = GenerationType.

Hibernate(十二)Criteria查询

一.简述 Criteria是一种比hql更面向对象的查询方式.Criteria 可使用 Criterion 和 Projection 设置查询条件.可以设置 FetchMode(联合查询抓取的模式 ) ,设置排序方式,Criteria 还可以设置 FlushModel (冲刷 Session 的方式)和 LockMode (数据库锁模式). Criteria本身只是查询的容器.Criteria查询又称对象查询 Criteria查询采用面向对象的方式封装查询条件.由Hibernater自动生成SQ

Hibernate(二)

1. 对象的状态 代码 public class StateTest extends HiberanteUtils{ /** * session.save方法把一个临时状态的对象转化成持久化状态的对象 */ @Test public void testSavePerson(){ Session session = sessionFactory.openSession(); Transaction transaction = session.beginTransaction(); Person p

spring mvc+spring + hibernate 整合(二)

在上篇文章中,我建立了工程并配置了spring + hibernate.今天我们检验下上篇文章的成果,如何检查呢?那就是进行单元测试.本篇文章就让大家和我一起来就前面的建的工程进行单元测试.     本项目使用Junit进行单元测试,需要引用单元测试的包,在的工程建立中已有了如何引入单元测试的依赖,这里就不多说了.要进行单元单元测试,我们就按下面的步骤进行 一:建立实体 本例是刚弄开始学习,所以表不弄得太复杂,我们就以用户登录为例:建立一个用户对象,拥有用户名和密码两个属性,密码开始也使用名文的

Hibernate(二)之Hibernate-api详解

一.Hibernate体系结构 二.Hibernate-api详解 2.1.Configuration配置对象 Configuration是用来加载配置文件的 我们Hibernate中主要有两个配置文件,第一个是核心的配置文件,第二个是映射文件. 2.2.SessionFactory工厂 SessionFactory 相当于java web连接池,用于管理所有session 获得方式:config.buildSessionFactory(); sessionFactory hibernate缓存

Hibernate学习(二)

一.Hibernate持久化状态 瞬时态 瞬时态也称为临时态或者自由态,瞬时态的实例是由new命令创建.开辟内存空间的对象,不存在持久化OID(相当于键),尚未与Hibernate Session建立关联,在数据中也没有任何记录,失去引用后被JVM回收.瞬时态对象在内存中是孤立存在的,与数据库中的数据无任何关联,仅仅是信息的载体. 持久态 持久态的对象存在持久化的标识OID,加入Session缓存中,并且相关联的Session没有关闭,在数据库中有相应的记录,每条记录只对应唯一的持久化对象,需要

hibernate笔记(二)

目标: 关联映射(hibernate映射) 1. 集合映射 2. 一对多与多对一映射 (重点) 3. 多对多映射 4. inverse/lazy/cascade 1. 集合映射 开发流程: 需求分析/数据库设计.项目设计/ 编码/测试/实施部署上线/验收 需求: 用户购买, 填写地址! 数据库: 代码: // javabean设计 public class User { private int userId; private String userName; // 一个用户,对应的多个地址 pr