Java JDBC连接数据库的CURD操作(JDK1.8 + MySQL8.0.33 + mysql-connector-java-8.0.27-bin驱动)
JDBC概述
JDBC(Java Database Connectivity)是一个独立于特定数据库管理系统、通用的SQL数据库存取和操作的公共接口(一组API),定义了用来访问数据库的标准Java类库,(java.sql,javax.sql)使用这些类库可以以一种标准的方法、方便地访问数据库资源。
JDBC为访问不同的数据库提供了一种统一的途径,为开发者屏蔽了一些细节问题。
JDBC的目标是使Java程序员使用JDBC可以连接任何提供了JDBC驱动程序的数据库系统,这样就使得程序员无需对特定的数据库系统的特点有过多的了解,从而大大简化和加快了开发过程。
连接数据库
java.sql.Driver 接口是所有 JDBC 驱动程序需要实现的接口。这个接口是提供给数据库厂商使用的,不同数据库厂商提供不同的实现。
在程序中不需要直接去访问实现了 Driver 接口的类,而是由驱动程序管理器类(java.sql.DriverManager)去调用这些Driver实现。
我使用的是 mysql-connector-java-8.0.27-bin 驱动
1、加载驱动
不用显式调用 DriverManager 类的 registerDriver() 方法来注册驱动程序类的实例,是因为 Driver 接口的驱动程序类都包含了静态代码块,在这个静态代码块中,会调用 DriverManager.registerDriver() 方法来注册自身的一个实例。所以建议使用以下代码加载驱动。
Class.forName(“com.mysql.cj.jdbc.Driver”);
注意:驱动版本8+以上的才需要在jdbc前面.cj,否则直接写“com.mysql.jdbc.Driver”
2、获取连接
使用DriverManager.getConnection(url,user,password);获取连接
MySQL的连接URL编写方式:
jdbc:mysql://主机名称:mysql服务端口号/数据库名称?参数=值&参数=值
jdbc:mysql://localhost:3306/数据库名
jdbc:mysql://localhost:3306/数据库名?useUnicode=true&characterEncoding=utf8(如果JDBC程序与服务器端的字符集不一致,会导致乱码,那么可以通过参数指定服务器端的字符集)
jdbc:mysql://localhost:3306/数据库名?user=root&password=123456
连接数据库的时候也可以使用配置文件的方式保存配置信息,在代码中加载配置文件,这里就不再赘述。
使用PreparedStatement实现CRUD操作
为什么要用PreparedStatement而不是Statements是因为使用Statement操作数据表存在弊端:
问题一:存在拼串操作,繁琐
问题二:存在SQL注入问题
SQL 注入是利用某些系统没有对用户输入的数据进行充分的检查,而在用户输入数据中注入非法的 SQL 语句段或命令(如:SELECT user, password FROM user_table WHERE user='a' OR 1 = ' AND password = ' OR '1' = '1') ,从而利用系统的 SQL 引擎完成恶意行为的做法。
对于 Java 而言,要防范 SQL 注入,只要用 PreparedStatement(从Statement扩展而来) 取代 Statement 就可以了。
PreparedStatement的使用
可以通过调用 Connection 对象的 preparedStatement(String sql) 方法获取 PreparedStatement 对象
PreparedStatement 接口是 Statement 的子接口,它表示一条预编译过的 SQL 语句
PreparedStatement 对象所代表的 SQL 语句中的参数用问号(?)来表示,调用 PreparedStatement 对象的 setXxx() 方法来设置这些参数. setXxx() 方法有两个参数,第一个参数是要设置的 SQL 语句中的参数的索引(从 1 开始),第二个是设置的 SQL 语句中的参数的值
具体步骤如下:
1 Class.forName("com.mysql.cj.jdbc.Driver");
2
3 Connection connection = DriverManager.getConnection(URL, name, password);
4
5 String sql = "SELECT * FROM t_user;";
6
7 PreparedStatement preparedStatement = connection.prepareStatement(sql);
8
9 ResultSet resultSet = preparedStatement.executeQuery();
10
11 while (resultSet.next()){
12 int id = resultSet.getInt("id");
13 String account = resultSet.getString("account");
14 String pw = resultSet.getString("PASSWORD");
15 String nickname = resultSet.getString("nickname");
16
17 System.out.println(id+"\t"+account+"\t"+pw+"\t"+nickname);
18 }
19
20 resultSet.close();
21
22 preparedStatement.close();
23
24 connection.close();
如果要传入参数,首先在sql语句中用?去占位,再调用setObject方法传递参数,如下所示:
1 Class.forName("com.mysql.cj.jdbc.Driver");
2
3 Connection connection = DriverManager.getConnection(url, name, password);
4
5 String sql = "SELECT * FROM t_user WHERE account=? AND password=?;";
6
7 PreparedStatement preparedStatement = connection.prepareStatement(sql);
8
9 String account = "root";
10 String pw = "123456";
11
12 preparedStatement.setObject(1,account);
13
14 preparedStatement.setObject(2,pw);
15
16 ResultSet resultSet = preparedStatement.executeQuery();
17
18 boolean next = resultSet.next();
19 System.out.println(next);
20
21 resultSet.close();
22
23 preparedStatement.close();
24
25 connection.close();
ResultSet
查询需要调用PreparedStatement 的 executeQuery() 方法,查询结果是一个ResultSet 对象
ResultSet 对象以逻辑表格的形式封装了执行数据库操作的结果集,ResultSet 接口由数据库厂商提供实现
ResultSet 返回的实际上就是一张数据表。有一个指针指向数据表的第一条记录的前面。
ResultSet 对象维护了一个指向当前数据行的游标,初始的时候,游标在第一行之前,可以通过 ResultSet 对象的 next() 方法移动到下一行。调用 next()方法检测下一行是否有效。若有效,该方法返回 true,且指针下移。相当于Iterator对象的 hasNext() 和 next() 方法的结合体。
当指针指向一行时, 可以通过调用 getXxx(int index) 或 getXxx(int columnName) 获取每一列的值。
例如: getInt(1), getString("name")
注意:Java与数据库交互涉及到的相关Java API中的索引都从1开始。
资源的释放
释放ResultSet, Statement,Connection。
数据库连接(Connection)是非常稀有的资源,用完后必须马上释放,如果Connection不能及时正确的关闭将导致系统宕机。Connection的使用原则是尽量晚创建,尽量早的释放。
可以在finally中关闭,保证及时其他代码出现异常,资源也一定能被关闭。
ResultSetMetaData
可用于获取关于 ResultSet 对象中列的类型和属性信息的对象
ResultSetMetaData meta = rs.getMetaData();
getColumnName(int column):获取指定列的名称
getColumnLabel(int column):获取指定列的别名
getColumnCount():返回当前 ResultSet 对象中的列数。
getColumnTypeName(int column):检索指定列的数据库特定的类型名称。
getColumnDisplaySize(int column):指示指定列的最大标准宽度,以字符为单位。
isNullable(int column):指示指定列中的值是否可以为 null。
isAutoIncrement(int column):指示是否自动为指定列进行编号,这样这些列仍然是只读的。
使用ResultSetMetaData 将ResultSe中的数据存入List<Map>中的集合里:
1 Class.forName("com.mysql.cj.jdbc.Driver");
2
3 Connection connection = DriverManager.getConnection(url, name, password);
4
5
6 String sql = "SELECT id as ID,account as 账号,password as 密码,nickname as 昵称 FROM t_user;";
7
8 PreparedStatement preparedStatement = connection.prepareStatement(sql);
9
10 ResultSet resultSet = preparedStatement.executeQuery();
11
12 ResultSetMetaData metaData = resultSet.getMetaData();
13
14 List<Map> res = new ArrayList<>();
15
16 while (resultSet.next()){
17 Map map = new HashMap();
18
19 int columnCount = metaData.getColumnCount();
20
21 for (int i = 1; i <= columnCount; i++) {
22 String columnName = metaData.getColumnLabel(i);
23 map.put(columnName,resultSet.getObject(i));
24 }
25
26 res.add(map);
27 }
28
29 for (Map re : res) {
30 System.out.println(re);
31 }
32
33 resultSet.close();
34
35 preparedStatement.close();
36
37 connection.close();
主键回显
利用getGeneratedKeys方法获取一个结果集,首先在connection.prepareStatement方法中再传入一个参数:Statement.RETURN_GENERATED_KEYS 也可以用1代替(不推荐)
1 Class.forName("com.mysql.cj.jdbc.Driver");
2
3 Connection connection = DriverManager.getConnection(url, name, password);
4
5 String sql = "INSERT INTO t_user(account,password,nickname) VALUES(?,?,?);";
6
7 PreparedStatement preparedStatement = connection.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
8
9 preparedStatement.setObject(1,"test01");
10 preparedStatement.setObject(2,"123456");
11 preparedStatement.setObject(3,"JDBC");
12
13 int i = preparedStatement.executeUpdate();
14
15 if (i!=0){
16 System.out.println("Success");
17 ResultSet generatedKeys = preparedStatement.getGeneratedKeys();
18 generatedKeys.next();
19 int anInt = generatedKeys.getInt(1);
20 System.out.println("主键="+anInt);
21 }else {
22 System.out.println("False");
23 }
24
25 preparedStatement.close();
26
27 connection.close();
批量执行SQL语句
当需要成批插入或者更新记录时,可以采用Java的批量更新机制,这一机制允许多条语句一次性提交给数据库批量处理。通常情况下比单独提交处理更有效率
JDBC的批量处理语句包括下面三个方法:
addBatch(String):添加需要批量处理的SQL语句或是参数;
executeBatch():执行批量处理语句;
clearBatch():清空缓存的数据
通常我们会遇到两种批量执行SQL语句的情况:
多条SQL语句的批量处理;
一个SQL语句的批量传参;
注意:mysql服务器默认是关闭批处理的,我们需要通过一个参数,让mysql开启批处理的支持。
String url = "jdbc:mysql://localhost:3306/databasename?rewriteBatchedStatements=true";写在配置文件的url后面
用preparedStatement.addBatch();将数据添加到sql语句后面
注意:写sql语句的时候后面不能写分号!
最后添加完了用
preparedStatement.executeBatch();执行sql语句,示例如下:
1 String url = "jdbc:mysql://localhost:3306/databasename?rewriteBatchedStatements=true";
2
3 Class.forName("com.mysql.cj.jdbc.Driver");
4
5 Connection connection = DriverManager.getConnection(url, name, password);
6
7 String sql = "INSERT INTO t_user(account,password,nickname) VALUES(?,?,?)";
8
9 PreparedStatement preparedStatement = connection.prepareStatement(sql);
10
11 for (int i = 0; i < 10000; i++) {
12 preparedStatement.setObject(1,"test"+i);
13 preparedStatement.setObject(2,"password"+i);
14 preparedStatement.setObject(3,"tt"+i);
15
16 preparedStatement.addBatch();
17 }
18
19 preparedStatement.executeBatch();
20
21 preparedStatement.close();
22
23 connection.close();
Java JDBC连接数据库的CURD操作(JDK1.8 + MySQL8.0.33 + mysql-connector-java-8.0.27-bin驱动)的更多相关文章
- 纯Java JDBC连接数据库,且用JDBC实现增删改查的功能
Java JDBC连接数据库 package cn.cqvie.yjq; import java.sql.*; /** * 注册数据库的驱动程序,并得到数据库的连接对象 * @author yu * ...
- Mybatis异常处理之MySQL Connector Java] will not be managed by Spring
很长时间没写后台代码有点生疏了,这不今天又出点小插曲,写个文章记录下. 由于要上传点数据到后台,顺手整了个mybatis+springmvc.在保存数据时出现了异常. Creating a new S ...
- Java JDBC批处理插入数据操作
在此笔记里,我们将看到我们如何可以使用像Statement和PreparedStatement JDBC API来批量在任何数据库中插入数据.此外,我们将努力探索一些场景,如在内存不足时正常运行,以及 ...
- Java JDBC批处理插入数据操作(转)
在此笔记里,我们将看到我们如何可以使用像Statement和PreparedStatement JDBC API来批量在任何数据库中插入数据.此外,我们将努力探索一些场景,如在内存不足时正常运行,以及 ...
- Java JDBC的 url 配置信息和Mybatis核心配置文件(MySQL 的配置信息)
JDBC 连接数据库的 url driver=com.mysql.jdbc.Driver url=jdbc:mysql://localhost:3306/smbms?uesSSL=true&u ...
- Java JDBC连接数据库 Access连接数据库
1.加载JDBC驱动程序: 在连接数据库之前,首先要加载想要连接的数据库的驱动到JVM(Java虚拟机),再通过java.lang.Class类的静态方法forName(String classN ...
- [原创] Java JDBC连接数据库,反射创建实体类对象并赋值数据库行记录(支持存储过程)
1.SqlHelper.java import java.lang.reflect.*; import java.sql.*; import java.util.*; public class Sql ...
- java-Eclipse中使用JDBC连接数据库及相关操作
准备工作:mysql-connector-java-5.1.6-bin.jar配置 package com.job; import java.sql.Connection; import java.s ...
- JDBC连接数据库及其执行操作
作者:Alvin 功能:数据库连接与实现增删改查 时间:2019年3月4日08点33分 参考文章:https://www.2cto.com/database/201805/743741.html 一. ...
- java jdbc连接数据库,Properties 属性设置参数方法
今天在整合为数据库发现在配置中实现的赋值方式,可以用代码实现.特记录下共以后参考: 代码: // 操作数据库 Connection conn; String strData ...
随机推荐
- netstat 某连接的 Recv-Q(接收队列)达到500多万字节的内核参数排查
思路: cat proc文件系统下的 sys/net 目录下所有文件,根据结果降序排序(如果打印前xx,可能会漏掉关键信息,在定位问题时需要注意,慎用过滤),根据结果使用 grep -rn xxx 找 ...
- 20.1K Star!Notion的开源替代方案:AFFiNE
Notion这款笔记软件相信很多开发者都比较熟悉了,很多读者,包括我自己都用它来记录和管理自己的笔记.今天给大家推荐一个最近比较火的开源替代方案:AFFiNE.目前该开源项目已经斩获20.1K Sta ...
- DateTime和DateTimeOffset是同胞兄弟吗?
小编在日常开发中,用得最多的时间类型就是DateTime,直到一次偶然的邂逅,让小编遇见了DateTimeOffset.当时小编也是一脸迷茫,因为在小编的C#编程字典里就没出现过DateTimeOff ...
- C#/.net/DotNet/Emgu.CV裁剪照片头像
头像裁剪有利于人脸识别批量照片预处理,安防领域可以快速通过视频定位人脸,进行抓拍,做人脸识别相关功能的可能会应用到人脸裁剪,以下是我在实践中应用的代码,如有需要复制粘贴即可使用. using Emgu ...
- C#.NET 国密SM4对称加解密 与JAVA互通 ver:20230731
C#.NET 国密SM4对称加解密 与JAVA互通 ver:20230731 .NET 环境:.NET6 控制台程序(.net core). JAVA 环境:JAVA8,带maven 的JAVA控制台 ...
- 【后端面经-数据库】Redis详解——Redis基本概念和特点
目录 1. Redis基本概念 2. Redis特点 2.1 优点 2.2 缺点 3. Redis的应用场景 面试模拟 参考资料 声明:Redis的相关知识是面试的一大热门知识点,同时也是一个庞大的体 ...
- 如何做一个完美的api接口?
如何做一个api接口?:我们知道API其实就是应用程序编程接口,可以把它理解为是一种通道,用来和不同软件系统间进行通信,本质上它是预先定义的函数:-api,接口 1 我们知道API其实就是应用程序编程 ...
- 好好回答下 TCP 和 UDP 的区别!
写了这么多篇关于 TCP 和 UDP 的文章,还没有好好聊过这两个协议的区别,这篇文章我们就来开诚布公的谈一谈. 关于 TCP 和 UDP ,想必大家都看过一张这样的图. 有一个小姑娘在对着瓶口慢慢的 ...
- vue + canvas 实现九宮格手势解锁器
前言 专栏分享:vue2源码专栏,vue router源码专栏,玩具项目专栏,硬核推荐 欢迎各位 ITer 关注点赞收藏 此篇文章用于记录柏成从零开发一个canvas九宮格手势解锁器的历程,最终效果如 ...
- 【算法】湖心岛上的数学梦--用c#实现一元多次方程的展开式
每天清晨,当第一缕阳光洒在湖面上,一个身影便会出现在湖心小岛上.她坐在一块大石头上,周围被茂盛的植物环绕,安静地沉浸在数学的世界中. 这个姑娘叫小悦,她的故事在这个美丽的湖心小岛上展开.每天早晨,她都 ...