zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    [LeetCode]2. Add Two Numbers链表相加
    Integration between Dynamics 365 and Dynamics 365 Finance and Operation
    向视图列添加自定义图标和提示信息 -- PowerApps / Dynamics365
    Update the Power Apps portals solution
    Migrate portal configuration
    Use variable to setup related components visible
    Loyalty management on Retail of Dynamic 365
    Modern Fluent UI controls in Power Apps
    Change screen size and orientation of a canvas app in Power App
    Communication Plan for Power Platform
  • 原文地址:https://www.cnblogs.com/chengang4747/p/6872919.html
Copyright © 2011-2022 走看看