jdbc基础
概念及基本实现步骤
概念
- jdbc就是使用java语言操作关系型数据库的一套API
- 同一套Java代码,可以操作不同的关系型数据库,就是考jdbc接口
- sql中的驱动就是对JDBC的实现类,其实也就是一个jar包
步骤
- 创建工程,导入jar包,这里的jar包是 mysql-connector-java-5.1.48.jar ,你自己使用的sql驱动
- 注册驱动,其实当你将jar包导入library中,就不需要以下代码了
java
Class.forName("com.mysql.cj.Driver");
- 获取连接
java
String url = "jdbc:mysql///shop";//shop是数据名字
String username = "root";
String password = "545454";
Connection conn = DriverManager.getConnection(url, username, password);
- 定义sql语句,这里所定义的sql语句即是你想要操作的,比如增删改查
java
String sql = "select * from shop";
- 获取stmt对象
java
Statement stmt = conn.createStatment();
- 执行sql
java
int count = stmt.executeUpdate(sql);
- 查看结果,及关闭缓存
java
System.out.println(count > 0); // 当count>0时,说明语句测试成功,输出true
stmt.close();
conn.close();
JDBC的API接口
1. DriverManager
DriverManager是一个驱动管理类,主要功能包括以下:
- 注册驱动,比如上文的:Class.forName
- 获取数据库连接。如上文的:Connection conn = DriverManager.getConnection(url, username,password);
2. Connection
Connection 是说明数据库连接对象的类,主要功能包括:
- 获取执行SQL的对象
- 普通执行SQL的对象:Statement stmt = conn.createStatement();
- 预编译SQL的执行对象:Prepared'Statement pstmt = conn.prepareStatement(sql);
- 执行存储过程的对象:callablestatement
- 事务的管理
有关事务的管理
- mysql中
- 开启事务:begin/start transaction
- 提交事务:commit
- 回滚事务:ROLLBACK
- 在jdbc中
- 开启事务:SetAutoCommit(false);
- 提交事务:commit()
- 回滚事务:rollback()
java
//下面展示事务
package com.huang.jdbc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
public class JDBCDemo01 {
public static void main(String[] args) throws SQLException, ClassNotFoundException {
//1.注册驱动
Class.forName("com.mysql.jdbc.Driver");
//2.获取链接
String url = "jdbc:mysql:///shop";
String username = "root";
String password = "1212";
Connection conn = DriverManager.getConnection(url, username, password);
//3.sql操作
String sql1 = "update pro set sale_price = 4000 where product_id = 0001;";
String sql2 = "update pro set sale_price = 4000 where product_id = 0002;";
//4.获取stmt对象
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();
throw new RuntimeException(e);
}
//7.释放资源
stmt.close();
conn.close();
}
}
事务可以保证同步化,查看上面两个sql操作,如果我们不加事务,那程序会在int i = 3/0;停止下来,这样就相当于我们只修改了id=0001的商品价格,但如果加入事务,则遇到错误,会一起回滚,两个商品价格都不会改变,即要改变一起改变,不如就一起回滚
3. Statement
statement是用于执行sql语句的类,其中
- executeUpdate(sql):执行DML和DDL
- excuteQuery(sql)则执行DQL
4. ResultSet
ResultSet是一个结果集对象,其中
- 封装了DQL查询的结果,即在使用查询的时,要用ResultSet来封装查询对象:ResultSet rs = Stmt.executeQuery(sql);
- 获取查询对象
- next():**会将光标从当前位置移动一行,判断当前行是否有效,如果有效则返回true
- getXxx(参数):获取数据,如getInt(1),getString(2),其中编号是列的编号
java
//生成Pro类
package com.huang.jdbc.pojo;
import java.sql.Date;
public class Pro {
private int product_id;
private String product_name;
private String product_type;
private double sale_price;
private double purchase_price;
private Date registe_date;
//重写setting和getting、toString(),自己重写
}
java
//应用:查询shop中的内容
package com.huang.jdbc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
public class JDBCDemo01 {
public static void main(String[] args) throws SQLException, ClassNotFoundException {
//1.注册驱动
Class.forName("com.mysql.jdbc.Driver");
//2.获取链接
String url = "jdbc:mysql:///shop";
String username = "root";
String password = "1212";
Connection conn = DriverManager.getConnection(url, username, password);
//3.sql操作
String sql = "select * from pro;";
//4.获取stmt对象
Statement stmt = conn.createStatement();
//5.执行sql
ResultSet rs = stmt.executeQuery(sql);
//6.建立一个list,用以封装查询内容
List<Pro> list = ArrayList<>();
//遍历数据库中的内容
while(rs.next()) {
//new对象
Pro pro = new Pro();
//getXxx获取数据
int id = rs.getId(1);
String name = rs.getString(2);
int money = rs.getInt(3);
//赋值
pro.setId(id);
pro.setName(name);
pro.setMoney(money);
//存入集合
list.add(pro);
}
System.out.println(list);
//7.释放资源
stmt.close();
conn.close();
}
}
5. preparedstatment
- 预编译SQL语句并执行,防止sql注入
- SQL注入:通过操作输入来修改事先定义好的SQL语句,用以达到执行代码对服务器进行攻击的方法
java
//这里演示一下sql如何注入
package com.huang.jdbc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
public class JDBCDemo01 {
public static void main(String[] args) throws SQLException, ClassNotFoundException {
//1.注册驱动
Class.forName("com.mysql.jdbc.Driver");
//2.获取链接
String url = "jdbc:mysql:///shop";
String username = "root";
String password = "12121";
Connection conn = DriverManager.getConnection(url, username, password);
//3.sql操作
String name = "carlos";
String pwd = "'or'1'='1";
String sql = "select * from tb_user where username = '"+name+"' and password = '"+pwd+"'";
//4.获取stmt对象
Statement stmt = conn.createStatement();
//5.执行sql
ResultSet rs = stmt.executeQuery(sql);
//6.判断是否成功
if (rs.next()) {
System.out.println("测试成功");
}else {
System.out.println("测试失败");
}
//7.释放资源
stmt.close();
conn.close();
}
}
发现password为'or'1'='1时,我们程序无论密码为多少,都可以直接进去对数据库进行操作,这是因为,当我们输入password时,在sql中会变成select * from tb_user where username = 'name' and password = ''or'1'='1',其中**or'1'='1'**即为true,而前面的是什么已经无所谓了,由此即为sql注入
java
//sql注入的解救办法:preparedstatement
package com.huang.jdbc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
public class JDBCDemo01 {
public static void main(String[] args) throws SQLException, ClassNotFoundException {
//1.注册驱动
Class.forName("com.mysql.jdbc.Driver");
//2.获取链接
String url = "jdbc:mysql:///shop";
String username = "root";
String password = "1212;
Connection conn = DriverManager.getConnection(url, username, password);
//3.sql操作,参数用?代替
String name = "carlos";
String pwd = "'or'1'='1";
String sql = "select * from tb_user where username = ? and password = ?";
//4.获取pstmt对象,需要传递sql
preparedStatement pstmt = conn.prepareStatement(sql);
//设置参数值
pstmt.setString(1,name);
pstmt.setString(2,pwd);
//5.执行sql
ResultSet rs = pstmt.executeQuery();
//6.判断是否成功
if (rs.next()) {
System.out.println("测试成功");
}else {
System.out.println("测试失败");
}
//7.释放资源
stmt.close();
conn.close();
}
}
运行,发现测试失败,说明preparedstatement对象可以很好的防止sql注入
原理:preparedstatement对'or'1'='1中的特殊字符进行转义,使其保持原义。
6. 数据库连接池
简介
- 数据库连接池其实就是一个容器,用来管理数据库的连接
- 允许应用程序重复使用一个现有的数据库连接,而不是通过重新建立一个连接,这样大大减少了步骤流程
- 数据库连接池可以通过释放空闲时间超过最大空闲时间的数据库连接来避免因没有释放数据库连接而引起的数据库遗漏。其实就是数据库连接池可以让停止运行时间最久的连接 去重新接待连接
- 打个比方,数据库连接池其实就是一个服务员经理,而每个连接就是一个服务员,数据库连接的优点就是,可以让一个服务员可以重复去接待客户,而不是接待完一个客户就把这个服务员开除,再重新招一个。还有一个优点就是,数据库连接池可以让休息最久的服务员重新去接待客户。
实现步骤
- 导入jar包,可以通过maven直接导入依赖包,也可以自己下载mysql-connector-java-5.1.48,这种jar包,然后放入项目
- 定义配置文件,导入的是数据库连接池的配置文件,
properties
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql:///shop?useSSL=false&useServerPrepStmts=true
username = root
password = 213214
initialSize=5
maxActive=10
maxWait=3000
其中,com.mysql.jdbc.Driver是你的驱动管理类,我这里用的是5.0x旧版本,新版本可以使用com.mysql.cj.jdbc.Driver,url、username、password即为地址,用户名和密码,initalsize为初始连接数量,maxactive为最大同时连接数,maxwait则为最大等待时间。
- 加载配置文件
java
Properties prop = new Properties();
prop.load(new FileInputStream("Druid.properties的路径"));
就是把Druid.properties中内容加载进去
- 获取DataSource对象
java
DataSource dataSource = DruidDataSourceFactory.createDataSource(prop);
这里是创建了一个名为dataSource的对象,也就是创建了一个连接池
- 获取连接
java
Connection connection = dataSource.getConnection();
即从连接池中获取了一个数据库连接
应用
下面我们来依次完成数据库的查询、删除、修改操作
查询
首先不使用数据库连接池
java
package example;
import com.huang.jdbc.pojo.Brand;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
public class BrandTest {
public static void main(String[] args) throws Exception {
//1.注册驱动
Class.forName("com.mysql.jdbc.Driver");
//2.建立联系
String url = "jdbc:mysql:///shop?useSSL=false";
String username = "root";
String password = "123";
Connection conn = DriverManager.getConnection(url, username, password);
//3.编写sql语句
String sql = "select * from tb_brand";
//4.获取pstmt对象
PreparedStatement pstmt = conn.PrepareStatement(sql);
//5.执行sql
ResultSet rs = pstmt.excuteQuery();
//6.创建出一个列表,将查询出来的放入列表
List<Brand> brands = new ArrayList<>();
while (rs.next()) {
Brand brand = new Brand();
//获取数据库中的信息
int id = rs.getInt("id");
String brandName = rs.getString("brand_name");
String companyName = rs.getString("company_name");
int ordered = rs.getInt("ordered");
String description = rs.getString("description");
int status = rs.getInt("status");
//赋值
brand.setId(id);
brand.setBrandName(brandName);
brand.setCompanyName(companyName);
brand.setOrdered(ordered);
brand.setDescription(description);
brand.setStatus(status);
//将读取出来的数据放入列表
brands.add(brand);
}
System.out.println(brands);
}
//7.释放资源
rs.close();
pstmt.close();
conn.close();
}
使用数据库连接池进行查询
java
package example;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import com.huang.jdbc.pojo.Brand;
import javax.sql.DataSource;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
public class BrandTest01 {
public static void main(String[] args) throws Exception {
//1.建立数据库连接池,并拉出一条连接
Properties prop = new Properties();
prop.load(new FileInputStream("Druid.properties的路径"));
DataSource dataSource = DruidDataSourceFactory.createDataSource(prop);
Connection connection = dataSource.getConnection();
//2.sql语句
String sql = "select * from tb_brand";
//3.定义pstmt对象
PreparedStatement pstmt = connection.prepareStatement(sql);
//4.执行sql
ResultSet rs = pstmt.executeQuery();
//5.将查询内容封装到列表中
List<Brand> brandList = ArrayList<>();
while (rs.next()) {
Brand brand = new Brand();
int id = rs.getInt("id");
String brandName = rs.getString("brand_name");
String companyName = rs.getString("company_name");
int ordered = rs.getInt("ordered");
String description = rs.getString("description");
int status = rs.getInt("status");
//赋值
brand.setId(id);
brand.setBrandName(brandName);
brand.setCompanyName(companyName);
brand.setOrdered(ordered);
brand.setDescription(description);
brand.setStatus(status);
brandList.add(brand);
}
System.out.println(brandList);
}
//6.释放资源
rs.close();
pstmt.close();
connection.close();
}
更改
java
package example;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import javax.sql.DataSource;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.util.Properties;
public class BrandTest02 {
public static void main(String[] args) throws Exception {
//1.先创建数据库连接池
Properties prop = new Properties();
prop.load(new FileInputStream("D:/java项目/jdbc-demo/src/druid.properties"));
DataSource dataSource = DruidDataSourceFactory.createDataSource(prop);
Connection connection = dataSource.getConnection();
//2.创建我们需要更改的内容
String brandName = "淘宝";
String companyName = "阿里巴巴";
int ordered = 1;
String description = "马云";
int status = 1;
//3.定义sql
String sql = "insert into tb_brand(brand_name, company_name, ordered, description, status) values (?,?,?,?,?)";
//4.获取pstmt对象
PreparedStatement pstmt = connection.prepareStatement(sql);
//5.设置参数
pstmt.setString(1,brandName);
pstmt.setString(2,companyName);
pstmt.setInt(3,oredered);
pstmt.setString(4,description);
pstmt.setInt(5,status);
//6.执行sql
int count = pstmt.executeUpdate();
//7.查看结果是否运行成功
if (count > 0) {
System.out.println("运行成功")
} else{
System.out.println("运行失败")
}
//关闭
pstmt.close();
connection.close();
}
}
更改数据库中的内容
java
package example;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import javax.sql.DataSource;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.util.Properties;
public class BrandTest02 {
public static void main(String[] args) throws Exception {
//1.先创建数据库连接池
Properties prop = new Properties();
prop.load(new FileInputStream("D:/java项目/jdbc-demo/src/druid.properties"));
DataSource dataSource = DruidDataSourceFactory.createDataSource(prop);
Connection connection = dataSource.getConnection();
//2.sql语句
String sql = "update tb_brand set description = '电商领导品牌' where company_name = '阿里巴巴'";
//3.获取pstmt对象
PreparedStatement pstmt = connection.prepareStatement(sql);
//4.执行sql
int count = pstmt.executeUpdate();
//5.查看结果
if (count > 0) {
System.out.println("运行成功")
} else{
System.out.println("运行失败")
}
//6.释放
pstmt.close();
connection.close();
}
}
删除
java
package example;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import javax.sql.DataSource;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.util.Properties;
public class BrandTest04 {
public static void main(String[] args) throws Exception {
//1.创建数据库连接池,并加入一条连接
Properties prop = new Properties();
prop.load(new FileInputStream("D:/java项目/jdbc-demo/src/druid.properties"));
DataSource dataSource = DruidDataSourceFactory.createDataSource(prop);
Connection conn = dataSource.getConnection();
//2.sql操作
String sql = "delete from tb_brand where company_Name = '阿里巴巴'";
//3.获取pstmt
PreparedStatement pstmt = conn.prepareStatement(sql);
//4.执行sql
int count = pstmt.executeUpdate();
//5.查看结果
if (count > 0) {
System.out.println("成功");
} else {
System.out.println("失败");
}
//6.关闭
pstmt.close();
conn.close();
}
}