jdbc 基础

1.jdbc 基础

本篇主要内容如下:

  1. 操作步骤
  2. 数据库常用对象
  3. SQL 注入与 PreperedStatement
  4. 数据库的 CRUD
  5. 数据库分页
  6. 获取数据库自增主键
  7. 调用存储过程
  8. 数据库的隔离级别(自学)
操作步骤

前期准备

1、在 mysql 中创建一个库,并创建相应测试表和插入一些测试数据。 

2、新建一个 Java 工程,并导入 MySQL 数据库驱动包,将 mysql 驱动拷入项目根目录并右键添加到项目依赖(Add As Library)。 

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

一、加载数据库驱动类。

Class.forName(driver)

二、建立连接(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();
}
}

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

  • mysql 驱动 com.mysql.jdbc.Driver
  • oracle 驱动 oracle.jdbc.driver.OracleDriver
  • sqlserver 驱动 com.microsoft.jdbc.sqlserver.SQLServerDriver

URL:

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

  • Oracle—
    jdbc:oracle:thin:@localhost:1521:实例ID
  • SqlServer—
    jdbc:microsoft:sqlserver://localhost:1433;DatabaseName=databaseName
  • MySql—
    jdbc:mysql://localhost:3306/databaseName

MySQL 连接的 url 格式如下,常用参数一般有 characterEncoding=utf-8&useSSL=false


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


数据库常用对象

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

1.Connection:

Jdbc 程序中的 Connection,它用于代表数据库的连接,Collection 是数据库编程中最重要的一个对象,客户端与数据库所有交互都是通过 Connection 对象完成的,这个对象的常用方法:

  •  createStatement():创建向数据库发送 sql 的 Statement 对象。
  •  prepareStatement(sql) :创建向数据库发送预编译 sql 的 PrepareSatement 对象。
  •  prepareCall(sql):创建执行存储过程的 callableStatement 对象。
  •  setAutoCommit(boolean autoCommit):设置事务是否自动提交。
  •  commit() :在链接上提交事务。
  •  rollback() :在此链接上回滚事务。 


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 语句执行。  


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 还提供了对结果集进行滚动的方法: 

  • next():移动到下一行 
  • previous():移动到前一行 
  • absolute(int row):移动到指定行 
  • beforeFirst():移动 resultSet 的最前面。 
  • afterLast() :移动到 resultSet 的最后面。

注意:释放资源,Jdbc 程序运行完后,切记要释放程序在运行过程中,创建的那些与数据库进行交互的对象,这些对象通常有 ResultSet,Statement 和 Connection 对象。  

释放资源按照“后开先关”原则,顺序如下:ResultSet → Statement → Connection

为确保资源释放代码能正确运行,资源释放代码在使用 try-catch 时一定要放在 finally 语句中。 


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 中执行不会报错,但是查询没有结果。


数据库的 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 分钟)

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

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

根据 id 删除 boolean ok = deleteById(int id);

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

④查询数据库中的数据的总数量 int 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;
}
}



数据库分页

在 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;
}
}



获取数据库自增主键

在实际开发中,我们经常需要获取插入数据的自增 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();
}



调用存储过程

创建表和存储过程

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();
}



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

对于同时运行的多个事务,当这些事务访问数据库中相同的数据时,如果没有采取必要的隔离机制,就会导致各种并发问题:

脏读:对于两个事务 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<Student> students = m1(connection);
System.out.println(students);

//2.统计每个学生的姓名和总分
Map<String, Double> 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<Student> m5(Connection connection, int i) throws SQLException {
PreparedStatement statement = connection.prepareStatement(
"select id,name,chinese,english,math from student where chinese+english+math > ?");
statement.setObject(1, i);
ResultSet resultSet = statement.executeQuery();
List<Student> list = new ArrayList<>();
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<Student> m4(Connection connection, int i) throws SQLException {
PreparedStatement statement = connection.prepareStatement("select id,name,chinese,english,math from student where english > ?");
statement.setObject(1, i);
ResultSet resultSet = statement.executeQuery();
List<Student> list = new ArrayList<>();
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<Student> 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<Student> list = new ArrayList<>();
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<String, Double> m2(Connection connection) throws SQLException {
PreparedStatement statement = connection.prepareStatement("select name,chinese+english+math sum from student");
ResultSet resultSet = statement.executeQuery();
Map<String, Double> map = new HashMap<>();
while (resultSet.next()) {
map.put(resultSet.getString("name"), resultSet.getDouble("sum"));
}
resultSet.close();
statement.close();
return map;
}

//1.在查询时对所有学生数学分数上加 10 分特长分。
private static List<Student> m1(Connection connection) throws SQLException {
PreparedStatement statement = connection.prepareStatement("select id,name,chinese,english,math+10 math from student");
ResultSet resultSet = statement.executeQuery();
List<Student> list = new ArrayList<>();
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();
}
}



posted @ 2021-10-04 02:37  柠檬色的橘猫  阅读(73)  评论(0)    收藏  举报