天猫总站JavaEE版本的实现(一):jdbc的学习

jdbc(java database connection)是java内部集成的一套负责与database交互api。用以在java端执行增删查找数据库数据的操作。
这一套操作为:
1.准备好数据库
先准备操作的数据库表为选课表。表结构如下:
这里写图片描述

2.连接数据库
- 为项目引用Jar包

这里写图片描述

  • 注册Driver到DriverManager里面

这里写图片描述

上面的代码中有加载类Class.forName("com.mysql.jdbc.Driver")的描述。

查看com.mysql.jdbc.Driver源码如下:
public class Driver extends NonRegisteringDriver implements java.sql.Driver {
    // ~ Static fields/initializers
    // ---------------------------------------------

    //
    // Register ourselves with the DriverManager
    //
    static {
        try {
            java.sql.DriverManager.registerDriver(new Driver());
        } catch (SQLException E) {
            throw new RuntimeException("Can't register driver!");
        }
    }

    // ~ Constructors
    // -----------------------------------------------------------

    /**
     * Construct a new driver and register it with DriverManager
     * 
     * @throws SQLException
     *             if a database error occurs.
     */
    public Driver() throws SQLException {
        // Required for Class.forName().newInstance()
    }
}

可知,在加载com.mysql.jdbc.Driver的时候,已经生成了一个Driver实例,并将其注册到DriverManager里面了。

3.执行insert的sql语句
这里写图片描述
查询Category表中数据为:

这里写图片描述

可见insert的sql语句起了作用。
上述代码中:

Connection c = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/tmall?characterEncoding=UTF-8", "root", "admin");

用以连接tmall数据库

Statement s = c.createStatement();
String sql = "insert into Category values(85," +"'ruff开发板')";
s.execute(sql);

用以执行SQL语句,向Category表中插入数据。

4.执行select语句,查询表中数据
这里写图片描述

其中
while(mResultSet.next()){
System.out.println("Category表中id > 80的产品名称为:" + mResultSet.getString(2));
}

取出结果集中,所有的第二列数据。其中ResultSet.next()方法的解释为:

Moves the cursor forward one row from its current position. A ResultSet cursor is initially positioned before the first row; the first call to the method next makes the first row the current row; the second call makes the second row the current row, and so on.

到此我们就基本上实现了JDBC的基本功能,可以开始业务开发了。

5.使用PreparedStatement实现数据库的操作。

    public static void main(String args[]){
        //new CategoryDao().executePreparedStatement();
        //new CategoryDao().executeStatement("空调 or 1= 1");
        //new CategoryDao().executePreparedStatement("空调 or 1= 1");
        new CategoryDao().executePreparedStatement("空调");
    }


    private void executePreparedStatement(String userInput){
        String sql = "select * from Category where name = ?";
        try{
            Connection c = getConnection();
            PreparedStatement ps = c.prepareStatement(sql);
            ps.setString(1, userInput);
            ps.execute();
            ResultSet rs = ps.getResultSet();
            while(rs.next()){
                System.out.printf("%d,%s",rs.getInt(1),rs.getString(2));
            }
        }catch(SQLException ex){
            ex.printStackTrace();
        }

    }

上面的函数执行了从Category数据库中查找id=80的项目并将name打印出来的功能,执行结果如下:

这里写图片描述
Console界面将name=空调 的条目打印出来了。

5.使用PreparedStatement与使用Statement的对比。
上述示例代码中的PreparedStatement.setString(1, userInput);是值往sql第一个参数传值,然而Statement中sql是通过字符串拼接得到的。下面的代码对比表示了其区别:

    public static void main(String args[]){
        //new CategoryDao().executePreparedStatement();
        new CategoryDao().executeStatement("75");
        //new CategoryDao().executePreparedStatement("空调 or 1= 1");
        //new CategoryDao().executePreparedStatement(75);
    }

        private void executeStatement(String userInput){
        String sql = "select * from Category where id = "   + userInput ;
        try{
            Connection c = getConnection();
            //PreparedStatement ps = c.prepareStatement(sql);
            //ps.setInt(1, 80);
            //ps.execute();
            Statement s = c.createStatement();
            s.execute(sql);
            ResultSet rs = s.getResultSet();
            while(rs.next()){
                System.out.printf("%d,%s",rs.getInt(1),rs.getString(2));
            }
        }catch(SQLException ex){
            ex.printStackTrace();
        }

    }

得到的结果为:
这里写图片描述

由此可见Statement的sql语句是采用字符串拼接得到的。
因此PreparedStatement可以在两方面比Statement好:

(1)书写很麻烦 。尤其是当sql字段涉及到char, varchar类型的数据时,转义字符(\”)写的人脑袋都要绕晕了。

(2)很重要的一点,PreparedStatement可以防止sql注入。

    public static void main(String args[]){
        //new CategoryDao().executePreparedStatement();
        new CategoryDao().executeStatement("75 or 1 = 1");
        //new CategoryDao().executePreparedStatement("空调 or 1= 1");
        //new CategoryDao().executePreparedStatement(75);
    }

        private void executeStatement(String userInput){
        String sql = "select * from Category where id = "   + userInput ;
        try{
            Connection c = getConnection();
            //PreparedStatement ps = c.prepareStatement(sql);
            //ps.setInt(1, 80);
            //ps.execute();
            Statement s = c.createStatement();
            s.execute(sql);
            ResultSet rs = s.getResultSet();
            while(rs.next()){
                System.out.printf("%d,%s",rs.getInt(1),rs.getString(2));
            }
        }catch(SQLException ex){
            ex.printStackTrace();
        }

    }

注意这行:

new CategoryDao().executeStatement("75 or 1 = 1");

执行结果为:
这里写图片描述

结果得知,打印出了Category表中所有的信息,这就是sql注入导致的信息泄露了。而在PreparedStatement中就不会产生这个结果,因为 “75 or 1 = 1”这个参数在Category表中是查不出来东西的。

(3)还有一点重要的区别是执行效率的区别

使用 PreparedStatement 最重要的一点好处是它拥有更佳的性能优势,SQL语句会预编译在数据库系统中。执行计划同样会被缓存起来,它允许数据库做参数化查询。使用预处理语句比普通的查询更快,因为它做的工作更少(数据库对SQL语句的分析,编译,优化已经在第一次查询前完成了)。为了减少数据库的负载,生产环境中德JDBC代码你应该总是使用PreparedStatement 。值得注意的一点是:为了获得性能上的优势,应该使用参数化sql查询而不是字符串追加的方式。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值