其他分享
首页 > 其他分享> > JDBC小结

JDBC小结

作者:互联网

JDBC简介

  1. 注册驱动(告诉Java程序,即将连接的是哪个品牌的数据库)
  2. 获取连接(表示JVM的进程和数据库进程之间的通道打开了,这属于进程之间的通信,使用完后记得关闭通道)
  3. 获取数据库操作对象(专门执行sql语句的对象)
  4. 执行SQL语句(DQL,DML…)
  5. 处理查询结果集 (只有当第四步执行的是select语句的时候,才有本步)
  6. 释放资源(使用完资源后一定要关闭资源,Java和数据库之间属于进程间的通信,开启之后一定要记得关闭)

 

 

 

 

 

IDEA编写JDBC连接MySQL

mysql-connector-java的不同版本对比

MySQL Connector / J 5.1 5.1版本支持java5及其以上的版本,支持5.6、5.7、8.0版本的mysql数据库,支持3.0、4.0、4.1、4.2版本的jdbc。在5.1中,Driver的实现类的全路径名是com.mysql.jdbc.Driver。

MySQL Connector / J 8.0 8.0版本支持java8及其以上的版本,支持5.6、5.7、8.0版本的mysql数据库,支持4.2版本的jdbc。在8.0中,Driver的实现类的全路径名是com.mysql.cj.jdbc.Driver。

下图是官网上mysql-connector-java的版本对应的mysql版本和jdk的版本。

 

下载驱动jar包 mysql-connector-java

要使用mysql连接器,就要先下载它。如果是一般的项目,那我们需要下载jar包,然后放到项目的lib目录下。如果使用maven构建的项目,我们可以通过maven直接安装。不同的下载方式有不同的操作,常见的有直接官网下载和maven下载(下周讲解maven)。 下载jar包最直接的方式是从官网下载,官网地址是:https://dev.mysql.com/downloads/connector/j/。直接点链接进入mysql官网,选择所需的版本和操作系统(要下载jar包就要选:Platform Independent),然后点击download按钮就可以下载了。为java提供的连接器是Connector / J,也就是mysql-connector-java,它分为5.1版本和8.0版本。Connector / J实现了JDBC,为使用java开发的程序提供连接,方便java程序操作数据库。

 

 

2、从maven安装 使用maven安装mysql-connector-java就简单很多,直接打开maven的中央仓库地址,输入mysql-connector-java就可以找到不同版本的依赖。地址:https://mvnrepository.com/artifact/mysql/mysql-connector-java

 

 

6.3 IDEA导入jar包

先检查jar包位置:在目录里新建一个文件夹 libs,把jar包复制进去

 

然后右键选择新建文件夹libs转成library

 

然后就可以写代码啦!

根据六步编写代码:先不写处理代码

 

6.4 JDBC连接mysql 程序编写

6.5.1 第一种注册驱动方式
package com.shujia.jdbc;

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

import com.mysql.jdbc.Driver;

/*
       1.注册驱动(告诉Java程序,即将连接的是哪个品牌的数据库)
       2.获取连接(表示JVM的进程和数据库进程之间的通道打开了,这属于进程之间的通信,使用完后记得关闭通道)。
       3.获取数据库操作对象(专门执行sql语句的对象)
       4.执行SQL语句(DQL,DML…)
       5.处理查询结果集 (只有当第四步执行的是select语句的时候,才有本步)
       6.释放资源(使用完资源后一定要关闭资源,Java和数据库之间属于进程间的通信,开启之后一定要记得关闭)


       工具类:DriverManager
          没有构造方法(构造方法私有化),方法是静态的。
*/
public class JDBCTest1 {
   private static Statement stat;
   private static Connection conn;


   public static void main(String[] args) {
       //1.注册驱动(告诉Java程序,即将连接的是哪个品牌的数据库)
       //第一种注册驱动的方式
       //jdk自己提供了一个工具类DriverManager给我们使用,其中有一个静态的方法registerDriver()可以实现注册驱动功能
       //static void registerDriver(Driver driver)
       //注册与给定的驱动程序 DriverManager 。
       //而jdkapi文档中发现,Driver是一个接口,而接口是不能直接实例化的
       //这里要想传入一个Driver的对象,就必须找到一个对应的实现类
       //我们现在是要使用mysql的驱动,所以就猜测mysql的驱动包中应该有一个类实现了jdk提供的Driver接口
       try {
           DriverManager.registerDriver(new Driver());
           //2.获取连接(表示JVM的进程和数据库进程之间的通道打开了,这属于进程之间的通信,使用完后记得关闭通道)。
           //jdk自身提供的工具类DriverManager中有一个静态方法,可以让我们调用并且获取与数据库的连接
           //static Connection getConnection(String url, String user, String password)
           //尝试建立与给定数据库URL的连接。
           /**
            *     url: 统一资源定位系统
            *         http/https: 通过网络请求去访问网络上的资源
            *         jdbc:mysql: 是驱动提供的请求头
            *         请求的地址: 指定mysql的服务器地址:192.168.254.150
            *         端口号: 3306
            *         useUnicode=true&characterCharset=utf8
            *
            *     jdbc:mysql://192.168.254.150:3306?useUnicode=true&characterCharset=utf8
            *
            *     user: 用户名 root
            *     password: 密码 123456
            */
           //在mysql5.7+版本不建议使用连接直接访问服务器
           String url = "jdbc:mysql://192.168.254.150:3306/bigdata19?useUnicode=true&characterEncoding=utf8&useSSL=false";
           String user = "root";
           String password = "123456";
           conn = DriverManager.getConnection(url, user, password);
           System.out.println("与mysql建立连接成功:"+conn); //com.mysql.jdbc.JDBC4Connection@7d9d1a19

           //3.获取数据库操作对象(专门执行sql语句的对象)
           stat = conn.createStatement();

           //4.执行SQL语句(DQL,DML…)
           //DQL
           //ResultSet executeQuery(String sql)
           //执行给定的SQL语句,该语句返回单个 ResultSet对象。

           //DML
           //int executeUpdate(String sql)
           //执行给定的SQL语句,这可能是 INSERT , UPDATE ,或 DELETE语句,或者不返回任何内容,如SQL DDL语句的SQL语句。
           // 方法的返回值指的是受影响的行数: Affected rows: 1
           int count = stat.executeUpdate("insert into dept(deptno,dname,loc) values(70,'教学部','安徽合肥')");
           if(count==1){
               System.out.println("数据保存成功!!");
          }else {
               System.out.println("数据保存失败!!");
          }
      } catch (SQLException e) {
           e.printStackTrace();
      }finally {
           //释放资源的代码
           if(stat!=null){
               try {
                   stat.close();
              } catch (SQLException e) {
                   e.printStackTrace();
              }
          }

           if(conn!=null){
               try {
                   conn.close();
              } catch (SQLException e) {
                   e.printStackTrace();
              }
          }
      }

  }
}

 

6.5.2 第二种注册驱动方式
package com.shujia.jdbc;

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

/*
       注册驱动的第二种方式:
           正常情况下,我们今后遇到的数据库肯定不止mysql一种,但是呢,使用java连接数据库的方式却大同小异,无非是内部的实现不一样
           如果按照上午所说的那样注册驱动的话,上午的程序案例只能连接mysql的驱动,将来如果想换成sqlserver的话还不太好换
           想一想,我们之前在安装jdk的过程在配置环境变量的时候,有一步我们可以借鉴它的思想
           所以,我们在这里注册驱动的时候,能不能传入字符串呢?

      注册驱动底层实际上就是用驱动包中对应的类,而驱动包中的类都是class后缀的编译好的文件
      要想直接使用编译好的类,使用反射来实现。
      想一想,反射是如何获取一个类的class文件对象呢?3种方式
      1、getClass
      2、.class
      3、Class.forName()
*/
public class JDBCTest2 {
   public static void main(String[] args) {
       Connection conn = null;
       Statement stat = null;

       try {
           //1、加载驱动
           //第二种方式来实现
           Class.forName("com.mysql.jdbc.Driver");

           //2、创建与数据库的连接对象
           String url = "jdbc:mysql://192.168.254.150:3306/bigdata19?useUnicode=true&characterEncoding=utf8&useSSL=False";
           String username = "root";
           String password = "123456";
           conn = DriverManager.getConnection(url, username, password);

           //3、获取与操作数据库的对象
           stat = conn.createStatement();

           //4、编写sql语句并执行
           //增
//           String sql = "insert into students(sno,sname,sgender,sage,sclass) values('110','小虎','男',18,'19独立营')";
//           int count = stat.executeUpdate(sql);
//           System.out.println(count==1?"数据保存成功!!":"数据保存失败!!");

           //改
//           String sql3 = "update students set sname='李凯迪' where sno='110'";
//           int count3 = stat.executeUpdate(sql3);
//           System.out.println(count3==1?"数据更新成功!!":"数据更新失败!!");
//
           //删
           String sql2 = "delete from students where sno='110'";
           int count2 = stat.executeUpdate(sql2);
           System.out.println(count2==1?"数据删除成功!!":"数据删除失败!!");


      } catch (Exception e) {
           e.printStackTrace();
      }finally {
           //释放资源
           if(stat!=null){
               try {
                   stat.close();
              } catch (SQLException e) {
                   e.printStackTrace();
              }
          }

           if (conn!=null){
               try {
                   conn.close();
              } catch (SQLException e) {
                   e.printStackTrace();
              }
          }
      }
  }
}

 

6.5.3 将连接数据库的所有信息配置到配置文件中
package com.shujia.jdbc;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.InputStreamReader;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;
import java.util.Properties;

/*
       使用配置文件将连接数据库的相关参数进行保存,然后在代码中使用
       使用jdk自身提供的Properties类来加载配置文件

       IO流:
           字节流
               字节输入流
               字节输出流
           字符流 = 字符转换流 = 字节流+编码表
               字符输入流
               字符输出流

      相对路径:将项目作为根目录
      绝对路径/完整路径:带盘符的路径
*/
public class JDBCTest3 {
   public static void main(String[] args) throws Exception {
       //使用无参构造方法创建Properties类的对象
       Properties prop = new Properties();

       //使用字符流读取配置文件
//       InputStreamReader , FileReader, BufferedReader
       BufferedReader br = new BufferedReader(new FileReader("E:\\projects\\IdeaProjects\\bigdata19-mysql\\resource\\jdbc.properties"));
       prop.load(br);

       String driver = prop.getProperty("driver");
       String url = prop.getProperty("url");
       String username = prop.getProperty("username");
       String password = prop.getProperty("password");

       //加载驱动
       Class.forName(driver);
       //获取连接对象
       Connection conn = DriverManager.getConnection(url, username, password);

       //获取数据库操作对象
       Statement stat = conn.createStatement();

       //执行sql语句
       int count = stat.executeUpdate("insert into dept(deptno,dname,loc) values(80,'管理层','安徽合肥')");

       System.out.println(count==1?"数据插入成功!!":"数据插入失败!!");

       //释放资源
       stat.close();
       conn.close();
  }
}

 

6.5.4 处理查询结果集
package com.shujia.jdbc;

import com.shujia.utils.MySqlTool;

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

/*
   使用jdbc查询数据库中的数据
*/
public class JDBCTest5 {
   public static void main(String[] args) throws Exception {
       //获取与数据库的连接对象
       //使用工具类的方式进行获取
       Connection conn = MySqlTool.init();

       //获取数据库操作对象
       Statement stat = conn.createStatement();

       //需求:查询dept表中的所有数据
       //查询sql语句中,把要查询的列进行罗列出来
       ResultSet resultSet = stat.executeQuery("select deptno as a1,dname,loc from dept");
       //boolean next()
       //将光标从当前位置向前移动一行。
       //这里的光标可以理解为集合中的光标
//       boolean b = resultSet.next();
//       //如果光标移动的位置有值,这里的返回值是true
//       if(b){
//           //获取一行中每一列的数值,第一种方式
//           //String getString(int columnIndex)
//           //这个检索的当前行中指定列的值 ResultSet对象为 String的Java编程语言。
//           //columnIndex从1开始,1表示一行中的第一列,以此类推
//           String deptno = resultSet.getString(1);
//           String dname = resultSet.getString(2);
//           String loc = resultSet.getString(3);
//           System.out.println("部门编号:"+deptno+",部门名称:"+dname+",地址:"+loc);
//       }

       //正常情况下,一张结果表的行数我们不确定,但是我们知道,当next的结果是false的时候,表示读取到末尾
       //使用while循环
       while (resultSet.next()) {
//           //获取一行中每一列的数值,第一种方式
//           //String getString(int columnIndex)
//           //这个检索的当前行中指定列的值 ResultSet对象为 String的Java编程语言。
//           //columnIndex从1开始,1表示一行中的第一列,以此类推
//           String deptno = resultSet.getString(1);
//           String dname = resultSet.getString(2);
//           String loc = resultSet.getString(3);
//           System.out.println("部门编号:" + deptno + ",部门名称:" + dname + ",地址:" + loc);

           //第二种方式:根据列名获取对应的列值
           //String getString(String columnLabel)
           //这个检索的当前行中指定列的值 ResultSet对象为 String的Java编程语言。
           //注意事项:当查询sql语句中存在起别名的情况时,通过列名获取列值的时候,使用名字是别名
           String deptno = resultSet.getString("a1");
           String dname = resultSet.getString("dname");
           String loc = resultSet.getString("loc");
           System.out.println("部门编号:" + deptno + ",部门名称:" + dname + ",地址:" + loc);
      }
       System.out.println("==================================================================");

       //注意事项2:同一个结果resultSet对象,只能遍历一次
//       while (resultSet.next()) {
////           //获取一行中每一列的数值,第一种方式
////           //String getString(int columnIndex)
////           //这个检索的当前行中指定列的值 ResultSet对象为 String的Java编程语言。
////           //columnIndex从1开始,1表示一行中的第一列,以此类推
////           String deptno = resultSet.getString(1);
////           String dname = resultSet.getString(2);
////           String loc = resultSet.getString(3);
////           System.out.println("部门编号:" + deptno + ",部门名称:" + dname + ",地址:" + loc);
//
//           //第二种方式:根据列名获取对应的列值
//           //String getString(String columnLabel)
//           //这个检索的当前行中指定列的值 ResultSet对象为 String的Java编程语言。
//           //注意事项:当查询sql语句中存在起别名的情况时,通过列名获取列值的时候,使用名字是别名
//           String deptno = resultSet.getString("a1");
//           String dname = resultSet.getString("dname");
//           String loc = resultSet.getString("loc");
//           System.out.println("部门编号:" + deptno + ",部门名称:" + dname + ",地址:" + loc);
//       }
       
       


       //释放资源
       stat.close();
       conn.close();


  }
}

登录注册案例
package com.shujia.jdbc;

/*
       使用JDBC模拟登录注册案例
       1、注册账号:往数据库插入一条数据
       2、登录账号:查询数据库

       实现步骤:
           1、建表
*/
import com.shujia.utils.MySqlTool;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Scanner;
import java.util.UUID;

public class JDBCTest6 {
   public static void main(String[] args) throws Exception {
       System.out.println("欢迎进入小虎婚介所");
       //创建键盘录入对象
       Scanner sc = new Scanner(System.in);
       System.out.println("请输入用户名:");
       String username = sc.next();
       System.out.println("请输入密码:");
       String password = sc.next();

       //使用工具类获取与数据库的连接对象
       Connection conn = MySqlTool.init();
       //获取数据库操作对象
       Statement stat = conn.createStatement();

       //编写sql语句
       String sql = "select username,password from user where username='"+username+"' and password='"+password+"'";
       //           select username,password from user where username='root' and password='123456'
       //执行sql语句
       ResultSet rs = stat.executeQuery(sql);
       boolean b = rs.next();
       if(b){
           //如果b为true表示,数据库中存在该用户,登录成功
           System.out.println("登录成功!!欢迎进入小虎婚介所!!");
      }else {
           //如果b为false,表示该用户还没有注册,需要先进行注册
           System.out.println("您还未注册,请先注册(Y/N)");
           String choice = sc.next();
           if("Y".equals(choice)){
               while (true){
                   System.out.println("请输入您的用户名:");
                   String new_username = sc.next();
                   System.out.println("请输入您设置的密码:");
                   String new_password = sc.next();
                   System.out.println("请确认密码:");
                   String password_again = sc.next();
                   if(password_again.equals(new_password)){
                       UUID uuid = UUID.randomUUID();
                       String new_uuid = uuid+"-"+System.currentTimeMillis();
                       String sql2 = "insert into user(uid,username,password) values('"+new_uuid+"','"+new_username+"','"+new_password+"')";
                       int count = stat.executeUpdate(sql2);
                       if(count==1){
                           System.out.println("用户注册成功!!!");
                      }else {
                           System.out.println("用户注册失败!!!");
                      }
                       break;
                  }else {
                       System.out.println("两次密码不一致!!请重新输入");
                  }
              }
          }
      }

       //释放资源
       stat.close();
       conn.close();


  }
}

 

6.5.6 解决sql注入问题
package com.shujia.jdbc;

/*
       使用JDBC模拟登录注册案例
       1、注册账号:往数据库插入一条数据
       2、登录账号:查询数据库

       实现步骤:
           1、建表

           1234' or '1'='1

       我们写完程序后发现,当我们将密码输入成1234' or '1'='1这个样子的时候,发现登录成功
       原因:sql在编译的时候,会将我们输入的内容存在关键字or,会把or当作sql语法关键字进行执行
       如何解决呢?
           这样的问题,称之为sql注入的问题
           解决的思路就是在sql编译完后再传入数据

      获取数据库操作对象另外一种方式,预编译的方式

*/
import com.shujia.utils.MySqlTool;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Scanner;
import java.util.UUID;

public class JDBCTest6 {
   public static void main(String[] args) throws Exception {
       System.out.println("欢迎进入小虎婚介所");
       //创建键盘录入对象
       Scanner sc = new Scanner(System.in);
       System.out.println("请输入用户名:");
       String username = sc.nextLine();
       System.out.println("请输入密码:");
       String password = sc.nextLine();

       //使用工具类获取与数据库的连接对象
       Connection conn = MySqlTool.init();
       //获取数据库操作对象
//       Statement stat = conn.createStatement();



       //编写sql语句
//       String sql = "select username,password from user where username='"+username+"' and password='"+password+"'";
       //           select username,password from user where username='root' and password='123456'
       //           select username,password from user where username='xiaohu' and password='1234' or '1'='1'

//       System.out.println(sql);


       //这里的问号相当于一个占位符,为了后面传值
       String sql = "select username,password from user where username=? and password=?";
       //创建预编译数据库操作对象
       PreparedStatement pps = conn.prepareStatement(sql);
       //将sql中的占位符附上值
       //第一个参数表示给第几个问号传值,第二个参数表示具体的值,序号从1开始
       pps.setString(1,username);
       pps.setString(2,password);


       //执行sql语句
//       ResultSet rs = stat.executeQuery(sql);
       ResultSet rs = pps.executeQuery();

       boolean b = rs.next();
       if(b){
           //如果b为true表示,数据库中存在该用户,登录成功
           System.out.println("登录成功!!欢迎进入小虎婚介所!!");
      }else {
           //如果b为false,表示该用户还没有注册,需要先进行注册
           System.out.println("您还未注册,请先注册(Y/N)");
           String choice = sc.next();
           if("Y".equals(choice)){
               while (true){
                   System.out.println("请输入您的用户名:");
                   String new_username = sc.next();
                   System.out.println("请输入您设置的密码:");
                   String new_password = sc.next();
                   System.out.println("请确认密码:");
                   String password_again = sc.next();
                   if(password_again.equals(new_password)){
                       UUID uuid = UUID.randomUUID();
                       String new_uuid = uuid+"-"+System.currentTimeMillis();
                       String sql2 = "insert into user(uid,username,password) values('"+new_uuid+"','"+new_username+"','"+new_password+"')";
//                       int count = stat.executeUpdate(sql2);
                       int count = pps.executeUpdate(sql2);
                       if(count==1){
                           System.out.println("用户注册成功!!!");
                      }else {
                           System.out.println("用户注册失败!!!");
                      }
                       break;
                  }else {
                       System.out.println("两次密码不一致!!请重新输入");
                  }
              }
          }
      }

       //释放资源
//       stat.close();
       pps.close();
       conn.close();


  }
}

 

JDBC事物机制: 1.JDBC中的事务自动提交的,什么是自动提交? 只要执行任意一条 DML语句,则自动提交一次。这是JDBC默认的事务行为。 但是在实际的业务中,通常都是N条DML语句共同联合才能完成,必须 保证这些DML语句在同一个事务中同时成功或者同时失败 解决方案:三行重要的代码 conn.setAutoCommit(false);//手动提交事务 conn.commit();//提交事务 conn.rooback;当发生异常时或者程序错误时,进行回滚。

6.5.7 工具类封装
package com.shujia.utils;


import java.io.BufferedReader;
import java.io.FileReader;
import java.sql.Connection;
import java.sql.DriverManager;
import java.util.Properties;

/*
   工具类:
       1、不能让外界实例化(构造方法私有化)
       2、方法必须是静态
*/
public class MySqlTool {
   private static Connection conn;

   private MySqlTool(){}

   public static Connection init(){
       try {
           //使用无参构造方法创建Properties类的对象
           Properties prop = new Properties();

           //使用字符流读取配置文件
//       InputStreamReader , FileReader, BufferedReader
           BufferedReader br = new BufferedReader(new FileReader("E:\\projects\\IdeaProjects\\bigdata19-mysql\\resource\\jdbc.properties"));
           prop.load(br);

           String driver = prop.getProperty("driver");
           String url = prop.getProperty("url");
           String username = prop.getProperty("username");
           String password = prop.getProperty("password");

           //加载驱动
           Class.forName(driver);
           //获取连接对象
           conn = DriverManager.getConnection(url, username, password);
      }catch (Exception e){
           e.printStackTrace();
      }

       return conn;
  }

}

工具类使用

package com.shujia.jdbc;

import com.shujia.utils.MySqlTool;
import java.sql.Connection;
import java.sql.Statement;

public class JDBCTest4 {
   public static void main(String[] args) throws Exception {
       //使用工具类获取连接对象
       Connection conn = MySqlTool.init();

       //获取数据库操作对象
       Statement stat = conn.createStatement();

       //执行sql语句
       int count = stat.executeUpdate("insert into dept(deptno,dname,loc) values(90,'行政部','数加科技')");

       System.out.println(count==1?"数据插入成功!!":"数据插入失败!!");

       //释放资源
       stat.close();
       conn.close();
  }
}

 

6.5.8 JDBC实现模糊查询
package com.shujia.jdbc;

import com.shujia.utils.MySqlTool;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

/*
        进行模糊查询
 */
public class JDBCTest {
    public static void main(String[] args) throws Exception {
        Connection conn = MySqlTool.init();
        PreparedStatement prep = conn.prepareStatement("select uid,username,password from user where username like ?");
        prep.setString(1, "%xiaohu%");
        ResultSet rs = prep.executeQuery();
        while (rs.next()) {
            String uid = rs.getString("uid");
            String username = rs.getString("username");
            String password = rs.getString("password");
            System.out.println("姓名:" + username + ",密码:" + password);

        }
        prep.close();
        conn.close();
    }
}

 

6.5 悲观锁和乐观锁的概念

事务1–>读取到版本号1.1 事务2—>读取到版本号1.1

其中事务1先修改了,修改之后看了版本号是1.1 ,于是提交修改的数据,将版本号修改为1.2 其中事务2后修改的,修改之后准备提交的时候,发现版本号是1.2 ,和它最初读的版本号不一致。回滚。

悲观锁:事务必须排队执行。数据锁住了,不允许并发。 (行级锁: select后面添加for update ) 乐观锁:支持并发,事务也不需要排队,只不过需要一个版本号。

 

6.6 演示索引的效率(springboot,redis,mysql)

 

 

 

 

 

 

标签:JDBC,java,String,System,sql,import,password,小结
来源: https://www.cnblogs.com/slm-1314521/p/16573714.html