Apusic4.0下,SLSB+ EJB3.0(edr2)持久化API事务性编程指南

一、  前言

  基于POJO的持久化技术,如HibernateJDO,如今受到广大J2EE开发者的追捧。当然,一门技术受到关注不会是凭空的。基于POJO的持久化技术,到底给我们带来了什么?

1、   对象驱动开发,使得基于OO方法学的开发过程更加流畅。基于JDBC、甚至EntityBean的开发,基本上是典型的数据驱动开发。

2、   提高开发效率。您不再需要大量的JDBC编码。

3、   功能强大。

4、   便于测试。

EJB3.0持久化模型和Hibernate如出一辙,但是以其权威性备受关注。

下面,我将和大家一起来探讨SLSB+EJB3.0(edr2)架构的实施方法。这里,我们采用Hibernate EJB3.0(edr2)实现。

 

二、  准备工作

1Apusic4.0应用服务器

  下载地址:http://www.apusic.com/product/download/Apusic-4.0.exe

  说明:Apusic4.0 AS是金蝶中间件公司的产品。J2EE1.4兼容。

2、数据库系统MS SQLServer

   Microsoft SQLServer 2000 Drivermsutil.jarmsbase.jarmssqlserver.jar

3Hibernate-3.0.1

  下载地址:http://prdownloads.sourceforge.net/hibernate/hibernate-3.0.1.zip?download

  说明:Hibernate Core。是EJB3.0(edr2)持久化技术的底层基础。

4Hibernate Annotations 3.0 Preview beta 1

  下载地址:

http://prdownloads.sourceforge.net/hibernate/hibernate-annotations-3.0beta1.zip?download

  说明:EJB3.0(edr2)绝大部分持久化Meatadata(Annotation)实现,并且提供了很多实用而强大的扩展Annotation

5Eclipse

6JDK必须1.5以上

 

三、  示例:作者/著作(Author/Work)

  这个示例来自Hibernate Manual(Author/Work)。这个Sample,涉及Many-ManyOne-One关系、继承,很适合做技术演示。

  假设,在基于OO方法学的开发过程中,我们在详细设计完成后,得到下面的UML图。

图中涉及的对象,都是需要持久化到数据库的。如果,你打算基于JDBC或者EntityBean来做开发,那么,显然,你的下一步工作就是设计数据库Schema。然后,针对Schema进行JDBCEntityBean编码。但是,作为一个纯粹而挑剔的OO开发者,这种数据驱动开发很别扭,而且,往往,这种开发模型的编码类似于过程编程。

  理想的状态:详细设计后,编码。我的代码只关心商业逻辑,至于在商业逻辑中涉及的对象持久化到什么地方、怎样持久化,我都没有兴趣。充其量,为了配合O/R Tool,我提供对象关系、有利于提高持久化性能、扩展性等等MetadataOK。就是这样。在UML图的基础上,我们接下来的工作就是:

1、   UML图转换成Java代码。(借助工具或者IDE的工程,高效完成)

2、   为对象添加Meatadata(在基于EJB3.0持久化技术的开发中,就是为JavaSource添加Annotation)

3、   O/R工具根据Meatadata自动生成Database Schema.

4、   基于O/R Tool编码。

 

四、  开发过程

1、准备Jars和配置文件

  假定Apusic4.0的安装目录为:${APUSIC_HOME}

假定hibernate-3.0.1.zip的解压缩目录为${hibernate_ext}

hibernate-annotations-3.0beta1.zip的解压缩目录为${hibernate_annotation_ext}

  1)Apusic 核心包。

    ${APUSIC_HOME}/lib/apusic.jar

2)Hibernate 核心包。

    ${hibernate_ext}

3)Hibernate Runtime 依赖的Jars

Hibernate Build依赖的Jars

这些包都放在${hibernate_ext}/lib目录下。

至于哪些是运行时依赖的、哪些是Build时依赖的,q请参考同目录下的README.txt

  5)Hibernate EJB3.0(edr2) Annotataion支持Jars

${hibernate_annotation_ext}/hibernate-annotations.jar

${hibernate_annotation_ext}/lib/ejb-3.0-edr2.jar

  6)配置文件

${hibernate_ext}/etc/hibernate.properties

${hibernate_ext}/etc/log4j.properties

${hibernate_ext}/etc/ehcache.xml

    Hibernate二级缓存支持多种Cache系统,包括JbossCacheJCSOSCache等等。这里,我选择EHCache,所以,我准备ehcache.xml而不是oscache.properties或者treecache.xml

2、修改配置文件hibernate.properties

  Hibernate提供设定的属性非常多,主要涉及以下几个大的方面:Query LanguagePlatformsHibernate Connection PoolTransaction APIMiscellaneous SettingsJDBC SettingsSecond-level CacheJNDI。这里,我不会详细说明每个配置项的作用,而将说明的重点放在和HibernateEJB容器环境下事务性编程相关的配置项上。

1)       Query Language

不作改动。

2)       Platforms

Action1:设定JNDI DataSource

## JNDI Datasource

hibernate.connection.datasource jdbc/sqlserver/publisher

#hibernate.connection.username sa

#hibernate.connection.password sa

说明:

1、因为,我们需要使用容器管理事务,所以必须使用Apusic应用服务器的DataSource,应用服务器的DataSource可以自动被事务征集。而普通的DataSource是不具有这样的功能的。

2、根据各应用服务器的实际情况,决定是否需要设置usernamepassword。譬如Apusic4.0DataSource等资源的远程客户是需要通过安全性检查的,只允许特定用户或者组(Role)的用户才可以使用,所以需要设定username或者password。而本机用户,没有这样的限制,就不需要设定。

Action2屏蔽HypersonicSQL配置

## HypersonicSQL

 

#hibernate.dialect org.hibernate.dialect.HSQLDialect

#hibernate.connection.driver_class org.hsqldb.jdbcDriver

#hibernate.connection.username sa

#hibernate.connection.password

#hibernate.connection.url jdbc:hsqldb:hsql://localhost

#hibernate.connection.url jdbc:hsqldb:test

#hibernate.connection.url jdbc:hsqldb:.

 Action3:设定数据库方言

## MS SQL Server

 

hibernate.dialect org.hibernate.dialect.SQLServerDialect

#hibernate.connection.username sa

#hibernate.connection.password sa

说明:因为Hibernate为了功能的增强和性能的提高,会将对象操作翻译成特定数据库系统的SQL。所以,你需要设定Dialect

 

3) Hibernate Connection Pool

Action1屏蔽hibernate.proxool.pool

##############################

### Proxool Connection Pool###

##############################

 

## Properties for external configuration of Proxool

#hibernate.proxool.pool_alias pool1

## Only need one of the following

#hibernate.proxool.existing_pool true

#hibernate.proxool.xml proxool.xml

#hibernate.proxool.properties proxool.properties

说明:因为我们使用Apusic应用服务器的DataSource,所以,取消Hibernate默认使用的Proxool Connection Pool

Action2:设定Plugin ConnectionProvider

#################################

### Plugin ConnectionProvider ###

#################################

 

## use a custom ConnectionProvider (if not set, Hibernate will choose a built-in #ConnectionProvider using hueristics)

#hibernate.connection.provider_class #org.hibernate.connection.DriverManagerConnectionProvider

hibernate.connection.provider_class org.hibernate.connection.DatasourceConnectionProvider

#hibernate.connection.provider_class org.hibernate.connection.C3P0ConnectionProvider

#hibernate.connection.provider_class org.hibernate.connection.ProxoolConnectionProvider

说明:打开配置:

hibernate.connection.provider_class org.hibernate.connection.DatasourceConnectionProvider

 

4)Transaction API

  Action1设定TransactionAPI

## the Transaction API abstracts application code from the underlying JTA or JDBC #transactions

#hibernate.transaction.factory_class org.hibernate.transaction.JTATransactionFactory

hibernate.transaction.factory_class org.hibernate.transaction.JDBCTransactionFactory

说明:事实上,在容器管理事务的环境下,这两个配置项任意选定一个都是没有问题的。

 Action2

## to use JTATransactionFactory, Hibernate must be able to locate the UserTransaction in #JNDI

## default is java:comp/UserTransaction

## you do NOT need this setting if you specify hibernate.transaction.manager_lookup_class

 

#jta.UserTransaction jta/usertransaction

#jta.UserTransaction javax.transaction.UserTransaction

#jta.UserTransaction UserTransaction

说明:因为我们选择容器管理事务,不会自己管理任何的事务,也不需要JTATransaction

所以屏蔽此项。

5Miscellaneous SettingsJDBC Settings

   不作改动。

6Second-level Cache

  Action1:配置cache implementation

 

## choose a cache implementation

 

hibernate.cache.provider_class org.hibernate.cache.EhCacheProvider

#hibernate.cache.provider_class org.hibernate.cache.EmptyCacheProvider

hibernate.cache.provider_class org.hibernate.cache.HashtableCacheProvider

#hibernate.cache.provider_class org.hibernate.cache.TreeCacheProvider

#hibernate.cache.provider_class org.hibernate.cache.OSCacheProvider

#hibernate.cache.provider_class org.hibernate.cache.SwarmCacheProvider

说明:我们上面提及将使用EHCache作为二级缓存的Provider。所以,这里打开

hibernate.cache.provider_class org.hibernate.cache.EhCacheProvider项。

 

7JNDI

Action1

 

############

### JNDI ###

############

 

## specify a JNDI name for the SessionFactory

 

#hibernate.session_factory_name hibernate/session_factory

 

 

## Hibernate uses JNDI to bind a name to a SessionFactory and to look up the JTA UserTransaction;

## if hibernate.jndi.* are not specified, Hibernate will use the default InitialContext() which

## is the best approach in an application server

 

#file system

#hibernate.jndi.class com.sun.jndi.fscontext.RefFSContextFactory

#hibernate.jndi.url file:/

 

#WebSphere

#hibernate.jndi.class com.ibm.websphere.naming.WsnInitialContextFactory

#hibernate.jndi.url iiop://localhost:900/

说明:

1、   hibernate.session_factory_name hibernate/session_factory

如果,你希望HibernateSessionFactory绑定到JNDI上,从而方便J2EE AS环境下Hibernate编程,那么需要指定这个项目。本实例中,我们不采用这种方式,所以,取消这项配置。

2、   hibernate.jndi.url

如果,你需要以远程的方式来使用JTA或者将SessionFactory绑定到JNDI,那么你需要配置应用服务器特定的ContextFactory ClassURI、甚至PrincipalCreditial

   本实例中,我们不会采用Hibernate JTA,也不会远程绑定SessionFactory,所以取消此项配置。

 

 

3Eclipse工程命名Publisher3

   结构如下图:

说明:

1)       为工程新建目录:dependedjars,存放所以build time/runtime 依赖的jars

出于工程编译和测试的需要,你需要将dependedjars中所有jars引用到工程中。

2)       ehcache.xmlhibernate.propertieslog4j.properties放到src目录下。

3)       tomhornson.ejb3.publisher.appexcepton:存放工程的应用级异常。

tomhornson.ejb3.publisher.client:存放Remote测试客户端。

tomhornson.ejb3.publisher.entity:存放带有AnnotataionPOJO形式的持久化Entity

tomhornson.ejb3.publisher.slsb:存放SLSB,作为应用的façade,通过O/R Tool操作持

POJO

   tomhornson.ejb3.publisher.util:工具类。

 

 

五、  部署

1、配置数据源

1)MS SQLServer JDBC Drivermsbase.jarmsutil.jarmssqlserver.jar放到

${APUSIC_HOME}/lib/ext目录下。

2)启动Apusic4.0应用服务器。

3)打开Apusic RemoteManager,通过默认用户名admin、默认密码admin登陆远程管理界

面。

4Apusic为几种流行的数据库,提供默认的URL格式和驱动类名称,所以你只需要输入

用户名(数据库登陆名)和密码,就可以了。当然,你也可以针对一些高级选项进行配置。

效果如下:

 

2、   部署应用到Apusic服务器

出于系统维护性和多Hibernate工程同应用服务器运行引起互相干扰的考虑,我们将以EAR为单位部署Hibernate运行环境。而是不是,将Hibernate运行依赖Jars防止到${APUSIC_HOME}/lib或者${APUSIC_HOME}/lib/ext目录中。

 

参考,Apusic4.0 Manual的《部署工具用户手册》新建一个EAR工程,添加一个EJB模块,为EJB模块添加AuthorFacade SLSB。你的EAR工程目录结构,如下:

 

3、为EJB模块编写MANIFEST.MF文件

   内容如下:

Class-Path:  hibernate3.jar asm.jar cglib-2.1.jar commons-collections-2.1.1.jar

commons-logging-1.0.4.jar dom4j-1.5.2 ehcache-1.1.jar ejb-3.0-edr2 hibernate-annotations versioncheck.jar xerces-2.6.2.jar

说明:这个MANIFEST.MF文件,保证AuthorFacade SLSB能够引入依赖的类。

MANIFEST.MF文件防止到AuthorFacadeMETA-INF目录中。

 

4Hibernate运行依赖Jars和配置文件到EAR工程目录。

这样,EAR根目录的结构如下所示:

5、   使用部署工具,将publisher3 EAR工程部署到Apusic服务器。

 

OK

 

一切工作完成。

 

六、  编程和原理探讨

1、   使用HibernateAnnotationed POJO JavaSource生成数据库Schema

Annotation 示例:

/*

 * Created on Apr 21, 2005

 * Author: TomHornson(at)hotmail.com

 */

package tomhornson.ejb3.publisher.entity;

 

import java.io.Serializable;

import javax.persistence.*;

import org.hibernate.annotations.*;

 

@org.hibernate.annotations.Entity(

        dynamicInsert = true,

        dynamicUpdate = true,

        selectBeforeUpdate = true,

        polymorphism = PolymorphismType.IMPLICIT

 )

@javax.persistence.Entity(access = AccessType.PROPERTY)

@BatchSize(size = 50)

@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)

/*

@Inheritance(

        strategy = InheritanceType.SINGLE_TABLE,

        discriminatorType=DiscriminatorType.STRING,

        discriminatorValue="person"

    )

@DiscriminatorColumn(name="person")

*/

@Inheritance(strategy = InheritanceType.JOINED)

public class Person implements Serializable{

    static final long serialVersionUID = -3387516993124229940L;

    protected long id;

    protected String name;

    protected int version;

   

    @Id(generate=GeneratorType.AUTO)

    @Column(updatable=false)

    public long getId() {

        return id;

    }

    public void setId(long id) {

        this.id = id;

    }

   

    @Column(nullable=false,updatable=false)

    public String getName() {

        return name;

    }

    public void setName(String name) {

        this.name = name;

    }

   

    @Version

    public int getVersion(){

        return version;

    }

    public void setVersion(int version){

        this.version = version;

    }

}

   如上面所示,我们的POJO都是Annotation标志过的,这些标志定义了一系列的对象关系、持久化策略、缓存策略、事务隔离性、乐观并发策略等等。

而,依赖于这些标志,HibernateSchemaExport Command可以自动生成Database Shema

代码片断如下:

        AnnotationConfiguration anno = new AnnotationConfiguration();

        Class[] cArr = {Person.class,Author.class,Work.class,Song.class,Book.class};

        List<Class> al = Arrays.asList(cArr);

        anno.addAnnotatedClasses(al);

        anno.setProperty(Environment.HBM2DDL_AUTO, "create-drop");

        sf = anno.buildSessionFactory();

        Session session = sf.openSession();

 

2、容器管理事务环境下Hibernate编程

   容器管理事务的原理概述:当设定启用CMT的方法被调用时,容器在方法调用前调动一个事务,并且和线程绑定(ThreadLocal)

               Session session = SessionHelper.openSession();

   上面的代码,别后发生的事情:HibernateApusic应用服务器的DataSource取得Connection,而来自服务器的DataSource是事务感应的,它在返回Connection之前,已经检测当前线程是否绑定事务,如果是,那么将Connection征集到事务中。所以,CMT Hibernate编程,你只需要任意的openSession,closeSession,不需要考虑事务回滚问题,当运行时异常或者系统级别异常发生时,容器会透明回滚所有的被征集的Connection。保证事务的原子性。

而对于事务隔离性和交叉存取问题,Hibernate也是支持的,所以基于SLSB+Hibernate可以开发事务要求很高的应用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值