`
anxin587
  • 浏览: 23935 次
最近访客 更多访客>>
社区版块
存档分类
最新评论

hibernate初级 映射一对多关联关系

阅读更多

在域模型中,类之间最普遍的关系是关联关系,关联是有方向的,分为单向关联和双向关联,在关系数据库中,为了避免冗余,只存在many 方参照one方,所以关系数据库实际上面是多对一,一对一的单向关联,

在类和类之间各种关系中,多对一的单向关联和关系数据库的外键参照关系最匹配,下面一个简单例子来说明这些

两个实体,分别为Customer和orders,同时一个customer可以拥有0个或者多个orders,他们的DDL如下所示

CREATE TABLE CUSTOMERS (ID INT AUTO_INCREMENT PRIMARY KEY,NAME VARCHAR(20))

CREATE TABLE ORDERS
(
 ID INT AUTO_INCREMENT PRIMARY KEY,
 CUSTOMER_ID INT,
 ORDERNUMBER INT,
 CONSTRAINT FK FOREIGN KEY(CUSTOMER_ID) REFERENCES CUSTOMERS(ID)
)

Customer类如下

package entity;
import java.util.*;
public class Customer
{
 private Long id;
 private String name;
 private Set orders=new HashSet();

 private void setId(Long id)
 {
  this.id=id;
 }
 public Long getId()
 {
  return this.id;
 }

 public void setName(String name)
 {
  this.name=name;
 }
 public String getName()
 {
  return this.name; 
 }

 public void setOrders(Set orders)
 {
  this.orders=orders;
 }
 public Set getOrders()
 {
  return this.orders;
 }
}

orders类如下

package entity;
public class Order
{
 private Long id;
 private Customer customer;
 private int ordernumber;

 private void setId(Long id)
 {
  this.id=id;
 }
 public Long getId()
 {
  return this.id;
 }

 public void setCustomer(Customer customer)
 {
  this.customer=customer;
 }
 public Customer getCustomer()
 {
  return this.customer;
 }

 public void setOrdernumber(int ordernumber)
 {
  this.ordernumber=ordernumber;
 }

 public int getOrdernumber()
 {
  return this.ordernumber;
 }
}

<?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="entity">
 <class name="Order" table="ORDERS">
  <id name="id" column="ID">
   <generator class="increment"/>
  </id>
  <property name="ordernumber"  column="ORDERNUMBER"/>
  <many-to-one name="customer" column="CUSTOMER_ID"     class="Customer" cascade="save-update"/>
 </class>
</hibernate-mapping>

<?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="entity">
 <class name="Customer" table="CUSTOMERS">
  <id name="id" column="ID">
   <generator class="increment"/>
  </id>
  <property name="name" type="string" column="NAME"/>
  <set name="orders" cascade="delete">
   <key column="CUSTOMER_ID"/>
   <one-to-many class="Order"/>
  </set>
 </class>

package service;
import util.*;
import entity.*;
import org.hibernate.*;
import java.util.*;
public class Test
{
 public static void saveCustomerAndOrder()
 {
  Session session=HibernateUtil.getSessionFactory().openSession();
  session.beginTransaction();
  
  Customer customer=new Customer();
  customer.setName("andy");
  session.save(customer);
  
  Order order=new Order();
  Order order1=new Order();
  order.setOrdernumber(1);
  order.setCustomer(customer);
  order1.setOrdernumber(2);
  order1.setCustomer(customer);
  session.save(order);
  session.save(order1);

  session.getTransaction().commit();
 }

 public static void saveCustomerAndOrderWithCascade()
 {
  Session session=HibernateUtil.getSessionFactory().openSession();
  session.beginTransaction();
  
  Customer customer=new Customer();
  customer.setName("cao");
  //session.save(customer);
  
  Order order=new Order();
  Order order1=new Order();
  order.setOrdernumber(1);
  order.setCustomer(customer);
  order1.setOrdernumber(2);
  order1.setCustomer(customer);
  session.save(order);
  session.save(order1);

  session.getTransaction().commit();

 }
 
 public static Customer getCustomerThOrder()
 {
  Session session=HibernateUtil.getSessionFactory().openSession();
  session.beginTransaction();
  
  Customer customer=((Order)session.load(Order.class,new Long(1))).getCustomer();
   
  session.getTransaction().commit();
  if(customer!=null)
   return customer;
  return null;
 }

 public static Set getOrderThCustomer()
 {
  Session session=HibernateUtil.getSessionFactory().openSession();
  session.beginTransaction();
  
  Set orders=((Customer)session.load(Customer.class,new Long(1))).getOrders();

  session.getTransaction().commit();
  if(orders.size()>0)
   return orders;
  return null;
 }

 public static void updateCustomerAndOrders()
 {
  Session session=HibernateUtil.getSessionFactory().openSession();
  session.beginTransaction();

  Customer customer=(Customer)session.load(Customer.class,new Long(1));
  Order order = (Order)session.load(Order.class,new Long(3));

  order.setCustomer(customer);
  customer.getOrders().add(order);

  session.getTransaction().commit();
 }

 public static void delCustomer()
 {
  Session session=HibernateUtil.getSessionFactory().openSession();
  session.beginTransaction();
  
  Customer customer=(Customer)session.load(Customer.class,new Long(1));
  session.delete(customer);

  session.getTransaction().commit();
 }

 public static void main(String[] args)
 {
  Test.delCustomer();
  //Customer cst=Test.getCustomerThOrder();
  //System.out.println(cst.getName());
  //Test.updateCustomerAndOrders(); 
  /*
  Set orders=Test.getOrderThCustomer();
  Iterator it=null;
  for(it=orders.iterator();it.hasNext();)
  {
   Order order=(Order)it.next();
   System.out.println(order.getId()+" || "+order.getOrdernumber()+" || "+order.getCustomer().getName());
  }
  //*/
  //Test.saveCustomerAndOrderWithCascade();
//System.out.println(  HibernateUtil.getSessionFactory());
 }
}


</hibernate-mapping>

建立多对一的单向关联,也就是在order类里面建立到customer的关联,即在order类里面增加customer属性,这样通过order类即可以获得与之对应的customer信息,同时配置文件里面增加

<many-to-one name="customer" // 为order类里面增加的属性的名称

column=‘customer id’这个是外键的列的名称

class =“mypack。customer” 这个是外键所关联的那一个类 >

name:设定待映射的持久化类的属性名 column:设定和持久化类的属性对应的表的外键, class 设定持久化类的属性类型

这样建立的单向关联就可以进行单向的访问,

public static void saveCustomerAndOrder()
 {
  Session session=HibernateUtil.getSessionFactory().openSession();
  session.beginTransaction();
  
  Customer customer=new Customer();
  customer.setName("andy");
  session.save(customer);
  
  Order order=new Order();
  Order order1=new Order();
  order.setOrdernumber(1);
  order.setCustomer(customer);
  order1.setOrdernumber(2);
  order1.setCustomer(customer);
  session.save(order);
  session.save(order1);

  session.getTransaction().commit();
 }
上面的方法就是先保存customer然后在保存orders,其中order多属于customer的,如果我们仅仅是定义了customer对象不对它进行持久化,而我们又象对order进行持久化这样就会违背数据库的参照完整性,所以hibernate会抛出相应的异常,

org.hibernate.PropertyValueException : not-null property references a null or transientvalue 也就是告诉我们说order类的customer属性是不允许为空的 ,我们可以设定级联保存和更新来解决这个问题,

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

在hibernate持久化一个临时对象(transient object)对象时,它不会自动持久化所关联的其他临时对象,这样就会抛出我们上面的那个异常,我们设定cascade为save-update,默认是none,这样保存orders的同时会先保存customer。

通过多对一的单向关联,我们可以通过order很容易的获得customer信息,但是如果反过来,现在我们需要根据customer信息来获得order信息,所以这样的时候,我们需要建立一对多的双向关联在customer类里面增加Set orders并且给出对应的get set方法,然后在hbmxml里面增加

<set name="orders">//这个是customer类里面的属性的名称

<key column="customer_id"/> 元素设定与所关联的持久化类对应的表的外键

<one-to -many class="order"/>  设定所关联的持久化类,此处为orders

</set>

通过这些我们就可以根据customer来获得自己的orders信息了,上面配置注意点:不要巴一个单元故意用enter来分成多行显示,否则会出现error

set元素的inverse

public static void updateCustomerAndOrders()
 {
  Session session=HibernateUtil.getSessionFactory().openSession();
  session.beginTransaction();

  Customer customer=(Customer)session.load(Customer.class,new Long(1));
  Order order = (Order)session.load(Order.class,new Long(3));

  order.setCustomer(customer);
  customer.getOrders().add(order);

  session.getTransaction().commit();
 }

上面这个update方法在hibernate中实际上面是执行了两句sql语句update orders set ordernumber='aaaa' customerid='2' where customerid='2' , update orders set customerid=2 where id=2,

因为hibernate是根据内存中持久化对象的状态变化来决定需要执行那些sql语句的。inverse=true加上以后则表明customer端的关联只是order端关联的镜像,这样的话,就只会执行一条sql语句

  <set name="orders" cascade="delete" inverse="true">
   <key column="CUSTOMER_ID"/>
   <one-to-many class="Order"/>
  </set>

public static void updateCustomerAndOrders()
 {
  Session session=HibernateUtil.getSessionFactory().openSession();
  session.beginTransaction();

  Customer customer=(Customer)session.load(Customer.class,new Long(1));
  Order order = (Order)session.load(Order.class,new Long(3));

  ??order.setCustomer(customer); 如果保留这一句会去更新database
  //customer.getOrders().add(order); 如果只保留这句的话数据库并不会被更新

  session.getTransaction().commit();
 }

所以这就要求我们最好在写代码的时候写好双向关联的代码,提高程序的健壮性,而不去依赖底层的数据库或者hibernate来解决这些问题,一般情况下many端的inverse设成true,在上面的应用中也就是customer端,好像这里说many端会有些迷惑,向这set端就对了

映射一对多自身双向关联,上一个项目中就有这样的情况,一个公司 公司有0个或1个自己的母公司,当然一个公司也就可能容有0个或n个子公司,这样数据库设计一般为

create table company( id int auto_increment primary key,name varchar(20), Company_id int

constraint fk company_id references company(id));

也就是公司表里面有一个属性关联着自己的主键,自身关联

package entity;
import java.util.*;
public class Company
{
 private Long id;
 private String name;
 private Company company;
 private Set companys=new HashSet();

 private void setId(Long id)
 {
  this.id=id;
 }
 public Long getId()
 {
  return this.id;
 }
 public void setName(String name)
 {
  this.name=name;
 }
 public String getName()
 {
  return this.name;
 }
 public void setCompany(Company company)
 {
  this.company=company;
 }
 public Company getCompany()
 {
  return this.company;
 }
 public void setCompanys(Set companys)
 {
  this.companys=companys;
 }
 public Set getCompanys()
 {
  return this.companys;
 }
}

<?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="entity">
 <class name="Company" table="COMPANY">
  <id name="id" column="ID">
   <generator class="increment"/>
  </id>
  <property name="name"  column="NAME" type="string"/>
  <many-to-one name="company" column="COMPANY_ID"     class="Company" cascade="save-update"/>
  <set name="companys">
   <key column="COMPANY_ID"/>
   <one-to-many class="Company"/>
  </set>
 </class>
</hibernate-mapping>

public static void saveCompany()
 {
  Session session=HibernateUtil.getSessionFactory().openSession();
  session.beginTransaction();
  Company company=new Company();
  company.setName("anxin_2");
  company.setCompany((Company)session.load(Company.class,new Long(1)));
  session.save(company);
  session.getTransaction().commit();
 }
 
 public static String findVdrCompany()
 {
  Session session=HibernateUtil.getSessionFactory().openSession();
  session.beginTransaction();
  Company company=(Company)session.load(Company.class,new Long(2));
  String r=company.getCompany().getName();
  session.getTransaction().commit();
  return r;
 }
上面就是自身关联相关的代码,但是有一个注意就是不要给里面的那个外键设定notnull,要不永远也加不进去数据了,呵呵

分享到:
评论

相关推荐

    hibernate初级教程图解

    ### Hibernate初级教程图解知识点详解 #### 一、概述 Hibernate是一个开源的对象关系映射(Object-Relational Mapping,简称ORM)框架,它为Java应用程序提供了面向对象的方式来进行数据库操作。通过Hibernate,...

    hibernate资料从初级到高级

    2. 关联映射:包括一对一、一对多、多对一、多对多关系的映射,以及懒加载和立即加载策略。 3. 集合映射:集合类型如List、Set、Map等在Hibernate中的映射方法和注意事项。 4. 动态模型和动态更新:允许程序在运行...

    Hibernate 文档 适合初级编程

    Hibernate支持一对一、一对多、多对一、多对多等多种关联关系映射,以及懒加载和立即加载策略。 九、性能优化 1. 批量操作:使用批处理来提高插入、更新和删除的效率。 2. 缓存策略:合理配置缓存,降低数据库访问...

    hibernate 经典题目 其中包括很多核心的题目

    基于标注的映射,如 `@Entity`(实体类型)、`@Table`(实体对应的表)、`@Id`(主键)、`@Basic`(普通属性)、`@Column`(映射列)、`@OneToOne`(一对一)、`@ManyToOne`(多对一)、`@OneToMany`(一对多)、`@...

    Hibernate初级学习

    ### Hibernate初级学习知识点详解 #### 一、Hibernate简介与ORM概念 - **ORM技术定义**:对象关系映射(Object/Relational Mapping, ORM)是一种编程技术,用于将对象模型与关系型数据库模型进行桥接。它使得开发...

    hibernate入门框架源码

    11. **多对一、一对多、多对多关系映射**:Hibernate可以方便地处理数据库中的这些关联关系,通过配置文件或注解设定关系映射。 **学习路线** 1. 首先,理解Hibernate的基础概念和架构。 2. 掌握配置文件的编写,...

    hibernate项目开发

    Hibernate支持多种关联关系映射,如一对一(OneToOne)、一对多(OneToMany)、多对一(ManyToOne)和多对多(ManyToMany)。正确配置关联关系,可以实现对象间的导航访问,简化数据操作。 九、缓存机制 Hibernate...

    极好的hibernate入门实例

    8. **关联映射**: 详细讲解一对一、一对多、多对一、多对多的关联映射实现。 9. **缓存机制**: Hibernate的一级缓存和二级缓存的概念,以及如何配置和使用。 10. **性能优化**: 提供一些优化Hibernate应用的建议,...

    hibernate3+mysql简单学习实例.rar

    2. **对象关系映射(ORM)**: ORM是Hibernate的核心特性,它通过映射文件将Java对象和数据库表关联起来,使得开发者可以使用面向对象的方式来处理数据库操作,减少了直接操作SQL的复杂度。 3. **Hibernate配置**: ...

    hibernate源程序

    10. **关联映射**:涵盖一对一、一对多、多对一、多对多等关联映射的配置和操作。 11. **延迟加载与立即加载**:理解懒加载和Eager加载的概念,以及它们在性能优化中的应用。 12. **事件监听器**:解释Hibernate的...

    hirbernate2

    6. **一对多和多对一关系映射**:理解如何配置和使用实体间的一对多和多对一关系,例如在一个用户类中关联多个订单类,或者在一个订单类中引用一个用户类。 7. **级联操作**:级联属性允许我们在操作一个实体时自动...

    简单功能的图书管理系统

    在Hibernate中,通过配置文件可以定义实体间的一对多、一对一、多对多等关系。例如,一个用户可以有多个订单,一个订单对应多本书。在处理这些关联时,Hibernate会自动处理相关的关联查询和数据更新。 在实际项目中...

    first_demo.rar_DEMO_struts2_struts2 hibernate_简历

    Hibernate则是一个对象关系映射(ORM)框架,允许开发者使用面向对象的编程方式来处理数据库操作。通过Hibernate,开发者可以将Java类与数据库表关联起来,减少了直接编写SQL语句的工作量,提高了开发效率和代码的可...

    HibenateJPA-BeginnerToAdvanced-Trainings

    1. 一对一(OneToOne)、一对多(OneToMany)、多对一(ManyToOne)、多对多(ManyToMany)关联映射的配置与使用。 2. 联合主键(Composite Key)和自增主键(GeneratedValue)的设置。 3. 集合映射的性能优化策略,...

    jsp titles struts 简单的OA系统

    【描述】"第二次做关于struts的开发 受益良多~ 做的很基础 适合" 提示我们这是一个初级或进阶学习的项目,开发者在使用Struts进行第二次开发时,获得了深入的理解和实践经验。Struts是一个开源的MVC(Model-View-...

    Java开发者就业需要掌握的9大专业技能

    4. **ORM框架**:Hibernate和MyBatis是常用的ORM框架,熟悉它们的核心API,理解关联映射、继承映射、缓存机制和事务管理,可以帮助优化数据访问性能。 5. **Web前端开发**:HTML、CSS和JavaScript是基础,jQuery和...

Global site tag (gtag.js) - Google Analytics