Java Data Object(JDO) API 是标准、基于接口的持久性 Java 模型抽象,可以直接把 Java 域模型实例保存到数据存储。JDO 是作为 Java Specification Request 的一部分开发的。
JDO、JDBC 和 Hibernate
JDO 简介 Java Data Object(JDO) API 是标准、基于接口的持久性 Java 模型抽象,可以直接把 Java 域模型实例保存到数据存储。JDO 是作为 Java Specification Request 的一部分
开发的。
开发应用程序时,程序员可以用 Java 编程语言编写代码,透明地访问底层数据存储,而不需要编写特定于数据库的代码。JDO 技术的特性有:
- 可移植性:用 JDO API 编写的应用程序可以运行在多个实现上,不需重新编译或修改源代码。
- 数据库独立性:用 JDO API 编写的应用程序独立于底层数据库。
- 专注于域模型:程序员现在可以专注于他们的域模型,把持久性的细节问题留给 JDO 实现处理。
- 高性能:程序员可以把持久性的细节委托给 JDO 实现,JDO 实现能够优化数据访问模式,从而获得最佳性能。
JDBC 简介 Java Database Connectivity(JDBC)API 是作为 Java 2 标准版(J2SE)和 Java 2 企业版(J2EE)平台的关键部分出现的。它是 Java 语言以编程方式访问关系数据库的基于标准的首要
机制。
JDBC API 为程序员提供了极大的灵活性,它提供了对数据库访问和缓存管理的直接控制。JDBC API 是项成熟的技术,是一种完善且已得到充分认识的 API,因而得到业内的广泛认同。
当前的 JDBC 版本(3.O)对旧版本进行了许多必要的改进。DB2 8 及之后的版本完全支持 JDBC 3.0 API。许多特性,例如从数据库检索自动生成键的能力、打开多个结果集的能力、改进的连接和语句池等都是 JDBC 3.0 中值得称道的新能力。例如,清单 1 显示了用 JDBC 3.0 检索自动生成键的代码片段:
清单 1. JDBC 自动生成键
Statement stmt = conn.createStatement(); //Obtain the generated` key from query. stmt.executeUpdate("INSERT INTO Accounts " + "(account_name, balance) " + "VALUES ('Smith Savings Account', 500.00)", Statement.RETURN_GENERATED_KEYS);
ResultSet rs = stmt.getGeneratedKeys(); if ( rs.next() ) { // Retrieve the auto generated key(s) i.e account_id. int accountIdkey = rs.getInt(1); } |
Hibernate 简介 Hibernate 是个强大的、高性能的对象/关系持久性和查询服务。Hibernate 支持开发符合面向对象风格的持久性类,包括关联、继承、多态、复合和集合。Hibernate 允许您用它自己的可移植 SQL 扩展(HQL)表示查询,也可以用纯粹的 SQL 或面向对象方式和示例 API 表示。与其他许多持久性解决方案不同,Hibernate 没有使您失去使用 SQL 的力量,从而保证了在关系技术上的现有投资和知识一直有效。
Hibernate 是专业的开放源码项目,比起其他持久性框架,它是应用和接受最为广泛的框架。像 Spring 这样的框架提供了对 Hibernate 丰富的支持,在这里 Spring 的面向方面编程(AOP)框架为开发人员提供了一种声明式地提供 Hibernate 事务的方式。
Hibernate 用 XML(*.hbm.xml)文件把 Java 类映射到表,把 Java Beans? 属性映射到数据库表。通过 JDBC 支持全部 SQL 数据库管理系统。Hibernate 可与所有流行的 J2EE 应用服务器和 Web 容器完美集成。
Hiābernate 与 JDO 的比较 Hibernate 是一种得到广泛信任和采用的持久性框架,比 JDO 这样的规范更成熟。两个框架在提供持久性时,都可以直接把 Java 域对象保存到持久存储。由于 JDO 是 Java 规范的一部分,而 Hibernate 具有开放源码这样的背景,所以在未来的一段时间内,JDO 仍将在一段时间内得到不同厂商的认同。
如果在 Hibernate 未来的发行版中,能在现有的开放源码持久性框架上提供对 JDO 的支持,将会很好,这样就可以把 JDO 规范的强大力量与 Hibernate 可靠的开放源码特性结合。
开始 在这份教程中,我们将构建一个示例应用程序,它整合了 Spring AOP 的声明式事务处理,以及 Spring 加 Hibernate 的持久性主干。Spring 是个开放源码框架,它的创建是为了解决企业应用程序开发的复杂性问题。Spring 是面向控制和面向方面的容器框架的轻量级版本。 Spring 框架提供了 AOP 框架、JDBC DAO 抽象、与 ORM 框架(像 JDO、Hibernate 和 IBATIS SQL 映射)的集成,带有声明式事务支持以及构建 Web 应用程序的全功能 MVC 框架。
Spring 的功能可以用于任何 J2EE 服务器,多数功能也可以用于非托管环境。Spring 的一个核心重点就是允许使用未绑定到特定 J2EE 服务上的可重用业务和数据访问对象。这类对象可以跨 J2EE 环境(Web 或 EJB)、独立应用程序、测试环境等重用,毫无困难。
我们的示例应用程序代表一个示例企业,其中包含多个部门和员工。我们的示例应用程序需要创建一个名为 orgdb 的 DB2 数据库,这也是即将介绍的第一步。 SampleOrgDB 容纳部门和员工
信息。假设部门和员工之间的关联是 1:N。
创建示例数据库 本节创建示例企业应用程序要使用的示例数据库。创建容纳部门和员工信息的示例 orgdb 数据库。创建源表的方法如下:
在 Windows 命令行提示符下,输入 db2cmd。
输入以下语句,创建所需数据库:
db2 create database orgdb
按下 Enter 键。
现在我们已经创建好了企业数据库。容纳部门和员工应用程序的表将由示例 Hibernate 应用程序创建。
构建示例应用程序 这一节用 Spring AOP 和 Hibernate 构建并逐步检查示例企业应用程序,程序将在 DB2 数据库中保存一个 Java 对象。应用程序允许企业添加部门和属于这些部门的员工。
为数据库交互实现 DOA(数据访问对象)模式。把 Spring AOP 的 TransactionProxyFactoryBean 设置为拦截方法调用,并声明式地把事务上下文应用到任何事务密集型操作的 DOA 上。
为 DB2 设置 JDBC 数据源和 HibernateSessionFactory 在 Spring 框架中,JDBC DataSource 或 Hibernate SessionFactory 这样的资源在应用程序上下文中可视为 bean。需要访问资源的应用程序对象只要通过 bean 引用检索到这类预定义实例的引用即可(下一节将更详细地介绍这方面的内容)。在 清单 2 中,可以看到从示例应用程序摘录的一段代码:XML 应用程序上下文定义,显示了如何设置 JDBC DataSource 及其上的 Hibernate SessionFactory。
清单 2 显示了如何为示例应用程序数据库(DB2)配置数据源 bean(exampleDataSource)。driverClassName 代表类型 Type 4 DB2 Java 类(com.ibm.db2.jcc.DB2Driver),url 代表 orgdb 数据库的位置(jdbc:db2://localhost:50000/orgdb)。将数据库连接 URL 中包含的主机名(localhost)和端口号(50000)改成 db2 服务器实际安装的位置。Hibernate.dialect 属性的值是 “net.sf.hibernate.dialect.DB2Dialect”,它指定 hiābernate 使用 DB2 术语,表示您处理的是 DB2 数据库。对于其他数据库服务器,这个值会有不同。例如,若要在 Derby 上运行应用程序,值应是 “net.sf.hibernate.dialect.DerbyDialect”。
exampleDataSource bean 被织入 Spring Hibernate 的 SessionFactory。请注意 *.hbm.xml 表示示例应用程序的 OR 映射文件。
清单 2. JDBC 数据源和 HibernateSessionFactory 织入
<bean id="exampleDataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName"><value>com.ibm.db2.jcc.DB2Driver</value></property>
<property name="url"><value>jdbc:db2://localhost:50000/orgdb</value></property>
<property name="username"><value>db2admin</value></property>
<property name="password"><value>db2admin</value></property>
</bean>
<bean id="exampleHibernateProperties"
class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="properties">
<props>
<prop key="hibernate.hbm2ddl.auto">update</prop>
<prop key="hibernate.dialect">net.sf.hibernate.dialect.DB2Dialect</prop>
<prop key="hibernate.query.substitutions">true 'T', false 'F'</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.c3p0.minPoolSize">5</prop>
<prop key="hibernate.c3p0.maxPoolSize">20</prop>
<prop key="hibernate.c3p0.timeout">600</prop>
<prop key="hibernate.c3p0.max_statement">50</prop>
<prop key="hibernate.c3p0.testConnectionOnCheckout">false</prop>
</props>
</property>
</bean>
<!-- Hibernate SessionFactory -->
<bean id="exampleSessionFactory"
class="org.springframework.orm.hibernate.LocalSessionFactoryBean">
<property name="dataSource"><ref local="exampleDataSource"/></property>
<property name="hibernateProperties">
<ref bean="exampleHibernateProperties" />
</property>
<!-- Must references all OR mapping files. -->
<property name="mappingResources">
<list>
<value>Department.hbm.xml</value>
<value>Employee.hbm.xml</value>
</list>
</property>
</bean>
|
织入 DAO 层
数据源和会话工厂设置好后,下一步是在织入 DAO(本例中为 DepartmentDAO)以便使用 SessionFactory。接下来,插入 Spring 的 TransactionProxyFactoryBean,它将拦截对应用
程序的 DepartmāentDAOImpl 对象的方法调用,并声明式地在上面应用事务上下文。
在这个示例中,DepartmentDAOImpl 类的 addDepartment 方法作为事务的一部分执行,带有事务属性 PROPAGATION_REQUIRED。这个属性相当于 EJB 容器的 TX_REQUIRED。如果希望让方法总是在事务中运行,可以使用 PROPAGATION_REQUIRED。如果事务已运行,bean 方法会加入这个事务,或者 Spring 轻量级事务管理器会另行启动一个事务。如果想在调用组件服务时总是启动新事务,可以使用 PROPAGATION_REQUIRES_NEW 属性。
清单 3. 编织
应用程序的 DAO 和 TransactionManager
<!-- Pass the session factory to our DepartmentDAO -->
<bean id="departmentDAOHelper" class="springexample.db2persist.hibernate.DepartmentDAOHelper"> <property name="departmentDAO"><ref local="departmentDAOTarget"/></property> </bean>
<bean id="departmentDAO" class="springexample.db2persist.hibernate.DepartmentDAOImpl"> <property name="sessionFactory"><ref local="exampleSessionFactory"/></property> </bean>
<bean id="transactionManager" class="org.springframework.orm.hibernate.HibernateTransactionManager"> <property name="sessionFactory"><ref bean="exampleSessionFactory"/></property> </bean>
<bean id="departmentDAOTarget" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"> <property name="transactionManager"><ref local="transactionManager"/></property> <property name="target"><ref local="departmentDAO"/></property> <property name="transactionAttributes"> <props> <prop key="addDepartment">PROPAGATION_REQUIRED</prop> </props> </property> </bean> |
有了这个之后,应用程序的织入就完成了。我们来看源代码。
分析源代码 如果您还没有下载
文章的源代码 (DB2SpringHB.zip),请从 下载 部分中下载。把源 zip 文件释放到桌面的任意位置,例如 c:\。会创建叫做 DB2SpringHB 的文件夹。src\spring 文件夹包含示例应用程序的 Hibernate 映射文件和 Spring 配置文件。src\springexample\db2persist\hibernate 文件包含应用程序的源代码。
在这里会找到两个类,名称分别为 Department 和 Employee,它们用 Hibernate 的映射文件 Department.hbm.xml 和 Employee.hbm.xml 映射到两个表。Department 类代表部门
信息,Employee 类代表与部门相关的员工信息。前面已经提到过,我们用 1: N 关系为这两个类建模,其中一个 Department 包含多个 Employee。 清单 4 显示了 Department 对象的 Hibernate 映射文件。
清单 4. Department 对象的 Hibernate 映射文件
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 2.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">
<hibernate-mapping>
<class
name="springexample.db2persist.hibernate.Department"
table="TBL_DEPARTMENT"
dynamic-update="false"
dynamic-insert="false">
<id
name="id"
column="DEPARTMENT_ID"
type="java.lang.Long"
unsaved-value="-1"
>
<generator class="native">
</generator>
</id>
<set name ="employees"
inverse = "true"
outer-join="auto"
cascade="all-delete-orphan">
<key column ="EMPLOYEE_ID"/>
<one-to-many class="springexample.db2persist.hibernate.Employee"/>
</set>
<property
name="name"
type="string"
update="false"
insert="true"
column="DEPARTMENT_NAME"
length="60"
not-null="true"
/>
</class>
</hibernate-mapping>
|
set name="employees" 和一对多类标记表示 Department 和 Employee 之间的关系。generator class="native" 表示 Hibernate 将使用 DB2 自己的标识值生成方法生成主键。
分析 DAO 源代码
DepartmentDAOImpl.
java 代表应用程序的 DAO,它把部门和员工信息插入应用程序数据库。DepartmentDAOImpl 扩展了 Spring 的 HibernateDaoSupport,它用 Spring 的 HibernateTemplate 简化了会话管理。这样就可以通过 getHibernateTemplate() 方法保存或检索数据。清单 5 所示的 getDepartmentEmployees() 用 HQL 和 getHibernateTemplate().find 方法对 Department 进行 find 操作,找到所有属于这个部门的员工。
清单 5. DAO 实现
public class DepartmentDAOImpl extends HibernateDaoSupport implements DepartmentDAO{ public void addDepartment(Department department) { getHibernateTemplate().save(department); }
public Department getDepartmentEmployees(Department department) {<āp> Department dep = null; List list = getHibernateTemplate().find("from Department department " + "where department.id = ?" , department.getId(),Hibernate.LONG);
if(list.size() > 0){ dep = (Department) list.get(0); } return dep; } } |
现在来看看代码运行的
效果吧!
运行应用程序 要运行示例应用程序,首先必须下载 Spring 框架及其全部相关文件。然后,解压框架(比如说解压到 c:\ 目录下),创建 C:\spring-framework-1.2-rc2 (针对当前发行版)的文件夹。在继续之前,还必须下载并解压 Apache Ant。
接下来,把源代码释放到一个文件夹,例如 c:\,创建 DB2SpringHB 文件夹。再修改 build.xml 文件入口,用实际安装 Spring 的位置替换 C:\spring-framework-1.2-rc2,用 DB2 Type 4 JDBC 驱动
程序所在的位置替换 C:\Installables\IBM\SQLLIB\java\。
打开命令提示符,更改目录到 DB2SpringHB,在命令提示符中输入以下命令:build。
这会构建并运行 CreateDepartmentEmployeeClient 类,该类又创建 Department 类对象,为其填充一些数据,创建 Employee 对象,为它填充数据,并把它添加到 Department 对象。
然后 CreateDepartmentEmployeeClient 调用 DepartmentDAOHelper.addDepartment 类,添加部门和员工
信息。一旦插入,CreateDepartmentEmployeeClient 就会调用 DepartmentDAOHelper.getDepartmentEmployees 方法,根据部门 id 得到部门和员工信息。如果 CreateDepartmentEmployeeClient 成功执行,将看到部门名称和员工信息输出到
控制台。也可以查询 DB2 数据库,检索部门和员工信息。
验证 DB2 数据库中的记录 为了验证 orgdb 数据库中的记录,请执行以下步骤:
在 Windows 命令提示符下,输入 db2cmd
输入以下语句:
db2 connect to orgdb
db2 select * from tbl_department
db2 select * from tbl_employee
您将看到保存在 DB2 数据库中的记录。
至此,您已成功地测试了示例企业应用程序。
结束语 在这份教程中,您学习了在 DB2 数据库中保持数据的各种方法,并逐步查看了构建示例应用程序的过程,示例应用程序整合了 Spring AOP 的声明式事务处理,并用 Spring 加 Hibernate 的持久性主干在 DB2 数据库中保持 Java 对象。这个基本的应用程序成为一个起点,使您快速走上为 DB2 数据库构建高度可维护、基于持久性的应用程序的大道。
查看本文来源