利用JDBC访问数据库:
try {
Class.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver");
Connection conn= DriverManager.getConnection(
"jdbc:microsoft:sqlserver://localhost:1433;databasename=test","root","212121"
);
Statement statement=conn.createStatement();
ResultSet rs=statement.executeQuery("select * from jobs");
} catch (Exception e) {
e.printStackTrace();
}
调用Class.forName(),利用反射机制加载并注册Microsoft SQL Server2000驱动程序类。
java.sql.Driver是所有JDBC驱动程序需要实现的接口。这个接口是提供给数据库厂商使用的,不同厂商实现该接口的类名是不同的:
1、微软SQL Server2000的JDBC驱动的类名
com.microsoft.jdbc.sqlserver.SQLServerDriver
2、微软SQL Server2005的JDBC驱动的类名
com.microsoft.sqlserver.jdbc.SQLServerDriver
3、Oralce的JDBC驱动的类名
oralce.jdbc.driver.OracleDriver
4、MySQL的JDBC驱动类名
com.mysql.jdbc.Driver
在程序中不需要直接去访问这些实现了Driver接口的类,而是由驱动程序管理器去调用这些驱动。驱动程序管理器注册每个驱动程序。它的所有方法都是静态的,提供registerDriver()方法来注册驱动程序类的实例。当调用Class.forName()方法加载驱动类实例时,类加载器会执行该类的静态代码块,从而注册驱动程序类的一个实例。
驱动程序管理器类提供的方法来建立数据库连接,而驱动程序管理器的连接方法则是调用驱动程序类的getConnection()方法建立到数据库的连接,返回一个Connection对象。提供3个重载的方法:
1、public static Connection getConnection(String url) throws SQLException
2、public static Connection getConnection(String url,String user,String password) throws SQLException
3、public static Connection getConnection(String url,Properties info) throws SQLException
Properties 包含了用于特定数据库所需的参数,以键-值对的方式指定连接参数。
JDBC URL用于标识一个被注册的驱动程序,驱动程序管理器提供这个URL选择正确的驱动程序,从而建立到数据库的连接,常用的URL的形式:
1、SQL Server2000和2005
jdbc:microsoft:sqlserver://localhost:1433;databasename=pubs
2、Oracle 9i和10g
jdbc:oracle:thin:@localhost:1521:ORCL
3、MySQL
jdbc:mysql://localhost:3306/databasename
数据库连接被用于向数据库服务器发送命令和SQL语句,在建立连接后,需要对数据库进行访问,执行SQL语句。
1、Statement
调用Connection对象的createStatement()方法创建一个Statement对象。没有参数的SQL语句通常用Statement对象来执行。Statement对象用于执行静态的SQL语句,返回执行结果:
Statement createStatement() throws SQLException
Statement接口也定义了一些方法用于执行SQL语句:
1、ResultSet executeQuery(String sql)throws SQLException
2、int executeUpdate(String sql)throws SQLException
执行sql指定的Insert、Update或者Delete语句。也可以执行SQL DDL语句,例如Create table;
3、int[] executeBatch()throws SQLException
允许向数据库提交一批命令,然后一起执行。如果所有命令都成功执行,返回值是一个更新行数的数组,按照加入命令的先后顺序存储,表示相应命令的更新行数。
4、void addBatch( String sql ) throws SQLException;
将SQL命令加入到命令列表。
ResultSet接口
ResultSet对象以逻辑表格的形式封装了执行数据库操作的结果集,ResultSet接口由数据库厂商实现。
ResultSet对象维护了一个指向当前数据行的游标,初始的时候,游标在第一行之前,通过next()方法移动游标到下一行:
boolean next() throws SQLException
通过判断这个方法的返回值,可以循环读取结果集中的数据行。
接口中定义了很多方法来获取当前行中列的数据,根据字段类型的不同,采用不同方法获取数据:
getInt()、getDate()、getString()……
在这些方法中,又提供两种形式的调用:
1、以列的索引作为参数(索引从1开始)
2、以列的名字作为参数
当不知道获取的列数据的类型,可以一律采用getString()方法来得到String类型的数据。
实例:向数据库中插入数据:
pom.xml中加入驱动文件jar
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.38</version>
</dependency>
public class CreateDBServlet extends HttpServlet {
private String url;
private String user;
private String password;
@Override
public void init() throws ServletException {
//这些信息在web.xml中配置
String driverClass=getInitParameter("dirverClass");
url=getInitParameter("url");
user=getInitParameter("user");
password=getInitParameter("password");
try{
Class.forName(driverClass);
}catch (Exception e){
throw new ServletException("加载数据库驱动失败!");
}
}
public void doGet(HttpServletRequest req, HttpServletResponse res)throws ServletException,IOException{
Connection conn=null;
Statement stmt=null;
try{
conn= DriverManager.getConnection(url,user,password);
stmt=conn.createStatement();
//避免重复创建
stmt.executeUpdate("drop database if exists bookstore");
stmt.executeUpdate("create database bookstore");
stmt.executeUpdate("use bookstore");
stmt.executeUpdate("create table bookinfo(id int not null primary key," +
"title varchar(50) not null)ENGINE=InnoDB");
//批量插入数据
stmt.addBatch("insert into bookinfo values(1,'javaweb开发')");
stmt.addBatch("insert into bookinfo values(2,'servlet/jsp开发')");
//批量执行
stmt.executeBatch();
res.setContentType("text/html;charset=GBK");
PrintWriter out=res.getWriter();
out.print("数据库创建成功");
out.close();
}catch (SQLException se){
throw new ServletException();
}finally {
if(stmt!=null){
try{
stmt.close();
}catch (SQLException se){
se.printStackTrace();
}
stmt=null;
}
if(conn!=null){
try{
conn.close();
}catch (SQLException se){
se.printStackTrace();
}
conn=null;
}
}
}
}
web.xml部署文件:
<servlet>
<servlet-name>CreateDBServlet</servlet-name>
<servlet-class>org.wdz.test.servlet.CreateDBServlet</servlet-class>
<init-param>
<param-name>dirverClass</param-name>
<param-value>com.mysql.jdbc.Driver</param-value>
</init-param>
<init-param>
<param-name>url</param-name>
<!--数据库中还未新建bookstore数据库-->
<param-value>jdbc:mysql://localhost:3306</param-value>
</init-param>
<init-param>
<param-name>user</param-name>
<param-value>root</param-value>
</init-param>
<init-param>
<param-name>password</param-name>
<param-value>123456</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>CreateDBServlet</servlet-name>
<url-pattern>/createdb</url-pattern>
</servlet-mapping>
当数据库中已经有存在的数据库和表,那么可以不用再新建,那配置文件可写为:
<init-param>
<param-name>url</param-name>
<param-value>jdbc:mysql://localhost:3306/bookstore</param-value>
</init-param>
//直接批量插入数据
stmt.addBatch("insert into bookinfo values(3,'javaweb开发')");
stmt.addBatch("insert into bookinfo values(4,'servlet/jsp开发')");
<\servlet>元素内部使用<\init-param>元素配置的初始化参数只能被这个servlet所访问,而使用<\context-param>元素配置的上下文参数可以被属于这个WEB应用程序的所有Servlet所访问。
如果多个Servlet都要访问数据库,那将驱动数据库类名、URL、用户名和密码设置成Servlet上下文的初始化参数。
1、init()方法修改为:
public void init() throws ServletException {
ServletContext sc=getServletContext();
String driverClass=sc.getInitParameter("driverClass");
url=sc.getInitParameter("url");
user=sc.getInitParameter("user");
password=sc.getInitParameter("password");
try{
Class.forName(driverClass);
}catch (Exception e){
throw new ServletException("加载数据库驱动失败!");
}
}
web.xml部署文件修改为:
<!--不要写在servlet中-->
<context-param>
<param-name>driverClass</param-name>
<param-value>com.mysql.jdbc.Driver</param-value>
</context-param>
<context-param>
<param-name>url</param-name>
<param-value>jdbc:mysql://localhost:3306</param-value>
</context-param>
<context-param>
<param-name>user</param-name>
<param-value>root</param-value>
</context-param>
<context-param>
<param-name>password</param-name>
<param-value>123456</param-value>
</context-param>
PrepareStatement
如果要用不同的参数来多次执行同一个SQL语句,可以使用PrepareStatement对象。它的对象表示一条预编译过的SQL语句。
PrepareStatement 对象所代表的SQL语句中的参数用问号(?)来表示,调用对象的setXXX()方法来设置这些参数。该方法有两个参数,第一个是要设置的SQL语句中参数的索引(从1开始),第二个参数是设置的参数的值。
conn= DriverManager.getConnection(url,user,password);
stmt=conn.createStatement();
//静态语句用statement执行
stmt.executeUpdate("drop database if exists bookstore");
stmt.executeUpdate("create database bookstore");
stmt.executeUpdate("use bookstore");
stmt.executeUpdate("create table bookinfo(id int not null primary key," +
"title varchar(50) not null)ENGINE=InnoDB");
//动态,带有参数的语句由PreparedStatement执行
PreparedStatement pstmt=conn.prepareStatement("insert into bookinfo values(?,?)");
//插入第一条数据,根据插入参数的类型不同
pstmt.setInt(1,1);
pstmt.setString(2,"java 开发");
pstmt.executeUpdate();
//插入第二条数据
pstmt.setInt(1,2);
pstmt.setString(2,"servlet 开发");
pstmt.executeUpdate();
注意:SQL数据类型与JAVA数据类型的对应关系有点不同:
因此,如果要插入日期类型,应该使用:
pstmt.setDate(3,java.sql.Date.valueOf("2017-06-04"));
JDBC数据源和连接池
javax.sql.DataSource接口提供了另外一种方式来建立数据库的连接。DataSource接口由驱动程序供应商来实现,利用DataSource来建立数据库的连接,不需要在客户程序中加载JDBC驱动,也不需要使用DriverManager类。
在程序中,通过向一个JNDI服务器查询来得到DataSource对象,然后调用DataSource对象的getConnection()方法来建立数据库的连接。
DataSource对象可以看成是连接工厂,用于提供此DataSource对象所表示的物理数据源的连接。
try {
javax.naming.Context ctx=new javax.naming.InitialContext();
javax.sql.DataSource ds=(javax.sql.DataSource)ctx.lookup("java:comp/env/jdbc/bookstore");
java.sql.Connection conn=ds.getConnection();
} catch (Exception e) {
e.printStackTrace();
}
连接池技术预先建立多个数据库连接对象,然后将连接对象保存到连接池中,当客户请求到来时,从池中取出一个连接对象为客户服务,当请求完成后,客户程序调用close()方法,将连接对象放回池中。
在普通的数据库访问程序中,客户程序得到的连接对象是物理连接,调用连接对象的close()方法将关闭连接;而采用连接池技术,客户程序得到的连接对象是连接池中物理连接的一个句柄,调用close()方法,物理连接并没有关闭,数据源的实现只是删除了客户程序中的连接对象和池中的连接对象之间的关系。
在Tomcat中,可以在<\Context>元素的内容中使用<\Resource>元素来配置JDBC数据源。
如果在开发阶段,WEB应用程序并不在webapps目录下,那么配置的文件在%CATALINA_HOME%\conf\Catalina\localhost\webName.xml(项目名称)中:
<Context docBase="F:\learnTest\servletTest" reloadable="true">
<Resource name="jdbc/bookstore" auth="wdz"
type="javax.sql.DataSource"
maxActive="100" maxIdle="30" maxWait="10000"
username="root" password="123456"
driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost:3306/bookstore?autoReconnect=true"/>
</Context>
指定的JNDI名是jdbc/bookstore;url属性值中autoReconnect=true,这是MySQL专用的。为了让MySQL的JDBC驱动在Mysql服务器关闭连接后自动重新连接数据库。默认情况下,服务器在连接空闲8小时后关闭这个连接。
要使用Tomcat提供的数据源实现来访问MySQL(数据源本身并不提供数据访问功能,它只是作为连接对象的工厂,实际的数据访问操作仍然是由JDBC驱动来完成),因此需要将JDBC的驱动复制到Tomcat安装目录的lib子目录中,以便Tomcat服务器能够找到MySQL的JDBC驱动。
如果web应用程序直接是在webapps目录下,那直接在META-INF\context.xml文件中进行设置,不再需要docBase指定应用程序的根目录:
<Context>
<Resource name="jdbc/bookstore" auth="wdz"
type="javax.sql.DataSource"
maxActive="100" maxIdle="30" maxWait="10000"
username="root" password="123456"
driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost:3306/bookstore?autoReconnect=true"/>
</Context>
完成数据源的设置后,可以直接建立数据库的连接:
try {
Context ctx=new InitialContext();
DataSource ds=(DataSource)ctx.lookup("java:comp/env/jdbc/bookstore");
Connection conn=ds.getConnection();
} catch (Exception e) {
e.printStackTrace();
}