JDBC从入门到精通
文章目录
- JDBC
- 概念
- 使用步骤
- idea 创建项目并导入jar包
- 入门案例
- SQL注入
- SQL注入的解决方案
- JDBC常见问题
- Class.forName这句话有用没?
- 驱动版本
- 中文乱码
- SQL注入
- PreparedStatement 语句
- 常见错误
- java.lang.ClassNotFoundException: com.mysql.jdbc.Driver
- Unknown database mydb;
- Access denied for user 'root123'@'localhost' (using password: YES)
- Table 'py-school-db.mydb' doesn't exist
JDBC
概念
我们学习了数据库,数据库实现了数据的持久化,但我们最终要在程序里处理数据啊,那java代码中怎么去访问数据库读写数据呢?
这就要用到sun公司设定的一套数据库标准了,这套标准就是JDBC(Java Database Connectivity)。但它只是规范,不做具体实现。于是数据库厂商又根据JDBC标准,实现自家的驱动Driver。如:mysql驱动com.mysql.cj.jdbc.Driver,Oracle的驱动oracle.jdbc.OracleDriver。有了这套解决方案,java就可以访问数据库中的数据了。
public interface Connection extends Wrapper, AutoCloseable {}public interface Statement extends Wrapper, AutoCloseable {}public interface PreparedStatement extends Statement {}public interface CallableStatement extends PreparedStatement {}public interface ResultSet extends Wrapper, AutoCloseable {}
Java中提倡面向接口开发,而最经典的接口设计莫过于JDBC数据库接口。
Connection链接、Statement语句、PreparedStatement预处理语句、CallableStatement存储过程、ResultSet结果集。
调用方式有三种:Statement语句、PreparedStatement预处理语句、CallableStatement存储过程,推荐使用第二种PreparedStatement,防止SQL注入,其也是预编译性能高。
使用步骤
导入jar包(丰富的工具类)
获取和数据库的连接(用户名、密码)
通过程序执行SQL
通过程序处理结果
idea 创建项目并导入jar包
- 创建stage2 Java工程
- 创建lib目录,拷贝驱动objbc6-11.1.0.7.0到lib目录下
- 项目引用这个外部jar包
入门案例
package cn.tedu.jdbc;import java.sql.*;//测试 jdbc
//需求:查询cgb2104库里的students表里的所有数据
public class Test1 {public static void main(String[] args) throws Exception {//1,注册驱动Class.forName("com.mysql.jdbc.Driver");//2,获取和数据库的连接
//String url= "jdbc:mysql://localhost:3306/cgb2104?characterEncoding=utf8";//指定要连接哪个数据库
String url= "jdbc:mysql:///cgb2104?characterEncoding=utf8";//指定要连接哪个数据库String user= "root" ; //使用的用户名String pwd= "root" ; //使用的密码Connection conn = DriverManager.getConnection(url, user, pwd);//3,获取传输器,执行SQLStatement st = conn.createStatement();//4,执行SQLResultSet rs = st.executeQuery("select * from students");//5,解析结果集while( rs.next() ){//next()判断结果集中是否有数据for (int i = 1; i <= 5 ; i++) {//获取每列的值并打印System.out.println( rs.getString(i) );}}//6,释放资源rs.close(); //关闭结果集st.close();//关闭传输器conn.close();//关闭连接}
}
SQL注入
/*自己准备user2表(id/name/password),准备数据CREATE TABLE `user2` (`id` int(11) PRIMARY KEY auto_increment,`name` varchar(10) default NULL,`password` varchar(10) default NULL) ;*/
//需求:利用jdbc,根据用户名和密码查询cgb2104库里的user表
//SQL注入攻击问题
private static void login() {try{Class.forName("com.mysql.jdbc.Driver");String url="jdbc:mysql:///cgb2104?characterEncoding=utf8";Connection conn = DriverManager.getConnection(url, "root", "root");Statement st = conn.createStatement();
// String sql ="select * from user2 where name='jack' and password='123456'";//写死了String user = new Scanner(System.in).nextLine();//用户输入jack'#String pwd = new Scanner(System.in).nextLine();//SQL注入攻击问题:本质上是因为SQL语句中出现了特殊符号#,改变了SQL语义
String sql ="select * from user2 where name='"+user+"' and password='"+pwd+"'";ResultSet rs = st.executeQuery(sql);//执行查询的SQL,返回结果集if(rs.next()){System.out.println("登录成功~");}else{System.out.println("登录失败~");}st.close();conn.close();}catch(Exception e){e.printStackTrace();//有异常,直接打印异常信息//System.out.println("执行失败。。。");//上线}}
SQL注入的解决方案
//解决SQL注入攻击的方案
private static void login2() {try{Class.forName("com.mysql.jdbc.Driver");String url="jdbc:mysql:///cgb2104?characterEncoding=utf8";Connection conn = DriverManager.getConnection(url, "root", "root");
// Statement st = conn.createStatement();不行,不安全,会被SQL攻击String user = new Scanner(System.in).nextLine();//用户输入jack'#String pwd = new Scanner(System.in).nextLine();//?叫占位符 ,SQL的骨架
String sql ="select * from user2 where name=? and password=?";//先把SQL骨架发给数据库执行PreparedStatement ps = conn.prepareStatement(sql);//给SQL里的? 设置参数ps.setString(1,user);//给第一个?设置值是userps.setString(2,pwd);//给第二个?设置值是pwdResultSet rs = ps.executeQuery();//执行拼接好的SQL,返回结果集if(rs.next()){System.out.println("登录成功~");}else{System.out.println("登录失败~");}ps.close();conn.close();}catch(Exception e){e.printStackTrace();//有异常,直接打印异常信息//System.out.println("执行失败。。。");//上线}
}
JDBC常见问题
Class.forName这句话有用没?
Class.forName可以指定class类路径进行动态创建对象实例,可JDBC这句话没有返回对象啊,那写这句有什么作用呢?看看java.sql.Driver.class的源码就找到真相了,原来它用了静态代码块创建对象。
static {try {DriverManager.registerDriver(new Driver());} catch (SQLException var1) {throw new RuntimeException("Can't register driver!");}}
写了创建了,那不写呢?怎么不写也能执行呢?
Java提供了SPI机制,用户可以自行配置类,JDBC高版本驱动就都引入了这个支持。如果用户使用了Class.forName方式就自己指定了驱动,如果未写这句话,则Java自动去META-INF/services/java.sql.Driver文件中找启动类。
驱动版本
不同版本的mysql需要不同版本的驱动
Mysql5.0x mysql-connector-java-5.1.32.jarMysql8.0x mysql-connector-java-8.0.21.jar
- Driver变成了: com.mysql.cj.jdbc.Driver,中间多了cj
- url必须加时区参数: serverTimezone=Asia/Shanghai
中文乱码
url增加参数:characterEncoding=utf8防止中文乱码
String url ="jdbc:mysql://localhost:3306/mydb?characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false";
SQL注入
String condition = "陈强";
String condition = "陈强' or 1=1 or '";
String condition = "陈强' or true or '";String sql = "select * from teachers where tname='" + condition+"'";
利用sql中'单撇是字符串的结束符,or只要一个条件成立其它就不用再判断,而恶意造成sql查询失效,本应该只展示一条数据,结果全部展现。
注入后形成的SQL:
SELECT * FROM teachers WHERE tname='陈强' OR 1=1 OR ''
大家试想如果是一个财务表,本你只能看自己的信息,结果你看了所有人的信息。结果新员工比你工资高,你说气人不。
PreparedStatement 语句
SQL注入解决方案:
Statement对象换为PreparedStatement对象
sql = "select * from teachers where tname=?"; #参数使用问号
PreparedStatement stat = cn.prepareStatement(sql); #对象换掉
stat.setString(1, condition); #对应参数类型,第几个问号
ResultSet rs = stat.executeQuery(); #去掉sql参数
PS后的结果:
SELECT * FROM teachers WHERE tname='陈强\' or 1=1 or \''
利用转义字符,屏蔽了SQL中的恶意字符。不仅解决了sql注入问题,使系统变的安全,PreparedStatement还有个极大的好处,它是预编译的语句,其主干部分mysql进行预编译后缓存,下次这部分就无需在解析,只把条件拼入,这样执行效率远高于statement每次都要编译sql语句。
常见错误
java.lang.ClassNotFoundException: com.mysql.jdbc.Driver
错误原因:
1)jar没有导入,没有builder path
2)Class.forName("com.mysql.jdbc.Driver"); 字符串拼写错误
Unknown database mydb;
错误原因:
数据库名称拼写错误
Access denied for user ‘root123’@‘localhost’ (using password: YES)
错误原因:
数据库用户名或者密码错误
Table ‘py-school-db.mydb’ doesn’t exist
错误原因:
表不存在,也可能表名写错了
JDBC从入门到精通相关推荐
- Mybatis从入门到精通(全)
目录 前言 1. idea软件小技巧 2. mybatis优势 3. mybatis入门项目 3.1 项目具体步骤 3.2 创建数据表 3.3 创建maven项目 3.4 pom.xml配置文件 3. ...
- java框架 零基础从入门到精通的学习路线 附开源项目面经等(超全)
目录 前言 1. 学习路线 2. 学习方法 前言 这篇文章主要总结我之前所学过的框架以及学习路线 从实打实的零基础到框架再到项目 之后实习工作 也在这篇博客中记录我的学习笔记 以及在笔记中遇到的配置安 ...
- java从入门到精通_想要开始学java?你要的java从入门到精通布列如下!
java从入门到精通,让我来告诉你! 毫无疑问,java是当下最火的编程语言之一.对于许多未曾涉足计算机编程的领域「小白」来说,深入地掌握java看似是一件十分困难的事.其实,只要掌握了科学的学习方法 ...
- Java学习从入门到精通
Java Learning Path (一).工具篇 一. JDK (Java Development Kit) JDK是整个Java的核心,包括了Java运行环境(Java Runtime Envi ...
- Mybatis从入门到精通下篇
Mybatis从入门到精通下篇: 输入类型: 输出类型: ResultMap: 动态sql: if标签: where标签: sql片段: foreach标签: 关联查询: 以订单作为主体: 一对一查询 ...
- Oracle 从入门到精通视频教程(11G版本)
<Oracle 从入门到精通>中的视频教程和PPT资料. 下载地址 Oracle 11G从入门到精通视频的PPT http://down.51cto.com/data/376701 第1章 ...
- @aspect注解类不生效_Spring Boot从入门到精通(三)常用注解含义及用法分析总结...
Spring Boot是目前非常流行的框架,而注解是Spring Boot的核心功能,接下来主要说一说Spring Boot常用注解的含义以及部分注解在项目中的使用方法. @RestControlle ...
- Java学习从入门到精通[转]
Java Learning Path (一).工具篇 一. JDK (Java Development Kit) JDK是整个Java的核心,包括了Java运行环境(Java Runtime En ...
- mybatis 存储过程 tmp_count_MyBatis从入门到精通
MyBatis是一款优秀的持久层框架,它支持定制化SQL.存储过程以及高级映射.MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集.MyBatis可以使用简单的 XML或注解 ...
最新文章
- ExecutorService 的理解与使用
- IIS日志清理CMD版,VBS版,JS版,WSH版
- 拖动改变Table的列宽度
- RabbitMQ消息手动应答生产者
- 【转】国密加密算法SM系列的C#实现方法
- 力扣 验证二叉搜索树
- ajax请求上传数组
- spring.net 对象创建 几种情况
- C++ std::condition_variable 是什么 有什么用 条件变量 线程同步 wait wait_for notify_one notify_all
- CRT和LCD显示器的区别
- Xcode:iOS崩溃日志分析方法
- 阿里云RDS数据库与自建数据库做主从同步
- 验证方法学的发展历程及比较
- 百面机器学习 自学笔记
- FPGA基础实验:点亮LED
- python实现将图像合成GIF图
- 【通信原理| OFDM技术的最简讲解(上)】窄带、宽带与频分复用、多载波调制的讲解
- Keystone 认证服务
- linux18安装anyconnect4.9遇到I/O问题
- 软驱光碟安装linux系统,无光驱和软驱安装debian的方法
热门文章
- 爱创课堂每日一题第二十三天- Expires和Cache-Control?
- 淘系自研前端研发工具 AppWorks 正式发布
- 基于matlab毕业设计题目,matlab毕业设计题目.doc
- Mixed Content: The page was loaded over HTTPS,blocked the content must be served over HTTPS.
- 从小白踏上程序员之路
- 手机用户对手机游戏的偏好调查
- 一文读懂GPU服务器
- 国庆福利赠书,书籍全部包邮送!
- 高仿网易评论列表效果之界面分析
- java 地图坐标转换_百度地图经纬度和地址互转(Java代码)