在J2EE规范中对JDBC和JNDI进行了充分说明。本文展现了两者间的一点联系,概要陈述下在WebSphere中如何配置JNDI数据源以及在应用中使用JNDI数据源,同时结合Spring简述应用中DB Session的管理。
JDBC说明及举例
JDBC API为访问不同的数据库提供了一种统一的途径,象ODBC一样,JDBC对开发者屏蔽了一些细节问题,另外,JDBC对数据库的访问也具有平台无关性。
访问DB最主要的是获取与DB沟通的桥梁:java.sql.Connection。有了它我们可以开启事务、提交事务、回滚事务,结合java.sql.PreparedStatement可以进行对DB数据进行增删改查(CRUD: CREATE、Retrieve、Update、Delete)。这些便形成了应用中持久层的常用功能。获取Connection的代码示意如下所示:
import java.sql.Connection;
import java.sql.DriverManager;
public static Connection getConn() {
Connection conn = null;
try {
Class.forName("oracle.jdbc.driver.OracleDriver");
String url = "jdbc\:oracle\:thin\:@10.13.193.103\:1521\:test";
String username = "filenet";
String password = "filenet";
conn = DriverManager.getConnection(url, username, password);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
return conn;
}
JNDI说明
JNDI(Java Naming and Directory Interface)是命名和目录接口,借助JNDI我们能够通过名称来访问对象(各类资源:组件、服务等)。下图展现了JNDI及应用的架构概况。
通过上图可以发现JNDI可以访问的目录和服务有很多,包括: LDAP、DNS、NIS、NDS、RMI、CORBA对象服务、XNam 、Novell、文件系统、Windows XP/2000/NT/Me/9x的注册表、DSML v1&v2等等。同时上图为我们展现了两组API:JNDI API和JNDI SPI,下文对 JNDI库的简析可以帮助我们了解他们的作用。
1)Javax.naming:包含了访问命名服务的类和接口。例如,它定义了Context接口,这是命名服务执行查询的入口。
2)Javax.naming.directory:对命名包的扩充,提供了访问目录服务的类和接口。例如,它为属性增加了新的类,提供了表示目录上下文的DirContext接口,定义了检查和更新目录对象的属性的方法。
3)Javax.naming.event:提供了对访问命名和目录服务时的事件通知的支持。例如,定义了NamingEvent类,这个类用来表示命名/目录服务产生的事件,定义了侦听NamingEvents的NamingListener接口。
4)Javax.naming.ldap:这个包提供了对LDAP 版本3扩充的操作和控制的支持,通用包javax.naming.directory没有包含这些操作和控制。
5)Javax.naming.spi:这个包提供了一个方法,通过javax.naming和有关包动态增加对访问命名和目录服务的支持。这个包是为有兴趣创建服务提供者的开发者提供的。
通过上面的讲解,通常在应用中使用JNDI访问网络服务时不会使用到Javax.naming.spi。如果我们想开发JNDI,则会用到此库。
为何使用JNDI
上文中使用JDBC获取Connection的过程包含在应用程序中,而其中包含DB的相关配置(url、用户名、密码、连接池参数等),即便这些配置在应用中能以配置文件的形式存在,然而其仍旧需要跟随应用来进行管理,使用JNDI则可以规避这些问题。
要注意区分JNDI与JDBC,不要将JNDI和JDBC混为一谈。由于通过JNDI能够访问到网络中的服务和组件,而JDBC也可作为组件或服务放到网络上而不必与应用保持物理上的关联性。从而对数据库连接的管理便可转移到J2EE规范下的WEB容器中了。这一点较上文中的原因更为重要,上段中所提及的往往在JPA(如Hibernate)等规范下是可以有效避免的,此点更为凸显了使用JNDI来获取访问DB数据源优点。
应用JNDI数据源获取Connection举例以及在WebSphere中的配置
上文中已提到Connection在java操作DB的作用,可以说这是入口,JNDI中提供了相应标准来获取Connection,其过程如下所示:
import java.sql.Connection;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.sql.DataSource;
public static Connection getConn() {
Connection conn = null;
try {
Context ctx = new InitialContext();
//通过JNDI查找DataSource,获取Connection
DataSource ds = (DataSource)ctx.lookup("java:comp/env/jdbc/test");
conn = ds.getConnection();
}catch(Exception e) {
e.printStackTrace();
}
return conn;
}
在应用中上述代码前,WEB容器中必须要存在Context要查找的数据源名称。在WebSphere中配置JNDI数据源,大致可分为以下几步:
1)设置数据库安全认证(安全性->JAAS->J2C authentication data ->新建和配置)
2)设置JDBC提供程序(资源->JDBC-> JDBC提供程序->新建)
3)建立JNDI数据源(资源->JDBC->Data Source->新建)
上面介绍了JNDI和JDBC的简单使用,同时获取了操作DB最关键的类,而在企业级应用中,DB session是需要统一管理的,开发人员只需要关系业务而不需要额外的事情,本文着重讲JNDB和JDBC的简单使用,其涉及到对DB的操作,故而此处结合Spring简述DB Session的统一管理。
Spring配置DB Session简要说明
在讲配置前,我们心里应该很清楚,无论是用什么DB框架,都有如下规律,即:
1)对数据库操作之前都要获取连接数据库的相关配置,继而能够获取访问DB的Session,进行增删改查,
2)进行上述DB操作时,要加以事务的控制,保证操作的粒子性。
有了上述思路后,剩下的就是如何利用框架了。此处仅就获取DB Session过程简要陈述以对比使用JDBC和JNDI的配置。Spring具有工厂的作用能够创建和注入其核心文件applicationContext.xml中配置的Bean。利用这一特性,Spring可以经过以下几步获取DB Session:
1)获取DB相关配置参数(DB url、userName、Password等)
2)获取数据源
3)创建sessionFactory(应用借此获取DB Session)注入数据源,配置数据库的相关参数
4)创建事务管理器transactionManager,注入sessionFactory
5)配置事务传播特性等
前三点在本文会有所体现,而4)和5)则不会影响JDBC和JNDI的选取。如果Spring集成的是Hibernate,则上述各Bean的创建会涉及到Spring实现的Hibernate类,此外我们还会利用Spring创建一些应用上的业务Bean等,例如创建dao层内容时,则会将上文中的SessionFactory注入dao中,以获取操作DB 的核心类(Session,注意区分上文中谈及的获取Connection类,上文是纯采用JDBC,此处则是借助了Hibernate)。
单就前三点的创建过程,Spring可使用注解形式和非注解形式来完成相同的工作。但这并不影响本文所讲内容。实际上使用JDBC和使用JNDI的区别(仅就应用于DB产品上而言),其关键点在上文的第二点获取数据源上。两者在Spring核心配置文件applicationContext.xml中的配置如下代码所示:
<!-- 数据源配置 -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<!-- 设置JDBC驱动名称 -->
<property name="driverClassName" value="${jdbc.driver}" />
<!-- 设置JDBC连接URL -->
<property name="url" value="${jdbc.url}" />
<!-- 设置数据库用户名 -->
<property name="username" value="${jdbc.username}" />
<!-- 设置数据库密码 -->
<property name="password" value="${jdbc.password}" />
<!-- 设置连接池初始值 -->
<property name="initialSize" value="1" />
<!-- 设置连接池最大值 -->
<property name="maxActive" value="100" />
<!-- 设置连接池最小空闲值 -->
<property name="minIdle" value="20" />
<!-- 设置连接池最大空闲值 -->
<property name="maxIdle" value="50" />
</bean>
<!-- JNDI数据源 -->
<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName">
<value>java:comp/env/jdbc/testDS</value>
</property>
</bean>
在使用中上述配置择一而用即可,而JNDI数据源的配置在上文中已简做陈述。
本文浅显讲解了下J2EE中JDBC和JNDI的简单使用及相关配置。兼顾了最基础和更为企业级的DB操作方法,结合Spring等框架明确了DB操作统一性管理的几个要点以及使用J2EE web容器实现下的JNDI数据源的相关配置。文章牵涉内容较为基础,每一方面仍旧有很多可深究的内容,后续实践逐渐领悟陈述。