JAVA——jdbc教程(一)

hello jdbc

为项目导入mysql-jdbc的jar包

访问MySQL数据库需要用到第三方的类,这些第三方的类,都被压缩在一个叫做Jar的文件里。
为了代码能够使用第三方的类,需要为项目导入mysql的专用Jar包。
该包mysql-connector-java-5.0.8-bin.jar可以在网上下载
通常都会把项目用到的jar包统一放在项目的lib目录下,在本例就会放在
E:\project\j2se\lib 这个位置
然后在eclipse中导入这个jar包

导包步骤: 右键project->property->java build path->libaries->add external jars

初始化驱动

通过Class.forName(“com.mysql.jdbc.Driver”);
初始化驱动类com.mysql.jdbc.Driver
就在 mysql-connector-java-5.0.8-bin.jar中
如果忘记了第一个步骤的导包,就会抛出ClassNotFoundException
Class.forName是把这个类加载到JVM中,加载的时候,就会执行其中的静态初始化块,完成驱动的初始化的相关工作。

package jdbc;

public class TestJDBC {
    public static void main(String[] args) {

        //初始化驱动
        try {
            //驱动类com.mysql.jdbc.Driver
            //就在 mysql-connector-java-5.0.8-bin.jar中
            //如果忘记了第一个步骤的导包,就会抛出ClassNotFoundException
            Class.forName("com.mysql.jdbc.Driver");

            System.out.println("数据库驱动加载成功 !");

        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }
}

链接数据库

建立与数据库的Connection连接

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

这里需要提供:
数据库所处于的ip:127.0.0.1 (本机)
数据库的端口号: 3306 (mysql专用端口号)
数据库名称 how2java
编码方式 UTF-8
账号 root
密码 admin
注: 这一步要成功执行,必须建立在mysql中有数据库how2java的基础上,如果没有,请前往MYSQL建立数据库

package jdbc;

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

public class TestJDBC {
    public static void main(String[] args) {

        try {
            Class.forName("com.mysql.jdbc.Driver");

            // 建立与数据库的Connection连接
            // 这里需要提供:
            // 数据库所处于的ip:127.0.0.1 (本机)
            // 数据库的端口号: 3306 (mysql专用端口号)
            // 数据库名称 how2java
            // 编码方式 UTF-8
            // 账号 root
            // 密码 admin

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

            System.out.println("连接成功,获取连接对象: " + c);

        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

创建Statement

Statement是用于执行SQL语句的,比如增加,删除

package jdbc;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;

public class TestJDBC {
    public static void main(String[] args) {

        try {
            Class.forName("com.mysql.jdbc.Driver");

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

            // 注意:使用的是 java.sql.Statement
            // 不要不小心使用到: com.mysql.jdbc.Statement;
            Statement s = c.createStatement();

            System.out.println("获取 Statement对象: " + s);

        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }
}

执行SQL语句

s.execute执行sql语句
执行成功后,用mysql-front进行查看,明确插入成功

执行SQL语句之前要确保数据库how2java中有表hero的存在,如果没有,需要事先创建表

package jdbc;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;

public class TestJDBC {
    public static void main(String[] args) {

        try {
            Class.forName("com.mysql.jdbc.Driver");

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

            Statement s = c.createStatement();

            // 准备sql语句
            // 注意: 字符串要用单引号'
            String sql = "insert into hero values(null,"+"'提莫'"+","+313.0f+","+50+")";
            s.execute(sql);

            System.out.println("执行插入语句成功");

        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }
}

关闭连接

数据库的连接是有限资源,相关操作结束后,养成关闭数据库的好习惯
先关闭Statement
后关闭Connection

public class TestJDBC {
    public static void main(String[] args) {

        Connection c = null;
        Statement s = null;
        try {
            Class.forName("com.mysql.jdbc.Driver");

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

            s = c.createStatement();

            String sql = "insert into hero values(null," + "'提莫'" + "," + 313.0f + "," + 50 + ")";

            s.execute(sql);

        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } finally {
            // 数据库的连接时有限资源,相关操作结束后,养成关闭数据库的好习惯
            // 先关闭Statement
            if (s != null)
                try {
                    s.close();
                } catch (SQLException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            // 后关闭Connection
            if (c != null)
                try {
                    c.close();
                } catch (SQLException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }

        }

    }
}

使用try-with-resource的方式自动关闭连接

如果觉得上一步的关闭连接的方式很麻烦,可以参考关闭流 的方式,使用try-with-resource的方式自动关闭连接,因为Connection和Statement都实现了AutoCloseable接口

class.forName(“com.mysql.jdbc.Driver”)会在classpath中查找并加载这个类。一旦com.mysql.jdbc.Driver被加载并连接后,就自动执行static静态代码块,这时就可以做一些初始化的工作了,最主要的作用就是执行java.sql.DriverManager.registerDriver()来注册驱动。如果没有class.forName这一步,就会报找不到合适的驱动程序。

package jdbc;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;

public class TestJDBC {
    public static void main(String[] args) {

        try {
            Class.forName("com.mysql.jdbc.Driver");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }

        try (
            Connection c = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/how2java?characterEncoding=UTF-8",
                "root", "admin");
            Statement s = c.createStatement();             
        )
        {
            String sql = "insert into hero values(null," + "'提莫'" + "," + 313.0f + "," + 50 + ")";
            s.execute(sql);

        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

CRUD是最常见的数据库操作,即增删改查
C 增加(Create)
R 读取查询(Retrieve)
U 更新(Update)
D 删除(Delete)

增、删、改(不用返回数据)

在JDBC中增加,删除,修改的操作都很类似,只是传递不同的SQL语句就行了。

String sql = "insert into hero values(null," + "'提莫'" + "," + 313.0f + "," + 50 + ")";
            s.execute(sql);
String sql = "delete from hero where id = 5";
            s.execute(sql);
String sql = "update hero set name = 'name 5' where id = 3";
            s.execute(sql);

查询(有返回数据)

executeQuery 执行SQL查询语句
ResultSet rs = s.executeQuery(sql);

ResultSet rs = s.executeQuery(sql);

注意: 在取第二列的数据的时候,用的是rs.get(2) ,而不是get(1). 这个是整个Java自带的api里唯二的地方,使用基1的,即2就代表第二个。

另一个地方是在PreparedStatement这里

package jdbc;

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

public class TestJDBC {
    public static void main(String[] args) {
        try {
            Class.forName("com.mysql.jdbc.Driver");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }

        try (Connection c = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/how2java?characterEncoding=UTF-8",
                "root", "admin"); Statement s = c.createStatement();) {

            String sql = "select * from hero";

            // 执行查询语句,并把结果集返回给ResultSet
            ResultSet rs = s.executeQuery(sql);
            while (rs.next()) {
                int id = rs.getInt("id");// 可以使用字段名
                String name = rs.getString(2);// 也可以使用字段的顺序
                float hp = rs.getFloat("hp");
                int damage = rs.getInt(4);
                System.out.printf("%d\t%s\t%f\t%d%n", id, name, hp, damage);
            }
            // 不一定要在这里关闭ReultSet,因为Statement关闭的时候,会自动关闭ResultSet
            // rs.close();

        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

SQL语句判断账号密码是否正确

  1. 创建一个用户表,有字段name,password
  2. 插入一条数据

insert into user values(null,’dashen’,’thisispassword’);

  1. SQL语句判断账号密码是否正确

判断账号密码的正确方式根据账号和密码到表中去找数据,如果有数据,就表明密码正确了,如果没数据,就表明密码错误。

不恰当的方式 是把uers表的数据全部查到内存中,挨个进行比较。 如果users表里有100万条数据呢? 内存都不够用的。


public class TestJDBC {
    public static void main(String[] args) {
        try {
            Class.forName("com.mysql.jdbc.Driver");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }

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

                ) {
            String name = "dashen";
            //正确的密码是:thisispassword
            String password = "thisispassword1";

            String sql = "select * from user where name = '" + name +"' and password = '" + password+"'";

            // 执行查询语句,并把结果集返回给ResultSet
            ResultSet rs = s.executeQuery(sql);

            if(rs.next())
                System.out.println("账号密码正确");
            else
                System.out.println("账号密码错误");

        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }
}

获取总数

String sql = "select count(*) from hero";

            ResultSet rs = s.executeQuery(sql);
            //rs 是个整数数组 
            int total = 0;
            while (rs.next()) {
                total = rs.getInt(1);
            }

            System.out.println("表Hero中总共有:" + total+" 条数据");

预编译

和 Statement一样,PreparedStatement也是用来执行sql语句的
与创建Statement不同的是,需要根据sql语句创建PreparedStatement
除此之外,还能够通过设置参数,指定相应的值,而不是Statement那样使用字符串拼接

注: 这是JAVA里唯二的基1的地方,另一个是查询语句中的ResultSet也是基1的。

String sql = "insert into hero values(null,?,?,?)";
        try (Connection c = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/how2java?characterEncoding=UTF-8","root", "admin");
            // 根据sql语句创建PreparedStatement
            PreparedStatement ps = c.prepareStatement(sql);
        ) {

            // 设置参数
            ps.setString(1, "提莫");
            ps.setFloat(2, 313.0f);
            ps.setInt(3, 50);
            // 执行
            ps.execute();

优点

1.Statement 需要进行字符串拼接,可读性和维护性比较差

String sql = “insert into hero values(null,”+”’提莫’”+”,”+313.0f+”,”+50+”)”;

PreparedStatement 使用参数设置,可读性好,不易犯错

String sql = “insert into hero values(null,?,?,?)”;
2.PreparedStatement有预编译机制,性能比Statement更快
3.PreparedStatement的优点3-防止SQL注入式攻击
假设name是用户提交来的数据

String name = “’盖伦’ OR 1=1”;

使用Statement就需要进行字符串拼接
拼接出来的语句是:

select * from hero where name = ‘盖伦’ OR 1=1

因为有OR 1=1,这是恒成立的
那么就会把所有的英雄都查出来,而不只是盖伦
如果Hero表里的数据时海量的,比如几百万条,把这个表里的数据全部查出来
会让数据库负载变高,CPU100%,内存消耗光,响应变得极其缓慢

而PreparedStatement使用的是参数设置,就不会有这个问题

JDBC中EXECUTE与EXECUTEUPDATE的区别

相同点:execute与executeUpdate的相同点:都可以执行增加,删除,修改

不同点:
不同1:
execute可以执行查询语句
然后通过getResultSet,把结果集取出来
executeUpdate不能执行查询语句

String sqlSelect = "select * from hero";

            s.execute(sqlSelect);
            ResultSet rs = s.getResultSet();
            while (rs.next()) {
                System.out.println(rs.getInt("id"));
            }

不同2:
execute返回boolean类型,true表示执行的是查询语句,false表示执行的是insert,delete,update等等
executeUpdate返回的是int,表示有多少条数据受到了影响

            // 不同2:
            // execute返回boolean类型,true表示执行的是查询语句,false表示执行的是insert,delete,update等等
            boolean isSelect = s.execute(sqlSelect);
            System.out.println(isSelect);

            // executeUpdate返回的是int,表示有多少条数据受到了影响
            String sqlUpdate = "update Hero set hp = 300 where id < 100";
            int number = s.executeUpdate(sqlUpdate);
            System.out.println(number);

猜你喜欢

转载自blog.csdn.net/jae_peng/article/details/79833762