码迷,mamicode.com
首页 > Web开发 > 详细

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

时间:2015-07-28 23:12:56      阅读:168      评论:0      收藏:0      [点我收藏+]

标签: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" />

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

标签:hibernate   多对一   单向   

原文地址:http://blog.csdn.net/fuyuwei2015/article/details/47112393

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!