EJB中EntityManager的管理方式有两种:Container-managed EntityManager和Application-managed EntityManager

即容器管理的EntityManager和应用管理的EntityManager

在EJB中,EntityManager所进行的持久化的方式与Hibernate的方式是不同的。

     1.在Hibernate的同一个事务中,通过getCurrentSession获取的session对象均为同一个,保存于threadlocal中,以保证对数据的操作为同一个对象。

     2.而EJB中,以容器管理的EntityManager为例,通过注解注入后,在同一个事物中,在各个Bean中获取的EntityManager为不同的对象,但其背后所指向的        persistenceContext  为同一个,所以保证对一个对象进行操作。

 

1)容器管理的EntityManager

    简单的说,就是使用注解,在程序启动的时候由容器自动注入的方式,这是一种普遍采用的方式。

@PersistenceContext(unitName="jbossDB")
    private EntityManager em;

     在使用结束时,不需要自己关闭,有容器来管理。unitName为数据库资源的名字,有presidence.xml中定义

     在该方式下,对应两种persistence类型:

     1.transaction-scope persistence:由容器管理的persistence,其生命周期为一个transaction,这是默认的模式

        一个transaction可认为是客户端向服务器端的一个请求,从开始到结束的一个周期

     2.Extended-scope persistence:用于stateful session bean中,其生命周期随stateful的生命周期

@PersistenceContext(unitName="jbossDB",type=PersistenceContextType.EXTENDED)
    private EntityManager em;

       其设置方式为通过PersistenceContextType来设置。

       Stateful Session Bean 和 Stateless Session Bean最大的区别就是前者会保存客户端的信息,使得同一个客户端在一个Bean中多次访问的时候均为访问同一个Bean。

       而后者则可看作单例模式,他不会保存客户端的信息,所以第二个客户端依然可以使用该Bean对象。

       实体:

import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Version;

@Entity
public class People implements Serializable{

    /**
     * 
     */
    private static final long serialVersionUID = 20151228215045281L;
    @Id
    @GeneratedValue
    private int id;
    private String name;
    private String password;
    
    @Version
    private int version;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public int getVersion() {
        return version;
    }

    public void setVersion(int version) {
        this.version = version;
    }
}

 

       Bean继承的接口:

import com.welv.jpa.People;

public interface PeopleManager {

    public void addPeople(People p);
    public People getPeople(int id);
    public void setName(String name);
    public void setPassword(String password);
    
}

       Bean的实现:

import javax.ejb.Remote;
import javax.ejb.Stateful;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.PersistenceContext;
import javax.persistence.PersistenceContextType;
import javax.persistence.PersistenceUnit;

import com.welv.ejb.PeopleManager;
import com.welv.jpa.People;

@Stateful
@Remote
public class PeopleManagerBean implements PeopleManager {

    @PersistenceContext(unitName="jbossDB",type=PersistenceContextType.EXTENDED)
    private EntityManager em;
    private People p;
    
    
    
    @Override
    public void addPeople(People p) {
        em.persist(p);

    }

    @Override
    public People getPeople(int id) {
        p = em.find(People.class, id);
        return p;
    }

    @Override
    public void setName(String name) {
        p.setName(name);
    }

    @Override
    public void setPassword(String password) {

        p.setPassword(password);
        
    }

}

       客户端代码:

import java.util.Properties;
import javax.naming.Context;
import javax.naming.InitialContext;
import com.welv.ejb.PeopleManager;
import com.welv.jpa.People;

public class JpaEJBClient {
    public static void main(String[] arg) {

        try {
            final Properties jndiProperties = new Properties();
            jndiProperties.put(Context.URL_PKG_PREFIXES,
                    "org.jboss.ejb.client.naming");
            final Context context = new InitialContext(jndiProperties);
            final String appName = "";
            // 部署的jar文件的名字
            final String moduleName = "EJB_06";
            final String distinctName = "";
            // 实现类的类名
            final String beanName = "PeopleManagerBean";
            // 接口类的全名
            final String viewClassName = PeopleManager.class.getName();

            String lookupStr = "ejb:" + appName + "/" + moduleName + "/"
                    + distinctName + "/" + beanName + "!" + viewClassName+"?stateful";

            System.out.println(lookupStr);

            
            PeopleManager ejb = (PeopleManager) context.lookup(lookupStr);
            
//            People p = new People();
//            
//            p.setName("ll");
//            p.setPassword("123456");
//            
//            ejb.addPeople(p);
            People p = ejb.getPeople(1);
            
            ejb.setName("cccc");
            ejb.setPassword("1234455");

        } catch (Exception e) {
            System.out.println("============================================");
            e.printStackTrace();
            System.out.println("============================================");
            System.out.println("请检查调用方法是否为远程");
        }
    }
}

       从Bean的实现中可以看出,对People对象操作的一些方法是没有加载People对象的。如果是通过Stateless将接口暴露出去,这无法实现相应方法的功能。

       a.由于使用的是StatefulBean,所以获取的Bean对象是有状态的,Stateful周期中多次的请求都是用同一个Bean,在远程使用getPeople()方法的时候,Session Bean中会

          将People对象保存在this.People对象中,所以在同一个Stateful周期中使用其他的方法对People对象进行操作时就不需要重新load People对象。

       b.若使用的是StatelessBean,则必须要在方法中重新加载,因为Stateless是不保存客户端信息的,也就是在同一个使用一个Stateless进行请求的时候,请求的Bean对象不

          是同一个,所以如果不加载对象,会有NullPointException产生。

2)应用管理的EntityManager

    由PersistenceUnit注入EntityManagerFactory中

@PersistenceUnit(unitName="jbossDB")
    private EntityManagerFactory emf;

     在transaction结束时需要手动将获取的EntityManager关闭(closs);

 

**private static final long serialVersionUID = 20151228215045281L;作用:

    该代码的作用用于匹配,在一般情况下,若EJB中的实体对象和客户端中的对象如果一致,则可以互相传递,但如果EJB中多加了属性,则再次访问的时候则会失败,而如果两边的代码中有相同的serialVersionUID则会认为对象相同,可以交互。

***由于刚了解该技术点,没有理解透

posted on 2015-12-28 23:01  welv  阅读(610)  评论(0编辑  收藏  举报