`

小弦教你学hibernate

阅读更多

映射关联关系

建立从OrderCustomer的多对一关联关系

public class Order {

              private Integer id ;

              private String orderno ;

              private float price;

 

/* 建立从OrderCustomer的多对一关联关系 */

             private Customer customer ;

             ...//get/set

}

要建立多对一关联 ,我在Order类里边加属性。

关联关系 以属性声明的方式体现,所以在Order里边加一个private Customer customer

性。

--------------------------------------

 

映射文件Order.hbm.xml

<hibernate-mapping package="cn.itcast.hibernate.domain">

              <class name="Order" table="orders" lazy="false">

                     <id name="id" column="id" type="integer">

                            <!-- 主键生成策略 -->

                            <generator class="identity" />

                     </id>

                     <property name="orderno" column="orderno" type="string" length="20" />

                     <property name="price" column="price" type="float"  />

                    

                     <!-- 关联元素 -->

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

                     <!--多对一单向关联,是从Order出发 ,往Customer映射-->

              </class>

       </hibernate-mapping>

<set inverse="true">

       inverse:反转,让缓存忽略的set的集合变化.set失去对关联关系的控制权.只按照对端的状态更新数据库.

 

级联保存:

       保存CustomerOrder对象时,如果只保存Order,不保存Customer,会出现临时对象异常(TransientObjectException),

       可以设置many-to-one元素的cascade属性为save-update,hibernate会自动将和Order关联的Customer保存和更新了.

              Order.hbm.xml

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

 

常见操作:

 

public void insert(){

       Session s = sf.openSession();

       Transaction tx = s.beginTransaction();

       Customer c = new Customer();

       c.setAge(12);

      

       Order o = new Order();

       o.setOrderno("No009");

       o.setPrice(500f);

 

       o.setCustomer(c);

       s.save(c);

       s.save(o);

    tx.commit();

    s.close();

}

我是先保存c好还是先保存o好呢??答案是先保存c好,因为如果先保存oorders表有外键,会先把外键置为空,然后在保存c,最后知道外键值了还要有一步跟新oders表操作。

------------------------------------------------

建立CustomerOrder之间一对多关联

       1.Customer.java

       {     //建立从CustomerOrder之间的一对多关联关系

              private Set <Order> orders = new HashSet<Set>();

       }

映射文件

       <!-- 映射一对多关联关系(关联元素) -->

       <set name="orders"> name是属性名称

              <key column="cid" />    columnorders表的外键

              <one-to-many class="cn.itcast.hibernate.domain.Order"/>

       </set>

可以在set集合中设置属性cascade="save-update",我保存Customer的同时,也会把客户的订单保存起来。

cascade属性(包括set元素的cascade)都是指操作行为的传播,即对关联的对象是否也能执行相同的操作.

可以包括的级联操作有save-update,delete.

接下来是重点哦??想想,我们为什么还要建立从客户到订单的一对多关系呢??

       建立一对多关系,也就是在Customer类中设一个Set <Order> order,的主要用途在于查询。当我们按照Customerid 查询一个客户(Customer对象)时,就会也同时查询到,这个客户有多少个订单咯。。。

public void loadCustomer(){

       Session s = sf.openSession();

       Transaction tx = s.beginTransaction();

       Customer  c = (Customer)s.load(Customer.class,1);

       Set<Order> orders = c.gerOrders();

       for(Order o:orders){

       System.out.println(o.getId());

       }

       tx.commit();

       s.close();

}             

                // 保存

                public void saveData(){

                     Session s = sf.openSession();

                     Transaction tx = s.beginTransaction();

                     Customer c = new Customer();

                     Order o = new Order();

                     //设置双向关系,保证程序健壮性

                     o.setCustomer(c);

                     c.getOrders().add(o);

                     s.save(c);

                     //s.save(o);

                    

                     tx.commit();

                     s.close();

                }

 

映射一对多双向关联关系时的注意点:

通常情况下:

1.

one方,把<set>元素的inverse属性设为true,<set inverse="true">

       inverse:反转,让缓存忽略set的集合变化。set失去对关联关系的控制权.只按照另一端的状态更新数据库.提高应用性能。

 

2.one方,如果设把<set>元素的cascade="save-update"

<set name="orders" cascade="save-update" inverse="true">

 

这样做是为了,因为CustomerOrder是一对多的关系,如果想保存Customer的同时,保存Order,就

 

要设置级联保存。总的来说通常情况下把<set>元素中,cascade="save-update" inverse="true"

 

理解<set>元素的inverse属性:举例

<set name="orders" cascade="save-update" inverse="true">

 

       public void insert(){

              Session s = sf.openSession();

              Transaction tx = s.beginTransaction();

              Customer c = new Customer();

              c.setName("tomas");

             

              Order order = new Order();

             

              order.setCustomer(customer);//建立从OrderCustomer的关联关系

              //customer.getOrders.add(order);不建立从CustomerOrder的关联关系

 

              tx.commit();

              s.close();

       }

       设置了Ordercustomer属性,Hibernate就会按照Order对象的变化来同步更新数据库。

而如果

 

       public void insert(){

              Session s = sf.openSession();

              Transaction tx = s.beginTransaction();

              Customer c = new Customer();

              c.setName("tomas");

             

              Order order = new Order();

             

              //order.setCustomer(customer);不建立从OrderCustomer的关联关系

              customer.getOrders.add(order);建立从CustomerOrder的关联关系

 

              tx.commit();

              s.close();

       }

而如果仅设置了Customerorders属性,由于<set>元素的inverse属性为true,因此Hibernate不会按照Customer对象的属性变化同步更新数据库。

补充:说白了吧。Customer 有orders 集合属性,而在Customer这边的映射文件中把<set>元素的inverse属性设为true,所以在保存Customer对象的时候,hibernate不会同步更新数据库.

引发数据错误。 hibernate不会按照Customer对象的属性变化而更新数据库.

所以我们在保存对象的时候,要尽量从Order一方下手,因为Order这边的映射文件

inverse是默认的false,保存order会同步更新数据库.

3.通常情况下,让one方的<set inverse="true">,而在many方,设置级联保存和更新,

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

------------------------------------------------------------------------------------------

常见问题

PropertyValueException异常

<many-to-one>not-null,2个值,一个是true,一个是false.默认值是false,就是外键可以为空,

 

而在表中如果设了外键不可以为空的话,我又在<many-to-one not-null="true">就是可以不为空

 

我用session只保存了Order,而没有先保存Customer的话,Hibernate会向orders表中的插入一条记录,而且把外键设为null,这样就矛盾了,所以会报PropertyValueException异常。

 

映射组成关系

public class Customer{

       id,

       name

}

public class Address{

       private String province;

       private String city;

       private String street;

       private String zipcode;

}

-----------------------------------------------------------------------------------------------------------------------------

一对一映射

外键关联 和多对一映射方式类似,通过多对一来模拟的

       外键具有唯一性

public class User{

       private Integer id;

       private String name;

       private Adder adder;

}

public class Addr{

       private Integer id;

       private String province;

       private User user;

}

 

Addr.hbm.xml

       <class name="Addr" table="addr_fk" lazy="false">

              <id name="id" column="id" type="integer">

                     <generator class="identity"/>

              </id>

              <property name="province" column="province" type="String" length="20">

 

<!--关联元素,唯一性约束-->

              <many-to-one name="user" column="userid" class="User" unique="true"/>

       </class>

 

User.hbm.xml

       <class name="User" table="addr_fk" lazy="false">

              <id name="id" column="id" type="integer">

                     <generator class="identity"/>

              </id>

              <property name="name" column="name" type="String" length="20">

 

<!--关联元素,映射UserAddr的一对一关联,property-ref属性参考,指定对端的关联属性-->

              <one-to-one name="addr" property-ref="user"/>

       </class>

 

-----------------------------------------------------------------------------------------

 

主键关联

 

User.hbm.xml

<class name="User" table="user_pk" lazy="false">

      <id name="id" column="id" type="integer">

             <generator class="identity"/>

      </id>

      <property name="name" column="name" type="string" length="20"/>

            

      <one-to-one name="addr" class="Address"/>

</class>

 

Address.hbm.xml

<id name="id" colunm="id" type="integer">

       <generator class="foreign"/>  从外部提取 ,让地址表的主键跟随用户表的主键保持一致

              <param property="user"> </param>

</id>

<one-to-one name="user" class="User" constrained="false"/>

 

我的id值是从外部的一个属性提取的 user属性

constrained:受到约束的,user!=null user.id!=null

 

----------------------------------------------------------------------------------------

多对多关联

public class Teacher{

 

       private Integer id;

       private String teaNo;

       private Set<Student> students = new HashSet<Student>();

}à一个教师有多个学生

 

//集合中的每个元素类型都是学生

public class Student{

 

       private Integer id;

       private String stuName;

       private Set<Teacher> teachers = new HashSet<Teacher>();

}  à一个学生有多个教师,两边都是一对多

 

-----------------------------------------------------------------------------------------

Teacher.hbm.xml

<!--映射多对多关系,要指定中间表links-->

<!--多对多关系要维护中间表,如果两边都维护的话,导致记录的冲突,所以一定要把一端的维护权消除-->

<set name="students" table="links" inverse="true">

       <key column="tid"/>

       <many-to-many class="Student" column="sid"/我要想查一个教师有几个学生,所以一定要查sid>

</set>

Student.hbm.xml

 

<set name="teachers" table="links" >

       <key column="sid"/>

       <many-to-many class="Teacher" column="tid"/>

</set>

-----------------------------------------------------------------------------------------

public class Teacher {

       private Integer id;

       private String teaNo;

       private Set<Student> students = new HashSet<Student>();

       public Integer getId() {

              return id;

       }

       public void setId(Integer id) {

              this.id = id;

       }

       public String getTeaNo() {

              return teaNo;

       }

       public void setTeaNo(String teaNo) {

              this.teaNo = teaNo;

       }

       public Set<Student> getStudents() {

              return students;

       }

       public void setStudents(Set<Student> students) {

              this.students = students;

       }

       //用一个可变参数往集合中添加元素

       public void addStudent(Student... students){

              for(Student s : students){

                     getStudents().add(s);

              }

       }

}

-----------------------------------------------------------------------------------------

public void save(){

       t1.addStudent(s1,s2,s3);

       s2.addTeacher(t1,t2);

}

-----------------------------------------------------------------------------------------

 

映射自关联 和多对一类似

 

parentid 引入上边的主键值

 

public calss Area{

       private Integer id;

       private String name;

       //建立到上级的多对一关系

       private Area parentArea;

       //建立到下级的一对多关系

       Private Set<Area> children =new HashSet<Area>();

}

Area.hbm.xml

//建立自关联的多对一关系

<many-to-one name="parentArea" column="parentid" class="Area"/>

//建立自关联的一对多关系

<set name="children" inserse="true">

       <key colunm="parentid">

       <one-to-many class="Area">

</set>

 

 

分享到:
评论

相关推荐

    hibernate的最佳实践,是你学习hibernate的最佳教程

    只是一份非常珍贵的hibernatePPT教程。从第一个hibernate的简介到hibernate的完全实践都非常详细,按照课件一步步的操作。你就可以快速掌握真正的企业级hibernate开发实践。是非常珍贵的学习资料

    hibernate 注解 annotation 教程

    hibernate 注解 annotation 教程

    Hibernate经典版 通过图解让你轻松学Hibernate

    Hibernate经典版 通过图解让你轻松学会Hibernate

    hibernate学习

    本人精心搜集了学习hibernate的资料,一些是我以前学习用的,一些是新搜集的 资料。 &lt;br&gt;搜集清单和说明 1:hibernate学习源码,这是我以前做练习的代码,希望对感兴趣的朋友 有些帮助。 2:...

    hibernate教程详解1

    hibernate教程,很详细的hibernate教程,很详细的hibernate教程,很详细的hibernate教程,很详细的hibernate教程,很详细的hibernate教程,很详细的hibernate教程,很详细的hibernate教程,很详细的hibernate教程,...

    hibernate个人学习笔记完整版

    总的来说,【hibernate个人学习笔记完整版】是全面学习Hibernate的理想资源,无论你是初学者还是有经验的开发者,都能从中获取宝贵的知识,提升你的ORM技能。通过系统的学习和实践,你将能够自如地运用Hibernate解决...

    hibernate3.3.2官方完整版-含教程

    hibernate3.3.2官方完整版,内含java调用完整教程

    hibernate完全教程源代码

    hibernate 教程 源代码, 包括关系映射,hql和帮助文档

    Hibernate教程01_Hibernate的HelloWorld及基本配置

    Hibernate教程01_Hibernate的HelloWorld及基本配置 http://blog.csdn.net/e421083458/article/details/8794127 该源码为Hibernate教程配套源码

    Hibernate教程(非常详细)

    Hibernate教程(非常详细)

    Hibernate完整使用教程

    Hibernate 完整使用教程 Hibernate 是一种流行的开源持久层框架,允许开发者使用面向对象编程语言来访问关系数据库。下面是关于 Hibernate 的详细知识点: Hibernate 介绍 Hibernate 是一个开源的持久层框架,它...

    Hibernate-5-教程 详细教程 225页

    Hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,它将POJO与数据库表建立映射关系,是一个全自动的orm框架,hibernate可以自动生成SQL语句,自动执行,使得Java程序员可以...

    Hibernate教程

    Hibernate教程Hibernate教程Hibernate教程Hibernate教程Hibernate教程

    最经典的hibernate教程_从入门到精通(全四篇)

    本教程将引导你从零基础开始,逐步深入理解并掌握Hibernate的核心概念和技术。 在【入门阶段】,你将学习到: 1. Hibernate概述:了解ORM的概念,以及Hibernate如何解决传统JDBC编程中的问题。 2. 安装与配置:设置...

    hibernate基础学习资料

    Java框架中关于hibernate的基础学习

    hibernate 4 详细教程(包全面)

    教程包含了hibernate4 的新特性; hibernate4和hibernate3的区别; hibernate4和spring3.2整合的问题; 文档以pdf,htm格式呈现给开发者; 详细教了hibernate4;

    hibernate教程,hibernate入门

    **Hibernate 教程:带你入门持久化框架** Hibernate 是一个流行的开源对象关系映射(ORM)框架,它为 Java 应用程序提供了便捷的数据持久化服务。本教程将引导你逐步了解 Hibernate 的基本概念、安装配置以及核心...

    北大青鸟Hibernate学习资料

    通过学习这些资料,你将能够有效地掌握Hibernate框架,实现Java对象与数据库之间的无缝转换,提升你在Java开发中的数据库操作能力。无论是对于初学者还是经验丰富的开发者,这都是一份宝贵的资源,帮助你更好地理解...

    Hibernate Spatial 4 教程

    Hibernate Spatial 4 教程 Hibernate Spatial 是一个基于 Hibernate 或 JPA 的空间几何对象数据库操作框架,提供了实现空间几何对象数据库操作的方法和配置说明。 一、 Hibernate Spatial 4 简介 Hibernate ...

Global site tag (gtag.js) - Google Analytics