一对多关系映射的crud操作:

1.单项的保存操作

/**

     * 保存操作

     * 正常的保存:创建一个联系人,需要关联客户

     */

    @Test

    public void test1(){

       Session s=HibernateUtils.getCurrentSession();

       Transaction tx=s.beginTransaction();

       //1.查询一个客户

       Customer c1=s.get(Customer.class,1L);

       //2.创建一个联系人

       LinkMan l=new LinkMan();

       l.setLkmName("一对多的联系人");

       //3.建立客户联系人的关联关系(让联系人知道他属于哪个客户)

       l.setCustomer(c1);

       //4.保存联系人

       s.save(l);

       tx.commit();

     }

2.双向的保存操作:

/**

     * 创建一个客户和一个联系人,创建客户和联系人的双向关系

     * 使用符合原则的保存

     * 先保存主表的实体,再保存从表的实体

     * 此时保存会有问题:

     * 保存应该只是两条insert语句,而执行结果是多了一条Update

      */

@Test

    public void test2(){

       Session s=HibernateUtils.getCurrentSession();

       Transaction tx=s.beginTransaction();

       //1.创建一个客户

       Customer c1=new Customer();//瞬时态对象

       c1.setCusname("一对多别的客户2");

       //2.创建一个联系人

       LinkMan l=new LinkMan();//瞬时态对象

       l.setLkmName("一对多的联系人2");

       //3.建立客户联系人的关联关系(双向)

       l.setCustomer(c1);

       c1.getLinkmans().add(l);

       //4.保存,要符合原则

       s.save(c1);//持久态,会有一级缓存和快照,有OID,和session有关系

       s.save(l);//持久态,会有一级缓存和快照,有OID,和session有关系

       tx.commit();

     }

注意:在此函数执行的时候,先执行了两条insert语句,然后执行了一条update语句,其原因如下:

是因为Hibernate的快照技术,使得先后执行的语句在快照区的内容不一样,只能在最后commit的时候重新刷新数据库,从而有了一条update语句。

解决办法:让客户在执行操作的时候,放弃维护关联关系的权利。

* 配置的方式,在customer的映射配置文件的set标签使用inverse属性

* inverse:是否放弃维护关联关系的权利,true:是,false:否(默认值)

<set name="linkmans" table="cust_linkman" inverse="true">

        <key column="lkm_cust_id" ></key>

        <one-to-many class="LinkMan"></one-to-many></set>

3.一对多的级联保存

加入有很多订单,一个一个保存太麻烦,直接用级联保存,就可以一次保存完,而不再用传统的方式一个一个去保存,方法如下:

/**

     * 保存操作,级联操作

     * 使用级联保存,配置的方式,

     *     使用customer的set标签

     *         在上面加入cascade属性

     *         cascade:配置级联操作

     *         级联保存更新的保存:save-update

     *     也可以配置在<one-to-many/>这个标签上

     */

    @Test

    public void test3(){

       Session s=HibernateUtils.getCurrentSession();

       Transaction tx=s.beginTransaction();

       //1.创建一个客户

       Customer c1=new Customer();//瞬时态对象

       c1.setCusname("一对多别的客户4");

       //2.创建一个联系人

       LinkMan l=new LinkMan();//瞬时态对象

       l.setLkmName("一对多的联系人4");

       //3.建立客户联系人的关联关系(双向)

       l.setCustomer(c1);

       c1.getLinkmans().add(l);

       //4.保存,要符合原则

       s.save(c1);//只保存了c1

       tx.commit();

    }

    @Test

    public void test4(){

       Session s=HibernateUtils.getCurrentSession();

       Transaction tx=s.beginTransaction();

       //1.创建一个客户

       Customer c1=new Customer();//瞬时态对象

       c1.setCusname("一对多别的客户5");

       //2.创建一个联系人

       LinkMan l=new LinkMan();//瞬时态对象

       l.setLkmName("一对多的联系人5");

       //3.建立客户联系人的关联关系(双向)

       l.setCustomer(c1);

       c1.getLinkmans().add(l);

       //4.保存,要符合原则

       s.save(l);//只保存了l

       tx.commit();

}

注意:在此时的实体类的映射配置中需要加入:

1,<set/>标签级联保存

<set name="linkmans" table="cust_linkman" inverse="true" cascade="save-update">

            <key column="lkm_cust_id" ></key>

            <one-to-many class="LinkMan"></one-to-many>

        </set>

2. <many-to-one name="customer" class="Customer" column="lkm_cust_id" cascade="save-update"></many-to-one>

用这两种方式都可以实现只需要在代码中保存一个实体,即可保存所有级联实体,只不过配置时候注意要对应配置。

4. 更新操作,双向的操作

/**

     * 更新操作:创建一个联系人,查询一个已有客户

     * 建立新联系人和已有客户的双向关联关系

     * 更新联系人

     */

    @Test

    public void test5(){

       Session s=HibernateUtils.getCurrentSession();

       Transaction tx=s.beginTransaction();

       //1.查询一个客户

       Customer c1=s.get(Customer.class,3L);

       //2.创建一个联系人

       LinkMan l=new LinkMan();

       l.setLkmName("一对多的联系人1");

       //3.建立客户联系人的关联关系(双向)

       l.setCustomer(c1);

       c1.getLinkmans().add(l);

       //4.更新客户

       s.update(c1);

       tx.commit();

    }  

需要注意的是在此时如果set的配置标签里面如果配置了inverse="true"的话,会忽略更新的,这儿需要注意一下,但是cascade必须是save-update,因为在update之前是没有保存那个联系人l,如果不设置这个的话直接报错的。

5.删除操作

1.删除的时候如果是从表,则直接删除,若是主表,同时从表的外键可以为null的时候,删除主表的同时直接将其从表中的外键直接置为null

 /**

     * 删除操作

     *     删除从表就是单表

     * 删除主表数据

     *     先看从表数据引用

     *     有引用:hibernate会吧从表中的外键置位null,然后再删除

     *     无引用:直接删

     */

    @Test

    public void test6(){

       //此时的外键允许为null

       Session s=HibernateUtils.getCurrentSession();

       Transaction tx=s.beginTransaction();

       //1.查询一个客户

       Customer c1=s.get(Customer.class,68L);

       //删除ID为68的客户

       s.delete(c1);

       tx.commit();

}

2.若果从表中要删除某个主表的数据,并且要删除与它级联的从表中的数据,则需要配置级联删除,如下,但是不建议使用该级联删除,是一个很危险的操作

<set name="linkmans" table="cust_linkman" inverse="false" cascade="save-update,delete">

            <key column="lkm_cust_id" ></key>

            <one-to-many class="LinkMan"></one-to-many>

        </set>

若从表的外键约束为not null的话,想要在主表中删除某数据,并且此数据在从表中有对应的外键引用,则需要配置主表的额inverse=true,只有配置了这个才可以级联删除,因为只有这样的话,主表才不会维护他的约束,才可以允许级联删除不。

6.对象导航查询

一对多的查询操作:OID查询,QBC查询,SQL查询

hibernate中的最后一种查询方式,对象导航查询

当两个实体类之间有关联关系时候(可以是任一一种)

通过调用getXXX方法即可达到实现查询功能(是有hibernate提供的方法)

eg:customer.getLinkMans()就可以得到当前客户的所有联系人

通过linkman.getCustomer()就可以得到当前联系人的所属客户

  1. 注意:一对多时候,根据一的一方查询多的一方是,需要使用延迟加载lazy=true(默认配置即可)
 <set name="linkmans" table="cust_linkman" lazy="true">

            <key column="lkm_cust_id" ></key>

            <one-to-many class="LinkMan"></one-to-many>

    </set>
/**

     *查询ID为1的客户下的所属联系人

     */

    @Test

    public void test1(){

       Session s=HibernateUtils.getCurrentSession();

       Transaction tx=s.beginTransaction();

       Customer c=s.get(Customer.class, 1L);//查询ID为1的客户

       /*System.out.println(c);

       System.out.println(c.getLinkmans());*/

       Set<LinkMan> linkmans=c.getLinkmans();

       System.out.println(c);

       System.out.println(linkmans);//注意此时是连查询带打印,而不是先查询,在打印

       tx.commit();

    }

2.多对一时候,根据多的一方查询一的一方时候,不需要使用延迟加载,而是立即加载,需要配置一下,需要找到联系人的<many-to-one>标签上,使用lazy属性,取值有false(立即加载),proxy(看是load方法是延迟加载,还是立即加载)

<class name="LinkMan" table="cust_linkman" lazy="false"><many-to-one name="customer" class="Customer" column="lkm_cust_id" lazy="proxy"></many-to-one>

        </class>

    /**

     *查询ID为5的联系人属于哪个客户

     *.多对一时候,根据多的一方查询一的一方时候,不需要使用延迟加载,而是立即加载,

     *需要配置一下,需要找到联系人的<many-to-one>标签上,

     *使用lazy属性,

     *     取值有:

     *     false(立即加载),

     *     proxy(看是load方法是延迟加载,还是立即加载)

     */ @Test

    public void test2(){

       Session s=HibernateUtils.getCurrentSession();

       Transaction tx=s.beginTransaction();

       LinkMan l=s.get(LinkMan.class,5L);

       System.out.println(l);

       System.out.println(l.getCustomer());//注意此时是连查询带打印,而不是先查询,在打印

       tx.commit();

    }
  1. 关于load方法的是否延迟加载

在多的一方配置文件里面的class属性设置lazy=false(这个地方的lazy只负责load方法的加载方式),即立即加载的时候,如果此时设置<many-to-one>里面的属性为lazy=proxy时候,则是根据load方法是否延迟加载来定的,但是<many-to-one>中lazy的级别大于class中配置lazy的级别

  /**

     * 关于load方法改为立即加载的方式

     * 找到查询实体类的映射配置文件,它的class属性上边也有一个lazy属性,是否延迟加载,

     * true为延迟加载,false为立即加载

     */

    @Test

    public void test3(){

       Session s=HibernateUtils.getCurrentSession();

       Transaction tx=s.beginTransaction();

       Customer c=s.load(Customer.class, 1L);//查询ID为1的客户

       System.out.println(c);

       tx.commit();

    }

Class标签的lazy;只能管load的方法是否是延迟加载

Set标签的lazy:管查询关联的集合对象是否延迟加载

Many-to-one标签的lazy:只管查询关联的主表实体是否是立即加载

hibernate的CRUD操作的更多相关文章

  1. hibernate之CRUD操作

    CRUD是指在做计算处理时的增加(Create).读取(Retrieve)(重新得到数据).更新(Update)和删除(Delete)几个单词的首字母简写. 下面列举实例来讲解这几个操作: 实体类: ...

  2. java框架篇---hibernate之CRUD操作

    CRUD是指在做计算处理时的增加(Create).读取(Retrieve)(重新得到数据).更新(Update)和删除(Delete)几个单词的首字母简写. 下面列举实例来讲解这几个操作: 实体类: ...

  3. 【Java EE 学习 44】【Hibernate学习第一天】【Hibernate对单表的CRUD操作】

    一.Hibernate简介 1.hibernate是对jdbc的二次开发 2.jdbc没有缓存机制,但是hibernate有. 3.hibernate的有点和缺点 (1)优点:有缓存,而且是二级缓存: ...

  4. hibernate入门-基本配置及简单的crud操作

    框架来说主要是需要写大量的配置文件,hibernate相比mybatis来说更强大,移植性更好: 1.类和数据库的映射配置:配置文件命名一般--类名.hbm.xml (user.hbm.xml),与实 ...

  5. 【SSH三大框架】Hibernate基础第五篇:利用Hibernate完毕简单的CRUD操作

    这里利用Hibernate操作数据库完毕简单的CRUD操作. 首先,我们须要先写一个javabean: package cn.itcast.domain; import java.util.Date; ...

  6. hibernate Session的CRUD操作

    使用Session里面的方法进行CRUD操作 (1) 增加 save 方法 (2) 查找 get 方法(根据id查) (3) 修改 update 方法 (4) 删除 delete 方法 1.增加 /* ...

  7. Hibernate 系列 03 - 使用Hibernate完成持久化操作

    引导目录: Hibernate 系列教程 目录 康姆昂,北鼻,来此狗.动次打次,Hibernate继续走起. 目录: 使用Hibernate实现按主键查询 使用Hibernate实现数据库的增.删.改 ...

  8. Hibernate基本CRUD

    1 hibernate 框架介绍 冬眠:开发的代码基本不变. 1.1回顾jdbc Java提供的标准的数据访问的API 作用:完成应用程序java程序中的数据和db中的数据进行交换. 工作过程: A ...

  9. Java实战之02Hibernate-01简介、常用接口、CRUD操作

    一.Hibernate简介 1.Hibernate在开发中所处的位置 2.ORM映射 Object :面向对象领域的 Relational:关系数据库领域的 Mapping:映射 Object: Re ...

随机推荐

  1. scss-@if指令

    @if指令接受表达式和使用嵌套样式,无论表达式的结果只不过是false或null. 语法: @if expression { //CSS codes are written here } scss实例 ...

  2. ZROJ#398. 【18提高7】随机游走(期望dp 树形dp)

    题意 [题目链接]版权原因就不发了.. 给出一棵树,求出任意两点之间期望距离的最大值 Sol 比较清真的一道题吧.. 设\(f[x]\)表示从\(x\)走到\(x\)的父亲的期望步数 \(g[x]\) ...

  3. 学习JVM虚拟机原理总结

    0x00:JAVA虚拟机的前世今生 1991年,在Sun公司工作期间,詹姆斯·高斯林和一群技术人员创建了一个名为Oak的项目,旨在开发运行于虚拟机的编程语言,允许程序多平台上运行.后来,这项工作就演变 ...

  4. Eclipse 各版本名称的由来

    2001年11月7日 ,Eclipse 1.0发布 半年之后,2002年6月27日Eclipse进入了2.0时代.2.0时代的Eclipse经历了2.0和2.1两个大的版本.其中2.0在 之后又推出了 ...

  5. java面试之----堆(heap)、栈(stack)和方法区(method)

    JAVA的JVM的内存可分为3个区:堆(heap).栈(stack)和方法区(method)也叫静态存储区. 堆区: 1.存储的全部是对象,每个对象都包含一个与之对应的class的信息.(class的 ...

  6. 开发者为何对Service Fabric爱不释手?值得关注!

    有了它,人人都可开发高可用高伸缩应用.今天小编就为大家介绍一款开发者的“利器”——Service Fabric . 在介绍它之前,先来了解一下它的背景. Service Fabric 是一款应用程序平 ...

  7. Java 实现斐波那契数列

    public class Fibonacci { private static int getFibo(int i) { if (i == 1 || i == 2) return 1; else re ...

  8. 为什么有的系统的事务码BSP_WD_CMPWB看不见Enhance Component这个按钮

    我的同事问我,为什么有的系统看不到下图7的按钮? 对比两张图里工具栏的差异. 答案 这是因为在图2(看不见Enhance Component按钮)的系统里,该系统的类型被设置为"SAP&qu ...

  9. UVA1184 Air Raid

    嘟嘟嘟 最小路径覆盖板子题. 建二分图,然后跑Dinic(因为我不会匈牙利),然后ans = n - maxflow(). 主要是发一下用链前存图的写法.(好像比vector短一点) #include ...

  10. UVA515 King

    嘟嘟嘟 题目翻译:有n个数,m个限制条件.每一个限制条件形如:1.x y gt c:表示ax + ax+1 + … +ay > c.2.x y It c:表示ax + ax+1 + …… +ay ...