一、Jdbc原理示意图
二、Jdbc的概述
三、JDBC的快速入门
代码如下,具体讲解在注释中已经说明
public class Jdbc01 { public static void main(String[] args) throws SQLException { //前置工作:在项目下创建一个文件夹比如libs //将mysql.jar拷贝到该目录下,点击add to project ..加入到项目 //1.注册驱动 Driver driver = new Driver();//创建Driver对象 //2.得到连接 //解读 //1.jdbc:mysql:// 规定好的协议,通过jdbc的方式连接mysql //2.localhost 主机,可以是ip地址 //3.3306 表示sql监听的端口 //4.db_ly 连接到mysql dbms的哪个数据库 //5.mysql的连接本质就是socket连接 String url = "jdbc:mysql://localhost:3306/db_ly?serverTimezone=GMT"; //将用户名和密码放入到Properties对象 Properties properties = new Properties(); //说明 user 和 password 是规定好的,后面的值根据实际情况写 properties.setProperty("user", "root");//用户 properties.setProperty("password", "123456");//密码 Connection connect = driver.connect(url, properties); //3.执行sql // String sql = "insert into actor values(null,'刘德华','男','1970-01-01','110')" + // ",(null,'周星驰','男','1980-01-03','123456789')"; String sql = "update actor set name='王宝强' where id = 3"; // String sql = "delete from actor where id =1"; //statement:用于执行静态的sql语句并返回其生成的结果对象 Statement statement = connect.createStatement(); //如果是dml语句,返回的就是影响行数 int rows = statement.executeUpdate(sql); System.out.println(rows); System.out.println(rows > 0 ? "成功" : "失败"); //4.关闭连接资源 statement.close(); connect.close(); } }
输出结果如下
成功
四、Java操作数据库需要获得Connection连接,获取Connection连接的五种方式如下
public class JdbcConn { //方式1 @Test public void connect01() throws SQLException { //1.注册驱动 Driver driver = new Driver();//创建Driver对象 String url = "jdbc:mysql://localhost:3306/db_ly?serverTimezone=GMT"; //将用户名和密码放入到Properties对象 Properties properties = new Properties(); //说明 user 和 password 是规定好的,后面的值根据实际情况写 properties.setProperty("user", "root");//用户 properties.setProperty("password", "123456");//密码 Connection connect = driver.connect(url, properties); System.out.println(connect); } //方式2 @Test public void connect02() throws ClassNotFoundException, IllegalAccessException, InstantiationException, SQLException { //使用反射获取Driver类,动态加载,更加的灵活,减少依赖性 Class<?> aClass = Class.forName("com.mysql.cj.jdbc.Driver"); Driver driver = (Driver) aClass.newInstance(); String url = "jdbc:mysql://localhost:3306/db_ly?serverTimezone=GMT"; //将用户名和密码放入到Properties对象 Properties properties = new Properties(); //说明 user 和 password 是规定好的,后面的值根据实际情况写 properties.setProperty("user", "root");//用户 properties.setProperty("password", "123456");//密码 Connection connect = driver.connect(url, properties); System.out.println(connect); } //方法3 使用DriverManager 替代driver 进行统一管理 @Test public void connect03() throws IllegalAccessException, InstantiationException, ClassNotFoundException, SQLException { Class<?> aClass = Class.forName("com.mysql.cj.jdbc.Driver"); Driver driver = (Driver) aClass.newInstance(); //创建url和user的password String url = "jdbc:mysql://localhost:3306/db_ly?serverTimezone=GMT"; String user = "root"; String password = "123456"; //注册driver驱动 DriverManager.registerDriver(driver); Connection connection = DriverManager.getConnection(url, user, password); System.out.println("第三种方式:" + connection); } //方式4:使用Class.forName() 自动完成注册驱动,简化代码 //这种方式获取连接是使用的最多的,推荐使用 @Test public void connect04() throws ClassNotFoundException, SQLException { //使用反射加载了Driver类 //在加载Driver类时,完成注册 /* 源码:1.静态代码块,在类加载时,会执行一次 2. DriverManager.registerDriver(new Driver()); 3.因此注册driver的工作已经完成 static { try { DriverManager.registerDriver(new Driver()); } catch (SQLException var1) { throw new RuntimeException("Can't register driver!"); } } */ Class.forName("com.mysql.cj.jdbc.Driver"); //创建url和user的password String url = "jdbc:mysql://localhost:3306/db_ly?serverTimezone=GMT"; String user = "root"; String password = "123456"; Connection connection = DriverManager.getConnection(url, user, password); System.out.println("第四种方式:" + connection); } //方式5:在方式4的基础上改进,增加配置文件,让连接mysql更加灵活 @Test public void connect05() throws IOException, ClassNotFoundException, SQLException { //通过Properties,获取相关配置文件的信息 Properties properties = new Properties(); properties.load(new FileInputStream("src\\mysql.properties")); //获取相关的值 String user = properties.getProperty("user"); String password = properties.getProperty("password"); String driver = properties.getProperty("driver"); String url = properties.getProperty("url"); Class.forName(driver); Connection connection = DriverManager.getConnection(url, user, password); System.out.println("第五种方式:" + connection); } }
输出结果
com.mysql.cj.jdbc.ConnectionImpl@1a38c59b com.mysql.cj.jdbc.ConnectionImpl@1a38c59b 第三种方式:com.mysql.cj.jdbc.ConnectionImpl@7f77e91b 第四种方式:com.mysql.cj.jdbc.ConnectionImpl@1a38c59b 第五种方式:com.mysql.cj.jdbc.ConnectionImpl@1a38c59b
四、ResultSet的详解
对应的代码如下
@SuppressWarnings({"all"}) public class ResultSet_ { public static void main(String[] args) throws Exception { //通过Properties配置相关信息 Properties properties = new Properties(); properties.load(new FileInputStream("src\\mysql.properties")); //获取相关的值 String url = properties.getProperty("url"); String user = properties.getProperty("user"); String password = properties.getProperty("password"); String driver = properties.getProperty("driver"); //1.注册驱动 Class.forName(driver); //建立与给定数据库的url连接 //2.建立连接 Connection connection = DriverManager.getConnection(url, user, password); //3.得到Statement Statement statement = connection.createStatement(); //4.组织sql String sql = "SELECT id,name,sex,borndate,phone FROM ACTOR"; //执行给定的SQL语句,该语句返回单个 ResultSet对象。 /* +----+--------+-----+---------------------+-----------+ | id | NAME | sex | borndate | phone | +----+--------+-----+---------------------+-----------+ | 1 | 刘德华 | 男 | 1970-01-01 00:00:00 | 110 | | 2 | 王宝强 | 男 | 1980-01-03 00:00:00 | 123456789 | +----+--------+-----+---------------------+-----------+ */ /* resultSet对象的结构,debug进行阅读 查询到的数据,底层使用byte[] 数组存的,比如id =1 存放的1对应的ASCII码49 */ ResultSet resultSet = statement.executeQuery(sql); //5.使用while取出数据 while (resultSet.next()) {//让光标向后移动,如果没有更多行,则返回false // int id = resultSet.getInt(1);//获取该行的第一列数据 int id = resultSet.getInt("id");//通过列名来获取值,推荐使用 String name = resultSet.getString(2);//获取该行第二列 String sex = resultSet.getString(3);//获取该行第三列 Date date = resultSet.getDate(4);//获取该行第四列 String phone = resultSet.getString(5);//获取该行第五列 System.out.println(id + "\t" + name + "\t" + sex + "\t" + date + "\t" + phone); } //6.关闭连接 resultSet.close(); statement.close(); connection.close(); } }
输出结果
1 刘德华 男 1970-01-01 110 2 王宝强 男 1980-01-03 123456789
resultSet对象的结构如下
Statement的介绍
使用Statement会存在SQL注入的风险,所以开发中一般使用PreparedStatement。
SQL注入演示:
CREATE TABLE ADMIN( NAME VARCHAR(32) NOT NULL UNIQUE, pwd VARCHAR(32) NOT NULL DEFAULT '' ); INSERT INTO ADMIN VALUES('jack','123456'); SELECT * FROM ADMIN WHERE NAME='jack' AND pwd = '12456'; -- name 输入 1'or -- pwd 输入or '1'='1 -- 条件'1'='1' 永远成立 能查到数据库中的数据,JAVA程序在拼接的时候就发生了SQL注入 SELECT * FROM ADMIN WHERE NAME='1'or' AND pwd = 'or '1'='1';
下面演示使用Statement会发生SQL注入的风险
public class Statement_ { public static void main(String[] args) throws Exception { Scanner scanner = new Scanner(System.in); //让用户输入管理员名和密码 System.out.println("请输入管理员的名字:");//next():当接收到空格或者 '就是表示结束 String admin_name = scanner.nextLine();//如果希望看到SQL注入效果,这里需要nextLine() 这个回车才表示结束 System.out.println("请输入管理员的密码:"); String admin_pwd = scanner.nextLine(); //通过Properties配置相关信息 Properties properties = new Properties(); properties.load(new FileInputStream("src\\mysql.properties")); //获取相关的值 String url = properties.getProperty("url"); String user = properties.getProperty("user"); String password = properties.getProperty("password"); String driver = properties.getProperty("driver"); //1.注册驱动 Class.forName(driver); //建立与给定数据库的url连接 //2.建立连接 Connection connection = DriverManager.getConnection(url, user, password); //3.得到Statement Statement statement = connection.createStatement(); //4.组织sql String sql = "SELECT NAME,pwd FROM ADMIN WHERE NAME='" + admin_name + "' AND pwd= '" + admin_pwd + "'"; ResultSet resultSet = statement.executeQuery(sql); if (resultSet.next()) {//如果查询到一条记录,则说明该管理存在 System.out.println("恭喜登录成功!"); } else { System.out.println("登录失败!"); } //关闭连接 resultSet.close(); statement.close(); connection.close(); } }
输出结果如下
请输入管理员的名字: 1'or 请输入管理员的密码: or '1'='1 恭喜登录成功!
五、PrepareStatement的介绍与使用
PrepareStatement的好处
1、下面是演示代码,解决了SQL注入的问题
public class PrepareStatement_ { public static void main(String[] args) throws Exception { Scanner scanner = new Scanner(System.in); //让用户输入管理员名和密码 System.out.println("请输入管理员的名字:");//next():当接收到空格或者 '就是表示结束 String admin_name = scanner.nextLine();//如果希望看到SQL注入效果,这里需要nextLine() 这个回车才表示结束 System.out.println("请输入管理员的密码:"); String admin_pwd = scanner.nextLine(); //通过Properties配置相关信息 Properties properties = new Properties(); properties.load(new FileInputStream("src\\mysql.properties")); //获取相关的值 String url = properties.getProperty("url"); String user = properties.getProperty("user"); String password = properties.getProperty("password"); String driver = properties.getProperty("driver"); //1.注册驱动 Class.forName(driver); //建立与给定数据库的url连接 //2.建立连接 Connection connection = DriverManager.getConnection(url, user, password); //3.组织sql语句,sql语句的? 就相当于占位符 String sql = "SELECT name,pwd FROM ADMIN WHERE name=? AND pwd=?"; //4.得到preparedStatement //preparedStatement对象是实现了PreparedStatement接口的实现类对象 PreparedStatement preparedStatement = connection.prepareStatement(sql); //给?赋值 preparedStatement.setString(1, admin_name); preparedStatement.setString(2, admin_pwd); //执行select语句,使用executeQuery() //如果执行的是dml(update,insert,delete) 使用executeUpdate() //这里执行executeQuery,不要写sql ResultSet resultSet = preparedStatement.executeQuery(); if (resultSet.next()) {//如果查询到一条记录,则说明该管理存在 System.out.println("登录成功!"); } else { System.out.println("登录失败!"); } //关闭连接 resultSet.close(); preparedStatement.close(); connection.close(); } }
输出结果
请输入管理员的名字: 1 'or 请输入管理员的密码: or '1'='1 登录失败!
2、使用PrepareStatement进行DML操作
public class PrepareStatement_DML { public static void main(String[] args) throws Exception { Scanner scanner = new Scanner(System.in); //让用户输入管理员名和密码 System.out.println("请输入要删除的管理员的名字:");//next():当接收到空格或者 '就是表示结束 String admin_name = scanner.nextLine();//如果希望看到SQL注入效果,这里需要nextLine() 这个回车才表示结束 // System.out.println("请输入管理员的密码:"); // String admin_pwd = scanner.nextLine(); //通过Properties配置相关信息 Properties properties = new Properties(); properties.load(new FileInputStream("src\\mysql.properties")); //获取相关的值 String url = properties.getProperty("url"); String user = properties.getProperty("user"); String password = properties.getProperty("password"); String driver = properties.getProperty("driver"); //1.注册驱动 Class.forName(driver); //建立与给定数据库的url连接 //2.建立连接 Connection connection = DriverManager.getConnection(url, user, password); //3.组织sql语句,sql语句的? 就相当于占位符 //添加记录 // String sql = "insert into admin values(?,?)"; //修改记录 // String sql = "update admin set name=? where pwd=?"; //删除记录 String sql = "delete from admin where name=?"; //4.得到preparedStatement //preparedStatement对象是实现了PreparedStatement接口的实现类对象 PreparedStatement preparedStatement = connection.prepareStatement(sql); //给?赋值 preparedStatement.setString(1, admin_name); // preparedStatement.setString(2, admin_pwd); //如果执行的是dml(update,insert,delete) 使用executeUpdate() int rows = preparedStatement.executeUpdate(); System.out.println(rows > 0 ? "执行成功" : "执行失败"); //关闭连接 preparedStatement.close(); connection.close(); } }
输出结果
请输入要删除的管理员的名字: smith 执行成功