摘要
Java Persistence API(JPA)和Spring Framework的2.0版本已经引发开发人员普遍的兴趣。本文将考察如何将Spring 2.0和JPA与BEA WebLogic Server一块儿使用。具体来讲,咱们将使用Spring和JPA对WebLogic Server的病历示例应用程序进行更新。本文将展现Spring和JPA这个功能强大的组合如何造成基于POJO的简化应用架构的基础。使用的技术主要包括WebLogic Server 9.一、Spring 2.0和Kodo JPA。
简介
病历示例应用程序(MedRec)是一个综合应用程序,它演示了如何在WebLogic Server中使用多种技术。这些技术包括开源技术(如Spring和Struts)以及WebLogic Server所使用的技术(如Web services、JSP、消息驱动bean和JDBC)。
本文描述在MedRec更新版本中Java Persistence API(JPA)是如何与Spring Framework配合使用的。本文的一个重要目的是向开发人员展现Spring 2.0、WebLogic Server 9.1和Kodo 4.0如何一块儿使用。经过阅读本文,开发人员将得到对有关使用JPA和Spring 2.0版本中新增的JPA支持的了解。本文还将讨论在企业应用的多个层次中重用JavaBean(POJO)时可能出现的挑战。重用是基于Spring和JPA的应用架构所带来的重要获益之一。
对于不熟悉
Java Persistence API的人来讲,JPA是一个指定如何将Java对象保存在数据库中的新增简化API。JPA正在做为EJB 3.0(
JSR 220)的一部分而被开发,由于它将取代EJB 2.x实体bean,可是它在J2EE和J2SE应用程序中都可使用。JPA的一个最重要的特性是:它是基于POJO的。JPA还使用Java 5.0注释来简化指定从Java对象到关系数据库的映射的方式。BEA已经宣告创建
OpenJPA(一个很快就可用的基于Kodo的开源项目),可是您如今就能够开始使用
Kodo 4.0的早期访问版本。
本文将从对Spring中的POJO和数据访问的概述开始。接下来概述MedRec的架构,并对MedRec数据访问层进行更详细的描述。而后咱们将详细考察JPA persistent类,并讨论它们须要遵循的设计模式。最后,咱们将介绍Spring和Kodo JPA的XML配置,以便将全部内容联系起来。MedRec的完整源代码可随本文
下载。
Spring中的POJO和数据访问
Spring Framework最著名的优势多是简化了的业务组件开发。熟悉Spring的人都知道,经过使用反向控制(IoC)和面向方面编程(AOP),Spring容许开发人员编写功能强大的业务组件,这些业务组件仍然是常规JavaBean或POJO (Plain Old Java Object)——正如它们一般被称做的那样。
对于须要访问数据库的企业应用程序,Spring也提供了一个框架来简化对封装持久化数据访问的数据访问对象(DAO)的建立。Spring的POJO功能还涉及数据访问领域,由于它们查询和修改的数据访问对象和域模型对象都可以是POJO。
Spring对POJO模式的使用具备一些重要的实际优势。首先,就业务组件而言,POJO减轻了开发人员为实现应用程序而必须作的工做。它不只减小了代码行,并且因为这些代码自己就是标准Java,因此它们更简单。其次,使用POJO意味着应用程序调用数据访问对象的其他代码不依赖于特定的持久化技术。例如,若是应用程序正在使用原始JDBC或JDO,那么使用POJO则会使转换到使用JPA做为持久化解决方案的行为相对容易。
第三个优势涉及域模型对象自己。在MedRec中,域模型对象表明诸如病人、医生和处方之类的实体。因为这些类是POJO,并且不像传统的EJB 2.x实体bean那样依赖于特定的持久化环境,因此这些类能够在多个应用程序代码须要访问域模型的层次中重用。在MedRec中,这包括JSP使用域模型对象呈现用户界面的Web层,以及使用域模型类做为参数并将类型返回给Web服务方法的Web服务层。
MedRec概览
图1展现了MedRec的总体架构。在最高层,MedRec其实是两个独立的J2EE应用(EAR文件):MedRec应用程序和Physician应用程序。全部的数据访问都由MedRec部分完成,因此咱们将关注这部分。
图1:MedRec应用程序架构
如图1所示,MedRec应用程序分为几个层:一个包含Web服务的表示层、一个服务层、一个包括数据访问的集成层以及数据库层。做为集成层一部分的Spring数据访问对象(DAO)主要由服务层的业务对象调用。DAO和服务对象都是由Spring应用程序上下文配置的Spring bean。服务对象使用Spring的声明式事务支持来控制事务。
MedRec数据访问
Medical Records应用程序使用4种不一样的DAO,每一种对应于一个须要保存的域模型类——Patient、Prescription、Record和User。DAO实现类分别被称为JpaPatientDAO、JpaPrescriptionDAO、JpaRecordDAO和JpaUserDAO,能够在com.bea.medrec.dao.orm包中找到。
让咱们更详细地考察Patient DAO,以便弄清楚它是如何工做的。如下是用于处理病历应用程序中病人数据的检索和更新的数据访问对象接口:
public interface PatientDao {
public Patient getById(Integer patientId)
throws DataAccessException;
public List getByEmail(String email)
throws DataAccessException;
public List getByLastName(String lastName)
throws DataAccessException;
public List getByLastNameFirstName(String lastName,
String firstName) throws DataAccessException;
public List getByLastNameWild(String lastName)
throws DataAccessException;
public Patient getBySsn(String ssn)
throws DataAccessException;
public List getByStatus(String status)
throws DataAccessException;
public Patient getByUsername(String username)
throws DataAccessException;
public Patient save(Patient patient)
throws DataAccessException;
public Patient update(Patient patient)
throws DataAccessException;
}
请注意,Patient DAO接口是plain old Java interface(POJI)。它不扩展或导入任何特定于所使用的持久化技术(本例中是JPA)的Java类型。大多数Patient DAO方法执行查询并返回病人列表或单个病人对的。最后两个方法分别用于在数据库中保存新病人的信息或者更新现有病人的信息。
该接口上的每一个方法都声明了一个DataAccessException,它是由Spring framework定义的运行时异常。关于DataAccessException,有两件事须要注意。首先,它是运行时异常,因此使用数据访问对象的应用程序代码不须要像在JDBC和EJB 2.x实体bean的状况下那样使用try-catch块包装每次调用。第二,DataAccessException是有用的,由于它包装底层持久化技术所使用的特定异常类,从而使应用程序的其余部分独立于持久化层。
关于接口就说这么多了。接下来,让咱们考察一下Patient DAO的实现。如下是基类BaseDAO,MedRec中的全部数据访问对象都对它进行扩展:
package com.bea.medrec.dao.orm;
import org.springframework.orm.jpa.support.JpaDaoSupport;
public abstract class BaseDao extends JpaDaoSupport {
...
}
在咱们的例子中,这是一个很是简单的类,可是通常来讲,它可用于在不一样数据访问对象实现上所共有的任何代码。BaseDAO扩展了Spring的JpaDaoSupport类。这是必须的,由于它为咱们的DAO实现类提供到Spring的特定于JPA的API的访问。
Patient DAO实现类JpaPatientDao扩展了BaseDao:
public class JpaPatientDao extends BaseDao implements PatientDao {
public Patient getById(Integer pId)
throws DataAccessException {
return getJpaTemplate().find(Patient.class, pId);
}
public List getByLastName(String pLastName)
throws DataAccessException {
List patients = getJpaTemplate().find(
"SELECT p " +
"FROM " + Patient.class.getSimpleName() + " p " +
"WHERE p.lastName LIKE ?1", pLastName);
return (patients.isEmpty())?
Collections.EMPTY_LIST : patients;
}
...
}
此代码示例还展现了两个示范查询方法实现。第一个是getById(),它经过病人的唯一标识字段查找病人。这是经过调用Spring的JpaTemplate上的专用find方法完成的,它将Patient类和唯一的id做为参数,并返回具备此id的Patient对象。getByLastName()方法返回具备类似的姓的病人列表。getByLastName()使用JpaTemplate.find()的替代版本,它将后跟查询参数的EJB QL查询做为参数,并返回匹配查询的对象列表。如下是patient DAO的保存和更新方法:
public class JpaPatientDao extends BaseDao implements PatientDao {
...
public Patient save(Patient pPatient)
throws DataAccessException {
getJpaTemplate().persist(pPatient);
return pPatient;
}
public Patient update(Patient pPatient)
throws DataAccessException {
return getJpaTemplate().merge(pPatient);
}
}
在此patient DAO的保存和更新方法的实现中,save()方法用于将新病人的记录插入数据库,而update()则修改现有的病人记录。每一个方法返回一个对新的或更新后的Patient对象的引用。重点是要理解保存和合并不会当即致使数据库更新。更改一般由JPA缓存直到当前事务提交。而后更改被批量发送到数据库,可是只要有查询在运行,未决更改也能够经常被刷新。
请注意一件有趣的事,咱们的Patient DAO对象对JPA API的依赖不多,由于Spring模板被用于全部数据访问操做,它又内部委托给JPA。事实上,到目前为止,咱们看到的对JPA的唯一直接依赖是getByLastName()方法使用的EJB QL查询字符串。还请注意,虽然早些时候咱们将Spring DAO称做POJO,可是这并不彻底正确,由于DAO须要扩展Spring的JpaDaoSupport类。然而,重要的是,暴露给应用程序其余部分的接口DAO是不依赖于JPA或Spring类型的plain old Java interface。
JPA持久化类
到目前为止,咱们已经看到一些处理查询和更新的示例数据访问代码,那么持久化类又是什么呢?想一想POJO和元数据。可是,持久化POJO须要遵循许多规则,或者说是设计模式。这些规则部分由JPA指定,而其余的是根据整个应用架构的要求而产生的,正如咱们下面将看到的。
首先是一条关于元数据的注意事项。JPA为开发人员提供了几种选项来指定与持久化和对象-关系映射相关的JPA元数据:在外部XML文件中指定、在Java 5.0注释中指定,或者使用这两者的组合。病历应用程序使用JPA元数据的Java注释。这样作的好处是:元数据与应用该元数据的Java类、字段和方法一块儿配置,这样能够帮助理解。若是想使元数据与代码分离,可使用XML来代替。
让咱们考察一下Patient类及其字段声明,看看示例注释JPA类是什么样的:
package com.bea.medrec.domain;
import javax.persistence.*;
import kodo.persistence.jdbc.ElementJoinColumn;
@Entity()
public class Patient implements Serializable
{
@Id()
@GeneratedValue(strategy=IDENTITY)
private Integer id;
private Date dob;
@Column(name = "first_name")
private String firstName;
private String gender;
@Column(name = "last_name")
private String lastName;
@Column(name = "middle_name")
private String middleName;
private String phone;
private String ssn;
@ManyToOne(cascade={PERSIST, MERGE})
@JoinColumn (name="address_id")
private Address address;
@OneToOne(cascade={PERSIST, MERGE})
@JoinColumn (name="email")
private User user;
@OneToMany(tar on getEntity = Prescription.class)
@ElementJoinColumn(name="pat_id")
private Set prescriptions=null;
@OneToMany (targetEntity=Record.class)
@ElementJoinColumn(name="pat_id")
private Set records =null;
...
}
请注意,Patient类使用Entity注释进行注释。这是使用注释的全部持久化类必须遵循的。Entity注释的存在告诉持久化引擎该类是JPA实体。一般不要求Entity类是公有的,可是MedRec的持久化类须要是公有的,以便Web和Web服务层可使用它们。
实体类还须要实现Serializable,可是因为Patient类由MedRec struts操做置于HTTP会话中,因此它须要是可串行化的。这样应用程序能够在集群环境中工做,其中会话状态能够在集群中各节点之间进行串行化。关于实体类的其余要求是:它必须是顶级类且不是final。请参阅JPA规范(JSR220)以得到完整的规则列表。
持久化字段
JPA实现须要在运行时读取和写入实体类的状态(持久化字段)。JPA规范容许实现或者经过直接访问实体字段的方式或者经过调用JavaBean风格的accessor方法(getter/setter)的方式来进行此操做。使用的访问方式由持久化注释的位置决定。例如,若是注释位于类的字段上,则使用字段访问。
您可能要问:为何JPA支持字段和方法两种访问方式呢?答案是灵活性。一些类在它们的公有accessor方法中执行验证。若是因为数据库中的值溢出而抛出异常,这可能致使JPA实现出现问题。若是类在其setter中执行验证,则最好对字段进行注释。另外一方面,若是但愿支持虚拟持久化属性之类的功能,那么就注释accessor方法。
在JPA实体中,全部未使用Transient注释(由JPA定义)进行注释的非瞬态字段都是持久化字段。“持久化”意味着字段被映射到数据库中的列。请注意,Patient类中的一些持久化字段没有注释。这是因为JPA定义的默认值(如默认的列名称)对于这些字段来讲是正确的。若是字段名称与其映射的数据库列名称不一样,则必须使用Column注释来为数据库列指定一个不一样的列名称。
每一个实体必须具备主键。JPA支持简单(单字段)和复合(多字段)的主键。若是能够,最好一直使用简单主键,并让数据库生成主键值。这是由于,一旦对象被保存,JPA就不容许更改主键值。因为此缘由,病历应用程序中的大多数持久化类(包括Patient类)都使用简单的生成主键。关于具备复合主键的类的示例,请参考Group类。Id注释用于标记主键字段或标识字段。
GeneratedValue注释用于表示在插入新的Patient时主键值是由数据库生成的。数据库能够以数种方式生成主键值,可以使用strategy属性来选择其中一个。Patient类使用标识策略,这意味着id字段应被映射到数据库自动-增量或标识列。
在使用标识策略时,须要注意这对类的equals和hashcode方法所产生的影响。例如,若是equals方法比较id字段的值,请确保使用对象的方式不会致使equals方法在进行数据库插入操做以前(一般在事务提交时)被调用,由于主键值直到这时才被分配。避免这种状况的一种方法是,(若是类有的话)在equals方法中使用天然键而不是生成键。例如,Patient Social Security number是可用于Patient equals方法中的很好的天然键。
关系
大多数实体具备与域模型中其余的单个或多个实体的关系,Patient类也不例外。图2展现了Patient类及其关系图。
图2.Patient类关系
JPA使用一对1、多对1、一对多和多对多注释来指定关系及其基数。每一个关系字段必须使用这些注释中的一个进行注释。例如,Patient具备与Address的多对一关系。这意味着许多病人可能具备相同的地址。Patient与User类具备一对一关系,该类包含病人的用户名和密码信息。这意味着每一个Patient与单个的User相关。
Patient具备与Prescriptions和Records的一对多关系,由于特定的病人能够有多个处方,并可能屡次看医生(这将致使建立病历)。相反,每一个Prescription或Record只能够与一个Patient关联。
级联操做
JPA关系的一个有趣特性是操做的级联。您可能已经熟悉了大多数关系数据库所支持的“级联删除”特性。JPA采用了相似于删除的级联操做的理念,并将其应用于其余操做(例如插入和更新)。Patient类将插入和关系操做级联到相关的Address和User。在JPA中插入被视为持久化,由于数据库插入是在对对象持久化时执行的。更新被视做合并,由于更新将对象中的更改合并到当前JPA持久化上下文中。这看上去有些混乱,可是请别担忧;只需记住:在但愿更新已经被保存的对象时,要调用合并;当要在数据库中插入新的持久化对象时,要调用持久化。
肯定是否对特定操做(例如持久化、合并或移除)进行级联是须要技巧的。在Patient类的状况中,持久化被级联到Address和User,由于应用程序也须要在插入Patient的地方插入新的Address和User。相似地,在更新Patient的时候,Address和User可能也须要更新。Prescriptions和Records则不一样。应用程序具备显式持久化(以及更新)Prescription或Record的操做,因此不须要将这些操做从Patient级联到这些类。
您可能还记得前一节中咱们曾说多个Patient被容许引用相同的Address——从Patient到Address的关系是多对一。可是,咱们刚刚也说了Patient将插入级联到Address,这致使为数据库中的每位病人建立一个新地址。这是怎么回事呢?您在这里看到的是在Patient和Address之间使用生成的主键和级联插入的有趣效果。由于用于地址的主键由数据库自动生成,因此每一个Address将有唯一的主键,指向相同实际地址的两个不一样Address对象有可能都被插入到数据库中。这对于许多应用程序(包括MedRec)来讲没什么问题,可是若是您但愿阻止复制这样的地址,则DAO须要执行一些附加的逻辑。
Web Services注意事项
JPA将MedRec的实体类映射到数据库模式,而WebLogic Server 9.1 Web services实现将其映射到XML,这引起了一些影响实体类设计的其余问题。
JPA支持单向和双向关系,可是若是考察MedRec中的实体类,会看到全部关系都是单向的。这是必要的,由于Web services绑定不支持双向关系。
因为JPA要求Java Collection类型(如java.util.Set)用于多值关系字段,这引起了另外一个问题。实践代表9.1中的Web services不支持Collection类型。那么咱们如何解决这一问题呢?
不知您是否还记得,对象-关系映射能够在实体的字段或方法上定义。实践代表,JPA的此灵活性很是重要。另外一方面,Web services使用类的公有属性accessor方法(getXXX()方法)定义被封送为XML的属性。经过使用字段定义持久化映射以及由类上的方法定义XML绑定,咱们可以将两个映射分离!多值关系为了持久化在内部使用Set,可是能够经过属性访问方法将其暴露为XML绑定可以处理的数组。
为了具体说明,下面是一个来自Record类的执行此转换的属性访问方法示例:
public Prescription[] getPrescriptions() {
if (prescriptions == null)
return null;
return (Prescription[]) prescriptions.toArray(new
Prescription[prescriptions.size()]);
}
此方法在内部访问具备java.util.Set类型的持久化处方字段。此Set被转换为Web services实现可以处理的数组。关于Web services集成的体验使咱们对JPA及其与现有应用程序和基础架构集成的能力印象深入。
如今对持久化类的讨论就结束了。看起来彷佛须要遵循许多规则和限制,但事实上大多数JPA只是将好的编码实践具体化了,您可能会发现您没有过多考虑就在遵循它们。
使用DAO实现服务
如今咱们看到了如何使用Spring 2.0和JPA实现数据访问对象,接下来让咱们快速考察一下使用DAO的MedRec服务对象。如下的代码示例显示了PatientServiceImpl类及其业务方法之一,processNewRegistration方法:
public class PatientServiceImpl
extends BaseService implements PatientService {
protected PatientDao patientDao;
public void setPatientDao(PatientDao patientDao) {
this.patientDao = patientDao;
}
public void processNewRegistration(Registration registration) {
try {
User user = registration.getUser();
Patient patient = registration.getPatient();
patient.setUser(user);
user.setStatus(MedRecConstants.USER_NEW);
patientDao.save(pPatient);
} catch (Exception ex) {
...
}
}
...
}
当新病人使用MedRec Web接口自我注册时会调用processNewRegistration方法。它将保存新病人注册信息的Registration对象做为参数。ProcessNewRegistration首先从Registration对象获取Patient和User,并初始化它们之间的关系。User对象包含病人的用户名和密码信息,还保存被设置为USER_NEW的病人状态,由于这是位必须由管理员批准的新病人。而后调用Patient DAO将新的病人插入到数据库。
针对MedRec服务对象对Spring声明式事务进行配置,以便在调用业务方法(如processNewRegistration)以前由Spring启动事务,并在此方法完成时提交该事务。这确保了DAO做为可自动提交的现有事务的一部分而运行。还请注意Spring所使用的、将对DAO对象的引用注入服务bean中的setPatientDao方法。
配置
到目前为止,咱们已经考察了一些构成此版本的病历应用程序的Java代码。本节将为您介绍Spring和Kodo要求的外部配置。咱们从Spring开始。
Spring配置
咱们使用一组模块化XML配置文件来配置Spring ApplicationContext。包含数据访问对象配置的配置文件是applicationContext-orm.xml,它位于MedRec安装目录下的src\medrecEar\APP-INF\classes目录中。如下是applicationContext-orm.xml中声明Patient DAO的片断:
<bean id="patientDao"
class="com.bea.medrec.dao.orm.JpaPatientDao"
autowire="byType"/>
Spring的JPA DAO具备须要被注入的单一依赖,即JPA EntityManagerFactory。DAO使用此EntityManagerFactory建立执行实际持久化工做的JPA EntityManagers。这里使用Spring自动绑定特性完成绑定,这就是为何咱们在XML中看不到对EntityManagerFactory的显式依赖。自动绑定特性自动将DAO绑定到基于DAO的EntityManagerFactory属性(继承自全部MedRec DAO类对其进行扩展的Spring JpaDaoSupport类)类型的EntityManagerFactory。
如下代码是声明建立EntityManagerFactory的Spring工厂bean的片断。因为这里讨论了两个工厂,可能听起来有些混乱,可是请记住:Spring工厂bean的目的就是提供一个中间层,以便容许咱们执行某些自定义代码以建立EntityManagerFactory。此EntityManagerFactory是DAO对象唯一知道或关心的工厂。
<bean id="entityManagerFactory"
class="com.bea.medrec.utils.KodoEntityManagerFactoryBean">
<property name="jndiName">
<value>kodo-jpa</value>
</property>
</bean>
由于在撰写本文的时候,WebLogic Server不支持与JPA的标准集成,因此EntityManagerFactory经过使用自定义工厂bean而建立。EntityManagerFactory须要知道在JNDI中的什么地方查找Kodo资源适配器。该信息被配置为Spring工厂bean上的属性,后者将其传送到EntityManagerFactory。请记住,工厂bean的任务是建立EntityManagerFactory事件并将其返回到Spring,以使Spring可以将EntityManagerFactory注入DAO bean。用于建立实体管理器工厂实例的工厂bean代码以下所示:
public class KodoEntityManagerFactoryBean
implements FactoryBean, InitializingBean {
private String jndiName = "kodo-jpa";
private EntityManagerFactory entityManagerFactory = null;
public void setJndiName(String jndiName) {
this.jndiName = jndiName;
}
public Object getObject() throws Exception {
return entityManagerFactory;
}
public Class getObjectType() {
return EntityManagerFactory.class;
}
public boolean isSingleton() {
return true;
}
public void afterPropertiesSet() throws Exception {
try {
entityManagerFactory =
KodoPersistence.createEntityManagerFactory(
jndiName, new InitialContext());
} catch (Throwable throwable) {
throw new RuntimeException(throwable);
}
}
}
KodoEntityManagerFactoryBean是一个至关简单的Spring工厂bean。在运行时,Spring首先调用默认的构造函数建立bean实例。而后,Spring调用setJndiName()方法设置Kodo资源适配器的JNDI名称。一旦全部属性被注入,Spring就调用建立EntityManagerFactory实例的afterPropertiesSet()。最后,Spring调用getObject()来获取将被注入DAO的EntityManagerFactory。
咱们已经看到了如何使用Kodo EntityManagerFactory(DAO使用它来完成全部持久化工做)注入Spring DAO。而后Kodo EntityManagerFactory经过JNDI链接到Kodo资源适配器。接下来,咱们将考察Kodo资源适配器的配置,可是首先须要知道一点关于Spring配置的其余内容,这将有助于将全部事情联系起来。
Spring须要被告知使用WebLogic JTA事务管理器来启动和提交事务。此操做在如下的XML片断中完成:
<bean id="transactionManager"
class="org.springframework.transaction.jta.WebLogicJtaTransactionManager">
<property name="transactionManagerName"
value="javax.transaction.TransactionManager"/>
</bean>
这里要明白一件重要的事情,即,须要专门告诉Spring将事务工做委托给WebLogic JTA实现。稍后,咱们将看到Kodo也被告知在其配置中使用JTA事务。这将安排好事情以便MedRec服务对象启动WebLogic JTA事务,而后在此事务中调用DAO。随后DAO调用Kodo,它做为现有WebLogic JTA事务的一部分执行数据库读出和写入。
Kodo配置
咱们使用Kodo 4.0 EA4,它是Kodo的JPA实现的早期访问版本。在撰写本文的时候,定义JPA的EJB 3.0规范还没有完成,因此Kodo支持JPA的pre-final版本。Kodo做为资源适配器被部署到WebLogic Server。此资源适配器在JNDI中进行注册。资源适配器的配置在标准ra.xml描述符文件中进行,它位于资源适配器RAR文件的META-INF目录中。
若是考察ra.xml文件,会看到Kodo支持多种配置选项(成熟产品的标志)。然而,示例应用程序仅须要咱们修改其中的一小部分。让咱们看看示例应用程序须要的属性:
<config-property>
<config-property-name>ConnectionFactory2Name</config-property-name>
<config-property-type>java.lang.String</config-property-type>
<config-property-value>jdbc/MedRecGlobalDataSource
</config-property-value>
</config-property>
<config-property>
<config-property-name>ConnectionFactoryName</config-property-name>
<config-property-type>java.lang.String</config-property-type>
<config-property-value>jdbc/MedRecGlobalDataSourceXA
</config-property-value>
</config-property>
<config-property>
<config-property-name>TransactionMode</config-property-name>
<config-property-type>java.lang.String</config-property-type>
<config-property-value>managed</config-property-value>
</config-property>
<config-property>
<config-property-name>LicenseKey</config-property-name>
<config-property-type>java.lang.String</config-property-type>
<config-property-value>XXXXXXXXXXXXXXXXXXXX</config-property-value>
</config-property>
<config-property>
<config-property-name>PersistentClasses</config-property-name>
<config-property-type>java.lang.String</config-property-type>
<config-property-value>
com.bea.medrec.domain.Patient,com.bea.medrec.domain.Address,
com.bea.medrec.domain.User,com.bea.medrec.domain.Physician,
com.bea.medrec.domain.Prescription,com.bea.medrec.domain.Record,
com.bea.medrec.domain.Group,com.bea.medrec.domain.VitalSigns
</config-property-value>
</config-property>
Kodo须要被告知JDBC数据源的JNDI位置,以便它可以与数据库交互。事实上,Kodo须要知道两个数据源:一个数据源用于处理事务工做,另外一个用于非事务工做,由于Kodo有时访问数据库执行不属于全局事务的工做。您可能已经猜到了,ConnectionFactoryName和ConnectionFactory2Name属性正是用于此目的。每一个属性的值是WebLogic数据源的JNDI名称。请确保ConnectionFactory2Name引用的数据源不将其链接加入全局JTA事务。
Kodo还须要知道此应用程序是否正在使用JTA管理的事务或本地事务。由于控制事务的MedRec服务bean被配置为使用JTA,因此咱们将TransactionMode属性值设为托管。此外,还须要在资源适配器文件中配置Kodo许可,并列出应用程序将使用的持久化类。用于此用途的属性应该是自解释的。
若是您曾经考察过JPA规范,您可能据说过persistence.xml文件。这是包含与JPA持久化相关的元数据的标准配置文件。Kodo还支持persistence.xml文件。然而,在应用服务器环境中使用Kodo的当前早期访问版本时,persistence.xml文件仅包含资源适配器配置中指定的信息的子集,且只能经过工具(例如Kodo加强程序)使用。
下载
如下下载包括本文所讨论的MedRec版本的全部Java和其余源文件,以及Spring 2.0和Kodo二进制文件及其依赖性:
medrec-spring-jpa.zip。您大概须要27MB的磁盘空间来存放下载文件。
结束语
本文详细考察了对Spring 2.0中的新增JPA支持的使用,该特性被用于从新实现MedRec示例应用程序的数据访问层。但愿本文为您提供了开始使用这些新API所需的信息。若是您但愿进行更深刻地研究,咱们建议您考察本文所包含的实际MedRec代码。示例应用程序代码演示了如何以集成方式协同使用WebLogic 9.一、Spring 2.0和Kodo JPA。
咱们已经看到新的JPA API易用、直观且具备灵活性。Java注释在下降指定数据库映射所需的元数据数量方面表现突出。虽然JPA是新增的,可是其强大功能足以容许咱们继续在持久化层、Web层和Web服务层中的应用程序中使用域模型类。此重用大大简化了应用架构,并显著下降了开发人员须要编写的Java类的数量。
而Spring 2.0方面提供了一个利用JPA建立数据访问对象的优秀工具。Spring的数据访问架构使得咱们能够轻松地在不一样持久化技术之间进行转换,而无需重写其余应用程序代码。
参考资料
做者简介 |
 Seth White |
Seth White 是BEA的高级工程师,近6年来,他是WebLogic Server工程团队的成员。目前他是WebLogic Server开源团队的成员。 |