概述:JDBC 是 Java 访问数据库的标准规范,真正怎么操作数据库还需要具体的实现类,也就是数据库驱动。每个数据库厂商根据自家数据库的通信格式编写好自己数据库的驱动。所以我们只需要会调用 JDBC 接口中的方法即可,数据库驱动由数据库厂商提供。
Jar包:下载相对应的Jar包
JDBC核心API(api是java标准类库提供的函数)
接口或类 | 功能 |
DriverManager类 | 1.管理和注册数据库驱动 2.得到数据库连接对象 |
Connection接口 | 一个连接对象,可用于创建Statement和PreparedStatement对象 |
Statement接口 | 一个SQL语句对象,用于将SQL对象发送给数据库服务器 |
preparedStatement接口 | 一个SQL语句对象,是Statement的子接口 |
ResultSet | 用于封装数据库封装的结果集,返回给客户端Java程序 |
注册驱动:
格式:
Class.forName(数据库驱动)
数据库驱动:com.mysql.cj.jdbc.Driver
示例代码:Class.forName(“com.mysql.cj.jdbc.Driver”);
DriverManager类
作用:注册和管理驱动;创建数据库连接对象
方法:
静态方法 | 功能 |
Connection.getConnection(String url,String user,String password) | 通过连接字符串,用户名,密码来得到数据库连接对象 |
Connection.getCollection(String url,Properties info) | 通过连接字符串,属性对象来得到连接对象 |
四个参数:
参数名 | 说明 |
用户名 | 数据库库账户(root) |
密码 | 数据库密码 |
URL | Mysql的URL:jdbc.mysql://localhost:3306/数据库名[?参数名=参数值]( [?参数名=参数值]用于设置编码,防止乱码 例如:?useUnicode=true&characterEncoding=UTF8) |
字符串 | Com.mysql.cj.jdbc.Driver |
连接数据库:
Properties
property复数形式,属性的意思。属性名 = 属性值 key=value。
位于java.util包
理解:
1.属性集合对象
2.属于Map中的一员,继承Hashtable,可以直接使用map的方法
3.key和value都只能是字符串。
4.可以读取流中数据也可以将数据保存到流中
5.持久化的属性集对象
构造方法:
Properties():空列表
Properties(Properties prop):带有指定内容的列表
获取连接对象的两种方式:
1、使用用户名,密码,url获取连接对象
String url = “jdbc.mysql://localhost:3306/数据库名?characterEncoding=utf8”
String username = “root”;
String password = “数据库密码”
Connection connection = null;
Statement statement = null;
Class.forName(“com.mysql.cj.jdbc.Driver”)
connection = DriverManager.getConnection(url,username,password)
2、使用属性文件和url得到连接对象
String url = “jdbc.mysql://localhost:3306/数据库名?characterEncoding=utf8“;
String username = 数据库账号
String password = 数据库密码
Connection connection = null;
Statement statement = null;
Class.forName(“com.mysql.cj.jdbc.Driver”);
Properties pro = new Propertise();
pro.getproperty(“user”,username);
pro.getproperty(“password”,password);
connection = DriverManager.getConnection(url,pro);
Connection 创建Statement方法
方法 | 描述 |
Statement createStatement() | 创建一条sql语句对象 |
Statement接口
代表一条sql语句对象,用于发送sql语句给服务器,用于执行静态sql语句并返回它所生成的结果的对象
Statement中的方法
方法 | 描述 |
int executeUpdate(String sql) | 用于发送 DML 语句,增删改的操作,insert、update、delete 参数:SQL 语句 返回值:返回对数据库影响的行数 |
ResultSet executeQuery(String sql) | 用于发送 DQL 语句,执行查询的操作。select 参数:SQL 语句 返回值:查询的结果集 |
释放资源:
代码一般放在finally代码块中
finally {
//释放statement
if (null != st) {
try {
st.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
//释放connection
if (null != connection) {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
ResultSet就是一张二维的表格,它内部有一个“行光标”,光标默认的位置在“第一行上方”,我们可以调用rs对象的next()方法把“行光标”向下移动一行,当第一次调用next()方法时,“行光标”就到了第一行记录的位置,这时就可以使用ResultSet提供的getXXX(int col)方法来获取指定列的数据了。
当你使用rs.getInt(1)方法时,你必须可以肯定第1列的数据类型就是int类型,如果你不能肯定,那么可以使用rs.getObject(1),但是一般不建议这么用,最好还是能确定数据类型。
ResultSet提供了一系列的方法来移动游标
方法 | 功能 |
void beforeFirst() | 把光标放到第一行的前面,这也是光标默认的位置 |
void afterLast() | 把光标放到最后一行的后面 |
boolean first() | 把光标放到第一行的位置上,返回值表示调控光标是否成功 |
boolean last() | 把光标放到最后一行的位置上 |
boolean isBeforeFirst() | 当前光标位置是否在第一行前面 |
boolean isAfterLast() | 当前光标位置是否在最后一行的后面 |
boolean isFirst() | 当前光标位置是否在第一行上 |
boolean isLast() | 当前光标位置是否在最后一行上 |
boolean previous() | 把光标向上挪一行 |
boolean next() | 把光标向下挪一行 |
boolean relative(int row) | 相对位移,当row为正数时,表示向下移动row行,为负数时表示向上移动row行 |
boolean absolute(int row) | 绝对位移,把光标移动到指定的行上 |
int getRow() | 返回当前光标所有行 |
通过使用StringBuilder的append()方法,将不同的值拼接成一个字符串。
sb.append("ID:").append(id).append(",").append("Name:").append(name).append(",").append("Balance:").append(balance);
如果id=1,name=“John”,balance=1000,那么最终拼接的字符串就是"ID:1,Name:John,Balance:1000"。
最常用的是next()方法,可以通过next()方法使ResultSet的游标向下移动,当游标移动到你需要的行时,就需要来获取该行的数据了,ResultSet提供了一系列的获取列数据的方法:
方法 | 功能 |
String getString(int columnIndex) | 获取指定列的String类型数据 |
int getInt(int columnIndex) | 获取指定列的int类型数据 |
double getDouble(int columnIndex) | 获取指定列的double类型数据 |
boolean getBoolean(int columnIndex) | 获取指定列的boolean类型数据 |
Object getObject(int columnIndex) | 获取指定列的Object类型的数据 |
上面方法中,参数columnIndex表示列的索引,列索引从1开始,而不是0,这第一点与数组不同。
ResultSet 接口中的注意事项:
① 如果光标在第一行之前,使用 rs.getXX()获取列值,报错:Before start of result set
② 如果光标在最后一行之后,使用 rs.getXX()获取列值,报错:After end of result set
③ 使用完毕以后要关闭结果集 ResultSet,再关闭 Statement,再关闭 Connection
PreparedStatement(可以解决Statement引发的SQL注入问题)
是Statement接口的子接口,继承于父类中的所有方法,它是一个预编译SQL语句
PreparedStatement接口与Statement接口的比较
1、Statement 在进行输入插入的时候,都会发送一条SQL语句给数据库,数据库先编译SQL语句,然后执行,返回结果,如果有一万条插入的SQL语句,那么数据库就需要先编译一万次,这样就会导致效率低下;PreparedStatement在进行数据插入的时候,会先发送SQL语句预编译,PreparedStatement就会引用预编译的结果,如果多次插入的内容相同的话,就只需要预编译一次,只是每一次执行SQL语句的时候参数不一样。这样就提高了效率。
2、PreparedStatement可以有效的防止 SQL 注入的问题,安全性更高。
注意:调用executeUpdate()或executeQuery()方法时要注意,调用没有参数的方法
PreparedStatement使用步骤
编写 SQL 语句,未知内容使用?占位:"SELECT * FROM user WHERE name=? AND pwd=?";
获得 PreparedStatement 对象;
设置实际参数:setXxx(占位符的位置, 真实的值);
执行参数化 SQL 语句;
关闭资源。
PreparedStatement 的常用方法
PreparedStatement 中设置参数的方法 | 描述 |
void setDouble(int parameterIndex, double x) | 将指定参数设置为给定 Java double 值 |
void setFloat(int parameterIndex, float x) | 将指定参数设置为给定 Java REAL 值 |
void setInt(int parameterIndex, int x) | 将指定参数设置为给定 Java int 值 |
void setLong(int parameterIndex, long x) | 将指定参数设置为给定 Java long 值 |
void setObject(int parameterIndex, Object x) | 使用给定对象设置指定参数的值 |
void setString(int parameterIndex, String x) | 将指定参数设置为给定 Java String 值 |