JDBC基础知识

JDBC 简介

1.持久化

 把数据保存到可掉电式存储设备中以供之后使用。大多数情况下,特别是企业级应用,数据持久化意味着将内存中的数据保存到硬盘上加以”固化”,而持久化的实现过程大多通过各种关系数据库来完成。 持久化的主要应用是将内存中的数据存储在关系型数据库中,当然也可以存储在磁盘文件、XML数据文件中。

2.JDBC概念(Java Database Connectivity)

JDBC(Java Data Base Connectivity)是一种用于执行 SQL 语句的 Java API,可以为多种关系数据库提供统一访问,它由一组用 Java 语言编写的类和接口组成。JDBC 提供了一种基准,据此可以构建更高级的工具和接口,使数据库开发人员能够编写数据库应用程序。
JDBC 为访问不同的数据库提供了一种统一的路径,为开发者屏蔽了一些细节问题。 
JDBC 的目标是使 Java 程序员使用 JDBC 可以连接任何提供了 JDBC 驱动程序的数据库系统,这样就使得程序员无需对特定的数据库系统的特点有过多的了解,从而大大简化和加快了开发过程。

3.数据库驱动

我们安装好数据库之后,我们的应用程序也是不能直接使用数据库的,必须要通过相应的数据库驱动程序,通过驱动程序去和数据库打交道。其实也就是数据库厂商的 JDBC 接口实现,即对 Connection 等接口的实现类的 jar 文件。
# JDB

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Mmit36uW-1636196187557)(C:\Users\admin\AppData\Roaming\Typora\typora-user-images\image-20211103095920377.png)]

JDBC 基础

1.操作步骤

前期准备

1、在 mysql 中创建一个库,并创建相应测试表和插入一些测试数据。
2、新建一个 Java 工程,并导入 MySQL 数据库驱动包,将 mysql 驱动拷入项目根目录并右键添加到项目依赖(Add As Library)。

JDBC 操作数据步骤一般分为如下五个步骤:

一、加载数据库驱动类

JDBC 操作数据步骤一般分为如下五个步骤:

二、建立连接(Connection)

Connection connection = DriverManager.getConnection(url,user,password);

三、创建用于向数据库发送 SQL 的 Statement 对象,并发送 sql

Statement statement = connection.createStatement();

四、从结果集的 ResultSet 中取出返回数据。

ResultSet resultSet = statement.excuteQuery(sql);

五、关闭相关资源,并释放内存

*.close()

案例:

import java.sql.*;public class Jdbc01 {public static void main(String[] args) throws ClassNotFoundException, SQLException {Class.forName("com.mysql.jdbc.Driver");Connection connection = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/mydb?useSSL=false", "root", "123456");Statement statement = connection.createStatement();ResultSet resultSet = statement.executeQuery("select * from student");while (resultSet.next()) {System.out.println(resultSet.getString(1));}resultSet.close();statement.close();connection.close();}
}

2.常见驱动类(driver)

全路径一般如下,导入相应的驱动 jar 包后即可加载相应的驱动类:

mysql 驱动 com.mysql.jdbc.Driveroracle 驱动 oracle.jdbc.driver.OracleDriversqlserver 驱动 com.microsoft.jdbc.sqlserver.SQLServerDriver

3.URL:

用于标识数据库的位置,一般由协议、主机、端口和数据库名构成,程序员通过 URL 地址指定 JDBC 程序连接的数据库信息,常见 URL 的写法如下:

Oracle— jdbc:oracle:thin:@localhost:1521:实例IDSqlServer— jdbc:microsoft:sqlserver://localhost:1433;DatabaseName=databaseNameMySql— jdbc:mysql://localhost:3306/databaseNameMySQL 连接的 url 格式如下,常用参数一般有 characterEncoding=utf-8&useSSL=false

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-k3bOKEwP-1636196187561)(C:\Users\admin\AppData\Roaming\Typora\typora-user-images\image-20211103112237821.png)]

注意:如果是连接本地,主机一般填写 127.0.0.1 或 localhost 和省略主机和端口。如果是连接服务器或虚拟机上的数据库服务则填写对应设备的 ip 地址和端口即可。

4.数据库常用对象

在使用 jdbc 过程中经常会使用到如下对象。

4.1.Connection:

Jdbc 程序中的 Connection,它用于代表数据库的连接,Collection 是数据库编程中最重要的一个对象,客户端与数据库所有交互都是通过 Connection 对象完成的,这个对象的常用方法:createStatement():创建向数据库发送 sql 的 Statement 对象。prepareStatement(sql) :创建向数据库发送预编译 sql 的 PrepareSatement 对象。prepareCall(sql):创建执行存储过程的 callableStatement 对象。setAutoCommit(boolean autoCommit):设置事务是否自动提交。commit() :在链接上提交事务。rollback() :在此链接上回滚事务。

4.2.Statement:

Jdbc 程序中的 Statement 对象用于向数据库发送 SQL 语句, Statement 对象常用方法:
executeQuery(String sql) :用于向数据发送查询语句。
executeUpdate(String sql):用于向数据库发送 insert、update 或 delete 语句
execute(String sql):用于向数据库发送任意 sql 语句
addBatch(String sql) :把多条 sql 语句放到一个批处理中。
executeBatch():向数据库发送一批 sql 语句执行。

4.3.ResultSet:

Jdbc 程序中的 ResultSet 用于代表 Sql 语句的执行结果。Resultset 封装执行结果时,采用的类似于表格的方式。ResultSet 对象维护了一个指向表格数据行的游标,初始的时候,游标在第一行之前,调用 resultSet.next() 方法,可以使游标指向具体的数据行,进行调用方法获取该行的数据。
ResultSet 提供检索不同类型字段的方法,常用的有:
getString(int index)、getString(String columnName):通过索引或者字段名获得在数据库里是 varchar、char 等类型的数据对象。
getFloat(int index)、getFloat(String columnName):通过索引或者字段名获得在数据库里是 Float 类型的数据对象。
getDate(int index)、getDate(String columnName):通过索引或者字段名获得在数据库里是 Date 类型的数据。
getBoolean(int index)、getBoolean(String columnName):通过索引或者字段名获得在数据库里是 Boolean 类型的数据。
getObject(int index)、getObject(String columnName):通过索引或者字段名获取在数据库里任意类型的数据。
注意:
ResultSet 的 index 是从 1 开始的,这与我们平时所写代码注意区分。
ResultSet 还提供了对结果集进行滚动的方法:
previous():移动到前一行
absolute(int row):移动到指定行
beforeFirst():移动 resultSet 的最前面。
afterLast() :移动到 resultSet 的最后面。
注意:释放资源,
Jdbc 程序运行完后,切记要释放程序在运行过程中,创建的那些与数据库进行交互的对象,这些对象通常有 ResultSet,Statement 和 Connection 对象。
释放资源按照“后开先关”原则,顺序如下:ResultSet → Statement → Connection
为确保资源释放代码能正确运行,资源释放代码在使用 try-catch 时一定要放在 finally 语句中。

5.SQL 注入与 PreparedStatement

是用户利用某些系统没有对输入数据进行充分的检查,从而进行恶意破坏的行为。statement 存在 sql 注入攻击问题,例如登陆用户名采用’ or 1=1 # or 时无论密码是否正确都将登录成功。

import java.sql.*;public class Jdbc01 {public static void main(String[] args) throws ClassNotFoundException, SQLException {Class.forName("com.mysql.jdbc.Driver");//String name = "Jack";String name = "'or 1=1 #";Connection connection = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/mydb?useSSL=false", "root", "123456");Statement statement = connection.createStatement();ResultSet resultSet = statement.executeQuery("select * from student where studentname='" + name + "' and studentage='20'");//最终SQL变成下面这种//SELECT * FROM student WHERE studentname=''or 1=1 #' and studentage='20'while (resultSet.next()) {System.out.println(resultSet.getString("studentname"));}resultSet.close();statement.close();connection.close();}
}

SQL 注入的根本原因是 SQL 字符串的原始拼接。它可能会导致数据库被恶意破坏,这是任何开发都需要注意的问题。随着 jdbc 的发展,为防范 SQL 注入,可以采用 PreparedStatement 取代 Statement。

PreperedStatement 是 Statement 的子类,它的实例对象可以通过调用 connection.preparedStatement() 方法获得,相对于 Statement 对象而言: PreperedStatement 可以避免 SQL 注入的问题。 Statement 会使数据库频繁编译 SQL,可能造成数据库缓冲区溢出。PreparedStatement 可对 SQL 进行预编译,从而提高数据库的执行效率。 并且 PreperedStatement 对于 SQL 中的参数,允许使用占位符的形式进行替换,简化 SQL 语句的编写。
Class.forName("com.mysql.jdbc.Driver");
Connection connection = DriverManager.getConnection("jdbc:mysql:///my_test?useSSL=false", "root", "123456");
PreparedStatement statement = connection.prepareStatement("select * from `jdbc_test` where `name` = ? and `pwd` = ?");
statement.setObject(1,"admin");
statement.setObject(2,"123");
ResultSet resultSet = statement.executeQuery();
while (resultSet.next()) {System.out.println(resultSet.getString(1) + "\t" + resultSet.getString(2) + "\t" + resultSet.getString(3));
}
resultSet.close();
statement.close();
connection.close();

注意:?不能作为字段名和表名的占位符,PreparedStatement 会为占位符 ? 的两边自动加上单引号,这样会使得 SQL 语句不可执行或找不到对应的表和字段,比如使用将表名设置为占位符,数据库执行 SQL 语句时,表名会用单引号引起来,这样会使得 SQL 语句执行出错或者查询不出数据。但这句代码在 SQL 中执行不会报错,但是查询没有结果。

6.数据库的 CRUD

CRUD 是增删改查的简写,分别对应:增加(Create)、查询(Retrieve)、修改(Update)和删除(Delete),使用 jdbc 通常也就是为了完成数据库的增删改查。增删改三种操作对 jdbc 都是相同的语法执行

statement.executeUpdate() 方法,该方法返回数据库的影响行数。如果数据库的影响行数为 0 这说明修改失败。

增加:

private static boolean add(User user) throws ClassNotFoundException, SQLException {Class.forName("com.mysql.jdbc.Driver");Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb?useSSL=false", "root", "123456");PreparedStatement statement = connection.prepareStatement("insert into user (name,password,age) values (?,?,?)");statement.setObject(1, user.getName());statement.setObject(2, user.getPassword());statement.setObject(3, user.getAge());int i = statement.executeUpdate();//返回数据库影响行数statement.close();connection.close();return i != 0;
}

查询:

private static List<User> query() throws ClassNotFoundException, SQLException {Class.forName("com.mysql.jdbc.Driver");Connection connection = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/mydb?useSSL=false", "root", "123456");PreparedStatement statement = connection.prepareStatement("select * from user");ResultSet resultSet = statement.executeQuery();List<User> list = new ArrayList<>();while (resultSet.next()) {int id = resultSet.getInt("id");int age = resultSet.getInt("age");String name = resultSet.getString("name");String password = resultSet.getString("password");list.add(new User(id, name, password, age));}resultSet.close();statement.close();connection.close();return list;
}

作业:(默写 30 分钟 6 个方法)

写完上面的两个案例后并补充两个方法。

参考代码:

1.完成用户的修改(根据 id 修改)boolean ok = update(User user) 。

2.根据id删除boolean ok = deleteByld(int id);

3.根据id查询用户信息User user=findById(int id);

4.查询数据库中的数据的总数量long count=countAll();

import java.sql.*;public class JdbcTest {private static boolean update(User user) throws ClassNotFoundException, SQLException {if (user.getId() == null)throw new RuntimeException("id 不能为空");Class.forName("com.mysql.jdbc.Driver");Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb?useSSL=false", "root", "123456");PreparedStatement statement = connection.prepareStatement("update user set name = ?,password=?,age=? where id =?");statement.setObject(1, user.getName());statement.setObject(2, user.getPassword());statement.setObject(3, user.getAge());statement.setObject(4, user.getId());int i = statement.executeUpdate();//返回数据库影响行数statement.close();statement.close();connection.close();return i != 0;}private static long countAll() throws ClassNotFoundException, SQLException {Class.forName("com.mysql.jdbc.Driver");Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb?useSSL=false", "root", "123456");PreparedStatement statement = connection.prepareStatement("select count(0) from user");ResultSet resultSet = statement.executeQuery();long count = 0;if (resultSet.next()) {count = resultSet.getLong(1);}statement.close();statement.close();connection.close();return count;}private static boolean deleteById(int id) throws ClassNotFoundException, SQLException {Class.forName("com.mysql.jdbc.Driver");Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb?useSSL=false", "root", "123456");PreparedStatement statement = connection.prepareStatement("delete from user where id =?");statement.setObject(1, id);int i = statement.executeUpdate();//返回数据库影响行数statement.close();statement.close();connection.close();return i != 0;}private static User findById(int id) throws ClassNotFoundException, SQLException {Class.forName("com.mysql.jdbc.Driver");Connection connection = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/mydb?useSSL=false", "root", "123456");PreparedStatement statement = connection.prepareStatement("select * from user where id =?");statement.setObject(1, id);ResultSet resultSet = statement.executeQuery();User user = null;if (resultSet.next()) {int age = resultSet.getInt("age");String name = resultSet.getString("name");String password = resultSet.getString("password");user = new User(id, name, password, age);}resultSet.close();statement.close();connection.close();return user;}
}

7.数据库分页

在 MySQL 中分页使用 limit 关键字实现:
Select * from table limit [M,]N ;
M:记录开始索引位置(从0开始)
N:取多少条记录
一般来说 M 和我们的 page 的关系为 M =(page-1)*size 换句话说,我们分页查询第 page 页,有 size 条数据时使用的 SQL

如下:

select * from user limit (page-1)*size,size

注意:

limit 后面不能进行数值运算,所以我们需要在 java 代码中运算后填入,代码如下:

int page = 2;
int size = 10;
Class.forName("com.mysql.jdbc.Driver");
Connection connection = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/mydb?useSSL=false", "root", "123456");
PreparedStatement statement = connection.prepareStatement("select * from student limit ?,?");
statement.setObject(1, (page - 1) * size);
statement.setObject(2, size);
ResultSet resultSet = statement.executeQuery();
while (resultSet.next()) {System.out.println(resultSet.getObject(2));
}
resultSet.close();
statement.close();
connection.close();

Oracle 中没有 limit 关键字,分页需要依赖行号(rownum)和子查询完成分页,SQL 如下:

select * from ( select rownum r_, row_.* from ( select * from student order by id ) row_ where rownum <=Y ) where r_>=X ;
X:起始索引位置。
Y:结束索引位置。
练习:
1.设计一个方法,进行分页查询 List<User> list(int page, int size)。page 表示当前页数,size 表示一页显示的总条数
List<User> list = list(1,5) ;表示获取第一页,一共显示 5 条数据
List<User> list = list(3,5) ;表示第三页,一共显示 5 条数据
2.向数据库中插入1000 条数据,分别使用 Statement 和 PreparedStatement,比较各自花的时间差异。
3.在题 2 的基础上,校验使用数据库索引和没有索引时的查询耗时对比。

参考代码:

import java.sql.*;
import java.util.ArrayList;
import java.util.List;public class JdbcTest {private static void t3() throws ClassNotFoundException, SQLException {Class.forName("com.mysql.jdbc.Driver");Connection connection = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/mydb?useSSL=false", "root", "123456");long start = System.currentTimeMillis();PreparedStatement prepareStatement = connection.prepareStatement("select * from user where name ='姓名699'");ResultSet resultSet = prepareStatement.executeQuery();System.out.println(System.currentTimeMillis() - start);resultSet.close();prepareStatement.close();connection.close();}private static void t2() throws ClassNotFoundException, SQLException {Class.forName("com.mysql.jdbc.Driver");Connection connection = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/mydb?useSSL=false", "root", "123456");PreparedStatement prepareStatement = connection.prepareStatement("insert into user (name,password,age) values (?,?,?)");long start = System.currentTimeMillis();System.out.println("PreparedStatement:执行开始计时");for (int i = 0; i < 1000; i++) {prepareStatement.setObject(1, "姓名" + i);prepareStatement.setObject(2, "密码" + i);prepareStatement.setObject(3, 18);prepareStatement.executeUpdate();}System.out.println("PreparedStatement:执行时间" + (System.currentTimeMillis() - start));prepareStatement.close();Statement statement = connection.createStatement();long start2 = System.currentTimeMillis();for (int i = 0; i < 1000; i++) {statement.executeUpdate("insert into user (name,password,age) values ('姓名" + i + "','密码" + i + "',18)");}System.out.println("Statement:执行时间" + (System.currentTimeMillis() - start2));statement.close();connection.close();}private static List<User> list(int page, int size) throws ClassNotFoundException, SQLException {Class.forName("com.mysql.jdbc.Driver");Connection connection = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/mydb?useSSL=false", "root", "123456");PreparedStatement statement = connection.prepareStatement("select * from user limit ?,?");statement.setObject(1, (page - 1) * size);statement.setObject(2, size);ResultSet resultSet = statement.executeQuery();List<User> list = new ArrayList<>();while (resultSet.next()) {int id = resultSet.getInt("id");int age = resultSet.getInt("age");String name = resultSet.getString("name");String password = resultSet.getString("password");list.add(new User(id, name, password, age));}resultSet.close();statement.close();connection.close();return list;}
}

8.获取数据库自增主键

在实际开发中,我们经常需要获取插入数据的自增 id 针对这样的需求通常我们有两种解决办法。

1.插入完成后查询最大的 id 值:适用低并发的情况,如果数据库有多个线程同时插入时获取到的 id 将是不准确的。

2.使用 jdbc 中相应的 API 获取自增主键:适用全部情况。

获取数据库自增主键只能针对插入 SQL,用法如下:

String sql = "insert into user(name,password,email,birthday) values('abc','123','abc@sina.com','1978-08-08')";
PreparedStatement st = conn.prepareStatement(sql,Statement.RETURN_GENERATED_KEYS);
st.executeUpdate();
ResultSet rs = st.getGeneratedKeys();  //得到插入行的主键
if(rs.next())System.out.println(rs.getObject(1));
}

练习:

1.当插入一条数据之后,通过获取自增长 id,得到这条数据的 id,比如说是 55。删除这条数据的前一条,如果 54 不存在,则删除 53,以此类推直到删除上一条数据。

参考代码:

private static void t1() throws ClassNotFoundException, SQLException {Class.forName("com.mysql.jdbc.Driver");Connection connection = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/mydb?useSSL=false", "root", "123456");PreparedStatement statement = connection.prepareStatement("insert into user (name,password,age) values ('姓名','密码',18)", Statement.RETURN_GENERATED_KEYS);statement.executeUpdate();ResultSet resultSet = statement.getGeneratedKeys();resultSet.next();int maxId = resultSet.getInt(1);System.out.println("插入的id是:" + maxId);for (int id = maxId - 1; id > 0; id--) {PreparedStatement statement1 = connection.prepareStatement("select * from user where id=?");statement1.setObject(1, id);ResultSet resultSet1 = statement1.executeQuery();if (!resultSet1.next()) {resultSet.close();statement1.close();continue;} else {System.out.println("删除数据:" + id);PreparedStatement statement2 = connection.prepareStatement("delete from user where id = ?");statement2.setObject(1, id);statement2.executeUpdate();statement2.close();resultSet1.close();statement1.close();break;}}resultSet.close();statement.close();connection.close();
}

9.调用存储过程

调用存储过程

create table p_user(  id int primary key auto_increment,  name varchar(10),sex char(2)
)ENGINE=InnoDB DEFAULT CHARSET=utf8;
insert into p_user(name,sex) values('A',"男");
insert into p_user(name,sex) values('B',"女");
insert into p_user(name,sex) values('C',"男");

创建存储过程(查询得到男性或女性的数量,如果传入的是0就女性否则是男性)

DELIMITER $
CREATE PROCEDURE ges_user_count(IN sex_id INT, OUT user_count INT)
BEGIN
IF sex_id=0 THEN
SELECT COUNT(*) FROM p_user WHERE p_user.sex='女' INTO user_count;
ELSE
SELECT COUNT(*) FROM p_user WHERE p_user.sex='男' INTO user_count;
END IF;
END
$

测试调用存储过程

DELIMITER ;
SET @user_count = 0;
CALL ges_user_count(1, @user_count);
SELECT @user_count;

查询得到男性或女性的数量, 如果传入的是 0 就女性否则是男性

jdbc 调用存储过程

private static void t2() throws ClassNotFoundException, SQLException {Class.forName("com.mysql.jdbc.Driver");Connection connection = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/mydb?useSSL=false", "root", "123456");CallableStatement prepareCall = connection.prepareCall("{call ges_user_count(?, ?)}");prepareCall.setInt(1, 1);prepareCall.registerOutParameter(2, Types.INTEGER);prepareCall.execute();System.out.println(prepareCall.getString(2));connection.close();
}

10.数据库的隔离级别(自学)

对于同时运行的多个事务,当这些事务访问数据库中相同的数据时,如果没有采取必要的隔离机制,就会导致各种并发问题:
脏读:对于两个事务 T1,T2,T1 读取了已经被 T2 更新但还没有被提交的字段之后,若 T2 回滚,T1 读取的内容就是临时且无效的。
不可重复读:对于两个事务 T1,T2,T1 读取了一个字段,然后 T2 更新了该字段. 之后,T1 再次读取同一个字段,值就不同了。
幻读:对于两个事务 T1,T2,T1 从一个表中读取了一个字段,然后 T2 在该表中插入了一些新的行。之后,如果 T1 再次读取同一个表,就会多出几行。
数据库事务的隔离性:数据库系统必须具有隔离并发运行各个事务的能力,使它们不会相互影响,避免各种并发问题. 一个事务与其他事务隔离的程度称为隔离级别. 数据库规定了多种事务隔离级别,不同隔离级别对应不同的干扰程度,隔离级别越高,数据一致性就越好,但并发性越弱。

数据库共定义了四种隔离级别:

Serializable:可避免脏读、不可重复读、虚读情况的发生。(串行化)
Repeatable read:可避免脏读、不可重复读情况的发生。
Read committed:可避免脏读情况发生。
Read uncommitted:最低级别,以上情况均无法保证。(读未提交)

Oracle 支持 2 种事务隔离级别:READ COMMITED,SERIALIZABLE。Oracle 默认的事务隔离级别为: READ COMMITED

Mysql 支持 4 种事务隔离级别。Mysql 默认的事务隔离级别为: REPEATABLE READ

章节练习:

1.使用 SQLYog 完成如下数据表的创建并使用 jdbc 将下面全部学生的信息插入到数据库

CREATE TABLE `student` (`id` int(11) NOT NULL AUTO_INCREMENT,`name` varchar(20) DEFAULT NULL,`chinese` float DEFAULT NULL,`english` float DEFAULT NULL,`math` float DEFAULT NULL,PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8;insert  into `student`(`id`,`name`,`chinese`,`english`,`math`) values (1,'张小明',89,78,90);
insert  into `student`(`id`,`name`,`chinese`,`english`,`math`) values (2,'李进',67,98,56);
insert  into `student`(`id`,`name`,`chinese`,`english`,`math`) values (3,'王五',87,78,77);
insert  into `student`(`id`,`name`,`chinese`,`english`,`math`) values (4,'李一',88,98,90);
insert  into `student`(`id`,`name`,`chinese`,`english`,`math`) values (5,'李来财',82,84,67);
insert  into `student`(`id`,`name`,`chinese`,`english`,`math`) values (6,'张进宝',55,85,45);
insert  into `student`(`id`,`name`,`chinese`,`english`,`math`) values (7,'黄蓉',75,65,30);

2.在题目 1 的基础上完成如下的查询,并封装对应的返回结果 Student(无法映射时可以采用 Map)

1.在查询时对所有学生数学分数上加 10 分特长分。
2.统计每个学生的姓名和总分。
3.查询所有姓李的学生成绩。
4.查询英语成绩大于90分的同学。
5.查询总分大于200分的所有同学。

参考代码:

import java.sql.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;public class JdbcTest {private static void t2() throws ClassNotFoundException, SQLException {Class.forName("com.mysql.jdbc.Driver");Connection connection = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/mydb?useSSL=false", "root", "123456");// 1.在查询时对所有学生数学分数上加 10 分特长分。List&lt;Student&gt; students = m1(connection);System.out.println(students);//2.统计每个学生的姓名和总分。Map&lt;String, Double&gt; all = m2(connection);System.out.println(all);//3.查询所有姓李的学生成绩students = m3(connection, "李%");System.out.println(students);//4.查询英语成绩大于90分的同学students = m4(connection, 90);System.out.println(students);//5.查询总分大于200分的所有同学students = m5(connection, 200);System.out.println(students);connection.close();}//5.查询总分大于200分的所有同学private static List&lt;Student&gt; m5(Connection connection, int i) throws SQLException {PreparedStatement statement = connection.prepareStatement("select `id`,`name`,`chinese`,`english`,`math` from student where `chinese`+`english`+`math` &gt; ?");statement.setObject(1, i);ResultSet resultSet = statement.executeQuery();List&lt;Student&gt; list = new ArrayList&lt;&gt;();while (resultSet.next()) {list.add(new Student(resultSet.getInt("id"), resultSet.getString("name"), resultSet.getDouble("chinese"), resultSet.getDouble("english"), resultSet.getDouble("math")));}resultSet.close();statement.close();return list;}//4.查询英语成绩大于90分的同学private static List&lt;Student&gt; m4(Connection connection, int i) throws SQLException {PreparedStatement statement = connection.prepareStatement("select `id`,`name`,`chinese`,`english`,`math` from student where english &gt; ?");statement.setObject(1, i);ResultSet resultSet = statement.executeQuery();List&lt;Student&gt; list = new ArrayList&lt;&gt;();while (resultSet.next()) {list.add(new Student(resultSet.getInt("id"), resultSet.getString("name"), resultSet.getDouble("chinese"), resultSet.getDouble("english"), resultSet.getDouble("math")));}resultSet.close();statement.close();return list;}//3.查询所有姓李的学生成绩private static List&lt;Student&gt; m3(Connection connection, String s) throws SQLException {PreparedStatement statement = connection.prepareStatement("select `id`,`name`,`chinese`,`english`,`math` from student where name like ?");statement.setObject(1, s);ResultSet resultSet = statement.executeQuery();List&lt;Student&gt; list = new ArrayList&lt;&gt;();while (resultSet.next()) {list.add(new Student(resultSet.getInt("id"), resultSet.getString("name"), resultSet.getDouble("chinese"), resultSet.getDouble("english"), resultSet.getDouble("math")));}resultSet.close();statement.close();return list;}//2.统计每个学生的姓名和总分。private static Map&lt;String, Double&gt; m2(Connection connection) throws SQLException {PreparedStatement statement = connection.prepareStatement("select `name`,`chinese`+`english`+`math` `sum` from student");ResultSet resultSet = statement.executeQuery();Map&lt;String, Double&gt; map = new HashMap&lt;&gt;();while (resultSet.next()) {map.put(resultSet.getString("name"), resultSet.getDouble("sum"));}resultSet.close();statement.close();return map;}//1.在查询时对所有学生数学分数上加 10 分特长分。private static List&lt;Student&gt; m1(Connection connection) throws SQLException {PreparedStatement statement = connection.prepareStatement("select `id`,`name`,`chinese`,`english`,`math`+10 math from student");ResultSet resultSet = statement.executeQuery();List&lt;Student&gt; list = new ArrayList&lt;&gt;();while (resultSet.next()) {list.add(new Student(resultSet.getInt("id"), resultSet.getString("name"), resultSet.getDouble("chinese"), resultSet.getDouble("english"), resultSet.getDouble("math")));}resultSet.close();statement.close();return list;}private static void t1() throws ClassNotFoundException, SQLException {Class.forName("com.mysql.jdbc.Driver");Connection connection = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/mydb?useSSL=false", "root", "123456");String sql = "insert  into `student`(`id`,`name`,`chinese`,`english`,`math`) values (1,'张小明',89,78,90);" +"insert  into `student`(`id`,`name`,`chinese`,`english`,`math`) values (2,'李进',67,98,56);" +"insert  into `student`(`id`,`name`,`chinese`,`english`,`math`) values (3,'王五',87,78,77);" +"insert  into `student`(`id`,`name`,`chinese`,`english`,`math`) values (4,'李一',88,98,90);" +"insert  into `student`(`id`,`name`,`chinese`,`english`,`math`) values (5,'李来财',82,84,67);" +"insert  into `student`(`id`,`name`,`chinese`,`english`,`math`) values (6,'张进宝',55,85,45);" +"insert  into `student`(`id`,`name`,`chinese`,`english`,`math`) values (7,'黄蓉',75,65,30);";String[] split = sql.split(";");for (String s : split) {if (s == null || s == "")continue;PreparedStatement statement = connection.prepareStatement(s);statement.executeUpdate();statement.close();}connection.close();}
}

JDBC 基础、CRUD、分页 第一节相关推荐

  1. 零基础学习SQL第一节

    零基础学习SQL第一大节 第一节:数据库与SQL 我们身边的数据库 大家都有过下面这样的经历吧? 收到曾经为自己诊治过的牙医寄来的明信片,上面写着"距上次检查已有半年,请您再来做个牙齿健康查 ...

  2. Python基础系列教程 第一节 安装运行Python

    安装Python解释器 Python 是一门解释性脚本语言,因此要想让你编写的代码得以运行,需要先安装 CPython 解释器. 根据你电脑的系统以及位数不同,安装步骤也有所差异. Windows 系 ...

  3. python基础知识整理 第一节:入门记录(包含代码与执行结果)

    选中一个单元格,点击Esc,再点击h键,即可出现帮助界面.

  4. Linux 基础学习(第一节)

    IP地址的配置 配置临时IP地址 ifconfig etho 192.168.0.91 255.255.255.0 图形化下面配置IP地址: 重启网卡服务: shell环境配置网卡信息 必备的参数 关 ...

  5. html5画布funcition,2020前端基础知识学习第一节(示例代码)

    一.选择题 1. 浏览器端的存储技术有哪些() A.cookie B.localStorage C.session D.userData 答案:A B D 分析:cookie通常用于存储用户等登录信息 ...

  6. c++基础学习 (第一节课)

    一.new和delete 一.介绍 new:关键字,申请内存 delete:关键字,释放内存 二.使用和特点 一.new的使用 /*new的使用*///申请内存//1事情单个内存(一个自己所需要的大小 ...

  7. 机器学习从零基础开始【第一节】

  8. 第一节计算机课开场白,第一节课有趣的开场白

    我是一名新老师,请问第一堂课的开场白怎么讲 我:上课 学生:起立 我:同学们好 学生:老师好 我:请坐 我:很高兴见到大家. 我是你们的英语(或其他的学科)老师 我叫* 老师有一个小小的请求. 大家一 ...

  9. JDBC 学习笔记(一)—— 基础知识 + 分页技术

    2019独角兽企业重金招聘Python工程师标准>>> 本文查阅方法:     1.查阅目录 -- 查阅本文目录,确定想要查阅的目录标题     2.快捷"查找" ...

最新文章

  1. [羊城杯 2020]RRRRRRRSA
  2. Spark SQL之jdbc方式访问
  3. WIN7 64位系统注册银行支付组件
  4. 每日一题(38)—— 一个32位的机器,该机器的指针是多少位?
  5. android 8.0 用户体验优化--day02
  6. 抖音何以为“抖音”?少不了A/B测试的功劳
  7. undefined reference to `inflateInit2_'
  8. 2021新鲜出炉软件测试的真实面试题(一篇足以)
  9. C#信息采集系统,常见控件练习
  10. DevOps技术学习路线图 初阶+中阶+高阶
  11. Docker容器实战(七) - 容器中进程视野下的文件系统
  12. 在echarts中使用百度地图扩展,实现在地图上叠加显示栅格热力图
  13. java基础:面向对象编程23-this课后练习boygirl
  14. python爬虫———多线程threading模块爬取抖音用户信息
  15. iframe X-Frame-Options
  16. 2022年了,虚拟内存还是那个虚拟内存吗?
  17. ❤️数据可视化❤️:基于Echarts + GeoJson实现的地图视觉映射散点(气泡)组件【15】 - 江西省
  18. 使用install安装应用的时候出现INSTALL_FAILED_SHARED_USER_INCOMPATIBLE问题的解决方法
  19. 百度地图WebAPI
  20. 率土之滨鸿蒙团,关于率土之滨几个顶级大盟的实力分析

热门文章

  1. 【Vitis Accel】1 - HLS 简介
  2. 使用Python输出正金字塔
  3. swag_ios安卓 testlight /apps/android官方开发包安装
  4. Zookeeper 3.5.7学习记录(一)——集群的坑
  5. 10. JavaScript
  6. properties文件
  7. 如何从零开始设计一款小程序原型?
  8. URL请求加密 参数的sign签名 与验签
  9. 从csv文件中导入数据到MySQL数据库
  10. 怎样批量修改图片名称,一键处理