java第八次作业

认真看书并查阅相关资料,掌握以下内容掌握应用JDBC访问数据库的基本步骤掌握DriverManager类、Connection接口、Statement接口、PreparedStatement接口、ResultSet接口的使用理解分层设计思想###

JDBC 是Java操作数据库的规范,它实际上定义了一组标准的数据库的接口,为了实现通过java操作数据库,必须实现这些接口,不同的数据库厂商都提供了对JDBC接口的实现,这些具体的实现被打包成一个jar包(也就是数据库驱动),供我们在开发的时候直接使用。
JDBC API 中的主要接口:

第一: Driver接口是所有JDBC程序必须实现的接口,该接口专门提供给数据库厂商使用,定义了驱动的样式

第二:DriverManager 用于加载JDBC驱动并创建与数据库的连接
有两个重要的方法:

1 DriverManager.registerDriver(Driver driver) // 用于向DriverManager注册给定的JDBC驱动程序
2 DriverManager.getConnection(String url, String user, String pwd) // 建立与数据库的连接,返回表示连接的Connection对象

第三: Connection 接口 主要方法有三个

  1. Connection.createStatement(); // 创建一个Statement对象,静态sql语句查询

  2. Connection.prepareStatement(String sql); // 创建一个PreparedStatement对象,实现动态sql语句查询

  3. Connection.prepareCall(String sql); // 创建一个CallableStatement对象来调用数据库存储过程

第四:Statement接口 用于执行查询返回查询结果
1 Statement.execute(String sql); // 执行各种SQL语句,返回一个boolean类型值,true表示执行的SQL语句具备查询结果,可通过Statement.getResultSet()方法获取
2 Statement.executeUpdate(String sql); // 执行SQL中的insert/update/delete语句,返回一个int值,表示受影响的记录的数目
3 Statement.executeQuery(String sql); // 执行SQL中的select语句,返回一个表示查询结果的ResultSet对象

第五:ResultSet接口 用于查询结果的操作

1 ResultSet.next(); // 将游标由当前位置移动到下一行
2 ResultSet.getString(String columnName); // 获取指定字段的String类型值
3 ResultSet.getString(int columnIndex); // 获取指定索引的String类型值
4 ResuleSet.previous(); // 将游标由当前位置移动到上一行

JDBC操作数据库的一般步骤

注册驱动 (只做一次)

建立连接(Connection)

创建执行SQL的语句(Statement)

执行语句并处理执行结果(ResultSet)

释放资源

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

// 这里测试的是mysql数据库名是test; 表是 user; 表的字段 有 id ,name ,age ,salary
public class JDBCTest {
    public static void main(String[] args) {
        // 第一步: 首先注册驱动, 驱动一般只会注册一次
        try {
            Class.forName("com.mysql.jdbc.Driver");
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            System.out.println("找不到驱动程序类,加载驱动失败");
            e.printStackTrace();
        }
        // 第二步:建立连接 Connect, 设置url ,用户名, 密码
        // url格式:JDBC:子协议:子名称//主机名:端口/数据库名?属性名=属性值&…
        // 注意的是url中一定不要加多余的空格,否则会出错, useSSL=false是为了解决身份验证时出现的警告的问题
        // String url = "jdbc:mysql://localhost:3306/test?" + "user=root&password=wsw011152&useUnicode=true&characterEncoding=UTF-8&useSSL=false";
        String url = "jdbc:mysql://localhost:3306/test?useSSL=false";
        String name = "root";
        String psw = "root";
        Connection connect = null;
        try {
            connect = DriverManager.getConnection(url, name, psw);
            // connect = DriverManager.getConnection(url);
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            System.out.println("数据库连接失败");
            e.printStackTrace();
        }
        // 第三步: 创建一个 Statement ,一般建议使用 PreparedStatement
        // 1、执行静态SQL语句。通常通过Statement实例实现。
        // 2、执行动态SQL语句。通常通过PreparedStatement实例实现。
        // 3、执行数据库存储过程。通常通过CallableStatement实例实现。
        // String sql = "select * from user where id = ?";
        String sql = "select * from user where id = ?";
        try {
            PreparedStatement ps = connect.prepareStatement(sql);
            ps.setInt(1, 1); // 设置参数
            // 第四步: 执行语句,获得一个结果集,处理获得的结果
            ResultSet result = ps.executeQuery();
            while (result.next()) {
                System.out.println(result.getInt("id"));
                System.out.println(result.getString("name"));
                System.out.println(result.getInt("age"));
                System.out.println(result.getString("salary"));
            }
            // 第五步: 关闭资源
            result.close();
            ps.close();
            connect.close();
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

1.用思维导图对本周的学习内容进行总结。####

2.通过实验内容中的具体实例说明在执行executeUpdate()方法和executeQuery()方法中使用动态参数时,为什么要使用PreparedStatement接口而不使用Statement,比较使用两种接口的不同之处。####

首先java提供了三种方式来执行sql语句
CallableStatement;主要用于存储过程的查询,
Statement;主要用于通用查询,适合只对数据库进行一次性存取的时候,使用它会为每一条sql语句生成一个执行计划,即使这两条语句只有参数的不同而已。
PreparedStatement :主要用于参数化查询,会传递参数,反复查询

PreparedStatement 相对比与Statement的优势在下面的几点:

  1. 使用PreparedStatement,数据库系统会对sql语句进行预编译(需要JDBC驱动支持预编译SQL查询),进行预处理,这条预处理的sql查询语句可以在将来的查询中被重用,节省了创建执行计划的时间,减少了系统的开销,因此它比Statement的查询速度更快。
    比如使用 Statement进行下面两句的查询,则会生成两个执行计划,1000个查询就会生成1000个执行计划,生成执行计划十分消耗资源,
    select colume from table where colume=1;
    select colume from table where colume=2;
    但是使用PreparedStatement, 则系统会对sql语句进行预编译处理,只会生成1个执行计划,1000个这样的查询不会再产生执行计划,这个执行计划会被下面同样的查询语句所重用,大大提高了速度。
    select colume from table where colume=?;
    PreparedStatement .setInt(1, 1);
    PreparedStatement .setInt(1, 2);

  2. 可以写动态参数化的查询,用PreparedStatement你可以写带参数的sql查询语句,通过使用相同的sql语句和不同的参数值来做查询

  3. PreparedStatement可以防止SQL注入式攻击,更加安全
    使用PreparedStatement的参数化的查询可以阻止大部分的SQL注入攻击。
    第一:在使用参数化查询的情况下,数据库系统不会将参数的内容视为SQL指令的一部分来处理,而是在数据库完成SQL指令的编译后,才套用参数运行,因此就算参数中含有破坏性的指令,也不会被数据库所运行
    第二:在组合SQL字符串的时候,先对所传入的参数做字符取代(将单引号字符取代为连续2个单引号字符,因为连续2个单引号字符在SQL数据库中会视为字符中的一个单引号字符。

     strSQL = “SELECT * FROM users WHERE name = ‘” + userName + “’;” 
     传入字符串: 
     userName = ” 1’ OR 1=1 “
     
     把userName做字符替换后变成: 
     userName = ” 1” OR 1=1”
     
     最后生成的SQL查询语句为: 
     strSQL = “SELECT * FROM users WHERE name = ‘1” OR 1=1’ 
     这样数据库就会去系统查找name为“1′ ‘ OR 1=1”的记录,而避免了SQL注入。
     
     PreparedStatement的局限性: 
     为了防止SQL注入攻击,PreparedStatement不允许一个占位符(?)有多个值,在执行有*IN子句查询的时候这个问题变得棘手起来*。下面这个SQL查询使用PreparedStatement就不会返回任何结果: 
     SELECT * FROM loan WHERE loan_type IN (?) 
     preparedSatement.setString(1, “‘personal loan’, ‘home loan’, ‘gold loan’”); 
     
     // 将in 里面的变量首先存储成一个数组
     String[] in_datas=new String[]{"1", "2", "3"}; 
     StringBuffer buffer = new StringBuffer();
     for(int i=0;i<in_datas.length-1;i++){ 
         buffer.append("?,"); 
     }
     buffer.append("?");
     // 在in字句 里面使用N个 ?。 然后为每一个?赋值
     pst = conn.prepareStatement("select id,name from B where id in ( "+buffer.toString()+" )");  //  buffer.toString() ="?,?,?,?...?"
     for(int i=0;i<in_datas.length;i++){  
         pst.set(i, in_datas[i]);  
     }
     // 解决 like 查询的方式
        String expr = "select * from  table where url like ?";  
        pstmt = con.prepareStatement(expr);  
        String a="a";  
        pstmt.setString(1, "%"+a+"%");//自动添加单引号 (包装后的参数)  
        pstmt.execute(); 
    

(二)实验总结###

程序设计思路:根据老师的fruit给的程序,理解和改动,主要是分为主函数类,主界面类(两个),数据库属性类,方法功能与数据库连接类,内部内容类,工具类,两个面板功能实现类即可。

类图结构:
问题1:如何将数据库里面的数据与java功能类建立连接并读出来
原因:不知道该如何在其他类中与数据库建立连接
解决方案:让数据库属性类建立返回值,在与数据库建立连接的时候,可以通过导入包,利用返回值建立关系和链接。

码云截图###

码云链接https://git.oschina.net/hebau_cs15/cg.git

posted @ 2017-05-18 13:38  计科陈刚  阅读(209)  评论(0编辑  收藏  举报