BSTEK Development Framework2(BDF2) : 2.BDF2-ORM

      BDF2-ORM模块有两个,分别是BDF2-ORM-HIBERNATE3与BDF2-ORM-HIBERNATE4,如同ORM名字一样,BDF2-ORM模块主要提供针对数据库持久化的相关操作,这其中BDF2-ORM-HIBERNATE3是支持Hibernate3,而BDF2-ORM-HIBERNATE4则支持Hibernate4,值得注意的是这两个版本当中提供的针对Hibernate、Jdbc以及JPA的API完全一样,只是在编译的时候针对Hibernate部分不太一样,但对于我们程序员来说,看到的API则完全相同,BDF2当中所有涉及到ORM的操作全部都依赖BDF2-ORM-HIBERNATE3,也就是说默认都是基于Hibernate3编译的,当然如果你需要使用Hibernate4版本,可以到我们的nexus.bsdn.org上下载,如果您使用Maven,那么可以通过添加classier属性,将classifier属性设置为hibernate4即可,例如:

classier示例
		<dependency>
			<groupId>com.bstek.bdf2</groupId>
			<artifactId>bdf2-core</artifactId>
			<version>2.0.6</version>
			<classifier>hibernate4</classifier>
			<exclusions>
				<exclusion>
					<artifactId>bdf2-orm-hibernate3</artifactId>
					<groupId>com.bstek.bdf2</groupId>
				</exclusion>
			</exclusions>
		</dependency>

      上面的代码当中,如果去掉classier标记,那么将采用基于Hibernate3编译的bdf2-core包。在BDF2目前提供的各模块当中,除BDF2-JBPM4、BDF2-EXPORT两模块之外,其它各模块皆分Hibernate3与Hibernate4两不同编译版本,当然默认采用Hibernate3对于我们项目来说已经足够了。

      要使用BDF2-ORM模块,需要在Spring环境当中配置数据源,具体配置方法参见项目创建与配置中关于配置数据源部分的描述,当然如果未使用BDF2-CORE模块(项目创建与配置当中是使用了BDF2-CORE模块的),那么需要将配置的datasources.xml文件import到WEB-INF/dorado-home目录下的context.xml当中,否则这个datasources.xml文件将不会被Spring初始化,需要注意的是,默认的datasources.xml文件中添加了BDF2提供的namespace schema定义,如果没有BDF2-CORE模块,需要将这个定义信息删除,因为只有BDF2-CORE中才能解析这个namespace schema,否则会出现异常。

      数据源配置好之后,我们就可以使用BDF2-ORM模块当中提供的三个实现与数据库交互的基类了,它们是:JdbcDao、HibernateDao及JpaDao,顾名思义,JdbcDao是采用JDBC方式与数据库交互;HibernateDao采用Hibernate;JpaDao则是采用的是JPA规范实现(基于Hibernate实现的JPA规范)。这三个DAO基类当中,提供了大量针对数据库操作的方法,其中最多的是查询方法,以paging开头的query方法主要实现分页查询,它可以直接处理Dorado7中的Page对象,当前不同DAO要求输入的查询语句也不相同,比如JDBC中的query方法要求的是标准的SQL,Hibernate则是HQL,JPA则是JPQL;如果需要对数据库中数据进行更新插入动作,那以在JdbcDao中我们可以通过获取Spring提供的JdbcTemplate实现,在HibernateDao当中则通过获取Session实现(Spring3.2已不推荐使用HibernateTemplate),JpaDao则是获取EntityManager实现。

      值得一提的是这三个DAO类都继承自AbstractDao,这个DAO当中提供了用于解析Dorado7提交上来的基于表格过滤栏的查询操作的名为Criteria对象的方法( 我们知道Dorado7支持基于表格过滤栏的查询操作):

解析过滤栏查询对象的方法
/**
	 * @param criteria 要解析的目标Criteria对象
	 * @param useParameterName 在接装查询条件时是否采用参数名
	 * @param alias 别名字符串
	 * @return ParseResult对象,其中包含解析生成SQL拼装对象以及查询条件的值对象Map,其中key为查询字段名,value为具体条件值
	 */
	protected ParseResult parseCriteria(Criteria criteria,boolean useParameterName,String alias)

      可以看到返回的是一个ParseResult对象,如果调用时给出的第一个Criteria参数为空,那么返回的ParseResult对象也相应为空。除此之后,我们如果直接使用Hibernate来进行查询,那么还可以直接调用HibernateDao当中提供的buildDetachedCriteria方法将表格过滤栏查询对象直接转换成Hibernate所需要的DetachedCriteria对象实现数据的快速查询操作,具体大家可以参见源码或javadoc(两者皆可以到http://nexus.bsdn.org上下载)。

      在项目当中,无论我们项目采用哪种类型的DAO,我们都希望都在这个DAO外再包一层,把这个包好的DAO给具体的业务开发人员使用,因为标准的DAO当中包含太多的方法,可能我们的项目当中只需要用到其中的几种就行,大多数是用不到的,所以对DAO做个facade是最佳操作。

      我们知道,BDF2的ORM是支持多数据源的,在每个DAO当中就可以实现数据源的切换,所以我们在DAO中看到很多方法都可以指定采用哪个数据源(调用方法时指定一个数据源名称),如果我们采用了不需要指定数据源的方法,那么系统会采用默认的数据源与数据库进行交互。在AbstractDao当中有个名为getModuleFixDataSourceName的方法,它的作用就是固化当前DAO采用的数据源名称的,除非你手工指定数据源名称,否则系统将采用这个数据源,而不再使用默认数据源(当然有可能你固化的数据源就是默认数据源)。一般来说,如果你需要让你的某个业务模块可以采用某个固定数据源,就可以覆盖这个方法,比如我们的CoreJdbcDao就允许采用某个固定的数据源名称,其代码如下:

固定数据源示例
public abstract class CoreJdbcDao extends JdbcDao {
	@Override
	protected String getModuleFixDataSourceName() {
		return Configure.getString("bdf2.coreDataSourceName");
	}
}

      实际上,BDF2当中各模块固定数据源就是采用这个方法实现的。对于扩展自这三个DAO的类,我们需要做的就是将其直接配置到Spring环境当中,不用注入或依赖其它任何对象,系统会自动为这这些扩展自三个DAO的实现类填充诸如数据源之类信息的。

      除了上述这种通过调用代码来指定要采用的数据源名,BDF2中还允许你通过ContextHolder中的setCurrentDataSourceName方法来为当前线程中未指定数据源的方法固化一个数据源,这样就可以实现数据源的动态切换,比如利用这种方法让某个人采用某个数据源等,具体这里就不再展开,大家可以发挥一下想象。

       ORM模块允许用户覆盖的属性如下表所示:

属性名类型默认值描述
bdf2.terracottaServerString用于分布式缓存的terracotta server的地址,多个地址用逗号分隔,多在集群时使用,以保证各集群实例缓存一致,默认为空,表示不采用集群缓存。
bdf2.smtpHostString系统提供的Email发送器发送Email时采用的SMTP服务地址。
bdf2.smtpIsAuthbooleantrue系统提供的Email发送器发送Email时采用的SMTP服务是否需要验证。
bdf2.smtpUserString系统提供的Email发送器发送Email时采用的SMTP服务需要验证时的用户名。
bdf2.smtpPasswordString系统提供的Email发送器发送Email时采用的SMTP服务需要验证时的密码。
bdf2.defaultSenderEmailAddresString系统提供的Email发送器发送Email时采用的发送Email地址。
bdf2.systemTempDirStringBDF2中存放临时文件的目录,默认采用的是java.io.tempdir属性对应的值。如果我们需要指定服务器上某个文件夹作为临时文件存放目录,那么可以覆盖该属性,同时指定的目录一定要真实存在,否则会出现错误。