一、JDBC概念
JDBC全称Java DataBase Connectivity,是使用Java语言操作关系型数据库的一套API。
JDBC出现的原因:解决用一套Java代码,操作不同的关系型数据库的问题。
JDBC的本质是一套接口,各数据库厂商去实现这套接口,提供数据库驱动jar包,我们用这套接口编程,真正执行的代码是驱动jar包中的实现类。
二、核心api使用步骤
1、静态SQL使用方法(SQL语句程序中已经写好了)
1)注册驱动
调用静态方法,但是会注册两次
// 依赖:驱动版本8+com.mysql.cj.jdbc.Driver
// 驱动版本5+com.mysql.jdbc.Driver
DriverManager.registerDriver(new com.mysql.cj.jdbc.Driver());
反射触发
// 依赖:驱动版本8+com.mysql.cj.jdbc.Driver
// 驱动版本5+com.mysql.jdbc.Driver
Class.forName("com.mysql.cj.jdbc.Driver");
2)获取连接(有三种方法)
- 传三个参数的写法
// 1、传三个参数
// 参数url;jdbc:数据库厂商名://ip地址|主机名:port端口号/数据库名?key=value&key=value
// 数据库ip地址:127.0.0.1 | localhost
// 数据库端口号:3306
// 数据库名字:s_t
// ?key=value&key=value后面的是可选信息
String url="jdbc:mysql://localhost:3306/s_t";
// 或者:String url="jdbc:mysql://127.0.0.1:3306/s_t";
// 参数username:数据库的账号
String username="root";
// 参数password:数据库的密码
String password="123";
Connection conn=DriverManager.getConnection(url,username,password);
- 传两参数的写法
// 2、传两个参数
String url="jdbc:mysql://localhost:3306/s_t";
// Properties info:存账号和密码
Properties info=new Properties();
// 账号信息
info.put("user","root");
// 密码信息
info.put("password","123");
Connection conn=DriverManager.getConnection(url,info);
- 传一个参数的写法
// 3、传一个参数
String url="jdbc:mysql://localhost:3306/s_t?user=root&password=123";
Connection conn=DriverManager.getConnection(url);
注:
?key=value&key=value后面的是可选信息
// 8.0.27版本之前要加 serverTimezone=Asia/Shanghai,8.0.27版本之后自动识别时区就不用写了
// 8版本以后,默认使用的就是utf-8格式,所以不用写 useUnicode=true&characterEncoding=utf8&useSSL=true
3)创建发送SQL语句对象
基于statement存在的问题
1. SQL语句需要字符拼接
2. 只能拼接字符串类型,其他的数据库类型无法处理
3. 会发生SQL注入
// statement 可以发送SQL语句到数据库,并且获取返回结果
Statement stnt=conn.createStatement();
4)发送SQL语句,并获取返回结果
- 用executeUpdate方法
// 1)定义SQL
"UPDATE cno_count SET `COUNT(*)` =4 WHERE Cno='C001'";
// 2)执行sql
// SQL分类:DDL(数据库、表的创建、修改、删除) DML(数据的插入、修改、删除) DQL(查询) DCL(权限控制) TPL(事物控制语言)
// 方法1:executeUpdate
// 参数:SQL 非DQL
// 返回:int
// 使用方法:
// 1.DML返回影响的行数,如删1条数据就return 1;
// 2.非DML return 0;
int updateResults=stnt.executeUpdate(sqlUpdate);
- 用executeQuery方法
// 1)定义SQL
String sqlSelect="SELECT * FROM cno_count WHERE Cno='C001";
// 2)执行sql
// SQL分类:DDL(数据库、表的创建、修改、删除) DML(数据的插入、修改、删除) DQL(查询) DCL(权限控制) TPL(事物控制语言)
// 方法2:executeQuery
// 参数:SQL DQL
// 返回:resultSet 结果封装对象
ResultSet selectResults=stnt.executeQuery(sqlSelect);
5)结果处理
- 用executeUpdate方法
// 输出executeUpdate的返回结果
System.out.println(updateResults);
- 用executeQuery方法
// 输出executeQuery的返回结果
// 解析resultSet 结果封装对象
// 1、移动游标指定获取数据行
// resultSet内部包含一个游标,指定当前行数据
// 默认游标指定的是第一行数据之前
// 可以调用next方法向后移动一行游标,next()方法的返回值类型是boolean,true:有下一行;false:没有下一行
while (selectResults.next())
{
// 2、获取指定数据行的列数据即可
// resultSet.get类型(String columnLabel | int columnIndex);
// columnLabel:列名获取(如果有别名写别名)
String Cno=selectResults.getString("Cno");
// columnIndex:列的下角标获取(从左到右,从1开始)
int count=selectResults.getInt(2);
}
6)释放资源
// 第三步的statement的对象
stnt.close();
// 第二步的Connection的对象
conn.close();
// 第四步的resultSet结果封装对象
selectResults.close();
7)s_t数据库cno_count表
8)完整的一个例子:
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
public class Main {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
// 1、注册驱动
// 依赖:驱动版本8+com.mysql.cj.jdbc.Driver
// 驱动版本5+com.mysql.jdbc.Driver
Class.forName("com.mysql.cj.jdbc.Driver");
// 2、获取连接
// 参数url;jdbc:数据库厂商名://ip地址:port/数据库名
// 数据库ip地址:127.0.0.1
// 数据库端口号:3306
String url="jdbc:mysql://127.0.0.1:3306/s_t";
// 参数username:数据库的账号
String username="root";
// 参数password:数据库的密码
String password="123";
Connection conn=DriverManager.getConnection(url,username,password);
// 3、获取sql对象
Statement stnt=conn.createStatement();
// 4、发送SQL语句,并获取返回结果
// 定义SQL
String sql="UPDATE cno_count SET `COUNT(*)` =4 WHERE Cno='C001'";
// 执行sql
int count=stnt.executeUpdate(sql);
// 5、处理结果
System.out.println(count);
// 6、释放资源
stnt.close();
conn.close();
}
}
2、预编译SQL使用方法
1)注册驱动(同上)
Class.forName("com.mysql.cj.jdbc.Driver");
2)获取连接,有三种方法(同上)
String url="jdbc:mysql://localhost:3306/s_t?serverTimezone=GMT%2B8";
// 参数username:数据库的账号
String username="root";
// 参数password:数据库的密码
String password="123";
Connection conn= DriverManager.getConnection(url,username,password);
3)发送SQL语句,并返回结果
- 用executeUpdate方法
// 获取查询信息
Scanner input =new Scanner(System.in);
System.out.println("请输入学号");
String Cno=input.next();
// preparedStatement
// 1、编写SQL语句,动态值部分使用占位符 ? 代替(?只能代替动态值)
String sqlUpdate="UPDATE cno_count SET `COUNT(*)` =4 WHERE Cno= ?;";
// 2、创建预编译preparedStatement并且设置SQL语句结果
PreparedStatement preparedStatementUpdate=conn.prepareStatement(sqlUpdate);
// 3、单独的占位符进行赋值
// 参数1:intdex 占位符的位置(从左向右数,从1开始,Cno count)
// 参数2:object 占位符的值(可以设置任何类型的数据)
preparedStatementUpdate.setObject(1,Cno);
// 4、发送SQL语句,并获取返回结果
// preparedStatement.executeUpdate | executeQuery();
int updateResults=preparedStatementUpdate.executeUpdate();
- 用executeQuery方法
// 获取查询信息
Scanner input =new Scanner(System.in);
System.out.println("请输入学号");
String Cno=input.next();
System.out.println("请输入选课数");
int count=input.nextInt();
// preparedStatement
// 1、编写SQL语句,动态值部分使用占位符 ? 代替(?只能代替动态值)
String sqlSelect="SELECT * FROM cno_count WHERE Cno= ? AND COUNT(*)= ?;";
// 2、创建预编译preparedStatement并且设置SQL语句结果
PreparedStatement preparedStatementSelect=conn.prepareStatement(sqlSelect);
// 3、单独的占位符进行赋值
// 参数1:intdex 占位符的位置(从左向右数,从1开始,Cno count)
// 参数2:object 占位符的值(可以设置任何类型的数据)
preparedStatementSelect.setObject(1,Cno);
preparedStatementSelect.setObject(2,count);
// 4、发送SQL语句,并获取返回结果
// preparedStatement.executeUpdate | executeQuery();
ResultSet selectResults=preparedStatementSelect.executeQuery();
4)处理结果(同上)
- 用executeUpdate方法
// 输出executeUpdate的返回结果
System.out.println(updateResults);
- 用executeQuery方法
返回一行数据可用
输出executeQuery的返回结果
// 解析resultSet 结果封装对象
// 1)移动游标指定获取数据行
// resultSet内部包含一个游标,指定当前行数据
// 默认游标指定的是第一行数据之前
// 可以调用next方法向后移动一行游标,next()方法的返回值类型是boolean,true:有下一行;false:没有下一行
while (selectResults.next())
{
// 2)获取指定数据行的列数据即可
// resultSet.get类型(String columnLabel | int columnIndex);
// columnLabel:列名获取(如果有别名写别名)
String Cno=selectResults.getString("Cno");
// columnIndex:列的下角标获取(从左到右,从1开始)
int count=selectResults.getInt(2);
}
若返回多行数据可用
// 输出executeQuery的返回结果
// 解析resultSet 结果封装对象
// 1、移动游标指定获取数据行
// resultSet内部包含一个游标,指定当前行数据
// 默认游标指定的是第一行数据之前
// 可以调用next方法向后移动一行游标,next()方法的返回值类型是boolean,true:有下一行;false:没有下一行
List<Map> list=new ArrayList<>();
while (selectResults.next())
{
Map map=new HashMap();
// 一行数据对应一个map
// 2)获取指定数据行的列数据即可
// resultSet.get类型(String columnLabel | int columnIndex);
// columnLabel:列名获取(如果有别名写别名)
map.put("Cno",selectResults.getString("Cno"));
// columnIndex:列的下角标获取(从左到右,从1开始)
map.put("count",selectResults.getInt(2));
// 将map存储到集合中
list.add(map);
}
若返回多行数据可用(更好)
// 输出executeQuery的返回结果
// 解析resultSet 结果封装对象
// 1、移动游标指定获取数据行
// resultSet内部包含一个游标,指定当前行数据
// 默认游标指定的是第一行数据之前
// 可以调用next方法向后移动一行游标,next()方法的返回值类型是boolean,true:有下一行;false:没有下一行
List<Map> list=new ArrayList<>();
// 获取列的信息对象
ResultSetMetaData metaData=selectResults.getMetaData();
// 有了它就可以水平遍历
int columnCount=metaData.getColumnCount();
while (selectResults.next())
{
Map map=new HashMap();
// 一行数据对应一个map
// 自动遍历列(从一开始)
for (int i = 1; i <= columnCount; i++) {
// 获取指定列下角标的值 resultSet
Objects value= (Objects) selectResults.getObject(i);
// 获取指定列下角标的列的名称
// getColumnLabel:会获取别名,如果没有写别名才是列名的名称
// getColumnName:只会获取列的名称
String columnLabel=metaData.getColumnLabel(i);
map.put(columnLabel,value);
}
// 将map存储到集合中
list.add(map);
}
System.out.println("list="+list);