web开发 jdbc

JDBC数据库

jdbc相关的组件

jdbc主要与两个库有关java.sql.* 和 javax.sql.*有关,java.sql定义了数据库连接接口和类,一些接口由数据库厂商来实现。

使用jdbc访问数据库时候主要用到下面几个代码。

//加载数据库驱动

Class.forName("com.mysql.jdbc.Driver");

//获得到数据库的连接

Connection conn = DriverManager.getConnection(url,user,password);

//执行sql语句

Statement stmt = conn.createStatement();

ResultSet ret = stmt.execute("select* from bookstore");                       

java.sql.Driver接口

这个接口是所有数据库厂商都必须实现的接口,

com.mysql.jdbc.Driver 是mysql的驱动类

oracle.jdbc.driver.OracleDriver是oracle的驱动类

使用Class.forName("com.mysql.jdbc.Driver");可以加载该驱动。

DriverManager 管理驱动

驱动是DriverManager来管理的,它的所以方法都是静态的,在加载驱动的时候,DriverManager调用静态registerDriver方法会自动注册一个Driver实例。

连接也是由DriverManager来管理的,传入url,用户名,密码就可以建立到数据库服务器

Connection conn = DriverManager.getConnection(url,user,password);

Statement 执行sql语句

sql语句是由Statement来执行的,有三种:Statement,PreparedStatement,CallableStatement

Statement stmt = conn.createStatement();

ResultSet ret = stmt.execute("select *from bookstore");   

PreparedStatement 执行sql语句

sql语句必须经过语法分析,编译,优化等步骤才能执行,如果只有参数不同其的sql语句,使用Statement是比较低效的。可以使用PreparedStatementPreparedStatement中的?代表参数,可以使用SetXXX来设置。

获取元数据

在数据库中,描述数据库和表的数据叫做元数据,使用

DatabaseMetaData dbmeta = conn.getMetaData();来获取数据库信息,使用

ResultSetMetaData resMeta = res.getMetaData();来获取一个数据表的信息。

 

提交与回滚(事务)

事务是一组数据库操作的单元,它可以保证事务中的所有操作都生效或者都不生效。当事务中有异常发生的时候,可以回滚rollback,如果没有的话commit

jdbc中时自动提交的,我们可以通过

// 不自动提交

conn.setAutoCommit(false);

jdbc 不自动提交。

在结果集中删除,更新,插入数据。

可以在result中更新,删除,插入数据,并保存到数据库中。这样可以使得工作更为方便。

获取一个可以更新数据库的statement,必须提供一些参数

Statement stmt =conn.createStatement (ResultSet.TYPE_SCROLL_SENSITIVE,

                                                        ResultSet.CONCUR_UPDATABLE);

第一个参数:

 ResultSet.TYPE_FORWARD_ONLY:只能调用resultSetnext方法,来移动结果集

ResultSet.TYPE_SCROLL_INSENSITIVE,能调用resultSetnextprevious等方法,来移动结果集。但是对数据库变化不敏感。

 ResultSet.TYPE_SCROLL_SENSITIVE:能调用resultSetnextprevious等方法,来移动结果集。但是对数据库变化敏感。例如如果结果集合中返回了10条数据,另一个线程删掉了2条数据,那么这个结果集合就只有8个了。

 

其中第二个参数

ResultSet.CONCUR_UPDATABLE,表示又这个stmt执行的结果ResultSet是可以更新数据库的。

ResultSet.CONCUR_READ_ONLY ,表示ResultSet不可以更新数据库。

//update 结果集

res.first();

//将结果集中第一行行的title修改为1.11,调用updateRow才会生效

res.updateFloat("price", (float) 1.11);

res.updateString("title","updated row");

res.updateRow();

只有执行了 updateRow才会执行update操作。

 

//删除最后一个结果集

res.last();

res.deleteRow();

只有执行了 deleteRow才会执行删除操作

 

//插入一行 

//将游标移动到可以插入的缓存行

res.moveToInsertRow();

res.updateString("author","daniangdaye");

res.updateString("title","inserted row");

res.updateDate("publis_date",new java.sql.Date(new Date().getTime()));    

res.updateFloat("price", (float) 1.11);

res.insertRow();

只有执行了 insertRow才会执行插入操作。

 

配置数据源

使用DirverManager,可以连接数据库,但是每一次close一个连接connection,都会真正的关闭一个与数据库的连接,而建立连接是非常消耗资源的。DataSource使用连接池管理连接可以更有效的利用资源。当调用close的时候并不是关闭连接而是把连接归还连接池。

 

 

使用DriverManager来管理mysql的连接

/**

     * 使用 DriverManager 来管理mysql的连接

     * @throws ServletException

     */

    privatevoid initUsingDriverManager()throws ServletException

    {

        //web.xml中顶一顶servlet中去取得初始化参数

        String driverClass=this.getInitParameter("driverClass");

        url =this.getInitParameter("url");

        user =this.getInitParameter("user");

        password =this.getInitParameter("password");

        //加载数据库驱动

        try

        {

            Class.forName(driverClass);

        }

        catch(Exception e)

        {

            e.printStackTrace();

            //加载失败抛出UnavailableException后这个servlet将永久不可用。以后如果有请求访问服务器会返回404

            thrownew UnavailableException("加载数据库驱动失败");

        }

    }

使用DataSource来管理连接:

需要在context中配置数据源Source的信息:

<ContextdocBase="servletJspLearn"path="/servletJspLearn"reloadable="true"source="org.eclipse.jst.jee.server:servletJspLearn">

            <Resource

                  name="jdbc/bookstore"

                  type="javax.sql.DataSource"

                  password=""

                  driverClassName="com.mysql.jdbc.Driver"

                  maxIdle="2"

                  maxWait="5000"

                  username="root"

                  url="jdbc:mysql://localhost:3306/bookstore"

                  maxActive="4"/>   

      </Context>

WEB-INFO中的web.xml中也需要加入对这个数据源的引用:

<web-appxmlns:xsi=http://www.w3.org/2001/XMLSchema-instance

xmlns=http://java.sun.com/xml/ns/javaee

xmlns:web=http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd

xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"version="3.0">

 <resource-ref>

            <res-ref-name>jdbc/bookstore</res-ref-name>

            <res-type>javax.sql.DataSource</res-type>

            <res-auth>Container</res-auth>

 </resource-ref>

</web-app>

注意在eclipse中配置数据源是在server中:的server.xml中进行配置。

例如:对于servletJspLearn, 在server.xml中找到

<Context docBase="servletJspLearn" path="/servletJspLearn" reloadable="true">

然后加入resource的配置

在代码中如下面方式得到连接

/**

 * 使用数据源来取得数据库的连接

 */

Context initialContext = new javax.naming.InitialContext();

Context envContext  = (Context)initialContext.lookup("java:comp/env");

DataSource ds = (DataSource) envContext.lookup("jdbc/bookstore");

conn = ds.getConnection();

实例:

创建数据库,创建表,插入数据,提交,回滚

下面是一个使用jdbc创建数据库建立表,插入数据的servlet,手动提交,回滚等操作的实例:

 

package junjun.chapter8;

import java.io.IOException; import java.io.PrintWriter; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.Statement; import java.util.Date; import java.sql.Timestamp;

import javax.servlet.ServletException; import javax.servlet.UnavailableException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /**  * 创建数据库  * 创建表  * 插入数据  * @author andyWebsense  *  */ public class CreateDBServlet extends HttpServlet {  private String url ;  //到数据库的连接  private String user;    // 用户名  private String password;//密码    @Override  public void init() throws ServletException  {   super.init();      // 从web.xml中顶一顶servlet中去取得初始化参数   String driverClass=this.getInitParameter("driverClass");   url = this.getInitParameter("url");   user = this.getInitParameter("user");   password = this.getInitParameter("password");      //加载数据库驱动   try   {    Class.forName(driverClass);   }   catch(Exception e)   {    e.printStackTrace();    // 加载失败抛出UnavailableException后这个 servlet将永久不可用。以后如果有请求访问服务器会返回404。    throw new UnavailableException("加载数据库驱动失败");   }  }    @Override  protected void doGet(HttpServletRequest req, HttpServletResponse resp)    throws ServletException, IOException  {   Connection conn = null;   Statement stmt = null;   try   {    conn = DriverManager.getConnection(url,user,password);    // 不自动提交    conn.setAutoCommit(false);    stmt = conn.createStatement();        // 如果已经存在该数据库 删掉    stmt.execute("drop database if exists bookstore");    //创建数据库       stmt.execute("create database bookstore");    stmt.execute("use bookstore");

   //创建数据表    stmt.executeUpdate(      " create table bookinfo(" +      "id INT not null primary key auto_increment , " +      "author varchar(50)," +      "title varchar(50) not null," +      " publis_date Date not null, " +      "price float(4,2) not null ," +      "amount smallint," +      "remark varchar(200) )" +      " AUTO_INCREMENT = 0 engine=InnoDB");       //批量插入一批数据    stmt.addBatch("insert into bookinfo values(1,'junjun','java','2012-1-1',12.11,10,null)");    stmt.addBatch("insert into bookinfo values(2,'xiaolan','python','2012-11-1',2.11,10,null)");    stmt.addBatch("insert into bookinfo values(3,'junjun','ruby','2012-12-1',1.11,10,null)");    stmt.executeBatch();        /*     *使用prepareStatment 优化     */    PreparedStatement pstmt = conn.prepareStatement("insert into bookinfo values(? , ? , ? ,?,12.11,10,null)");    pstmt.setInt(1, 4);    pstmt.setString(2, "xiaohai");    pstmt.setString(3,"google");    pstmt.setDate(4, new java.sql.Date(new Date().getTime()));      pstmt.execute();        pstmt.setInt(1, 5);    pstmt.setString(2, "haihai");    pstmt.setString(3,"ws");    pstmt.setDate(4, new java.sql.Date(new Date().getTime()));      pstmt.execute();        //提交给数据库    conn.commit();    PrintWriter p = resp.getWriter();    p.println("success!");   }   catch(Exception e)   {    e.printStackTrace();    if(conn!=null)    {     try     {      // 如果出现错误回滚      conn.rollback();     }     catch(Exception e1)     {      e1.printStackTrace();     }     stmt = null;    }   }   finally   {

   if(stmt!=null)    {     try     {      stmt.close();     }     catch(Exception e1)     {      e1.printStackTrace();     }     stmt = null;    }        if(conn!=null)    {     try     {      conn.close();     }     catch(Exception e1)     {      e1.printStackTrace();     }     conn = null;    }   }     }    @Override  protected void doPost(HttpServletRequest req, HttpServletResponse resp)    throws ServletException, IOException  {   // TODO Auto-generated method stub   this.doPost(req, resp);  } }

使用DataSource管理连接、获取数据库元数据,打印表信息,在结果集合中执行修改,删除,插入操作,

 

package junjun.chapter8;

import java.io.IOException; import java.io.PrintWriter; import java.sql.Connection; import java.sql.DatabaseMetaData; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.SQLException; import java.sql.Statement; import java.util.Date;

import javax.naming.Context; import javax.servlet.ServletException; import javax.servlet.UnavailableException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.sql.DataSource;

import com.mysql.jdbc.Driver; /**  * 列出数据库的内容  * @author andyWebsense  *  */ public class ListServlet extends HttpServlet {  private String url ;  //到数据库的连接  private String user;    // 用户名  private String password;//密码    @Override  public void init() throws ServletException  {   super.init();   initUsingDriverManager();  }    @Override  protected void doGet(HttpServletRequest req, HttpServletResponse resp)    throws ServletException, IOException  {   Connection conn = null;   Statement stmt = null;   try   {    //conn = DriverManager.getConnection(url,user,password);    /**     * 使用 数据源来取得数据库的连接     */    Context initialContext = new javax.naming.InitialContext();    Context envContext  = (Context)initialContext.lookup("java:comp/env");    DataSource ds = (DataSource) envContext.lookup("jdbc/bookstore");    conn = ds.getConnection();        //获取一个可以更新数据库的statement    stmt = conn.createStatement (ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_UPDATABLE);        //打印所有书籍的信息    PrintWriter p = resp.getWriter();    printBook(stmt,p);       //打印数据库的元数据    p.println("<br/>all the  meta Data of database bookstore<br/>");    //返回数据库的所有信息    DatabaseMetaData dbmeta = conn.getMetaData();    //获取这个数据库中所有的table的信息    ResultSet resTable = dbmeta.getTables(null, null, null, new String[] {"TABLE"});    while(resTable.next())    {     p.println(resTable.getString("TABLE_NAME"));     p.println("<br>");    }        // 打印bookinfo的信息:名字,类型,长度    p.println("<br/>all the meta info of table bookinfo<br/>");    ResultSet res = stmt.executeQuery("select * from bookinfo");    ResultSetMetaData resMeta = res.getMetaData();    int columntCount = resMeta.getColumnCount();    for(int i = 1;i < columntCount; i++)    {     p.println(resMeta.getColumnName(i)+"  "+resMeta.getColumnTypeName(i)+"  "+resMeta.getColumnDisplaySize(i));     p.println("<br>");    }        /*     * 在结果集中操作     */    //update 结果集    res.first();    //将结果集中第一行行的title修改为1.11,调用updateRow才会生效    res.updateFloat("price", (float) 1.11);    res.updateString("title","updated row");    res.updateRow();       //删除最后一个结果集    res.last();    res.deleteRow();        //插入一行     //将游标移动到可以插入的缓存行    res.moveToInsertRow();    res.updateString("author", "daniangdaye");    res.updateString("title","inserted row");    res.updateDate("publis_date", new java.sql.Date(new Date().getTime()));      res.updateFloat("price", (float) 1.11);    res.insertRow();       //打印所有书籍的信息    printBook(stmt,p);               }   catch(Exception e)   {    e.printStackTrace();   }   finally   {

   if(stmt!=null)    {     try     {      stmt.close();     }     catch(Exception e1)     {      e1.printStackTrace();     }     stmt = null;    }        if(conn!=null)    {     try     {      conn.close();     }     catch(Exception e1)     {      e1.printStackTrace();     }     conn = null;    }   }     }    /**打印所有的书   * @param stmt   * @param p   * @throws SQLException   */  private void printBook(Statement stmt,PrintWriter p) throws SQLException  {     ResultSet res = stmt.executeQuery("select * from bookinfo");   p.println("<br/>all the information of books<br/>");   while(res.next())   {    String title = res.getString("title");    String author = res.getString("author");    Float price = res.getFloat("price");    Date publishDate = res.getDate("publis_date");        p.println(title+"  " +author+ "  "+price+"  "+publishDate);    p.println("<br>");   }     }    /**   * 使用 DriverManager 来管理mysql的连接   * @throws ServletException   */  private void initUsingDriverManager() throws ServletException  {   // 从web.xml中顶一顶servlet中去取得初始化参数   String driverClass=this.getInitParameter("driverClass");   url = this.getInitParameter("url");   user = this.getInitParameter("user");   password = this.getInitParameter("password");      //加载数据库驱动   try   {    Class.forName(driverClass);   }   catch(Exception e)   {    e.printStackTrace();    // 加载失败抛出UnavailableException后这个 servlet将永久不可用。以后如果有请求访问服务器会返回404。    throw new UnavailableException("加载数据库驱动失败");   }  }      @Override  protected void doPost(HttpServletRequest req, HttpServletResponse resp)    throws ServletException, IOException  {   // TODO Auto-generated method stub   this.doPost(req, resp);  } }

 

这个servlet的配置信息

<?xml version="1.0" encoding="ISO-8859-1"?>

<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0">  <resource-ref>             <res-ref-name>jdbc/bookstore</res-ref-name>             <res-type>javax.sql.DataSource</res-type>             <res-auth>Container</res-auth>  </resource-ref>       <!-- chapter 8 -->     <servlet>      <servlet-name>CreateDBServlet</servlet-name>      <servlet-class>junjun.chapter8.CreateDBServlet</servlet-class>      <init-param>       <description>数据库的驱动</description>       <param-name>driverClass</param-name>       <param-value>com.mysql.jdbc.Driver</param-value>      </init-param>           <init-param>       <description>数据库的连接</description>       <param-name>url</param-name>       <param-value>jdbc:mysql://localhost:3306/mysql</param-value>      </init-param>           <init-param>       <description>数据库用户名</description>       <param-name>user</param-name>       <param-value>root</param-value>      </init-param>           <init-param>       <description>数据库密码</description>       <param-name>password</param-name>       <param-value></param-value>      </init-param>   </servlet>     <servlet-mapping>     <servlet-name>CreateDBServlet</servlet-name>     <url-pattern>/createdb</url-pattern>   </servlet-mapping>      <servlet>      <servlet-name>ListServlet</servlet-name>      <servlet-class>junjun.chapter8.ListServlet</servlet-class>      <init-param>       <description>数据库的驱动</description>       <param-name>driverClass</param-name>       <param-value>com.mysql.jdbc.Driver</param-value>      </init-param>           <init-param>       <description>数据库的连接</description>       <param-name>url</param-name>       <param-value>jdbc:mysql://localhost:3306/bookstore</param-value>      </init-param>           <init-param>       <description>数据库用户名</description>       <param-name>user</param-name>       <param-value>root</param-value>      </init-param>           <init-param>       <description>数据库密码</description>       <param-name>password</param-name>       <param-value></param-value>      </init-param>   </servlet>     <servlet-mapping>      <servlet-name>ListServlet</servlet-name>     <url-pattern>/listServlet</url-pattern>   </servlet-mapping>

</web-app>


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值