目录
JDBC的概念:
JDBC的本质----一套接口
JDBC编程六步
1、注册驱动(作用:告诉Java程序,即将要连接的是哪个品牌的数据库)
2、获取连接(表示JVM的进程和数据库进程之间的通道打开了,这属于进程之间的通讯, 重量级的,使用完之后一定要关闭)
3、获取数据库操作对象(专门执行sql语句的对象)
4、执行SQL语句(DQL , DML ......)
5、处理查询结果集(只有当第四步执行的是select语句的时候,才有这第五步处理查询结果 集。)
6、释放资源(使用完资源以后一定要关闭资源。Java和数据库属于进程间的通讯,开启以 后一定要关闭。)
代码实现:
import java.sql.*; public class JDBCTested { public static void main(String[] args) throws SQLException { Connection connection = null; Statement stmt = null; try { //1、注册驱动 Driver driver = new com.mysql.cj.jdbc.Driver();//多态,父类型引用指向子类型对象 DriverManager.registerDriver(driver); //2、获取链接 /* url:统一资源定位符(网络中某个资源的绝对路径) http://182.61.200.7:80/index.html URL包括下面几个部分 协议 --- http:// (通信协议) IP --- 182.61.200.7 (服务器IP) PORT --- 80 (服务器上软件的端口) 资源名 --- index.html (是服务器上某个资源名) */ //什么是通讯协议,有什么用?(去网上查) //通讯协议是通讯之前就提前定好的数据传输格式。 //数据包具体怎么传数据,格式提前定好的。 String url = "jdbc:mysql://localhost:3306/ysb"; String user = "root"; String password = "021028qwe"; connection = DriverManager.getConnection(url,user,password); //数据库连接对象com.mysql.cj.jdbc.ConnectionImpl@35a50a4c System.out.println("数据库连接对象" + connection); //3、获取数据库操作对象(Statement专门执行sql语句的) stmt = connection.createStatement(); System.out.println(stmt.getConnection()); //4、执行SQL String S = "insert into ddd (deptno,dname,loc) values (50,'\u4EBA\u4E8B\u90E8','\u5317\u4EAC')"; //专门执行DML语句的(insert delete update) //返回值是“影响数据库中的记录条数” int count = stmt.executeUpdate(S); System.out.println(count == 1 ? "保存成功" : "保存失败"); //5、处理查询结果集 } catch (SQLException e){ e.printStackTrace(); } finally { //6、释放数据 //为了保证资源一定释放,在finally语句块中关闭资源 //并且要遵循从小到大依次关闭 //分别对其try..catch try { if (stmt != null) { stmt.close(); } }catch (SQLException e) { e.printStackTrace(); } try { if (connection != null) { connection.close(); } }catch (SQLException e) { e.printStackTrace(); } } } }
数据库实现登录操作:
* 实现的功能:
* 1、要求:
* 模拟用户登录功能得实现。
* 2、业务描述:
* 程序运行得时候,提供一个输入的入口,可以让用户输入用户名和密码
* 用户输入用户名和密码以后,提交信息,Java程序收集到用户信息
* Java程序连接数据库验证用户名和密码是否合法
* 合法:显示登录成功
* 不合法:显示登录失败
* 3、数据得准备:
* 建表
* 4、当前程序存在的问题
* 用户名:fdsa
* 密码:fdsa' or '1'='1
* 登陆成功
* 这种现象被称为SQL注入(安全隐患)。
* 5、导致SQL注入的根本原因是
* 用户输入的信息中含有sql语句的关键字,并且这些关键字参与sql语句的编译过程,
* 导致sql语句的原意被扭曲,进而到达sql注入。/* * 实现的功能: * 1、要求: * 模拟用户登录功能得实现。 * 2、业务描述: * 程序运行得时候,提供一个输入的入口,可以让用户输入用户名和密码 * 用户输入用户名和密码以后,提交信息,Java程序收集到用户信息 * Java程序连接数据库验证用户名和密码是否合法 * 合法:显示登录成功 * 不合法:显示登录失败 * 3、数据得准备: * 建表 * 4、当前程序存在的问题 * 用户名:fdsa * 密码:fdsa' or '1'='1 * 登陆成功 * 这种现象被称为SQL注入(安全隐患)。 * 5、导致SQL注入的根本原因是 * 用户输入的信息中含有sql语句的关键字,并且这些关键字参与sql语句的编译过程, * 导致sql语句的原意被扭曲,进而到达sql注入。 * */ import javax.net.ssl.SSLException; import java.sql.*; import java.util.HashMap; import java.util.Map; import java.util.Scanner; public class JDBCTest{ public static void main(String[] args) { // 初始化一个界面 Map<String,String> userLoginInfo = initUI(); // 验证用户名和密码 boolean loginSuccess = login(userLoginInfo); if (loginSuccess == true){ System.out.println("登陆成功"); } else { System.out.println("登录失败"); } } /* * 用户登录 * @param userLoginInfo 用户登录信息 * @return false表示失败 , true表示成功 * */ private static boolean login(Map<String, String> userLoginInfo) { //达标记的意识 boolean loginSuccess = false; // JDBC代码 Connection conn = null; Statement stmt = null; ResultSet rs = null; try { //1、注册驱动 Class.forName("com.mysql.cj.jdbc.Driver"); //2、获取连接 conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/ysb","root","021028qwe"); //3、获取数据库操作对象 stmt = conn.createStatement(); //4、执行sql String sql = "select * from ulogin where loginName = '"+userLoginInfo.get("loginName")+"' and loginPwd = '"+userLoginInfo.get("loginPwd")+"'"; rs = stmt.executeQuery(sql); //5、处理结果集 if (rs.next()) { //登录成功 loginSuccess = true; } } catch (Exception e) { e.printStackTrace(); } finally { //6、释放资源 if (rs != null) { try { rs.close(); } catch (SQLException e) { e.printStackTrace(); } } if (stmt != null) { try { stmt.close(); } catch (SQLException e) { e.printStackTrace(); } } if (conn != null) { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } return loginSuccess; } /* * 初始化用户界面 * @return 用户输入的用户名和密码等登录信息 * */ private static Map<String, String> initUI() { Scanner s = new Scanner(System.in); System.out.print("用户名:"); String loginName = s.nextLine(); System.out.print("密码:"); String loginPwd = s.nextLine(); Map<String,String> userLoginInfo = new HashMap<>(); userLoginInfo.put("loginName",loginName); userLoginInfo.put("loginPwd",loginPwd); return userLoginInfo; } }
解决SQL注入:
import javax.net.ssl.SSLException; import java.sql.*; import java.util.HashMap; import java.util.Map; import java.util.Scanner; public class JDBCTest{ public static void main(String[] args) { // 初始化一个界面 Map<String,String> userLoginInfo = initUI(); // 验证用户名和密码 boolean loginSuccess = login(userLoginInfo); if (loginSuccess == true){ System.out.println("登陆成功"); } else { System.out.println("登录失败"); } } /* * 用户登录 * @param userLoginInfo 用户登录信息 * @return false表示失败 , true表示成功 * */ private static boolean login(Map<String, String> userLoginInfo) { //达标记的意识 boolean loginSuccess = false; // 单独定义变量 String loginName = userLoginInfo.get("loginName"); String loginPwd = userLoginInfo.get("loginPwd"); // JDBC代码 Connection conn = null; PreparedStatement ps = null;//这里使用PreparedStatement(预编译的数据库操作对象) ResultSet rs = null; try { //1、注册驱动 Class.forName("com.mysql.cj.jdbc.Driver"); //2、获取连接 conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/ysb","root","021028qwe"); //3、获取预编译的数据库操作对象 // SQL语句的框子。其中一个?,表示一个占位符,一个?将来接受一个“值”,注意:占位符不能使用单引号括起来。 String sql = "select * from ulogin where loginName = ? and loginPwd = ?"; ps = conn.prepareStatement(sql); // 程序执行到此处,会发送sql语句框子给DBMS,然后DBMS进行sql语句的预先编译。 // 给占位符?传值(第1个问号下表是1,第2个问号下表是2,JDBC中所有的下表从1开始。) ps.setString(1,loginName); ps.setString(2,loginPwd); //4、执行sql rs = ps.executeQuery(); //5、处理结果集 if (rs.next()) { //登录成功 loginSuccess = true; } } catch (Exception e) { e.printStackTrace(); } finally { //6、释放资源 if (rs != null) { try { rs.close(); } catch (SQLException e) { e.printStackTrace(); } } if (ps != null) { try { ps.close(); } catch (SQLException e) { e.printStackTrace(); } } if (conn != null) { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } return loginSuccess; } /* * 初始化用户界面 * @return 用户输入的用户名和密码等登录信息 * */ private static Map<String, String> initUI() { Scanner s = new Scanner(System.in); System.out.print("用户名:"); String loginName = s.nextLine(); System.out.print("密码:"); String loginPwd = s.nextLine(); Map<String,String> userLoginInfo = new HashMap<>(); userLoginInfo.put("loginName",loginName); userLoginInfo.put("loginPwd",loginPwd); return userLoginInfo; } }
比较 Statement 和 PreparedStatement:
- Statement存在sql注入问题,PreparedStatement 解决了SQL注入问题
- Statement是编译一次执行一次。PreparedStatement是编译一次,可执行N次。 PreparedStatement效率较高一些。
- PreparedStatement会在编译阶段做类型的安全检查。
综上所述:PreparedStatement使用较多。只有极少数的情况下需要使用Statement
sql语句中升序降序的改变必须要用Statement。
用的时候再学:
JDBC工具类的封装:
连接池: