• 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

  • 相关阅读:
    12分布式文件存储
    编写高性能java程序
    Linux常用命令
    jQuery控制文本框只能输入数字
    在代码中动态绑定TabHost内容的两种方法(Android)
    maven快速使用教程
    silverlight利用代码添加带图标的treeviewItem
    快速认识ESB
    代码中控制TabHost中标签Tab的高度和宽度(Android)
    Maven2快速认识和使用
  • 原文地址:https://www.cnblogs.com/chengang4747/p/6872919.html
Copyright © 2020-2023  润新知