JDBC、ORM、SQL注入、DBUtil
创始人
2025-06-01 00:56:29
0

一、 如何操作数据库

使用客户端工具访问数据库,需要手工建立连接,输入用户名和密码登录,编写 SQL 语句,点击执行,查看操作结果(结果集或受影响行数)。

二、JDBC

JDBC(Java Database Connectivity) Java 连接数据库的规范(标准),可以使用 Java 语言连接数据库完成 CRUD 操作。

Java 中定义了访问数据库的接口,可以为多种关系型数据库提供统一的访问方式。由数据库厂商提供驱动实现类(Driver 数据库驱动)。

环境搭建

1.打开项目结构(Project Structure)

2.选择libraries,添加jar包

3.点击右下角apply,查看是否成功

三、JDBC编程

JDBC编程有标准步骤(八股文)

  • 注册驱动

  • 将sql语句的运行环境加载到JVM

  • 连接数据库

  • 获得执行SQL的对象

  • 执行SQL语句,获得结果

  • 关流

3.1 注册驱动

使用 Class.forName("com.mysql.jdbc.Driver");手动加载字节码文件到 JVM 中。

Class.forName("com.mysql.jdbc.Driver");//加载驱动// 8.0驱动要加上 cjClass.forName("com.mysql.cj.jdbc.Driver");

3.2 连接数据库

  • 通过 DriverManager.getConnection(url,user,password) 获取数据库连接对象

  • URL:jdbc:mysql://localhost:3306/database

  • username:root

  • password:123

Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/database?useUnicode=true&characterEncoding=utf8", "root","123");

PS:URL(Uniform Resource Locator) 统一资源定位符:由协议、IP、端口、SID(程序实例名称)组成

3.3 获取发送 SQL 的对象

通过 Connection 对象获得 Statement 对象,用于对数据库进行通用访问。

Statement statement = conn.createStatement();

3.4 执行SQL 语句

String sql ="INSERT INTO t_jobs(JOB_ID,JOB_TITLE,MIN_SALARY,MAX_SALARY) VALUES('JAVA_Le','JAVA_Lecturer',4000,10000);";int result = statement.executeUpdate(sql);//执行SQL语句并接收结果
  • 注意:在编写 DML 语句时,一定要注意字符串参数的符号是单引号 '值'

  • DML 语句:增删改时,返回受影响行数(int 类型)。

  • DQL 语句:查询时,返回结果数据(ResultSet 结果集)。

3.5 释放资源

遵循先开后关原则,释放所使用到的资源对象。

使用JDBC完成对tb_user表插入数据:

create table tb_user(id int(11) primary key auto_increment comment '用户编号',username varchar(10) comment '用户名',password varchar(10) comment '密码',phone varchar(11) comment '手机号',createTime date comment '注册时间',money double(10,2) comment '账户余额',sex int(1) comment '性别 1男2女'
);
public static void main(String[] args) throws ClassNotFoundException, SQLException {// 1 加载驱动// ps: 利用反射技术,将驱动类加载到JVMClass.forName("com.mysql.jdbc.Driver");// 2 通过驱动管理对象获得连接对象/*** 参数1 url: 数据库连接的地址*    协议://ip:端口/库名* 参数2 username: 数据库用户名* 参数3 password: 数据库密码*/String url = "jdbc:mysql://localhost:3306/java2217?useSSL=false&serverTimezone=UTC";String username = "root";String password = "123456";Connection conn = DriverManager.getConnection(url,username,password);// 3 通过连接对象,创建执行sql语句的对象Statement statement = conn.createStatement();// 4 通过执行语句对象,执行sql,获得结果String sql = "insert into tb_user (id,username,password,phone,createTime,money,sex) values (2,'root','123456','1122200','2022-11-21',2000.0,2)";// 执行查询,是executeQuery()// 执行增删改,是executeUpdate(),返回受影响的行数int num = statement.executeUpdate(sql);if (num > 0) {System.out.println("插入成功!!" );}// 5 关流statement.close();conn.close();}

四、查询结果集ResultSet【重要】

查询返回的是一种虚拟表,Java的JDBC中是使用结果集(ResultSet)来封装这个虚拟表,结果集就是一个集合,内部就存储了列名和每行数据,那么学习查询的重点是

  • 从结果集取值

 public static void main(String[] args) throws Exception {Class.forName("com.mysql.jdbc.Driver");Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/java2217?useSSL=false", "root", "123456");Statement statement = conn.createStatement( );String sql = "select id,username,password from tb_user";// 执行查询的方法executeQuery,方法返回值是ResultSetResultSet rs = statement.executeQuery(sql);/*** ResultSet 内部包含了整个查询返回的虚拟表数据* 内部提供了方法可以操作结果集* boolean next(); 判断结果集有没有下一行数据,返回false,即没有下一行数据返回*                 true就是有下一行数据,此时就可以进入取值* Object getObject(int columnIndex)      获得数据,返回值是Object* Object getObject(String columnLabel)* getInt/getString/getDate() 获得数据,返回对应数据类型* --------------------------------------* getXxx(int columnIndex)  通过列下标获得对应Xxx数据类型的数据*                         下标从1开始,顺序是按照查询返回虚拟表顺序* getXxx(String columnLabel)  通过列名获得对应Xxx数据类型的数据*                         根据虚拟表列名,如果有别名那就是别名*/while (rs.next()) {// 通过列下标获得数据// int id =  rs.getInt(2);// String username = rs.getString(1);// 通过列名获得数据 【推荐】int id = rs.getInt("id");String username = rs.getString("username");System.out.println(id + "-" + username);}statement.close();conn.close();}

五、ORM【重要】

5.1 什么是ORM

目前使用JDBC完成了CRUD,但是现在是进行CRUD,增删改方法要设计很多参数,查询的方法需要设计集合才能返回

在实际开发中,我们需要将零散的数据封装到对象处理.

ORM (Object Relational Mapping) 对象关系映射

是指数据库表与Java的实体类有关系,可以进行映射

  • 数据库表 --> Java的类

  • tb_user ---> User.java

  • 字段 --> 类的属性

  • id int --> private int id;

  • username varchar --> private String username;

  • ...

  • 一行数据 --> 类的对象

5.2 实体类

实体类: 数据表中零散数据的载体,用来封装数据.

  • 表名 设计 类名

  • 将列名设计成属性名

  • id --> id

  • create_time --> createTime (下划线转驼峰)

  • 将列的数据类型设计成属性的数据类型

  • 给类提供对应set get

一般项目中一个表就会对应一个实体类,所有的实体类都会放在model/entity/pojo/javabeen包结构中

将来写项目,数据库设计完,搭建完项目,第一件事件就是根据表结构,创建实体类

六、SQL注入

6.1 什么是SQL注入

用户输入的数据中有SQL关键词,导致在执行SQL语句时出现一些不正常的情况.这就是SQL注入!

6.2 避免SQL注入

问题出现在用户输入数据时,里面有关键词,再配合字符串拼接导致出现SQL注入.所以为了避免SQL注入,可以在用户输入数据到SQL之前,先把SQL语句预编译,预处理后,JDBC就会知道此SQL需要几个参数,后续再将用户输入的数据给参数填充.

这就是PreparedStatement

七、PreparedStatement【重点】

PreparedStatement是Statement的子接口,用来预处理SQL语句

PreparedStatement使用

  • 先写SQL语句,SQL语句中的参数不能直接拼接,而是使用?占位

  • 使用ps预处理SQL语句,处理的?号,ps内部就会知道此SQL语句需要几个参数

  • 再动态给?处填充值

 public static void main(String[] args) throws Exception {Scanner scanner = new Scanner(System.in);System.out.println("请输入用户名:" );String username = scanner.nextLine( );System.out.println("请输入密码:" );String password = scanner.nextLine( );Class.forName("com.mysql.jdbc.Driver");Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/java2217?useSSL=false", "root", "123456");// 改造SQL,将拼接变量,变成?占位String sql = "select * from tb_user where username = ? and password = ?";System.out.println("处理前:  " + sql);// 由之前的Statement换成PreparedStatement// 将改造好的SQL,传入方法PreparedStatement ps = conn.prepareStatement(sql);System.out.println("处理后: " + ps );// 给处理好的占位参数赋值// ps.setXxx() 给指定Xxx类型赋值// 第一个?,下标是1ps.setString(1,username);ps.setString(2,password);System.out.println("填充后: " + ps );//【特别注意!!!!】 此处executeQuery不需要再传入SQL参数!!!ResultSet rs = ps.executeQuery();if (rs.next()) {System.out.println("登录成功!!" );} else {System.out.println("用户名或密码错误!" );}rs.close();ps.close();conn.close();}

八、DBUtil

DBUtil操作数据库的工具类,因为发现每次操作数据库,JDBC的步骤第1,2,5步完全重复的,即加载驱动,获得连接对象,已经最后的关流是每次都要写但每次都是一样的

现在设计工具类,简化第1,2,5步

  • 设计个方法,调用直接获得连接对象

  • 设计个方法,调用直接关闭全部的流对象

在src下创建jdbc.properties文件

driverClass=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/java2301?useSSL=false
username=root
password=123456
   // 创建Properties类对象,专用于操作properties文件private static final Properties properties = new Properties();/*** 加载驱动的目的是为了在JVM中有sql运行的环境* 该环境有一份就行了,不用重复加载* ------------------------------------* static 静态代码块* 1) 保证内存中只有一份* 2) 保证随着类加载而加载,即该代码块会执行*/static {// 通过反射的技术获得字节码文件// 再通过字节码文件将配置文件读取成输入流InputStream inputStream = DBUtil.class.getResourceAsStream("/jdbc.properties");try {// 再通过流获得其中数据properties.load(inputStream);// 从properties对象取值Class.forName(properties.getProperty("driverClass"));} catch (Exception e) {System.out.println("加载驱动异常!!" );e.printStackTrace( );}}/*** 一般会将关于JDBC配置信息,抽取出来,形成一个配置文件,方便维护* 文件类型是properties文件,该文件类似map,键值对类型* 名字 jdbc.properties* 位置 src/jdbc.properties* 内容*/public static Connection getConnection() {Connection conn = null;try{conn = DriverManager.getConnection(properties.getProperty("url"),properties.getProperty("username") ,properties.getProperty("password") );} catch (Exception e) {System.out.println("获得连接出异常!!!" );e.printStackTrace();}return conn;}/*** 关闭所有流*/public static void closeAll(Connection conn, Statement s) {if (conn != null) {try {conn.close();} catch (SQLException throwables) {throwables.printStackTrace( );}}if (s != null) {try {s.close();} catch (SQLException throwables) {throwables.printStackTrace( );}}}public static void closeAll(Connection conn, Statement s, ResultSet rs){if (conn != null) {try {conn.close();} catch (SQLException throwables) {throwables.printStackTrace( );}}if (s != null) {try {s.close();} catch (SQLException throwables) {throwables.printStackTrace( );}}if (rs != null) {try {rs.close();} catch (SQLException throwables) {throwables.printStackTrace( );}}}
}

日后有更方便好用的方法

相关内容

热门资讯

原创 权... 作者:吕东平 摘要 在全球化与文明对话日益深入的今天,某些国家仍呈现出权力结构对法治原则的系统性侵...
分手后男子起诉按现金价折算金饰... 近日,宁夏同心县人民法院公布一起案例,2024年9月,宝某与周某经人介绍相识并按照习俗结婚,宝某依习...
连连数字盘中一度涨超78% 香... 连连数字(02598)盘中一度涨超78% ,高见18港元,股价创新高,截至发稿,股价上涨65.47%...
官员饮酒聚餐致死,安徽:绝不姑... 据《安徽日报》报道,6月1日晚,安徽省委常委会召开会议,传达学习中央层面深入贯彻中央八项规定精神学习...
3名干部被查,均已退休,年龄最... 原江西省工业和信息化委员会党组成员、副主任杨人平被查 据江西省纪委监委5月30日消息:原江西省工业和...
曼联门神奥纳纳爆转会!沙特土豪... 各位球迷朋友们,转会市场这潭水啊,是越来越深,越来越浑!今儿个咱聊聊曼联的门神——安德烈·奥纳纳。这...
女子搬新家遭邻居多次持刀砍门,... 极目新闻记者 王柳钦 近日,有辽宁大连的网友发视频称,疑似患精神疾病的邻居多次持刀上门,用刀砍其家门...
提高额度、放宽范围!济南公积金... 5月30日,“卖旧买新”购房补贴刚公布,济南住房公积金新政再度上新! 济南市住房公积金最新消息,为进...
乌“蛛网”行动战报称摧毁大量俄... 每经编辑:毕陆名 据央视新闻6月2日消息,当地时间6月1日,记者获悉,据一位未透露姓名的美国政府官员...
巨子生物声明:接受检测机构道歉... DoNews6月2日消息,据每日经济新闻报道,6月1日22点32分,巨子生物旗下可复美微信公众号发布...