• (三)JDBC之使用Statement,PreparedStatement,ResultSet


    1. 创建一个获取Connection对象和关闭资源的工具类

      在对数据库进行CRUD操作的时候,每一个操作都需要获取Connection对象,所以我们就可以把获取Connection对象的过程抽离到一个工具类当中,下面是具体代码。

      

    View Code
    public final class JdbcUtil
    {
        private JdbcUtil()
        {
        }
    
        private static String url = "jdbc:oracle:thin:@127.0.0.1:1521:ORCL";
        private static String user = "scott";
        private static String password = "tiger";
    
        static
        {
            try
            {
                Class.forName("oracle.jdbc.driver.OracleDriver");
            }
            catch (ClassNotFoundException e)
            {
                throw new ExceptionInInitializerError("加载驱动类出错!!");
            }
        }
    
        public static Connection getConnection() throws Exception
        {
            Connection connection = null;
            connection = DriverManager.getConnection(url, user, password);
            return connection;
        }
    
        public static void close(Connection connection, ResultSet rs, Statement statement)
        {
            if (rs != null)
            {
                try
                {
                    rs.close();
                }
                catch (SQLException e)
                {
                    e.printStackTrace();
                }
                finally
                {
                    if (statement != null)
                    {
                        try
                        {
                            statement.close();
                        }
                        catch (SQLException e)
                        {
                            e.printStackTrace();
                        }
                        finally
                        {
                            if (connection != null)
                            {
                                try
                                {
                                    connection.close();
                                }
                                catch (SQLException e)
                                {
                                    e.printStackTrace();
                                }
                            }
                        }
                    }
                }
    
            }
    
        }
    }

      我把url,username,password放在了类中,也可以将这些配置信息放入到配置文件中,一般的做法是放入到配置文件当中,此处就是简单些。将加载驱动类的方法放入到static静态块当中,当调用getConnection静态方法的时候,static静态块会先执行,就会先加载驱动类。Close方法就是关闭Statement, Connection ,ResultSet对象的资源。

    2.  使用StatementResultSet进行简单CRUD操作

      首先看一下Statement接口的文档说明:

      用于执行静态 SQL 语句并返回它所生成结果的对象。

      在默认情况下,同一时间每个 Statement 对象在只能打开一个 ResultSet 对象。因此,如果读取一个 ResultSet 对象与读取另一个交叉,则这两个对象必须是由不同的 Statement 对象生成的。如果存在某个语句的打开的当前 ResultSet 对象,则 Statement 接口中的所有执行方法都会隐式关闭它。

      Statement的主要作用就是执行SQL语句并且返回它所生产的结果对象。Statement对象是通过Connection对象进行获取的,通过

      Connection. createStatement()方法获取Statement对象。通过执行Statement对象的executeQuery()方法进行查询SQL,该语句返回单个 ResultSet 对象。

      下面是简单的代码示例:

      

    View Code
    public void read(String id, String password)
        {
            Connection connection = null;
            Statement statement = null;
            ResultSet resultSet = null;
            try
            {
                connection = JdbcUtil.getConnection();
                statement = connection.createStatement();
                resultSet = statement.executeQuery("select id, name from student where id = '" + id + "' and password = '" + password + "'");
                
                while (resultSet.next())
                {
                    System.out.println("id = " + resultSet.getInt("id") + ", name = " + resultSet.getString("name"));
                }
            }
            catch(SQLException e)
            {
                e.printStackTrace();
            }
            catch (Exception e)
            {
                e.printStackTrace();
            }
            finally
            {
                JdbcUtil.close(connection, resultSet, statement);
            }
        }

      模拟了一个简单的查询用户信息的sql,传入id和password对数据库进行查询,然后输出。Sql语句是通过传入的值拼接而成,所以这样就很容易被SQL注入。当我传入的password值为' or 1 = 1 or '的时候打印出来sql语句如下:

      select id, name from student where id = 'rcx' and password = '' or 1 = 1 or ''

      因此就可以查询到用户的信息,引起的不安全的漏洞。一般带参数的查询都需要使用PreparedStatement对象。

    3.  使用PreparedStatementResultSet进行简单CRUD操作

      首先看一下PreparedStatement接口,它继承于Statement接口。表示预编译的 SQL 语句的对象。SQL 语句被预编译并存储在 PreparedStatement 对象中。然后可以使用此对象多次高效地执行该语句。 通过调用Connection对象的prepareStatement(sql)方法来获取

      PreparedStatement对象的,传入的参数是预编译的sql语句,带参数部分通过?代替。上面的例子通过PreparedStatement进行查询代码如下:

    View Code
    public void read1(String id, String password)
        {
            Connection connection = null;
            PreparedStatement statement = null;
            ResultSet resultSet = null;
            try
            {
                connection = JdbcUtil.getConnection();
                String sql = "select id, name from student where id = ? and password = ?";
                statement = connection.prepareStatement(sql);
                statement.setString(1, id);
                statement.setString(2, password);
                
                resultSet = statement.executeQuery();
                
                while (resultSet.next())
                {
                    System.out.println("id = " + resultSet.getInt("id") + ", name = " + resultSet.getString("name"));
                }
            }
            catch(SQLException e)
            {
                e.printStackTrace();
            }
            catch (Exception e)
            {
                e.printStackTrace();
            }
            finally
            {
                JdbcUtil.close(connection, resultSet, statement);
            }
        }

      由于PreparedStatement的预处理sql,可以有效的防止sql注入的问题,同时还可以提高一些效率。

      注意:

      resultSet = statement.executeQuery();

      由于PreparedStatement继承与Statement,所以也有executeQuery(sql)带参数的方法,如果这样写的话那么执行的就是父接口当中的方法了,不会对sql进行预处理了。

    4.  一些其他的方法

      由于查询是调用executeQuery()方法的,在插入更新与删除操作是调用executeUpdate(Sql)方法,执行给定 SQL 语句,该语句可能为 INSERT、UPDATE 或 DELETE 语句,或者不返回任何内容的 SQL 语句(如 SQL DDL 语句)。

      ResultSet对象的next()方法:将光标从当前位置向前移一行。ResultSet 光标最初位于第一行之前;第一次调用 next 方法使第一行成为当前行;第二次调用使第二行成为当前行,依此类推。

    完整的CRUD代码:

    View Code
    public class CRUD {
    
        public static void main(String[] args) throws SQLException {
            // create();
            read();
            // update();
            // delete();
        }
    
        static void delete() throws SQLException {
            Connection conn = null;
            Statement st = null;
            ResultSet rs = null;
            try {
                // 2.建立连接
                conn = JdbcUtils.getConnection();
                // conn = JdbcUtilsSing.getInstance().getConnection();
                // 3.创建语句
                st = conn.createStatement();
    
                String sql = "delete from user where id>4";
    
                // 4.执行语句
                int i = st.executeUpdate(sql);
    
                System.out.println("i=" + i);
            } finally {
                JdbcUtils.free(rs, st, conn);
            }
        }
    
        static void update() throws SQLException {
            Connection conn = null;
            Statement st = null;
            ResultSet rs = null;
            try {
                // 2.建立连接
                conn = JdbcUtils.getConnection();
                // conn = JdbcUtilsSing.getInstance().getConnection();
                // 3.创建语句
                st = conn.createStatement();
    
                String sql = "update user set money=money+10 ";
    
                // 4.执行语句
                int i = st.executeUpdate(sql);
    
                System.out.println("i=" + i);
            } finally {
                JdbcUtils.free(rs, st, conn);
            }
        }
    
        static void create() throws SQLException {
            Connection conn = null;
            Statement st = null;
            ResultSet rs = null;
            try {
                // 2.建立连接
                conn = JdbcUtils.getConnection();
                // conn = JdbcUtilsSing.getInstance().getConnection();
                // 3.创建语句
                st = conn.createStatement();
    
                String sql = "insert into user(name,birthday, money) values ('name1', '1987-01-01', 400) ";
    
                // 4.执行语句
                int i = st.executeUpdate(sql);
    
                System.out.println("i=" + i);
            } finally {
                JdbcUtils.free(rs, st, conn);
            }
        }
    
        static void read() throws SQLException {
            Connection conn = null;
            Statement st = null;
            ResultSet rs = null;
            try {
                // 2.建立连接
                conn = JdbcUtils.getConnection();
                // conn = JdbcUtilsSing.getInstance().getConnection();
                // 3.创建语句
                st = conn.createStatement();
    
                // 4.执行语句
                rs = st.executeQuery("select id, name, money, birthday  from user");
    
                // 5.处理结果
                while (rs.next()) {
                    System.out.println(rs.getObject("id") + "\t"
                            + rs.getObject("name") + "\t"
                            + rs.getObject("birthday") + "\t"
                            + rs.getObject("money"));
                }
            } finally {
                JdbcUtils.free(rs, st, conn);
            }
        }
    
    }
  • 相关阅读:
    循环链表问题
    非常有用的编程学习网站
    我的单例模式(C++)
    C# xml解析
    设计模式趣解
    简单工厂(C++)
    贝塞尔曲线 原理
    C++ 1.#QNAN0;1.#QNAN0
    [NOI2018]屠龙勇士 excrt
    [NOI.AC#30]candy 贪心
  • 原文地址:https://www.cnblogs.com/renchunxiao/p/3021485.html
Copyright © 2020-2023  润新知