JDBC
简介
概念
JDBC就是使用java语言操作关系型数据库的一套API,全称(Java DataBase Connectivity) Java数据库连接
本质
- sun公司定义的一套所有关系型数据库的规则,即接口
- 各个数据库厂商去实现这套接口,提供数据库驱动jar包
- 我们可以使用这套接口(JDBC)编程,真正执行的代码是驱动jar包中的实现类
好处
- 各个数据库厂商使用相同的接口,Java代码不需要针对不同数据库分别开发
- 可随时替换底层数据库,访问数据库的Java代码可基本不变
JDBC驱动(JDBCjar包)不同厂商的SQL只需要换jar包即可使用,面向接口编程
JDBC快速入门
//1.注册驱动
Class.forName("com.mysql.jdbc.Driver");
//2.建立链接
Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/db5", "root", "root");
//3.获取执行者对象
String sql = "delete from emp where eid = '1001' ";
Statement statement = connection.prepareStatement(sql);
//4.使用执行者来执行sql语句
int row = statement.executeUpdate();
//5.处理结果
System.out.println(row);
//6.释放资源
statement.close();
connection.close();
JDBC API详解
DriverManager
注册驱动
DriverManger.reisterDriver(new Dirver); //注册驱动,但是不用
Class.forName("com.mysql.jdbc.Driver");//使用这种 因为这种方式会加载Driver类,Driver类有静态代码块,这个静态代码块中极影注册过了,如果还是采用传统方式,会注册俩次 可以省略,但是不建议省略
获取连接
DriverManager.getConnection(url,username,password);
url:jdbc:mysql://localhosr:3306/数据库名 (固定写法) 如果数据库是本机 可以直接写jdbc:mysql:///数据库名
username: 用户名
password:密码
示例代码
Class.forName("com.mysql.jdbc.Driver");
Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/wan","root","root");//wan 是我的数据库名字 这些基本固定写法
Connection
获取执行者对象
createStatement() //该方法获取执行者对象 后面执行SQL语句容易被SQL注入攻击被淘汰了
PrepareStatement(String sql);//获取预编译的执行者对象
管理事务
setAutoCommit(false) 开启事务
commit() 提交事务
rollback() 回滚事务
注意:想要被事务管理必须保证连接是同一条!!
事务示例代码
/**
* JDBC API 详解:Connection
*/
public class JDBCDemo3_Connection {
public static void main(String[] args) throws Exception {
//1. 注册驱动
//Class.forName("com.mysql.jdbc.Driver");
//2. 获取连接:如果连接的是本机mysql并且端口是默认的 3306 可以简化书写
String url = "jdbc:mysql:///db1?useSSL=false";
String username = "root";
String password = "1234";
Connection conn = DriverManager.getConnection(url, username, password);
//3. 定义sql
String sql1 = "update account set money = 3000 where id = 1";
String sql2 = "update account set money = 3000 where id = 2";
//4. 获取执行sql的对象 Statement
Statement stmt = conn.createStatement();
try {
// ============开启事务==========
conn.setAutoCommit(false);
//5. 执行sql
int count1 = stmt.executeUpdate(sql1);//受影响的行数
//6. 处理结果
System.out.println(count1);
int i = 3/0;
//5. 执行sql
int count2 = stmt.executeUpdate(sql2);//受影响的行数
//6. 处理结果
System.out.println(count2);
// ============提交事务==========
//程序运行到此处,说明没有出现任何问题,则需求提交事务
conn.commit();
} catch (Exception e) {
// ============回滚事务==========
//程序在出现异常时会执行到这个地方,此时就需要回滚事务
conn.rollback();
e.printStackTrace();
}
//7. 释放资源
stmt.close();
conn.close();
}
}
PrepareStatement
String sql="select * from student";
PreparedStatement pps = connection.prepareStatement(sql);
获得这个对象需要传SQL语句,查询不需要添加占位符 增删改需要在数据的位置添加占位符
String sql2="update student set sname = ? where sid = ?";
PreparedStatement pps2 = connection.prepareStatement(sql2);
int executeUpdate() 专门执行增删改操作 返回值>0则证明操作成功
ResultSet executeQuery() 执行查询语句,返回结果集对象
setXxx的方法 ,填俩个变量,第一个填占位符的位置,第二个填添加的数据
示例代码:
pps2.setObject(1,"李智恩");
pps2.setObject(2,1002);
int i1 = pps2.executeUpdate();
if(i1>0){
System.out.println("修改成功");
}else{
System.out.println("修改失败");
}
最主要是为了解决SQL注入的问题
Statement
int executeUpdate(String sql) 专门执行增删改操作 返回值>0则证明操作成功
ResultSet executeQuery(String sql) 执行查询语句,返回结果集对象
因为存在SQL注入风险所以不推荐使用,SQL注入就是以字符串方式拼接进来(造成SQL语义发生改变),引入注入
示例代码
// 查询操作
//写查询SQL语句
String sql = "select * from dish";
//获得执行者对象
Statement statement = connection.createStatement();
ResultSet resultSet = statement.executeQuery(sql);
//增删改操作
//3 定义SQL语句
String sql = "delete from student where sid=1";
// 4 通过连接获取执行对象 然后执行SQL语句
Statement statement = connection.createStatement();
int rows = statement.executeUpdate(sql);
ResultSet
boolean next()方法 :游标的往下移动一行并返回改行是否有数据
getXxx(String columnName) 根据列名获得列值
代码示例
ResultSet res = pps.executeQuery();
while(res.next()){//类似迭代器的用法
int sid = res.getInt("sid"); // 获得sid的列值
String sname = res.getString("sname");
String classroom = res.getString("classroom");
Date birth = res.getDate("birth");
}
数据库连接池简介
- 数据库连接池是个容器,负责分配、管理数据库连接(Connection)
- 它允许应用程序重复使用一个现有的数据库连接,而不是再重新建立一个;
- 释放空闲时间超过最大空闲时间的数据库连接来避免因为没有释放数据库连接而引起的数据库连接遗漏
- 好处
- 资源重用
- 提升系统响应速度
- 避免数据库连接遗漏
之前我们代码中使用连接是没有使用都创建一个Connection对象,使用完毕就会将其销毁。这样重复创建销毁的过程是特别耗费计算机的性能的及消耗时间的。
而数据库使用了数据库连接池后,就能达到Connection对象的复用,如下图
连接池是在一开始就创建好了一些连接(Connection)对象存储起来。用户需要连接数据库时,不需要自己创建连接,而只需要从连接池中获取一个连接进行使用,使用完毕后再将连接对象归还给连接池;这样就可以起到资源重用,也节省了频繁创建连接销毁连接所花费的时间,从而提升了系统响应的速度。
数据库连接池实现
-
标准接口:==DataSource==
官方(SUN) 提供的数据库连接池标准接口,由第三方组织实现此接口。该接口提供了获取连接的功能:
Connection getConnection()
那么以后就不需要通过
DriverManager
对象获取Connection
对象,而是通过连接池(DataSource)获取Connection
对象。 -
常见的数据库连接池
- DBCP
- C3P0
- Druid
我们现在使用更多的是Druid,它的性能比其他两个会好一些。
-
Druid(德鲁伊)
- Druid连接池是阿里巴巴开源的数据库连接池项目
- 功能强大,性能优秀,是Java语言最好的数据库连接池之一
Driud使用
- 导入jar包 druid-1.1.12.jar
- 定义配置文件
- 加载配置文件
- 获取数据库连接池对象
- 获取连接
现在通过代码实现,首先需要先将druid的jar包放到项目下的lib下并添加为库文件
项目结构如下:
编写配置文件如下:
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql:///db1?useSSL=false&useServerPrepStmts=true
username=root
password=1234
# 初始化连接数量
initialSize=5
# 最大连接数
maxActive=10
# 最大等待时间
maxWait=3000
使用druid的代码如下:
/**
* Druid数据库连接池演示
*/
public class DruidDemo {
public static void main(String[] args) throws Exception {
//1.导入jar包
//2.定义配置文件
//3. 加载配置文件
Properties prop = new Properties();
prop.load(new FileInputStream("jdbc-demo/src/druid.properties"));
//4. 获取连接池对象
DataSource dataSource = DruidDataSourceFactory.createDataSource(prop);
//5. 获取数据库连接 Connection
Connection connection = dataSource.getConnection();
System.out.println(connection); //获取到了连接后就可以继续做其他操作了
//System.out.println(System.getProperty("user.dir"));
}
}