`

Java tutorial中JDBC一节的读书笔记

阅读更多

* JDBC 架构

    JDBC支持两层和三层架构

        * 两层架构
            应用->JDBC->数据库

        * 三层架构
            Java appletor/Html浏览器->应用服务器/JDBC->数据库

        * 三层架构的好处
            性能、安全、多线程、鲁棒性等

    JDBC包括四个组建
        * JDBC API
        * JDBC 驱动管理器
        * JDBC 测试套件
        * JDBC-ODBC桥

* 创建/获取连接

    * JDBC的四种驱动类型

        * Type 1
            实现了JDBC API到其他的数据存取API(比如ODBC)的映射,这种驱动一般依赖于本地类库。可移植性不好。
        * Type 2
            部分使用Java语言实现部分使用本地代码实现的驱动,这种驱动使用了所连接数据库的原生的客户类库,
            因此也依赖于本地类库, 可移植性不好。
        * Type 3
            驱动使用纯Java客户端与中间服务器进行连接,连接使用与数据库无关的协议。
        * Type 4
            驱动使用纯Java客户端直接与数据库进行连接,与数据库相关的网络连接协议使用Java实现。

    * 两层架构:

        1. 载入驱动
            Class.forName("org.apache.derby.jdbc.EmbeddedDriver");
        2. 建立连接
            String url = "jdbc:derby:Fred";//包括数据库地址、和待连接数据库名
            Connection con = DriverManager.getConnection(url, "Fernanda", "J8");//使用特定用户名和密码进行连接

    * 三层架构:

         //初始化上下文环境
         InitialContext ic = new InitialContext()
         //查找数据源
         DataSource ds = ic.lookup("java:comp/env/jdbc/myDB");
         //取得连接,这里的连接一般是从应用服务器的连接池当中取得
         Connection con = ds.getConnection();

         //手动创建数据源
         DataSource ds = (DataSource) org.apache.derby.jdbc.ClientDataSource()
         ds.setPort(1527);
         ds.setHost("localhost");
         ds.setUser("APP")
         ds.setPassword("APP");
        
         //获得连接,连接仍然是由外部(应用服务器)管理器进行管理
         Connection con = ds.getConnection();

    * 使用Ant执行创建数据库的任务

         # Database properties are in derby.properties
         db.delimiter=;
         db.root=${javaee.home}/derby
         db.driver=org.apache.derby.jdbc.ClientDriver
         db.datasource=org.apache.derby.jdbc.ClientDataSource
         db.host=localhost
         db.port=1527
         db.sid=sun-appserv-samples
         db.url=jdbc:derby://${db.host}:${db.port}/${db.sid};create=true;
         db.user=APP
         db.pwd=APP

         <target name="create-db_common" depends="init,start-db,delete-db"
                       description="Create database tables and populate database.">
            <sql driver="${db.driver}" url="${db.url}" userid="${db.user}"
                 password="${db.password}" classpathref="db.classpath"
                         delimiter="${db.delimiter}" autocommit="false" onerror="abort">
                 <transaction src="
                          {javaee.tutorial.home}/examples/common/sql/${db.vendor}/tutorial.sql"/>
             </sql>
         </target>


* 从结果集取得结果

    * 初始化Statement:

        Statement stmt = con.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,
                                             ResultSet.CONCUR_READ_ONLY);

            1. TYPE_FORWARD_ONLY :结果集的游标只能向前,无法进行滚动
            2. TYPE_SCROLL_INSENSITIVE: 结果集的游标可以向前、向后滚动或者移动到绝对位置
            3. TYPE_SCROLL_SENSITIVE:  结果集的游标可以向前、向后滚动或者移动到绝对位置

            1. CONCUR_READ_ONLY 表示结果集是只读类型的
            2. CONCUR_UPDATABLE 表示结果集是支持更新的

        如果不指定这两个参数,那么取得的Statement是 TYPE_FORWARD_ONLY 和 CONCUR_READ_ONLY的
   
    * 获取结果集

        ResultSet srs = stmt.executeQuery("SELECT COF_NAME, PRICE FROM COFFEES");

        * 移动游标的方法:
            next(), previous(), first(), last(), beforeFirst(), afterLast(),
            relative(int rows), absolute(int row)

        * 获取数据的方法:
            使用getXXX()方法,其参数可以为字段名或者整数下标,使用整数下标效率更高。

        * 更新数据的方式:
            使用updateXXX()方法,其参数为
                1. 待更新的字段名或者下标
                2. 待更新的值
            其返回值为更新成功的行数
            1. 在更新数据以后,必须调用结果集的updateRow()方法来将更新从结果集写入数据库。
            如果在调用updateRow()之前,将游标移动到了其他行,那对于当前行的更新将被丢失!
            2. 使用cancelRowUpdates()方法来取消对某行所有字段的更新。

* 使用preparedStatement.

    PreparedStatement updateSales = con.prepareStatement("UPDATE COFFEES SET SALES = ? WHERE COF_NAME LIKE ?");
    updateSales.setInt(1, 75);
    updateSales.setString(2, "Colombian");
    updateSales.executeUpdate():

    * 预编译的Statement的好处
        1. 可以在一个循环当中被重复调用
        2. SQL语句被先送给数据库进行预编译,提高了执行性能

    * executeUpdate()的返回值
        返回被更新的行数,如果返回0,可能是
            1. 该更新确实更新了0行
            2. 执行的语句是一个DDL语句

* 使用join

* 使用事务

    * 禁止Auto-commit模式
        con.setAutoCommit(false);

    * 提交事务

            con.setAutoCommit(false);//将自动提交设置为false
            try {
                .....//更新数据库语句
                con.commit();//提交到数据库
            } catch (SQLException e){
                con.rollback();//回滚事务
            } finally {
                con.setAutoCommit(true);// 记住在事务结束后,要将自动提交设置为true
            }

    * Savepoint: 回滚标签点
        Savepoint svpt1 = conn.setSavepoint("SAVEPOINT_1");//创建一个回滚标签点
        rows = stmt.executeUpdate("INSERT INTO TAB1 (COL1) " + "VALUES (?SECOND?)");
        ...
        conn.rollback(svpt1);// 回滚到保存的标签点

    * 释放回滚标签点
        回滚标签点在事务被提交或者回滚后被自动释放。

* 使用存储过程
    * 创建存储过程的方法与执行其他DDL语句一样

    * 使用 CallableStatement来调用存储过程
        CallableStatement cs = con.prepareCall("{call SHOW_SUPPLIERS}");
        ResultSet rs = cs.executeQuery();

        对于产生结果的query过程, 使用executeQuery来执行, 对于更新或者DDL语句,
        使用executeUpdate来执行, 存储过程可能含有多个SQL语句并返回多个结果集,
        需要使用execute方法来执行。CallableStatement对象可以有输入/输出参数。

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics