zoukankan      html  css  js  c++  java
  • Java持久性API(JPA)第7讲——实体生命周期及生命周期回调方法

    源贴地址:http://blog.csdn.net/javaeeteacher/archive/2007/06/25/1665345.aspx

    目标与主要内容:
    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)
    回调方法可以是任何访问控制类型,但是不能使用staticfinal修饰。
    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页。

  • 相关阅读:
    倒排索引
    线控的原理
    性格类型之ISFP艺术家型——有爱心的艺术工作者
    亚马逊面试题及解法
    关于过度设计的思考(zz)
    给Visual Studio 2010中文版添加Windows Phone 7模板
    MySQL性能优化zz
    上班玩游戏,老总是怎么知道的呢?
    基于AJAX的自动完成
    JavaScript在ASP.NET AJAX中的另类故事
  • 原文地址:https://www.cnblogs.com/beta2013/p/3377372.html
Copyright © 2011-2022 走看看