EJB是企业级系统的核心部分,用于运行业务逻辑,是处理业务逻辑的一种方案(O/RMapping)。EJB有下面3种类型:SessionBean分为StatelessSessionBean和StatefulSessionBean两种EntityBean分为Bean-ManagedPersistenceEntityBean(BMP)和Container-ManagedPersistenceEntityBean(CMP)。BMP要在Bean中包含访问数据库的SQL代码,故称为Bean-Managed;后者不需要编写SQL代码,SQL代码由Container或者包含Container的服务器自动产生,故称为Container-Managed。Message-DrivenBean专门接收和处理消息,而发送消息可以是一般的SessionBean、EntityBean或者其他类型的程序。JPA(JavaPersistenceAPI)是EJB3.0(JSR220)持久层的实现规范。JPA式样在制定的过程中,充分借鉴了Hibernate的优点,JPA的很多概念都可以从Hibernate中找到原型。目前,JPA规范有三种实现方案:HibernateEntityManager、OpenJPA、OracleTopLinkEssentials。HibernateEntityManager实现了EJB3.0JPA规范。HibernateEntityManager封装了成熟具有强大功能Hibernatecore功能,你可以在HibernateEntityManager里使用HibernateAPI,SQL,JDBC等。事实上,可以通过HibernateEntityManager,非常容易地把一个Hibernate应用改造成JPA应用。HibernateEntityManager可以作为一个标准的JavaPersistenceprovider,使用在任何JavaEE5.0应用服务器以及标准EJB3.0容器中,或者JDK5.0环境中。(使用HibernateEntityManager需要HibernateCore和HibernateAnnotations这两个包)。OpenJPA100%实现了EJB3.0(JSR220)中的JPA标准,为开发者提供功能强大、使用简单的持久层数据管理框架。OpenJPA当然实现了对象关系映射(ORM)与对象关系等功能。OpenJPA除了可以运行在符合EJB3.0标准的EJB容器中之外,还可以作为独立的持久层框架,轻松地与其它JavaEE应用框架集成。OracleTopLinkEssentials是由Oracle公司推出,EJB3.0规范(JSR220)中的JPA部分的标准实现。Java开发者可以利用TopLink所提供的强大功能,快速开发具有高性能的企业应用程序。持久化文件的配置EJB3entitybean需要的配置文件为persistence.xml,该文件要打包到EJBJar文件的META-INF目录下。persistence.xml文件用于指定实体Bean使用的数据源及EntityManager对象的默认行为。persistence.xml文件的配置说明如下:?xmlversion=1.0encoding=UTF-8?persistencexmlns=:xsi=:schemaLocation=://java.sun.com/xml/ns/persistence/persistence_1_0.xsdversion=1.0persistence-unitname=StrutsEjb3Persistencejta-data-sourcejava:/OracleDS/jta-data-sourcepropertiespropertyname=hibernate.hbm2ddl.autovalue=update/propertyname=hibernate.dialectvalue=org.hibernate.dialect.OracleDialect/!--propertyname=hibernate.dialectvalue=org.hibernate.dialect.Oracle10gDialect/--/properties/persistence-unit/persistencepersistence-unit节点可以有一个或多个,每个persistence-unit节点定义了持久化内容名称、使用的数据源及持久化产品专有属性。name属性定义持久化名称。jta-data-source节点指定实体Bean使用的数据源JNDI名称,如果应用发布在jboss下数据源名称必须带有java:/前缀,数据源名称大小写敏感。properties节点用作指定持久化产品的各项属性,各个应用服务器使用的持久化产品都不一样如JBoss使用Hibernate,weblogic10使用Kodo,glassfish/sunapplicationserver/Oralce使用Toplink。因为jboss采用Hibernate,Hibernate有一项属性hibernate.hbm2ddl.auto,该属性指定实体Bean发布时是否同步数据库结构,如果hibernate.hbm2ddl.auto的值设为create-drop,在实体Bean发布及卸载时将自动创建及删除相应数据库表(注意:JBoss服务器启动或关闭时也会引发实体Bean的发布及卸载)。TopLink产品的toplink.ddl-generation属性也起到同样的作用。如果你的表已经存在,并且想保留数据,发布实体bean时可以把hibernate.hbm2ddl.auto的值设为none或update,以后为了实体bean的改动能反应到数据表,建议使用update,这样实体Bean添加一个属性时能同时在数据表增加相应字段。EntityManagerSessionbeanorMDbean对Entitybean的操作(包括所有的query,insert,update,delete操作)都是通过EntityManager实例来完成的。EntityManager是由EJB容器自动地管理和配置的,不需要用户自己创建。那么SessionbeanorMDbean如何获得EntityManager实例呢??非常简单,就是通过下列代码进行依赖注入:Publicclasssessionbean1{@PersistenceContextEntityManagerem;。。。}注意:如果persistence.xml文件中配置了多个persistence-unit。那么在注入EntityManager对象时必须指定持久化名称,通过@PersistenceContext注释的unitName属性进行指定,例:@PersistenceContext(unitName=foshanshop)EntityManagerem;如果只有一个persistence-unit,不需要明确指定。请注意:EntityBean被EntityManager管理时,EntityManager会跟踪他的状态改变,在任何决定更新实体Bean的时候便会把发生改变的值同步到数据库中(跟hibernate一样)。但是如果entityBean从EntityManager分离后,他是不受管理的,EntityManager无法跟踪他的任何状态改变。EntityManager一些常用的API(包含query,insert,update,delete操作)1)getentity——find()orgetReference()Personperson=em.find(Person.class,1);/*try{Personperson=em.getReference(Person.class,1);}catch(EntityNotFoundExceptionnotFound){//找不到记录...}*/当在数据库中没有找到记录时,getReference()和find()是有区别的,find()方法会返回null,不会抛出异常;而getReference()方法会抛出javax.persistence.EntityNotFoundException异常,另外getReference()方法不保证entityBean已被初始化。如果传递进getReference()或find()方法的参数不是实体Bean,都会引发IllegalArgumentException例外。使用getReference()方法,如果缓存中没有指定的实体,EntityManager会创建一个新的实体(实体的属性值均为null),但是不会立即访问数据库加载记录信息到实体的属性中,而是在第一次访问该实体的某个持久属性的时候才加载相应的持久状态。如果在数据库中找不到对应的记录,就会抛出EntityNotFoundException。注意:执行getReference()时,并不会抛出该异常,该异常是在第一次访问实体属性时才会被抛出)。也就是说,在上面例子的代码中,即使没有记录,catch语句也是执行不到的。只有在后面使用person对象时,才会抛出该异常。在某些场合下使用getReference()方法可以避免从数据库加载持久化状态的性能开销,如下面的情况:2)insert——persist()Personperson=newPerson();person.setName(name);//把数据保存进数据库中em.persist(person);如果传递进persist()方法的参数不是实体Bean,会引发IllegalArgumentException。如果主键是自动生成的,在调用persist函数之后,从参数的实体对象中可以获得对象的主键(不需要调用flush函数就可以获取主键)。如果主键是自动生成的,那么persist方法的参数实体中,主键的值应该为null,否则将无法保存到数据库中。3)update——分2种情况情况1:当实体正在被容器管理时,你可以调用实体的set方法对数据进行修改,在容器决定flush时(这个由container自行判断),更新的数据才会同步到数据库,而不是在调用了set方法对数据进行修改后马上同步到数据库。如果你希望修改后的数据马上同步到数据库,你可以调用EntityManager.flush()方法。publicvoidupdatePerson(){try{Personperson=em.find(Person.class,1);person.setName(lihuoming);//方法执行完后即可更新数据}catch(Exceptione){e.printStackTrace();}}情况2:在实体Bean已经脱离了EntityManager的管理时,你调用实体的set方法对数据进行修改是无法同步更改到数据库的。你必须调用EntityManager.merge()方法。调用之后,在容器决定flush时(这个由container自行判断),更新的数据才会同步到数据库。如果你希望修改后的数据马上同步到数据库,你可以调用EntityManager.flush()方法。publicbooleanupdatePerson(Personperson){try{em.merge(person);}catch(Exceptione){e.printStackTrace();returnfalse;}returntrue;}下面的代码会调用上面的