Java持久性API(JPA)第7讲——实体生命周期及生命周期回调方法

 
目标与主要内容:
u        掌握实体的生命周期;
u        掌握实体的生命周期的转换;
u        掌握实体的生命周期回调方法的使用;
1、   实体的生命周期
参考书上 362 页。
4 种状态:
u        新建:没有持久标识,并且没有与上下文环境关联。
u        分离的:具有持久标识,并且没有与持久上下文环境关联。
u        管理的:具有持久标识,并且与持久上下文环境关联。
u        删除的:具有持久标识,并且与持久上下文环境关联,但是准备从数据库中删除。
2、   对实体的操作
对实体的各种操作可以改变实体的状态,对这些操作分别介绍如下:
2.1 持久化实体实例
通过 persist 方法或者被级联 persist 方法完成。例如可以直接持久化一个订单项,也可以通过持久化订单,该操作可以级联到订单项。
persist 操作结果如下:
u        如果是新的实体,则会变成管理的;
u        如果是被管理实体,则该操作被忽略;
u        如果是删除的实体,则将重新变成被管理的;
u        如果是分离的实体,会抛出异常;
u        如果关系中声明的级联操作包括 CascadeType.PERSIST ,则会把级联的实体持久化。
2.2 删除实体
通过 remove 方法或者被级联的 remove 方法完成。例如可以直接删除一个订单项,也可以通过删除订单来删除订单项。
Remove 操作的结果如下:
u        如果是新的实体,则该操作被忽略;
u        如果是被管理实体,则会变成删除的;
u        如果是删除的实体,则该操作被忽略;
u        如果是分离的实体,会抛出异常;
u        事务提交的时候或者作为 flush 操作的结果,删除的实体将从数据库中删除。
2.3 同步到数据库
通常自动完成,也可以使用 flush 操作完成。
flush 操作的结果如下:
u        如果实体是管理的实体,将被同步到数据库;
u        如果是实体是删除的实体,将从数据库中删除掉。
2.4 分离实体
分离的实体可能来自:
u        事务提交;
u        事务回滚;
u        删除持久上下文;
u        管理实体管理器;
u        串行化一个实体或者通过值传递参数;
在第 6 讲中,在 Servlet 中创建的 Ordertable 对象作为参数传递到会话 Bean 中的时候,就是这种状态,所以需要先通过 merge 操作转换成管理的状态,然后再持久化。
2.5 合并分离的实体状态
merge 操作可以完成合并操作。合并操作的语法如下:
u        如果是新的实体,则会创建一个新的管理的实体;
u        如果是被管理实体,则该操作被忽略;
u        如果是删除的实体,则产生异常;
u        如果是分离的实体,会创建一个新的管理的实体;
2.6 管理的实体实例
    可以通过 contains 方法来判断实体实例是否被管理。
3、   实体生命周期回调方法
生命周期方法可以定义在
u        实体类;
u        超类;
u        实体类所关联的实体监听器类;
u        超类所关联的实体监听器类;
实体监听器类必须有一个无参数的构造方法。
可以通过元注释指定,也可以通过 XML 配置文件指定。
3.1 生命周期回调方法的定义
定义在实体类或者超类的回调方法:
void <METHOD>()
定义在实体监听器类的回调方法:
Void <METHOD>(Object o)
回调方法可以是任何访问控制类型,但是不能使用 static final 修饰。
3.2 生命周期回调方法使用的元注释
使用的元注释及含义如下:
u        PrePersist ,持久化之前产生该事件
u        PostPersist ,持久化之候产生该事件
u        PreRemove ,删除之前产生该事件
u        PostRemove ,删除之后产生该事件
u        PreUpdate ,更新之前产生该事件
u        PostUpdate ,更新之后产生该事件
u        PostLoad ,加载之后产生该事件
3.3 实例
在第 6 讲的 Ordertable 实体类中增加如下 7 个生命周期回调方法:
    @PostLoad
    public void postLoad(){
        System.out.println("PreLoad 生命周期方法被调用! ");
    }
 
    @PreRemove
    public void preRemove(){
        System.out.println("PreRemove 生命周期方法被调用! ");
    }
 
    @PrePersist
    public void prePersist(){
        System.out.println("PrePersist 生命周期方法被调用! ");
    }
    @PreUpdate
    public void preUpdate(){
        System.out.println("PreUpdate 生命周期方法被调用! ");
    }
    @PostPersist
    public void postPersist(){
        System.out.println("PostPersist 生命周期方法被调用! ");
    }
    @PostRemove
    public void postRemove(){
        System.out.println("PostRemove 生命周期方法被调用! ");
    }
    @PostUpdate
    public void postUpdate(){
         System.out.println("PostUpdate 生命周期方法被调用! ");      
    }
    @Remove
    public void remove(){
         System.out.println("remove 方法被调用! ");         
    }
如果要持久化一个订单,会得到如下的输出结果:
PrePersist 生命周期方法被调用!
PostPersist 生命周期方法被调用!
如果要调用下面的代码:
        Ordertable order = em.find(Ordertable.class,orderid);
        Orderdetail item = new Orderdetail(orderid,goodsid);
        em.persist(item);
        item.setQuantity(quantity);
        if(order.getOrderdetailCollection()==null)
            order.setOrderdetailCllection(new Vector<Orderdetail>());
        order.getOrderdetailCollection().add(item);
        item.setOrdertable(order);
会得到如下的输出结果:
PreLoad 生命周期方法被调用!
PreLoad 生命周期方法被调用!
PreUpdate 生命周期方法被调用!
PostUpdate 生命周期方法被调用!
从运行结果看调用了两次 PreLoad 方法,这与持久性提供者有关。
如果执行下面的代码:
        Ordertable order = em.find(Ordertable.class,orderid);
        em.remove(order);  
会得到如下的输出结果:
PreLoad 生命周期方法被调用!
PreLoad 生命周期方法被调用!
PreRemove 生命周期方法被调用!
PostRemove 生命周期方法被调用!
因为要先查找到实体才能删除,所以调用了 PreLoad 方法。
删除也可以使用下面的方法:
em.createQuery("delete from Ordertable o where o.orderid = ?1").setParameter(1,orderid).executeUpdate();
3.4 一个生命周期事件的多个回调方法
同一个生命周期事件可以定义多个回调方法,可以在实体类、实体类的超类或者监听类上,如果定义了同一个生命周期事件的多个回调方法,则调用这些方法的顺序为:
如果有默认的监听器类,先调用默认的监听器类;
如果有实体监听器类,则先调用父层次的实体监听器类,后调用子层次的实体监听器类,如果在同一个实体类上定义了多个实体监听器类,按照定义的顺序执行;
如果父层次定义了生命周期回调方法,调用父层次的生命周期回调方法;
调用子层次的生命周期回调方法。
详细实例参考书上 367 页。
 
参考书籍:《 Java EE 5 实用教程——基于 WebLogic Eclipse
 
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值