[Servlet&JSP] 使用JDBC连接数据库
JDBC(Java DataBase Connectivity)时用于运行SQL的解决方案,开发人员使用JDBC的标准接口,数据库厂商则对接口进行实现,这样开发人员就可以无需接触底层数据库驱动程序的差异性。
JDBC简介厂商在实现JDBC驱动程序时,依方式可将驱动程序分为四种类型:
JDBC-ODBC Bridge Driver将JDBC调用转换为ODBC调用 Native API Driver
将JDBC调用转换为原生链接库中的相关API调用。特点:与平台相依,是四种类型中最快的驱动程序。 JDBC-Net Driver
将JDBC调用转换为特定的网络协议调用,目的是与远程数据库特定的中间服务器或组件进行协议操作,而中间件或组建再真正与数据库进行操作。特点:弹性最高。 Native Protocol Driver
主要作用是将JDBC调用转换为特定的网络协议,所以驱动驱动程序可以使用Java技术来实现,遗传你这类型的驱动程序可以跨平台,在性能上也有不错的表现。在不需要如第3种驱动类型的灵活性时,通常是会使用这类型驱动程序,该类型时最常见的驱动程序类型。
以下编写一个简单的JavaBean来测试可否连接数据库:
package club.chuxing; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.util.logging.Level; import java.util.logging.Logger; public class DbBean { private String url; private String username; private String password; public DbBean(){ try { Class.forName("com.mysql.jdbc.Driver"); } catch (ClassNotFoundException e) { Logger.getLogger(DbBean.class.getName()).log(Level.SEVERE, null, e); } } public boolean isConnectedOk() { boolean ok = false; Connection conn = null; try { conn = DriverManager.getConnection(url, username, password); if (!conn.isClosed()) { ok = true; } } catch (SQLException e) { Logger.getLogger(DbBean.class.getName()).log(Level.SEVERE, null, e); } finally { if (conn != null) { try { conn.close(); } catch (SQLException e) { Logger.getLogger(DbBean.class.getName()) .log(Level.SEVERE, null, e); } } } return ok; } public void setPassword(String password) { this.password = password; } public void setUrl(String url) { this.url = url; } public void setName(String username) { this.username = username; } }
之后就可以通过调用isConnectedOK()方法来看看是否可以连接成功。例如,可以写个简单的JSP网页,代码如下:
<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%> <%@taglib prefix="c" uri="https://java.sun.com/jsp/jstl/core" %> 连接成功 <%-- 连接成功 --%> 连接失败使用DataSource取得连接
在Java EE中的环境中,将取得连接等与数据库来源相关的行为规范在javax.sql.DataSource接口,实际如何取得Connection则由实现接口的对象来负责。
为了让应用程序在需要取得某些与系统相关的资源对象时,能与实际的系统配置、实体机器位置、环境架构等无关,在Java应用程序中可以通过JNDI(Java Naming Directory Interface)来取得所需的资源对象。可用如下方式取得DataSource实例:
try { Context initContext = new InitialContext(); Context envContext = (Context)initContext.lookup("java:/comp/env"); dataSource = (DataSource)envContext.lookup("jdbc/test"); } catch(NamingException ex) { //other process }
在创建Context对象的过程中会收集环境的相关数据,之后根据JNDI名称jdbc/demo向JNDI服务器查找DataSource实例并返回。在这个程序片段中,不会知道实际的资源配置、实体机器位置、环境架构等信息,应用程序不会与这些相依。
之前的DbBean类可以改为如下编写方式:
package club.chuxing; import java.sql.Connection; import java.sql.SQLException; import java.util.logging.Level; import java.util.logging.Logger; import javax.naming.Context; import javax.naming.InitialContext; import javax.naming.NamingException; import javax.sql.DataSource; public class DatabaseBean { private DataSource dataSource; public DatabaseBean(){ try { Context initContext = new InitialContext(); Context envContext = (Context)initContext.lookup("java:/comp/env"); dataSource = (DataSource)envContext.lookup("jdbc/test"); } catch(NamingException ex) { Logger.getLogger(DatabaseBean.class.getName()) .log(Level.SEVERE, null, ex); } } public boolean isConnectedOK(){ boolean ok = false; Connection conn = null; try { conn = dataSource.getConnection(); if (!conn.isClosed()) { ok = true; } } catch(SQLException ex) { Logger.getLogger(DatabaseBean.class.getName()) .log(Level.SEVERE, null, ex); } finally { if (conn != null) { try { conn.close(); } catch(SQLException ex) { Logger.getLogger(DatabaseBean.class.getName()) .log(Level.SEVERE, null, ex); } } } return ok; } }
以上代码并不含有驱动程序、数据库用户名、密码等信息,这些都由数据库管理人员或服务器管理人员负责设置,我们唯一需要知道的就是jdbc/test这个JNDI名称,并且告诉web容器,也就是要在web.xml中设置。
web.xml:
jdbc/demo javax.sql.DataSource Container Shareable
在web.xml中设置的目的,就是让web容器提供JNDI查找时所需的相关环境信息,这样创建Context对象时就不用设置一大堆参数了。接着可以编写一个简单的JSP来使用DatabaseBean。
<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%> <%@taglib prefix="c" uri="https://java.sun.com/jsp/jstl/core" %> 连接成功 <%-- 连接成功 --%> 连接失败
对于Java开发人员来说,它的工作已经完成了。现在假设你是服务器管理员,职责就是设置JNDI相关资源,但设置的方式并非标准的一部分,而是依应用程序服务器而有所不同。假设应用程序将部署在Tomcat6上,则可以要求web应用程序在封装为war文件时,必须在META-INF文件夹中包括一个context.xml文件。例如:
name属性用来设置JNDI名称,username与password用来设置数据库用户名和密码,driverClassName用来设置驱动程序类名称,url用来设置JDBC URL。其他属性则是与DBCP(Database Connection Pool)有关的,这是内置在Tomcat中的连接池机制。
当应用程序部署后,Tomcat会根据META-INF中context.xml的设置,寻找指定的驱动程序,所以必须将驱动程序的JAR文件放置在Tomcat的lib目录中,接着Tomcat就会为JNDI名称jdbc/demo设置相关的资源。
使用root来操作数据库是不安全的,root账号用于操作数据库的完整权限,应用设置具有适当权限的用户来操作数据库。