JDBC:提供连接各种常用数据库的能力

Java应用程序(客户端)/应用服务器(JSP、Servlet)通过JDBC来连接数据库服务器

JDBC的工作原理:

工作原理.png

说明:

JDBC API:包含供程序员调用的接口与类,集成在java.sql 和 javax.sql中,如 DriverManager类, Connection接口, Statement接口, ResultSet接口。功能:与数据库建立连接、执行Sql语句、处理结果

DriverManager类:管理各种不同的JDBC驱动

JDBC驱动:负责连接各种不同的数据库,由数据库厂商提供

JDBC编程步骤:

1.加载JDBC驱动

2.与数据库建立连接

3.执行sql语句

4.处理结果

5.释放资源

编程模板

上代码(可执行):

import java.sql.*;
public class TestDemo {
public static void main(String[] args){
Connection connection = null;
ResultSet rs = null;
Statement statement = null;
try{
//注意是 com.mysql.cj.jdbc.Driver,不是com.mysql.jdbc.Driver
//第一步:加载驱动
Class.forName("com.mysql.cj.jdbc.Driver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
try {
//第二步:建立连接
connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/library_ltg?characterEncoding=utf-8&serverTimezone=UTC", "root", "0011");
System.out.println("连接数据库成功");
//第三步:执行SQL语句
statement = connection.createStatement();
String strSql = "insert into book values('Python','Denis')";
statement.execute(strSql);
//System.out.println("插入成功");
//第四步:处理结果
rs = statement.executeQuery("select * from book");
while (rs.next()){
System.out.println(rs.getString(1)+ " " + rs.getString("author"));
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}finally {
//最后,关闭连接
try {
if(rs!=null){
rs.close();
}
if(statement != null){
statement.close();
}
if(connection!=null){
connection.close();
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
}

注意:pom文件里要包含以下依赖:

mysql
mysql-connector-java
8.0.16

tips:记得pom.xml右键 > maven > reload project

执行结果:

执行结果

Statement常用方法:

常用方法

ResultSet常用方法:

常用方法

注意事项:

ResultSet不能多个做笛卡尔积连接 (即不要嵌套遍历)

ResultSet最好不要超过百条,否则极其影响性能

ResultSet也不是一口气加载所有select结果数据

Connection很昂贵,及时关闭

ResultSetMetaData

用来获取ResultSet返回的属性

getColumnCount(),返回结果的列数
getColumnClassName(i), 返回第i列的数据的Java类名
getColumnTypeName(i), 返回第i列的数据库类型名称
getColumnType(i), 返回第i列的SQL类型
ResultMetaData meta = rs.getMetaData();
int cols = meta.getColumnCount();
for(int i=1; i<=cols; i++){ //i从1开始
//...
}

sql注入式攻击

举例:对于一个表 flowerowner 执行 select * from flowerowner where name = ‘小红’ and password = '123'

密码如果正确,会返回相应数据。错误则不返回

但是,如果在语句后面加上 or '1' = '1',这时所有语句都会被拿出来。这种方式就称为sql注入式攻击

解决方案:

使用PreparedStatement接口(该接口继承自Statement接口,比Statement接口更加灵活,更有效率,也更安全,可读性和可维护性也更强。是一种预编译的sql语句)

StringBuffer sbSql = new StringBuffer("select * from flowerowner where name = ? and password = ?"); //?为占位符
PreparedStatement pstmt = conn.getPreparedStatement(sbSql.toString());
pstmt.setString(1, "小红");
pstmt.setString(2, "123");
rs = pstmt.executeQuery();

PreparedStatement的好处:

防止注入攻击

防止繁琐的字符串拼接和错误

直接设置对象而不需要转换为字符串

使用预编译速度相对statement快很多

addBatch批量处理功能

SQL增删改查常见命令:

显示数据库列表:

show databases

创建:

create table tbl_name
(
id int unsigned not null auto_increment primary key,
name char(8) not null
);

插入:

insert into tbl_name values(1, '张三');

查询:

select * from tbl_name;

修改:

update tbl_name set name='李小四' where id = 1;

删除:

delete from tbl_name where id = 1;
drop table tbl_name;

数据库字段类型:

int 整数4个字节

double 小数8个字节

datetime 时间,7个字节

varchar 字符串,可变字节

数据库连接池:

运用共享技术来实现数据库连接池(享元模式),管理数据库连接

降低系统中数据库连接Connection对象的数量

降低数据库服务器的连接响应消耗

提高Connection获取的响应速度

常用的数据库连接池:

DBCP(Apache 性能较差)

C3P0
Druid(Alibaba )