精通Hibernate——建立单向多对一关联

在类与类之间各种各样的关系中,要算多对一的单向关联关系和关系数据库中的外键参照关系最匹配了。因此,通常选择从Order到Customer的多对一单向关联。简要代码如下:

public class Customer implements Serializable{
    private Long id;
    private String name;
    ....
}
public class Order implements Serializable{
    private Long id;
    private String orderNumber;
    private Customer customer;
    ....
}

Order类的orderNumber属性和ORDERS表的ORDER_NUMBER字段对应如下:

<property name="orderNumber" type="string">
    <column name="ORDER_NUMBER" length="15" />
</property>

Order类的customer属性是Customer类型, 和ORDERS表的外键CUSTOMER_ID对应,多对一配置如下:

<many-to-one name="customer" column="CUSTOMER_ID" class="Customer" not-null="true" />

依据以上配置我们接下来编写一段代码来保存以上实体

public class BusinessService{
    public static SessionFactory sessionFacctory;
    // 初始化Hibernate,创建SessionFactory实例
    static{....}
    // 查询与参数指定的Customer对象关联的所有Order对象
    public List findOrdersByCustomer(Customer customer) throws Exception{....}
    // 级联保存Order和Customer对象
    public void saveCustomerAndOrderWithCascase() throws Exception{....}
    // 分别保存Customer和Order对象
    public void saveCustomerAndOrder() throws Exception{....}
    // 打印Order对象信息
    public void printOrders(List orders){
        for(Iterator it = orders.iterator();it.hasNext();){
            Order order = (Order)it.next();
            // do something
        }
    }
}

(1)saveCustomerAndOrder():先创建并持久化一个Customer对象,然后创建两个Order对象,他们都和这个Customer对象关联,最后持久化这两个Order对象:

tx = session.beginTransaction();
Customer customer = new Customer("Tom");
session.save(customer);
Order order1 = new Order("tom_order_001",customer);
Order order2 = new Order("tom_order_002",customer);
session.save(order1);
session.save(order2);
tx.commit();
(2)saveCustomerAndOrderWithCascade():

tx = session.beginTransaction();
Customer customer = new Customer("Tom");
//session.save(customer);
Order order1 = new Order("tom_order_001",customer);
Order order2 = new Order("tom_order_002",customer);
session.save(order1);
session.save(order2);
tx.commit();

运行代码时会抛出如下异常:

net.sf.hibernate.PropertyValueException:not null property references a null or transient value

下面分析下异常产生的原因。在调用session.save(order1)方法之前,order1和customer对象都是临时(transient)对象。临时对象是指刚刚通过new语句创建,并且还没有被持久化的对象。假定session.save(order1)方法执行成功,order1对象被成功持久化,就便成了持久化对象,而Hibernate不会自动持久化order1锁关联的Customer对象,在数据库中意味着仅仅向ORDERS表中插入一条记录,并且记录CUSTOMER_ID字段为null,这违反了数据库完整性约束,因为不允许CUSTOMER_ID字段为null。索引这种情况下Hibernate不允许持久化order1对象。错误原因order1对象的非空属性Customer引用了一个临时对象。假如去掉配置文件many-to-one的not-null属性这时候order会持久化成功。

但是,当Hibernate自动清理缓存中所有持久化对象时抛出了新的异常:

net.sf.hibernate.TransactionObjectException:object refereneces an unsaved transient instance - save the transient instance before flushing:Customer

所谓的清理,是指Hibernate按照持久化对象的状态来同步更新数据库,Hibernate发现持久化对象order1和order2都引用临时对象Customer,而在ORDERS表中相应的两条记录的CUSTOMER_ID字段为null,这意味着了内存中的持久化对象的状态和数据库中记录不一致,Hibernate没有办法使两者同步,错误原因是持久化对象的属性引用了一个临时对象。

如果要Hibernate完成级联保存修改配置文件如下:

<many-to-one name="customer" column="CUSTOMER_ID"
class="Customer" not-null="true" cascade="save-update" />
时间: 2024-12-15 21:36:30

精通Hibernate——建立单向多对一关联的相关文章

Hibernate框架单向多对一关联映射关系

建立多对一的单向关联关系    Emp.java            private Integer empNo //员工编号            private String empName //员工姓名            //private Integer deptNo;  //部门编号            private Dept dept;    //所属部门    Dept.java            private Byte deptNo;              

精通Hibernate——建立双向一对多关联

当类与类之间建立了关联,就可以方便的从一个对象导航到另一个对象或者一组与他关联的对象. 对象位于内存中,在内存中从一个对象导航到另一个对象显然比到数据库中查询数据速度快多了.类与类之间到底建立双向还是单向都是由业务决定.以Customer和Order为例,如果软件应用有大量这样的需求: 根据客户可以查询该客户所有的订单 根据给定的订单可以查询发出订单的客户 以上需求就需要我们为Customer和Order类创建双向关联,代码如下: public class Customer{ private S

Hibernate单向“多对一”关联

1. 基于外键关联的单向"多对一"关联是最常见的单向关联其中指定many-to-one的unique="true",为单向"一对一",不指定就是单向"多对一" <class name="Person">    <id name="id" column="personId"><generator class="native&quo

Hibernate ManyToOne Mappings 多对一关联映射

Hibernate框架的使用步骤: 1.创建Hibernate的配置文件(hibernate.cfg.xml) 2.创建持久化类,即其实例需要保存到数据库中的类(Employee.java) 3.创建对象-关系映射文件(Employee.hbm.xml) 4.通过Hibernate API编写访问数据库的代码 例子:多个员工对应一个地址. 一.创建hibernate.cfg.xml 配置文件: 注意数据库名.用户名.密码是否填写正确. <?xml version="1.0" en

hibernate中配置单向多对一关联,和双向一对多

什么是一对多,多对一?双向多对一和双向一对多是不是同一个概念? 是一个概念,双向多对一和双向一对多都是配置一个 一对多和多对一 一对多,比如你去找一个父亲的所有孩子,孩子可能有两个,三个甚至四个孩子. 这就是一对多 父亲是1 孩子是多 多对一,比如你到了两个孩子,它们都是有一个共同的父亲. 此时孩子就是多 父亲是1  总结: 一对多就是: 1找到n 多对一就是: n找到1 有些人写概念写一大堆搞起我之前是一脸懵逼,还好弄懂了(手动滑稽) 配置单向多对一 通过上面我们可以了解,双向一对多是 1找n

Hibernate之实现多对多关联映射关系

直接以老师与学生的关系为例.在多对多关联关系中,其中一方都可通过Set保留另一方的所有信息,这样的关联是双向关联.在多对多关联关系中,也只能是双向关联.老师和学生分别对应一张表,通过一张有双方id的中间表来维护多对多的关联. 实体类 package test.hibernate.hbmManyToMany; import java.util.HashSet; import java.util.Set; public class Teacher { private Integer id; priv

hibernate一对一单向外键关联

Husband类里有一个Wife类的引用 wife类: package com.oracle.hibernate; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; @Entity public class Wife { private int id; private int age; @Id @GeneratedValue public i

【SSH系列】Hibernate映射 -- 多对多关联映射

     映射原理 在数据库学习阶段,我们知道,如果实体和实体之间的关系是多对多,那么我们就抽出来第三张表,第一张表和第二张表的主键作为第三表的联合主键,结合我们的hibernate,多对多关联,无论是单向关联还是双向关联都是通过第三张表,将两个表中的主键放到第三张表中做一个关联,用第三张表来解决可能造成的数据冗余问题.今天这篇博文小编来简单的介绍一下hibernate中的多对多关联映射. 在某些系统中,一个用户可以有多个角色,一个角色也可以有多个用户,so,她们之间的关系就是多对多,多对多关联

一口一口吃掉Hibernate(六)——多对多关联映射

今天来说说hibernate中的多对多关联映射,多对多关联映射涉及到单向映射和双向映射2种. 首先举个多对多关联例子:用户User和角色Role,一个用户可以属于多个角色,一个角色可以有多个用户.这就是典型的多对多关联的例子.而单向关联映射则是只能由A端去操作B端,B端不能操作A端的数据.而双向关联映射则是A,B两端都可以操作另一端的数据. 先说单向关联映射,实体类如下: <span style="font-size:18px">/** * 学生类 * @author Lo