JDBC学习笔记

1.JDBC是什么?

Java DataBase Connectivity(Java语言连接数据库)

2.JDBC的本质是什么?

JDBC是SUN公司制定的一套接口(interface)。

接口都有调用者和实现者。

面向接口调用、面向接口写实现类,这都属于面向接口编程。

3.为什么要面向接口编程?

解耦合:降低程序的耦合度,提高程序的扩展力。

多态机制就是非常典型的:面向抽象编程。(不要面向具体编程)

4.为什么SUN制定一套JDBC接口呢?

因为每一个数据库产品都有自己独特的实现原理

5.JDBC编程六步(需要背会)

1.注册驱动(告诉Java程序,即将连接的是哪个品牌的数据库)

2.获取连接(表示JVM的进程和数据库进程之间的通道打开了,这属于进程之间的通信,使用完后记得关闭通道)。

3.获取数据库操作对象(专门执行sql语句的对象)

4.执行SQL语句(DQL,DML…)

5.处理查询结果集 (只有当第四步执行的是select语句的时候,才有本步)

6.释放资源(使用完资源后一定要关闭资源,Java和数据库之间属于进程间的通信,开启之后一定要记得关闭)

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;/*JDBC编程六步*/
public class JDBCTest1 {public static void main(String[] args) throws SQLException {Statement stmt=null;Connection conn=null;try {//1.注册驱动DriverManager.registerDriver(new com.mysql.cj.jdbc.Driver());//2.获取连接/*url:统一资源定位符(网络中某个资源的绝对路径)URL包含哪几部分:协议、IP、PORT、资源名http://是通信协议   什么是协议?有什么用?通信协议是通信之前就提前定好的数据传送格式,数据包具体怎么传数据,提前定好了格式182.61.200.7是服务器IP地址80 是服务器上软件的端口index.html是服务器上某个资源名*/String url = "jdbc:mysql://localhost:3306/MySql?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT";String user ="root";String password="111111";conn=DriverManager.getConnection(url,user,password);System.out.println("数据库连接的对象 =" +conn);//3.获取数据库操作对象(statement专门执行sql语句的)stmt= conn.createStatement();//4.执行sqlString sql="insert into dept(deptno,dname,loc) values(50,'人事部','北京')";//专门执行DML语句(insert、delete、update)//返回值是‘影响数据库中的记录条数’int count=stmt.executeUpdate(sql);System.out.println(count==1?"保存成功":"保存失败");//insert保存一条语句// 5.处理查询结果集}catch (SQLException e){e.printStackTrace();}finally {//6.释放资源(为了保证资源一定释放,在finally语句块中关闭资源)//并且要遵循从小到大依次关闭//分别对其try...catchtry {if (stmt!=null){stmt.close();}}catch (SQLException e) {e.printStackTrace();}try {if (conn!=null){conn.close();}}catch (SQLException e){e.printStackTrace();}}}}

另外一种注册驱动的方式(利用反射机制,Driver中有一个自带静态方法)

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;public class JDBCTest3 {//注册驱动的另一种方式(常用)public static void main(String[] args) {try {//1.注册成功//这是注册驱动的第一种写法//DriverManager.registerDriver(new com.mysql.cj.jdbc.Driver());\//注册驱动的第二种写法(常用)//为什么这种写法常用?因为参数是一个字符串,字符串可以写到xxx.properties文件中。//以下方法不需要接收返回值,因为我们只想用它的类加载动作Class.forName("com.mysql.cj.jdbc.Driver");//2.获取连接Connection conn=DriverManager.getConnection("jdbc:mysql://localhost:3306/MySql?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT","root","111111");System.out.println(conn);} catch (SQLException | ClassNotFoundException e) {e.printStackTrace();}}}

将连接数据库的所有信息配置到配置文件中

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ResourceBundle;/*
* 实际开发中不建议把连接数据库的信息写死到Java程序中。
* */
public class JDBCTest4 {//将连接数据库的所有信息配置到配置文件中public static void main(String[] args) throws SQLException{//使用资源绑定器绑定属性配置文件ResourceBundle bundle=ResourceBundle.getBundle("jdbc");String driver=bundle.getString("driver");String url=bundle.getString("url");String user=bundle.getString("user");String password=bundle.getString("password");Connection conn=null;Statement stmt=null;try {//1.注册驱动Class.forName(driver);//2.获取连接conn=DriverManager.getConnection(url,user,password);//3.获取数据库操作对象stmt=conn.createStatement();//4.执行SQL语句String sql="delete from dept where deptno=40";int count=stmt.executeUpdate(sql);System.out.println(count==1 ?"删除成功":"删除失败");}catch (SQLException | ClassNotFoundException e){e.printStackTrace();}finally {//6.释放资源if (stmt!=null){try {stmt.close();}catch (SQLException e){e.printStackTrace();}}if (conn!=null){try {conn.close();}catch (SQLException e){e.printStackTrace();}}}}}

处理查询结果集

import java.sql.*;
import java.util.ResourceBundle;public class JDBCTest5 {//处理查询结果集public static void main(String[] args) {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/MySql?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT","root","111111");//3.获取数据库操作对象stmt=conn.createStatement();//4.执行sqlString sql="select empno,ename,sal from emp";//int excuteUpdate(insert/delete/update)//ResultSet excuteQuery(select)rs=stmt.executeQuery(sql);//专门执行DQL语句的方法//5.处理查询结果集/* boolean flag1=rs.next();
//            System.out.println(flag1);  trueif (flag1){//光标指向的行有数据//取数据//getString()方法的特点是:不管数据库中的数据是什么类型的,都按string形式取出//1,2,3 说的是第几列String empno=rs.getString(1);//JDBC所有下标从1开始String ename=rs.getString(2);String sal=rs.getString(3);System.out.println(empno+","+ename+","+sal);}*/while (rs.next()){/* String empno=rs.getString(1);//JDBC所有下标从1开始String ename=rs.getString(2);String sal=rs.getString(3);System.out.println(empno+","+ename+","+sal);*///这个不是以列的下标获取,以列的名字获取,(健壮性)//除了可以以String类型取出之外,还可以以特定了类型取出//int  getInt...String empno=rs.getString("empno");String ename=rs.getString("ename"); //假如有 AS a  则以a查询,因为是rs是结果集String sal=rs.getString("sal");System.out.println(empno+","+ename+","+sal);}}catch (Exception e){e.printStackTrace();}finally {//释放资源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();}}}}}

有安全隐患的用户登录界面

import java.sql.*;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;public class JDBCTest6 {/** 实现功能:* 1.需求:模拟用户登录功能的实现* 2.业务描述:程序运行的时候,提供一个输入的入口,可以让用户输入用户名和密码* .用户输入用户名和密码后,提交信息,Java程序收集到用户信息* .Java程序连接数据库验证用户名和密码是否合法* 合法:显示登录成功,不合法:显示登录失败* 3.数据的准备:在实际开发中,表的设计会使用专业的建模工具,我们这里安装一个建模工具:powerDesigner* 使用PD工具来进行数据库表的设计。* 4.当前程序存在问题 :* 用户:gsad* 密码:fsad' or'1'='1* 登陆成功* 这种现象被称为SQL注入(安全隐患)(黑客经常使用)* 导致这种现象的根本原因是什么?* 用户输入的信息中含有sql语句的关键字,并且这些关键字参与了sql语句的编译过程* 导致sql语句的原意被扭曲,进而达到sql注入。* */public static void main(String[] args) throws SQLException {//初始化一个界面Map<String,String> userLoginInfo= initUI();//验证用户名和密码boolean loginSuccess= login(userLoginInfo);//输出结果System.out.println(loginSuccess ?"登录成功":"登录失败");}private static boolean login(Map<String, String> userLoginInfo) throws SQLException {//打标记的意识boolean loginSuccess=false;//单独定义变量String loginName=userLoginInfo.get("loginName");String loginPwd =userLoginInfo.get("loginPwd");//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/MySql?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT","root","131138");//3.获取数据库操作对象stmt=conn.createStatement();//4.执行sql语句String sql="select * from t_user where loginName='"+loginName+"'and loginPwd='"+loginPwd+"'";rs=stmt.executeQuery(sql);//5.处理结果集if (rs.next()){loginSuccess=true;}} catch (ClassNotFoundException | SQLException e) {e.printStackTrace();}finally {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 scanner=new Scanner(System.in);System.out.println("用户名:");String loginName=scanner.nextLine();System.out.println("密码:");String loginPwd=scanner.nextLine();Map<String,String> userLoginInfo= new HashMap<>();userLoginInfo.put("loginName",loginName);userLoginInfo.put("loginPwd",loginPwd);return userLoginInfo;}}import java.sql.*;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;public class JDBCTest6 {/** 实现功能:* 1.需求:模拟用户登录功能的实现* 2.业务描述:程序运行的时候,提供一个输入的入口,可以让用户输入用户名和密码* .用户输入用户名和密码后,提交信息,Java程序收集到用户信息* .Java程序连接数据库验证用户名和密码是否合法* 合法:显示登录成功,不合法:显示登录失败* 3.数据的准备:在实际开发中,表的设计会使用专业的建模工具,我们这里安装一个建模工具:powerDesigner* 使用PD工具来进行数据库表的设计。* 4.当前程序存在问题 :* 用户:gsad* 密码:fsad' or'1'='1* 登陆成功* 这种现象被称为SQL注入(安全隐患)(黑客经常使用)* 导致这种现象的根本原因是什么?* 用户输入的信息中含有sql语句的关键字,并且这些关键字参与了sql语句的编译过程* 导致sql语句的原意被扭曲,进而达到sql注入。* */public static void main(String[] args) throws SQLException {//初始化一个界面Map<String,String> userLoginInfo= initUI();//验证用户名和密码boolean loginSuccess= login(userLoginInfo);//输出结果System.out.println(loginSuccess ?"登录成功":"登录失败");}private static boolean login(Map<String, String> userLoginInfo) throws SQLException {//打标记的意识boolean loginSuccess=false;//单独定义变量String loginName=userLoginInfo.get("loginName");String loginPwd =userLoginInfo.get("loginPwd");//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/MySql?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT","root","131138");//3.获取数据库操作对象stmt=conn.createStatement();//4.执行sql语句String sql="select * from t_user where loginName='"+loginName+"'and loginPwd='"+loginPwd+"'";rs=stmt.executeQuery(sql);//5.处理结果集if (rs.next()){loginSuccess=true;}} catch (ClassNotFoundException | SQLException e) {e.printStackTrace();}finally {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 scanner=new Scanner(System.in);System.out.println("用户名:");String loginName=scanner.nextLine();System.out.println("密码:");String loginPwd=scanner.nextLine();Map<String,String> userLoginInfo= new HashMap<>();userLoginInfo.put("loginName",loginName);userLoginInfo.put("loginPwd",loginPwd);return userLoginInfo;}}

解决sql注入问题

import java.sql.*;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
/*
* 解决sql注入问题
* 只要用户提供的信息 不参与sql语句的编译过程,问题就解决了
* 即使用户提供的信息中含有sql语句的关键字,但是没有参与编译,不起作用
* 要想用户信息不参与sql语句的编译,那么必须使用java.sql.PreparedStatement
* PreparedStatement接口继承了java.sql.PreparedStatement
* PreparedStatement是属于预编译的数据库操作对象。
* PreparedStatement的原理是:预先对sql语句的框架进行编译,然后再给sql语句传"值"
* 解决SQL注入问题的关键是什么?
* 用户提供的信息中即使含有sql语句的关键字 ,但是这些关键字并没有参与编译,不起作用。
对比PreparedStatement与Statement
* 1.Statement存在sql注入问题,PreparedStatement解决了sql注入问题
* 2.Statement是编译依次执行一次,PreparedStatement是编译一次,可以执行n次,效率略高
* 3.PreparedStatement会在编译阶段做类型安全检查
* 综上所述:大部分时候使用PreparedStatement   有些情况用statement,如需要输入desc(降序) asc(升序)
* */
public class JDBCTest7 {public static void main(String[] args) throws SQLException {//初始化一个界面Map<String,String> userLoginInfo= initUI();//验证用户名和密码boolean loginSuccess= login(userLoginInfo);//输出结果System.out.println(loginSuccess ?"登录成功":"登录失败");}private static boolean login(Map<String, String> userLoginInfo) throws SQLException {//打标记的意识boolean loginSuccess=false;//单独定义变量String loginName=userLoginInfo.get("loginName");String loginPwd =userLoginInfo.get("loginPwd");//jdbc代码Connection conn=null;PreparedStatement ps=null;ResultSet rs=null;try {//1.注册驱动Class.forName("com.mysql.cj.jdbc.Driver");//2.获取连接conn= DriverManager.getConnection("jdbc:mysql://localhost:3306/MySql?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT","root","131138");//3.获取预编译的数据库操作对象//SQl语句的框子,其中一个?代表一个占位符,一个?将来接收一个值。(占位符不可以用单引号括起来)String sql="select * from t_user where loginName=? and loginPwd=? ";//程序执行到此处。会发送sql语句框子给DBMS,然后DBMS进行sql语句的预编译ps=conn.prepareStatement(sql);//给占位符 ?传值,(第一个问号下标是1,第二个问号下标是2,JDBC都是1开始)ps.setString(1,loginName);ps.setString(2,loginPwd);//4.执行sql语句rs=ps.executeQuery();//5.处理结果集if (rs.next()){loginSuccess=true;}} catch (ClassNotFoundException | SQLException e) {e.printStackTrace();}finally {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 scanner=new Scanner(System.in);System.out.println("用户名:");String loginName=scanner.nextLine();System.out.println("密码:");String loginPwd=scanner.nextLine();Map<String,String> userLoginInfo= new HashMap<>();userLoginInfo.put("loginName",loginName);userLoginInfo.put("loginPwd",loginPwd);return userLoginInfo;}}

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

6.工具类封装

package utils;import java.sql.*;/*
* JDBC工具类,简化JDBC编程
* */
public class DBUtil {/*工具类中的构造方法都是私有的,以为工具类当中的方法都是静态的不需要new对象,直接采用类名调用。*/private DBUtil(){}//静态代码块在类加载时执行,并且只执行一次。static {try {Class.forName("com.mysql.cj.jdbc.Driver");} catch (ClassNotFoundException e) {e.printStackTrace();}}public static Connection getConnection() throws SQLException{//获取数据库连接对象,返回连接对象return DriverManager.getConnection("jdbc:mysql://localhost:3306/MySql?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT","root","131138");}//关闭资源,conn:连接对象,ps:数据库操作对象 rs:结果集public static void close(Connection conn, Statement ps, ResultSet rs){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();}}}
}

7.JDBC实现模糊查询

package utils;import javax.swing.text.html.HTMLWriter;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;/*
* 1.测试DBUtil是否好用
* 2.模糊查询怎么写?
* */
public class JDBCTest9 {public static void main(String[] args) throws SQLException {Connection conn=null;PreparedStatement ps=null;ResultSet rs=null;try {//获取连接conn= DBUtil.getConnection();//获取预编译的数据库操作对象//错误写法/* String sql="select ename from emp where name like '_?%'";ps=conn.prepareStatement(sql);ps.setString(1,'A');*/String sql="select ename from emp where name like ?";ps=conn.prepareStatement(sql);ps.setString(1,"_A%");rs=ps.executeQuery();while (rs.next()){System.out.println(rs.getString("ename"));}}catch (SQLException e){e.printStackTrace();}finally {//释放资源DBUtil.close(conn,ps,rs);}}
}

8.悲观锁和乐观锁的概念

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

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

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

JDBC学习笔记(动力节点+附代码分析)相关推荐

  1. JDBC学习笔记-动力节点

    JDBC (B站动力节点杜老师) 1.JDBC是什么 2.jdbc的本质是什么? 多态: ​ Animal a = new Cat ( ) -->面向抽象编程 父类型的引用 指向 子类型的对象 ...

  2. Ajax学习笔记-动力节点-王鹤老师

    Ajax学习笔记-动力节点-王鹤老师 视频教程来自:https://www.bilibili.com/video/BV15k4y167XM?spm_id_from=333.999.0.0 第一节 全局 ...

  3. 史上最全SpringBoot学习笔记-动力节点王鹤(2021最新版)

    SpringBoot 资料官方下载地址 动力节点springboot资料 视频观看地址 https://www.bilibili.com/video/BV1XQ4y1m7ex 第一章 JavaConf ...

  4. 学习笔记-第一章 恶意代码分析实战

    第一章 从可执行文件提取有用信息的多种方法,包括以下技术:1.使用反病毒软件来确认程序样本的恶意性:2.使用哈希来识别恶意代码:3.从文件的字符串列表,函数和文件头信息中发掘有用信息.字符串包括 AS ...

  5. JSP学习笔记(动力节点老杨)(自己总结方便复习)

    JSP动力节点老杨 互联网通信流程图 多线程三大特征:原子性 可见性 有序性 一.jsp主要作用替代响应对象将内容写入到响应包中 二.jsp导包 <%@ page import=" & ...

  6. 学习笔记-第九章 恶意代码分析实战

    第九章 OllyDbg 1.加载恶意代码直接加载可执行文件,甚至dll程序.如果恶意代码已经在你的系统上运行,你可以通过附加进程的方式调试它.另外,ollydbg是一个灵活的调试系统,可以使用命令行选 ...

  7. [Java]Mybatis学习笔记(动力节点老杜)

    文章目录

  8. [Java]JavaWeb学习笔记(动力节点老杜2022)【Javaweb+MVC架构模式完结】

    文章目录

  9. 一文弄懂元学习 (Meta Learing)(附代码实战)《繁凡的深度学习笔记》第 15 章 元学习详解 (上)万字中文综述

    <繁凡的深度学习笔记>第 15 章 元学习详解 (上)万字中文综述(DL笔记整理系列) 3043331995@qq.com https://fanfansann.blog.csdn.net ...

  10. JDBC学习笔记02【ResultSet类详解、JDBC登录案例练习、PreparedStatement类详解】

    黑马程序员-JDBC文档(腾讯微云)JDBC笔记.pdf:https://share.weiyun.com/Kxy7LmRm JDBC学习笔记01[JDBC快速入门.JDBC各个类详解.JDBC之CR ...

最新文章

  1. 【Spring】Bean的生命周期
  2. vc6可编译的 linux 源码,Linux 下源码编译FFMEG
  3. boost::mp11::mp_min_element_q相关用法的测试程序
  4. 变量的比较之equals 与 == 的区别
  5. /etc/fstab 文件配置项简单介绍
  6. 自定义View以及事件分发总结
  7. kotlin_Kotlin
  8. ajax点击a load,jQuery:在ajax load()之后运行脚本
  9. 【翻译】Siesta事件记录器入门
  10. 群晖NAS教程(十二)、利用Web Station安装Chevereto图床
  11. Android 多语言切换
  12. android手机文件管理器,4 款 Android 文件管理器,总有一款适合你
  13. resources下建包
  14. ElasticSearch简单使用
  15. 正则表达式练习题(含答案)
  16. 【已解决】Win10 更新失败的问题【错误代码为0x80070003】
  17. matlab三维绘图注释,Matlab三维绘图与图形处理
  18. 查看linux版本是多少位
  19. 通过PLSQL查看所连接的ORACLE的版本
  20. spark封神之路(7)-RDD算子详解第一部分

热门文章

  1. 光纤跳线接口_如何为10G SFP+光模块搭配对应的光纤跳线类型?
  2. STM32F429I-DISCO ucLinux 开发环境搭建
  3. 一个优化好的、成熟的代购网站需要哪些功能,操作流程又是怎么样的?
  4. 斗鱼弹幕服务器连接协议,斗鱼弹幕服务器第三方接入协议v1 6 2.pdf
  5. 测绘技能大赛选手图加密工具
  6. linux 查看vcf文件,转载-VCF格式详解
  7. ffmpeg所有的解码器(decoders)
  8. 典型相关分析(Canonical correlation analysis)(四): 中国城市竞争力与基础设施的相关分析
  9. BS 476-31 与BS 476-33 测试方法是类似的吗?
  10. 铲雪车(snow) UVA10203 Snow Clearing 题解