Java Data Base Connectivity(JDBC):Java数据库连接
- DriverManager: 用于注册驱动
- Connection: 表示数据库的连接
- Statement: 执行SQL语句的对象
- ResultSet: 结果集或一张虚拟表
static void registerDriver(Driver driver) | 向 DriverManager 注册给定驱动程序 |
static Connection getConnection(String url, String user, String password) |
连接到给定数据库 URL,并返回连接。 |
Statement createStatement() |
创建一个 Statement 对象来将 SQL 语句发送到数据库 |
// 1.注册驱动
// DriverManager.registerDriver(new Driver());
// 1.1 Mysql5版本之后,可以不用手动注册驱动
DriverManager.registerDriver(new com.mysql.jdbc.Driver());
// 2.获取数据库连接Connection对象
// 协议名:子协议://服务器名或IP地址:端口号/数据库名
Connection cn = DriverManager.getConnection("jdbc:mysql://localhost:3306/db1?useSSL=false", "root", "root");
// 2.1 如果连接的是本地,且端口是3306,localhost:3306可以省略
Connection cn2 = DriverManager.getConnection("jdbc:mysql:///db1?useSSL=false", "root", "root");
// 3.获取运送SQL的对象
Statement state = cn.createStatement();
ResultSet executeQuery(String sql) |
用于执行查询语句; 返回查询到的结果集 |
int executeUpdate(String sql) |
用于执行除查询外的SQL; 返回影响的行数 |
// 1.注册驱动(自动注册)
// 2.获取Connection连接
Connection cn = DriverManager.getConnection("jdbc:mysql://localhost:3306/db1",
"root", "root");
// 3.获取Statement(小货车)
Statement state = cn.createStatement();
// 4.执行SQL语句
String sql = "insert into user values (null,'NAME','1234');";
// 返回影响的行数
int row = state.executeUpdate(sql);
// 5.处理结果
System.out.println("row = " + row);
// 6.释放资源
state.close();
cn.close();
boolean next() | 将光标从当前位置向前移动一行 ,判断当前行是否为有效行,true:有效行,当前行有数据 |
boolean getBoolean(String columnLabel) |
获取boolean值 |
byte getByte(String columnLabel) |
获取byte值 |
double getDouble(String columnLabel) |
获取double值 |
int getInt(String columnLabel) |
获取int值 |
long getLong(String columnLabel) |
获取long值 |
String getString(String columnLabel) |
获取String值 |
// 4.执行SQL语句
String sql = "SELECT * FROM user;";
// executeQuery查询
ResultSet rs = state.executeQuery(sql);
// 5.处理结果
// System.out.println("rs = " + rs);
while (rs.next()){
// 获取这一行的数据
int id = rs.getInt("id");
String name = rs.getString("name");
String password = rs.getString("password");
System.out.println("id:" + id + ",name:" + name + ",password:" + password);
}
// 6.关闭资源
rs.close();
state.close();
cn.close();
// 4.执行SQL语句
String sql = "SELECT * FROM user;";
ResultSet rs = state.executeQuery(sql);
// 5.处理结果
// System.out.println("rs = " + rs);
List list = new ArrayList<>();
while (rs.next()){
// 获取这一行的数据
int id = rs.getInt("id");
String name = rs.getString("name");
String password = rs.getString("password");
// System.out.println("id:" + id + ",name:" + name + ",password:" + password);
// 封装成对象来使用
User user = new User(id, name, password);
list.add(user);
}
void setAutoCommit(boolean autoCommit) |
false:开启事务, ture:关闭事务 |
void commit() |
提交事务 |
void rollback() |
回滚事务 |
public class Demo05 {
public static void main(String[] args) {
// 作用域问题,定义在try之外
Connection cn = null;
Statement state = null;
try {
// 1.注册驱动(自动注册)
// 2.获取链接
cn = DriverManager.getConnection("jdbc:mysql://localhost:3306/db1",
"root", "root");
// 3.开启事务 false为开启事务,true为关闭事务
cn.setAutoCommit(false);
// 4.获取到Statement
state = cn.createStatement();
// 5.Statement执行SQL
// id1-500
state.executeUpdate("update account set balance = balance - 500 where id = 1");
// id2+500
// 计算异常
// int a = 10/0;
state.executeUpdate("update account set balance = balance + 500 where id = 2");
// 6.成功提交事务
cn.commit();
System.out.println("事务提交成功!");
} catch (Exception throwables) {
// 6.失败回滚事务
// 回滚事务也可能失败,重试机制,记录信息,手动回滚
try {
if (cn!=null){
cn.rollback();
}
System.out.println("事务失败回滚");
} catch (SQLException e) {
e.printStackTrace();
}
throwables.printStackTrace();
} finally {
// 关闭资源
try {
if (state !=null){
state.close();
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}
try {
if (cn!=null){
cn.close();
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
}
// 1.使用数据库保存用户的账号和密码
// 2.让用户输入账号和密码
Scanner sc = new Scanner(System.in);
System.out.println("请输入账号:");
String name = sc.nextLine();
System.out.println("请输入密码:");
String password = sc.nextLine();
// 3.使用SQL根据用户的账号和密码去数据库查询数据
// 3.1获取连接
Connection cn = DriverManager.getConnection("jdbc:mysql://localhost:3306/db1?useSSL=false","root", "root");
// 3.2获取Statement
Statement state = cn.createStatement();
// 3.3编写SQL语句,执行
String sql = "select * from user where name = '"+ name +"' and password = '"+ password +"';";
ResultSet rs = state.executeQuery(sql);
// 4.如果查询到数据,说明登录成功
// 只要有一个数据是有的,那就可以了
if (rs.next()){
System.out.println("欢迎你~"+name);
} else {
// 5.如果查询不到数据,说明登录失败
System.out.println("账号或密码错误......");
}
// 6.关闭资源
rs.close();
state.close();
cn.close();
}
上面那种方法若密码输入为a'or'1'='1 也登录成功,为了解决SQL注入,引入PrepareStatement
// ?是占位符
String sql = "SELECT * FROM USER WHERE NAME=? AND PASSWORD=?;";
setXxx(参数1,参数2); | Xxx代表:数据类型,参数1:第几个? (编号从1开始),参数2:?的实际参数 |
int executeUpdate(); | 执行insert、update、delete语句 |
ResultSet executeQuery(); | 执行select语句 |
// 1.获取连接
Connection cn = DriverManager.getConnection("jdbc:mysql://localhost:3306/db1",
"root", "root");
// 2.编写参数化SQL(带?的SQL语句)
String sql = "insert into user values (null,?,?);";
// 之前的是这样获取状态
// Statement state = cn.createStatement();
PreparedStatement pstate = cn.prepareStatement(sql);
// 3.给?赋值
pstate.setString(1,"adamin");
pstate.setString(2,"1234");
// 4.执行
int row = pstate.executeUpdate();
System.out.println("row = " + row);
// 5.释放资源
pstate.close();
cn.close();
之前JDBC访问数据库的步骤:创建数据库连接→运行SQL语句→关闭连接
缺点:
- 每次数据库访问执行这样重复的动作
- 获取数据库连接需要消耗比较多的资源,而每次操作都要重新获取新的连接对象,
- 执行一次操作就把连接关闭,而数据库创建连接通常需要消耗相对较多的资源。这样数据库连接对象的使用率低。
连接池的概念: 连接池就是一个容器,连接池中保存了一些数据库连接,这些连接是可以重复使用的。
连接池的原理
- 启动连接池,连接池就会初始化一些连接
- 当用户需要使用数据库连接,直接从连接池中取出
- 当用户使用完连接,会将连接重新放回连接池中
连接池优点
- 连接池中会保存一些连接,这些连接可以重复使用,降低数据资源的消耗
常见的连接池实现组件
- 阿里巴巴-德鲁伊Druid连接池:Druid是阿里巴巴开源平台上的一个项目
- C3P0是一个开源的连接池,目前使用它的开源项目有Hibernate,Spring等。
- DBCP(DataBase Connection Pool)数据库连接池,是Tomcat使用的连接池组件。
initialSize |
刚启动连接池时,连接池中包含连接的数量 |
maxActive |
连接池中最多可以放多少个连接 |
maxWait |
获取连接时最大等待时间,单位毫秒 |
Druid连接池在创建的时候需要一个Properties对象来设置参数,所以我们使用properties文件来保存对应的参数。Druid连接池的配置文件名称随便,放到src目录下面方便加载
druid.properties文件内容
url=jdbc:mysql://localhost:3306/database1?useSSL=false
username=root
password=root
driverClassName=com.mysql.jdbc.Driver
initialSize=5
maxActive=10
maxWait=2000
Druid连接池使用步骤
- 导入druid-1.0.0.jar的jar包
- 复制druid.properties文件到src下,并设置对应参数
- 加载properties文件的内容到Properties对象中
- 创建Druid连接池,使用配置文件中的参数
- 从Druid连接池中取出连接
- 执行SQL语句
- 关闭资源
// 3.加载properties文件的内容到Properties对象中
Properties pp = new Properties();
FileInputStream fis = new FileInputStream("项目的名称\\src\\druid.properties");
pp.load(fis);
// 4.创建Druid连接池,使用配置文件中的参数
DataSource ds = DruidDataSourceFactory.createDataSource(pp);
// 5.从Druid连接池中取出连接
Connection cn = ds.getConnection();
// 6.执行SQL语句,预编译的方式
String sql = "insert into user values (null,?,?);";
// 6.1 创建预编译的对象
PreparedStatement pstate = cn.prepareStatement(sql);
pstate.setString(1,"name1");
pstate.setString(2,"1234");
int row = pstate.executeUpdate();
// 7.关闭资源
pstate.close();
// 这里的close不是关闭连接,而是放回连接池
cn.close();
fis.close();
// 数据库连接池的工具类
public class DruidDataUtils {
// 静态资源可以被使用
public static DataSource ds = null;
// 如果资源只需要加载一次,后续使用的都是同样的资源,可以直接写在静态代码块里面
static{
try {
// 3.加载properties文件的内容到Properties对象中
Properties pp = new Properties();
FileInputStream fis = new FileInputStream("项目的名称\\src\\druid.properties");
pp.load(fis);
// 4.创建Druid连接池,使用配置文件中的参数
ds = DruidDataSourceFactory.createDataSource(pp);
fis.close();
} catch (Exception e) {
e.printStackTrace();
}
}
// 提供给别人获取连接池中连接的方法,工具类中方法经常被别人调用,一般谁调用谁处理
public static Connection getConnection() throws Exception {
return ds.getConnection();
}
}
// Druid连接池抽象类
Connection cn = DruidDataUtils.getConnection();
// 执行SQL语句,预编译的方式
String sql = "insert into user values (null,?,?);";
// 创建预编译的对象
PreparedStatement pstate = cn.prepareStatement(sql);
pstate.setString(1,"name");
pstate.setString(2,"1234");
int row = pstate.executeUpdate();
System.out.println(row);
// 关闭资源
pstate.close();
cn.close();
// 品牌类
public class Brand {
private Integer id;
private String brandName;
private String companyName;
private Integer ordered;
private String description;
private Integer status;
public Brand() {
}
public Brand(Integer id, String brandName, String companyName, Integer ordered, String description, Integer status) {
this.id = id;
this.brandName = brandName;
this.companyName = companyName;
this.ordered = ordered;
this.description = description;
this.status = status;
}
...
}
public static void queryAll() throws Exception {
// 1.获取连接
Connection cn = DruidDataUtils.getConnection();
// 2.编写SQL语句
String sql = "SELECT * FROM tb_brand;";
// 3.生成对应的预编译对象
PreparedStatement pstate = cn.prepareStatement(sql);
// 4.执行SQL
ResultSet rs = pstate.executeQuery();
List list = new ArrayList<>();
// 5.处理返回的结果
while (rs.next()){
// 获取数据
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 brand = new Brand(id, brandName, companyName, ordered, description, status);
list.add(brand);
}
// 6.释放资源
rs.close();
pstate.close();
cn.close(); // 还
list.forEach(System.out::println);
}
public static void add() throws Exception {
// 1.获取连接
Connection cn = DruidDataUtils.getConnection();
// 2.编写SQL语句
String sql = "insert into tb_brand values (null,?,?,?,?,?);";
// 3.生成对应的预编译对象
PreparedStatement pstate = cn.prepareStatement(sql);
// 3.1 设置?参数
pstate.setString(1,"品牌名称1");
pstate.setString(2,"企业名称1");
pstate.setInt(3,1); // 排序
pstate.setString(4,"这是备注信息");
pstate.setInt(5,1); // 当前状态
// 4.执行SQL
int row = pstate.executeUpdate();
// 5.处理返回的结果
System.out.println(row);
// 6.释放资源
pstate.close();
cn.close();
}
public static void update() throws Exception {
// 1.获取连接
Connection cn = DruidDataUtils.getConnection();
// 2.编写SQL语句
String sql = "update tb_brand set brand_name=?,company_name=?," +
"ordered=?,description=?,status=? where id = ?";
// 3.生成对应的预编译对象
PreparedStatement pstate = cn.prepareStatement(sql);
// 3.1 设置?参数
pstate.setString(1,"品牌名称11");
pstate.setString(2,"企业名称11");
pstate.setInt(3,2);
pstate.setString(4,"备注信息111");
pstate.setInt(5,1);
pstate.setInt(6,1);
// 4.执行SQL
int row = pstate.executeUpdate();
// 5.处理返回的结果
System.out.println(row);
// 6.释放资源
pstate.close();
cn.close();
}
public static void delete() throws Exception {
// 1.获取连接
Connection cn = DruidDataUtils.getConnection();
// 2.编写SQL语句
String sql = "DELETE FROM tb_brand WHERE id = ?;";
// 3.生成对应的预编译对象
PreparedStatement pstate = cn.prepareStatement(sql);
// 3.1 设置?参数
pstate.setInt(1,3);
// 4.执行SQL
int row = pstate.executeUpdate();
// 5.处理返回的结果
System.out.println("row = " + row);
// 6.释放资源
pstate.close();
cn.close();
}