⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 16. ejb note.txt

📁 在达内培训java笔记
💻 TXT
📖 第 1 页 / 共 4 页
字号:
       <enterprise-beans>
         <session>
            <ejb-name>BeanName</ejb-name>
            <remote>package.IBeanName</remote>
            <local>package.IBeanName</local>
            <ejb-class>package.IBeanImplements</ejb-class>
            <session-type>Stateless</session-type>
            <transaction-type>Container</transaction-type>
          </session>
        </enterprise-beans>
       </ejb-jar>
    2) 特定应用服务器部署描述符:
        JBoss:jboss.xml
        Weblogic:weblogic-ejb-jar.xml
        Sun:sun-ejb-jar.xml

    标注和部署描述符的区别:
        标注                      部署描述符
    简单便利,直观               复杂,容易出错
    分散管理,无法应付复杂应用     集中管理,可以应付较复杂应用
    EJB提供者和部署者不是同一人    适合于EJB提供者和部署者不是同一人的情况
    容易出错

    注意:标注与部署描述符同时使用,部署描述符的优先级更高,会覆盖标注!!!


6. Session Bean(会话Bean) 
   业务组件: 由客户端程序调用的一段业务逻辑, 作用相当于Spring管理的服务组件。一个EJB组件在容器中可能包含多个实例。
   会话Bean:对业务逻辑建模:用程序模拟处理一件事情的流程和步骤

7. 会话Bean的分类:
   Stateless Sesssion Bean(无状态会话Bean,简称:SLSB) 
    1)一次方法调用代表一次会话
    2)多次方法请求之间不保存状态 (只能调用方法,不能访问属性) 
    3)Bean的对象实例可以被任何客户调用

   Stateful session Bean(有状态会话Bean,简称:SFSB) 
    1)会话贯穿于多次方法调用之间
    2)多次方法请求之间保存状态
      SFSB像servlet中的Session对象,可以访问SFSB的属性,SFSB的属性值会自动保留,供下次访问
    3)只有一个客户能访问这个Bean的对象实例和它的状态


8. 无状态会话Bean的对象和并发服务
   1)实例数量是容器根据客户端数量,来创建的。创建以后不会销毁,容器销毁或删除此项目时才销毁
   2)不能区分不同的客户。由哪个实例响应客户端,是由容器决定的。按静态方法来使用。
   3)实例可共享,和客户stub是多对多。不能拥有实例变量,即使有,也不能暴露给客户
   4)生命周期:不存在 -> 就绪
   5)回调方法和Remove方法
   6)并发访问
     a.没有状态,因此也无需做并发处理
     b.串行共享
     c.对象池   --- 容器会初始化n个Bean对象应付成千上万的客户端的并发请求。
9. 无状态会话Bean的生命周期(状态图) 
   1)不存在 -> 就绪 
     过程: 1创建Bean实例 2依赖注入 3@PostConstrcut回调方法) 
   2)就绪 -> 不存在
     过程: @PreDestroy回调方法
   3)回调方法@PostConstrcut和@PreDestroy,可以定义在Bean类中,也可以定义在单独的类中
     @PostConstrcut 进行初始化工作,比如获取一些不能用依赖注入获得的资源
     @PreDestroy 释放初始化时获得的资源
   4)独立的回调类
     @Interceptors(Callback.class) 


10.有状态会话Bean的对象池和并发服务
   1)能区分不同的客户,可以记住客户信息
   2)跨越多个请求(方法调用),维护会话状态(bean类的实例变量) 
   3)Bean对象和stub一对一
   4)生命周期:不存在 -> 就绪 -> 钝化
     状态包括:
      成员变量是非transient类型的java基本类型或对象
      本地或者远程接口的EJB引用
      容器管理的资源
      JNDI命名上下文Context
   5)回调方法和Remove方法(初始化实例变量,获得或关掉外部资源等) 
   6)多用户并发访问:
     a.容器考虑,开发人员无需处理并发
     b.钝化和激活过程
     c.容器的并发策略(annotaion和DD) 
       需导包:jboss-annotation-ejb3.jar (这个包在 %jboss_home%/client/ 下) 
     d.Bean编写的要求,必须具备序列化能力(serializable) 
   7)占用更多资源:cpu(查找bean、激活、钝化)和内存(有多少个在线用户就有多少stateful bean) 

    有状态会话Bean:
    1.一个Stub就是一个客户,lookup到Stub以后,保存在servlet的session中
    2.EJB重新部署之后,需要lookup一个新的Stub

    生命周期:不存在 -> 就绪 -> 钝化
    1.当客户端lookup时,Bean并不存在;直到客户端首次请求调用时,服务器才构造bean实例,并调用postConstruct方法进入就绪状态;然后客户端才可以正常调用 
    2.如果客户端太久不用,服务器会调用prePassivate方法使bean钝化;当客户端再次请求调用时,又构造新实例,调用postActivate重新激活;然后客户端才正常调用
    3.客户端调用remove后,服务器端会调用preDestroy方法令bean不存在;此后不能再使用这个bean,如需再用要再次lookup


11. 示例:购物篮
    购物篮EJB组件
    包含状态:产品信息(产品,数量) 
    业务功能:1添加产品 2生成订单

   数据源 模板的位置:  %jboss_home%/docs/examples/jca/
   数据源配置文件位置: %jboss_home%/server/default/deploy/mysql-ds.xml
   mysql驱动程序位置: %jboss_home%/server/default/lib/

   issue:
    无法访问数据库时,注意: 
    1. 检查数据库驱动程序
    2. 检查mysql-ds.xml是否正确(url,username,password);放到 %jboss_home%/server/default/deploy/
    3. 检查数据源是否部署成功,JNDI引用名称是否正确( 以 "java:/" 开始) 



-----------------------------------------------------------
Day3
1. JPA(Java Persistence API)简介
   1)ORM(object relational mapping):  实现对象到关系数据库中的表的自动持久化(翻译) 
     通过元数据描述对象于数据库间的映射。
   2)JPA, Sun提出的又一套Java持久化规范标准
   3)整合当前各种ORM框架和技术,为各种ORM框架提供统一编程接口
   4)只是一套接口,要求持久化提供商实现支持
   5)使用Annotation和XML描述对象和关系表的关系
   6)EJB和普通Java程序都可使用

2. JPA编程
   EntityManager接口
   J2SE环境下JPA 编程步骤:
    a.导入包: Java EE 5 Libraries(MyEclipse的类库,javaee.jar);
      数据库驱动包;  PP(持久化提供者)的包
    b.配置persistence.xml(名字固定) 
      提供访问数据库的信息 和指定具体的PP(persistence provider) 
    c.开发实体(注解或orm.xml) 
      1)在POJO类上添加@Entity
      2)实体必须声明主键@Id,(可以使用@GeneratedValue配置主键产生的策略) 
      3)默认情况下,实体类名和属性名等同于表的字段名(可用@Table/@Column 加上(name="new_name")另外起名) 
      //4)实体能够包括业务方法(不建议这么做,会导致实体的职责不清) 
    d.Session Bean(注入EntityManager) 
    e.开发客户程序

3. JPA支持两种事务类型
    本地资源事务(RESOURCE_LOCAL):使用JDBC驱动管理的本地事务。不需发布。
    Java事务API(JTA):容器管理的事务。要使用JTA必须使用服务器的DataSource。

    JavaEE环境下
        容器管理的EntityManager(@PersistenceContext注入)必须使用JTA事务。
        应用程序管理的EntityManager可以使用本地资源事务,也可以使用JTA事务
    在JavaSE环境下,使用本地资源事务

   比较 Hibernate 与 JPA 的开发过程:
        Hibernate             jpa
     1.POJO(entity)        1.entity
     2.xxx.hbm.xml         2.Annotation(orm.xml)
     3.hibernate.cfg.xml   3.persistence.xml
     4.SessionFactory      4.EntityManagerFactory



-----------------------------------------------------------
Day4

4. EntityManager接口
    find(Class<T> entityClass, Object primaryKey):<T> T    //根据主键查找,没有符合条件记录,返回null
        Hibernate:get();
    getReference(Class<T> entityClass,Object primaryKey):<T>T //根据主键查找,没有符合条件记录,抛出异常
        Hibernate:load();                                  //EntityNotFoundException
    persist(Object entity):void        //将实体变成受管态,并持久化它,将在数据库中增加一条记录
        Hibernate:save();
    merge(T entity):T                  //合并一个实体到持久化上下文中,将更新数据库记录,并返回持久化对象
        Hibernate:merge();
    remove(Object entity):void         //删除一个实体,将删除数据库记录
    clear():void                       //清除持久化上下文,将导致托管态对象变成游离态对象
    contains(Object entity):boolean    //检查一个实体对象是否包在持久化上下文中
    close();                           //关闭持久化上下文
    flush();                           //对象同步到数据库,有两种同步方式
        FlushModeType.AUTO             //事务提交和执行查询时同步
        FlushModeType.COMMIT;          //只有事务提交时同步
        setFlushMode(FlushModeType flushMode)    //设置同步方式
    refresh();                         //数据库同步到对象
    getTransaction().begin();          //开启事务
    getTransaction().commit();         //提交事务,事务结束

5. 持久化上下文和实体的生命周期 
   新建 -> 托管(受管) -> 脱管(游离) -> 删除
    1) 新建new:new Instance persist(); 新建一个实体对象,还未持久化,没有持久化标志
    2) 托管managed:数据库里和持久化上下文中都有 实体对象
    3) 游离detached:持久化上下文中没有,但是又具有持久化标志(oid)  可调用merge(),不能调用persist();
    4) 删除removed:hibernate没有(数据库中和持久化上下文中都有,但是通过remove()标志实体是被删除的) 
   总结: 
    1) 不调用persist, 而是调用merge持久保存entity对象
    2) 在事务当中(ejb默认一个方法是一个事务)或者持久化上下文中,先查询entity, 再进行操作
    3) 调用find方法, 不要调用getReference() 

6. 持久化上下文类型
    容器管理的上下文
    @PersistenceContext(type=PersistenceContextType.TRANSACTION) 
    1)事务范围的(默认方式):
            事务结束时(一个方法默认为一个事务),上下文被关闭
    @PersistenceContext(type=PersistenceContextType.EXTENDED) 
    2)扩展范围的(多个事务):
            上下文跨越多个事务(事务结束时,上下文并不关闭) 
            *只有*有状态会话Bean适用,SFSB销毁时,上下文关闭
     应用程序管理的上下文,是扩展的上下文
    EntityManagerFactory emf;
    EntityManager em = emf.createEntityManager();

7. 实体回调
   1)注解方法
     @PrePersist    //insert into SQL执行之前调用
     @PostPersist   //insert into SQL执行之后调用
     @PreUpdate     //update SQL执行之前调用
     @PostUpdate    //update SQL执行之后调用
     @PreRemove     //delete SQL执行之前调用
     @PostRemove    //delete SQL执行之后调用
     @PostLoad      //加载实体之后,select SQL执行之后调用 (只有这个没有之前执行的) 
   2)独立的回调类
     @EntityListeners(Callback.class) 
     回调方法多一个Object 参数,如:
       Callback.java 里写:                     entity.java里写:
       @PreUpdate                              @PreUpdate
       public void preUpdate (Object obj);     public void preUpdate ();

8. JPA查询(JPQL) 
    1)javax.persistence.Query接口
      Query query = em.createQuery("select 别名 from entity类 别名"); //也可写 "from entity类"
       List<entity类> list = query.getResultList();
       for(entity类 obj : list){System.out.println(obj.getOid() + " : " + obj.getName());}
    2)本地查询
      Query query = em.createNativeQuery("select * from 表名", entity类.class);
      List<entity类> list = query.getResultList();
      for(entity类 obj :list){System.out.println(obj.getOid() + " : " + obj.getName());}
    3)命名查询
      a)在Entity里添加标注
        @NamedQuery(name="命名1", query="select h from entity类 h where h.age>?2 and h.name like ?1")
        //上面 ?1 ?2 的数字决定参数下标。也可以只用 ? ,但代码得保证对应这语句的顺序。(h是 entity类 的别名) 
        //query 语句也可写成:"from entity类 where age>:age and name like :name"
        //分号表示用名称代号代替之前的下标,来表示参数。这种方式更常用,不易出错
      b)查询代码
        Query query = em.createNamedQuery("命名1");
        query.setParameter(1, "%始%"); //如果query 语句用分号的,则query.setParameter("name", str);
        query.setParameter(2, 70);
        List<entity类> list = (List) query.getResultList();
        for (entity类 obj : list){
            System.out.println(obj.getOid() + " : " + obj.getName());}
    4)本地命名查询
      a)在Entity里添加标注

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -