数据库-JDBC

JDBC

学习目标

  1. 能够使用DCL处理MySQL中的用户
  2. 能够理解JDBC的概念
  3. 能够使用Connection接口(掌握)
  4. 能够使用Statement接口(掌握)
  5. 能够使用ResultSet接口(掌握)
  6. 能够使用JDBC实现对单表数据增、删、改、查(掌握)
  7. 能够使用JDBC操作事务(掌握)
  8. 能够编写JDBC工具类(掌握)
  9. 能够完成JDBC实现登录案例(掌握)

1、DCL创建用户,给用户授权,撤销授权

目标

能够使用DCL创建用户,给用户授权,撤销授权

讲解

回顾SQL

1)DDL: create / alter / drop 操作数据库和整个表

2)DML:insert /update/delete 操作数据库表中的数据

3)DQL :select 查询数据库表中的数据

4)DCL :grant /revoke 给用户授权和撤销权限的

​ 我们现在默认使用的都是root用户,超级管理员,拥有全部的权限。但是,一个公司里面的数据库服务器上面可能同时运行着很多个项目的数据库。所以,我们应该可以根据不同的项目建立不同的用户,分配不同的权限来管理和维护数据库。

注:mysqld.exe是MySQL的主程序,服务器端。Mysql.exe是MySQL的命令行工具,客户端。

[外链图片转存失败(img-JAq5McfO-1562514621875)(img/DCL01.png)]

创建用户
语法:
CREATE USER '用户名'@'主机名' IDENTIFIED BY '密码';

关键字说明:

  1. `用户名`:将创建的用户名,例如user1
  2. `主机名`:指定该用户在哪个主机上可以登陆,如果是本地用户可用localhost,如果想让该用户可以从任意远程主机登陆,可以使用通配符%
  3. `密码`:该用户的登陆密码,密码可以为空,如果为空则该用户可以不需要密码登陆服务器

具体操作:

需求1:创建u1用户,只能在localhost这个服务器登录mysql服务器,密码为1234.

说明:给普通用户授权,需要使用管理员root登录才可以实现。

创建用户语句:

-- u1用户只能在localhost这个IP登录mysql服务器
create user 'u1'@'localhost' identified by '1234';

具体的操作如下:

1)先打开一个dos窗口,然后使用root用户登录,并创建一个普通的用户。

[外链图片转存失败(img-5wUBojLQ-1562514621877)(img/DCL权限1.bmp)]

2)然后再打开一个dos窗口,使用新创键的普通用户u1进行登录。

[外链图片转存失败(img-fbMyov5q-1562514621877)(img/DCL权限2.bmp)]

需求2:创建u2用户可以在任何电脑上登录mysql服务器,密码为1234

创建用户语句:

create user 'u2'@'%' identified by '1234';

具体的操作如下:

1)使用root用户再创建一个新的普通用户u2

[外链图片转存失败(img-8qyu47k2-1562514621877)(img/DCL权限12.bmp)]

2)使用新创键的用户u2登录

[外链图片转存失败(img-us4LyDf4-1562514621878)(img/DCL权限13.bmp)]

注:创建的用户名都在mysql数据库中的user表中可以查看到,密码经过了加密。

[外链图片转存失败(img-2k5w3lNY-1562514621878)(img/可视化工具中查看用户1.bmp)]

授权用户

用户创建之后,基本没什么权限!需要给用户授权
[外链图片转存失败(img-eqmWXKIb-1562514621878)(img/DCL权限2.bmp)]

授权格式

GRANT 权限1, 权限2... ON 数据库名.表名 TO '用户名'@'主机名';

关键字说明

  1. `GRANT` 授权关键字
  2. 授予用户的权限,如`SELECT``INSERT``UPDATE`等。如果要授予所的权限则使用`ALL`
  3. `数据库名.表名`:该用户可以操作哪个数据库的哪些表。如果要授予该用户对所有数据库和表的相应操作权限则可用*表示,如`*.*`
  4. `'用户名'@'主机名'`: 给哪个用户授权

具体操作:

  1. 给u1用户分配对heima01这个数据库操作的权限:创建表,修改表,插入记录,更新记录,查询.

    A:使用root管理员创建一个heima01的数据库。

    [外链图片转存失败(img-Jjheac5N-1562514621878)(img/DCL权限3.bmp)]

    B:使用root管理员给普通用户u1进行上述需求的授权。

    语句:grant create,alter,insert,update,select on heima01.* to 'u1'@'localhost';
    

    [外链图片转存失败(img-VAq248XH-1562514621879)(img/DCL权限4.bmp)]

  2. 使用u1用户创建表person,并插入一条数据

    [外链图片转存失败(img-meZ1K99B-1562514621879)(img/DCL权限5.bmp)]

语句:create table person(age int);

[外链图片转存失败(img-TvljInQi-1562514621879)(img/DCL权限6.bmp)]

向person表中插入一条记录:

[外链图片转存失败(img-zRsSbcJh-1562514621879)(img/DCL权限7.bmp)]

语句:insert into person values(18);

注意:由于上述没有给普通用户授权删除表中的数据,所以当我们删除的时候,会出现如下错误:

[外链图片转存失败(img-mLcySgcn-1562514621880)(img/DCL权限8.bmp)]

撤销授权
REVOKE  权限1, 权限2... ON 数据库.表名 FROM '用户名'@'主机名';
举例:revoke all on heima01.* from 'user1'@'localhost'; 

注意:撤销用户权限必须使用root管理员。

关键字说明:

REVOKEONFROM	:撤销授权的关键字
权限	:用户的权限,如CREATEALTERSELECTINSERTUPDATE等,所有的权限则使用ALL
数据库名.表名	:对哪些数据库的哪些表,如果要取消该用户对所有数据库和表的操作权限则可用*表示,如*.*
'用户名'@'主机名':给哪个用户撤销 

具体操作:

  • 撤销u1用户对heima01数据库所有表的操作的权限.

    1. 首先使用root权限撤销用户u1的所有权限。

    [外链图片转存失败(img-NAbunLz0-1562514621880)(img/DCL权限9.bmp)]

    1. 使用用户u1登录,操作heima01数据库中的表。

    [外链图片转存失败(img-DeNWz7NR-1562514621880)(img/DCL权限10.bmp)]

查看权限
show grants for  '用户名'@'主机名';

具体操作:

  • 查看u1用户的权限
    SHOW GRANTS FOR 'u1'@'localhost';
    
    [外链图片转存失败(img-BiFLcPmk-1562514621881)(img/DCL权限11.bmp)]

注:usage是指连接(登陆)权限,建立一个用户,就会自动授予其usage权限(默认授予)

小结

  1. 创建用户:

    CREATE USER '用户'@'主机' ON 数据库名.表名 IDENDIFIED BY '密码';
    
  2. 添加权限:

    GRANT 权限1, 权限2,... ON 数据库名.表名 TO '用户'@'主机';
    
  3. 撤销权限:

    REVOKE 权限1, 权限2,... ON 数据库名.表名 FROM '用户'@'主机'
    

2、DCL删除用户,修改用户密码

目标

能够掌握DCL删除用户,修改用户密码

讲解

删除用户
DROP USER '用户名'@'主机名';

具体操作:

  • 删除u2
    drop user 'u2'@'%';
    
    [外链图片转存失败(img-RPicFqqy-1562514621881)(img/DCL权限14.bmp)]
修改管理员密码

注意:需要在未登陆MySQL的情况下操作。新密码不需要加上引号。

-- 新密码不需要加上引号
mysqladmin -u root -p password 新密码

具体操作:

1)将root管理员的新密码改成123456 
2)要求输入旧密码
3)使用新密码登录

[外链图片转存失败(img-eWfDe96z-1562514621881)(img/DCL权限15.bmp)]

修改普通用户密码

注意:需要使用root用户登陆MySQL的情况下操作。新密码要加单引号。

set password for '用户名'@'主机名' = password('新密码');

具体操作:

  1. 将’u1’@‘localhost’的密码改成’666’

使用root用户更改:

[外链图片转存失败(img-SpDdq5Sl-1562514621881)(img/DCL权限16.bmp)]

  1. 使用新密码登录,老密码登录不了

[外链图片转存失败(img-xBLgf1Sf-1562514621882)(img/DCL权限17.bmp)]

小结

  1. 删除用户?DROP USER ‘用户名’@‘主机名’;
  2. 修改用户密码?
    修改root用户: 不需要登录 mysqladmin -uroot -p密码 password 新密码
    修改普通用户:使用root登录: set password for ‘用户’@‘主机’ = password(‘新密码’);

3、JDBC的概念

目标

  1. 能够掌握JDBC的概念
  2. 能够理解JDBC的作用

讲解

客户端操作MySQL数据库的方式

  1. 使用第三方客户端来访问MySQL:SQLyog、Navicat

  2. 使用MySQL自带的命令行方式

  3. 通过Java来访问MySQL数据库,今天要学习的内容

    如何通过Java代码去操作数据库呢?

    Java中给我们提供专门的一套技术,可以通过其中的某些类和接口操作任何的数据库,这个技术就是今天要学习的JDBC。

    什么是JDBC:Sun公司为了简化、统一对数据库的操作,定义了一套java操作数据库的接口的规范,称之为JDBC。JDBC的全称为:java database connection (java和 数据库的连接 ) 就是使用java代码来操作数据库。
    JDBC的作用:Java通过JDBC就可以操作数据库

JDBC的由来
  1. java程序依赖于jdk,jdk和数据库是2个不同的应用程序,那他们是怎么进行访问的呢?

    要想搞清楚这个问题,我们必须了解下电脑是如何和其他硬件设备交互的。假设我们电脑安装完系统之后是一个无驱动的操作系统。那么当我们电脑想播放声音,即安装音响,必须得安装声卡驱动。同时电脑想和u盘硬件进行交互,也必须在电脑上安装对应的驱动。如果驱动安装失败,很显然他们是不能正常的交互的。这个安装驱动的其实就是为了定义他们两个相互交互的规则。只有统一了规则,才能交互。

    具体的解释如下图所示:

    [外链图片转存失败(img-A4RAOpUS-1562514621882)(img/电脑和其他硬件设备交互.bmp)]

同理:java程序想和数据库进行交互,也必须得安装数据库驱动,这样才能交互。但是,我们数据库有多种,这样就会导致不同的数据库具备不同的数据库驱动。

从而会导致在开发中作为程序员由于安装不同的数据库驱动而浪费很多时间,同时和数据库交互的java代码也得重新书写,这样都会导致效率很低。所以说,sun公司就会制定一套规则,这套规则就是用来java程序连接数据库的,然后各大数据库厂商只需要实现这个规则即可。这个规则就是jdbc技术,即接口。

换句话就是说,就是数据库厂商使用sun公司提供的接口,然后作为java程序员实现接口中的方法即可。接口中的方法体由具体的数据库厂商来实现。

[外链图片转存失败(img-v68cABtp-1562514621882)(img/jdbc连接数据库.bmp)]

JDBC的好处
  1. 我们只需要会调用JDBC接口中的方法即可,使用简单
  2. JDBC有关的类和接口:都在java.sql 和 javax.sql(扩展包) 包下
  3. 方法体由具体的数据库厂商来完成的
  4. 使用同一套Java代码,进行少量的修改就可以访问其他JDBC支持的数据库

小结

  1. 说出JDBC的概念?Java数据库连接(Java操作数据库的标准规范)
  2. 说出JDBC的作用?Java通过JDBC就可以操作数据库

4、JDBC核心API的介绍

目标

能够理解JDBC四个核心对象

讲解

JDBC会用到的包
  1. java.sql:JDBC访问数据库的基础包,在JavaSE中的包。如:java.sql.Connection
  2. javax.sql: JDBC访问数据库的扩展包
  3. 数据库的驱动,各大数据库厂商来实现。如:MySQL的驱动:com.mysql.jdbc.Driver
JDBC四个核心对象

这几个类都是在java.sql包中

  1. DriverManager(类): 数据库驱动管理类。这个类的作用:1)注册驱动; 2)创建java代码和数据库之间的连接,即获取Connection接口;
  2. Connection(接口): 是一个接口, 建立数据库连接的一个接口。作用:建立数据库和java代码之间的连接。表示与数据库创建的连接
  3. Statement(接口)、PreparedStatement(接口) (解决安全隐患问题,比如sql注入的问题): 数据库操作,向数据库发送sql语句。执行SQL语句的对象
  4. ResultSet: 结果集或一张虚拟表。 Statement 发送sql语句,得到的结果 封装在 ResultSet 中。
    [外链图片转存失败(img-2xZTAf5H-1562514621882)(img/jdbc03.png)]
JDBC访问数据库的步骤
  1. 由DriverManager注册驱动程序

  2. 创建和数据库的连接对象Connection

  3. 由客户端发送SQL语句给服务器执行,SQL语句封装成Statement对象

  4. 查询到的结果集封装成ResultSet对象

  5. 在客户端可以从ResultSet中取出数据,处理结果集

  6. 释放资源,关闭连接对象

小结

JDBC四个核心对象?

  1. DriverManager: 用于注册驱动
  2. Connection: 表示与数据库创建的连接
  3. Statement: 执行SQL语句的对象
  4. ResultSet: 结果集或一张虚拟表

5、JDBC注册驱动

Connection表示Java程序与数据库之间的连接,只有拿到Connection才能操作数据库。

JDBC获取连接步骤

1.导入mysql驱动Jar包
2.注册驱动
3.获取连接

目标

能够导入mysql驱动Jar包

能够通过JDBC注册数据库驱动

讲解

准备工作

1、确定启动mysql数据库。

此电脑-------》右键管理-------》选择服务

[外链图片转存失败(img-qxqwucXO-1562514621883)(img/jdbc连接数据库1.bmp)]

找到MySQL服务,查看MySQL服务是否已经启动了,如果启动是灰色,说明已经启动了。

[外链图片转存失败(img-s36EEun5-1562514621883)(img/jdbc连接数据库2.bmp)]

2、创建数据库和创建user表,并添加信息,sql语句如下。

打开可视化工具,将如下sql语句添加到可视化工具中,并执行以下sql语句即可。

[外链图片转存失败(img-oIuoAtYG-1562514621883)(img/jdbc连接数据库3.bmp)]

-- 创建数据库
create database day04_db;

-- 切换数据库
use day04_db;

-- 用户表
create table user (
  id int primary key auto_increment,
  username varchar(30) unique not null,
  password varchar(30)
);

insert into user(username, password) values('zhangsan','123');
insert into user(username, password) values('lisi','123');
insert into user(username, password) values('wangwu','123');

select * from user;

执行结果:

[外链图片转存失败(img-TgxjG4tW-1562514621884)(img/jdbc连接数据库4.bmp)]

导入驱动Jar包

1、新建项目day04,在项目day04上新建lib文件夹

[外链图片转存失败(img-gEHmMe9J-1562514621884)(img/jdbc连接数据库5.bmp)]

2、将mysql驱动的jar包导入到lib文件夹下

[外链图片转存失败(img-DN1ZNmoA-1562514621884)(img/jdbc连接数据库6.bmp)]

3、在导入的mysql的jar包上右键,选择Add as Library…

[外链图片转存失败(img-rkoIRsZP-1562514621885)(img/jdbc连接数据库7.bmp)]

注册驱动

我们Java程序需要通过数据库驱动才能连接到数据库,因此需要注册驱动。
MySQL的驱动的入口类是:com.mysql.jdbc.Driver
[外链图片转存失败(img-lCa4WL00-1562514621885)(img/jdbc07.png)]

API介绍

java.sql.DriverManager类用于注册驱动。提供如下方法注册驱动

static void registerDriver(Driver driver) 
向 DriverManager 注册给定驱动程序。 

说明:

​ 1)执行完上述语句之后,DriverManager就可以管理mysql驱动了。

​ 2)当前的DriverManager.registerDriver(Driver driver);方法的参数是Driver,这是jdbc的一个接口,所以我们需要给定实现该接口的实现类。如果我们连接的是mysql数据库,那么需要导入mysql数据库提供的包,也就是com.mysql.jdbc.Driver; 下的Driver类。如果我们连接的是oracle数据库,那么需要导入oracle数据库提供的包。

使用步骤

1.DriverManager.registerDriver(驱动对象); 传入对应参数即可

案例代码
public class Demo01 {
	public static void main(String[] args) throws Exception {
		// 注册驱动
		DriverManager.registerDriver(new com.mysql.jdbc.Driver());
	}
}

说明:这里的new Driver()的类Driver就是来自mysql数据库。

通过查询com.mysql.jdbc.Driver源码,我们发现Driver类“主动”将自己进行注册

public class Driver extends NonRegisteringDriver implements java.sql.Driver {
    static {
        try {
            // 自己自动注册
            java.sql.DriverManager.registerDriver(new Driver());
        } catch (SQLException E) {
            throw new RuntimeException("Can't register driver!");
        }
    }
    public Driver() throws SQLException {
    }
}

[外链图片转存失败(img-aOWofuHg-1562514621886)(img/jdbc08.png)]

注意:使用DriverManager.registerDriver(new com.mysql.jdbc.Driver());,存在以下方面不足

  1. 驱动被注册两次

使用Class.forName("com.mysql.jdbc.Driver");加载驱动,这样驱动只会注册一次

public class Demo01 {
	public static void main(String[] args) throws Exception {
		Class.forName("com.mysql.jdbc.Driver"); // 后期可以将"com.mysql.jdbc.Driver"字符串写在文件中.
	}
}

演示:Class.forName("包名.类名");会走这个类的静态代码块
[外链图片转存失败(img-u9nvbGW0-1562514621886)(img/jdbc10.png)]

通常开发我们使用Class.forName() 加载驱动。Class.forName("com.mysql.jdbc.Driver");会走Driver类的静态代码块。在静态代码块中注册一次驱动。
[外链图片转存失败(img-hqPXzNzY-1562514621886)(img/jdbc09.png)]

总结:注册MySQL驱动使用Class.forName("com.mysql.jdbc.Driver");

小结

  1. 导入mysql驱动Jar包

  2. 通过JDBC注册数据库驱动?

    Class.forName("com.mysql.jdbc.Driver");
    

6、获取连接

能够通过JDBC获取数据库连接

讲解

API介绍

java.sql.DriverManager类中有如下方法获取数据库连接

static Connection getConnection(String url, String user, String password) 
连接到给定数据库 URL ,并返回连接。 
参数说明
  1. String url:连接数据库的URL,用于说明连接数据库的位置
  2. String user:数据库的账号
  3. String password:数据库的密码

连接数据库的URL地址格式:协议名:子协议://服务器名或IP地址:端口号/数据库名?参数=参数值
[外链图片转存失败(img-RyQCj3aE-1562514621887)(img/jdbc13.png)]
MySQL写法:jdbc:mysql://localhost:3306/day04_db
如果是本地服务器,端口号是默认的3306,则可以简写:jdbc:mysql:///day04_db

[外链图片转存失败(img-5MqIrWVn-1562514621887)(img/url.bmp)]

注意事项

如果数据出现乱码需要加上参数: ?useUnicode=true&characterEncoding=utf8,表示让数据库以UTF8编码来处理数据。
如: jdbc:mysql://localhost:3306/day04_db?useUnicode=true&characterEncoding=utf8

使用步骤

1.DriverManager.getConnection(url, user, password); 传入对应参数即可

案例代码
public class Demo01 {
	public static void main(String[] args) throws Exception {
		Class.forName("com.mysql.jdbc.Driver");
		// 连接到MySQL
		// url: 连接数据库的URL
		// user: 数据库的账号
		// password: 数据库的密码
		Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/day04_db", "root", "1234");
		System.out.println(conn);
	}
}
案例效果

1.连接成功
[外链图片转存失败(img-2WZMOElb-1562514621887)(img/jdbc14.png)]
2.连接失败
[外链图片转存失败(img-RR5JIxXx-1562514621887)(img/jdbc15.png)]

小结

  1. JDBC获取数据库连接使用哪个API?

    DriverManager.getConnection(数据库url, 账号, 密码)
    
  2. 通过JDBC连接mysql的URL写法?

    jdbc:mysql://localhost:3306/数据库
    

7、JDBC实现对单表数据增、删、改、查

目标

通过JDBC实现对单表数据增、删、改、查

讲解

JDBC实现对单表数据增、删、改

我们要对数据库进行增、删、改、查,需要使用Statement对象来执行SQL语句。

API介绍

获取Statement对象

java.sql.Connection接口中有如下方法获取到Statement对象

Statement createStatement() 
创建一个 Statement 对象来将 SQL 语句发送到数据库

Statement的API介绍

  1. int executeUpdate(String sql)
    根据执行的DML(INSERT、UPDATE、DELETE)语句,返回受影响的行数
    
  2. ResultSet executeQuery(String sql)
    根据查询语句返回结果集,只能执行SELECT语句
    

    注意:在MySQL中,只要不是查询就是修改。
    executeUpdate:用于执行增删改
    executeQuery:用于执行查询

使用步骤
  1. 注册驱动
  2. 获取连接
  3. 获取Statement对象
  4. 使用Statement对象执行SQL语句
  5. 释放资源
案例代码
public class Demo03 {
	public static void main(String[] args) throws Exception {
		Class.forName("com.mysql.jdbc.Driver");

		Connection conn = DriverManager.getConnection("jdbc:mysql:///day04_db", "root", "1234");
		System.out.println(conn);

		// 从连接中拿到一个Statement对象
		Statement stmt = conn.createStatement();

		// 1.插入记录
		String sql = "insert into user values(null, 'zhaoliu', 'abc')";
		int i = stmt.executeUpdate(sql);
		System.out.println("影响的行数:" + i);

		// 2.修改记录
		sql = "update user set username='tianqi' where username='zhaoliu'";
		i = stmt.executeUpdate(sql);
		System.out.println("影响的行数:" + i);

		// 3.删除记录
		sql = "delete from user where id=4";
		i = stmt.executeUpdate(sql);
		System.out.println("影响的行数:" + i);
		
		// 释放资源
		stmt.close();
		conn.close();
	}
}

8、JDBC实现对单表数据查询

目标

能够掌握JDBC实现对单表数据查询

讲解

ResultSet用于保存执行查询SQL语句的结果。
我们不能一次性取出所有的数据,需要一行一行的取出。

ResultSet的原理
  1. ResultSet内部有一个指针,刚开始记录开始位置
  2. 调用next方法, ResultSet内部指针会移动到下一行数据
  3. 我们可以通过ResultSet得到一行数据 getXxx得到某列数据
    [外链图片转存失败(img-60O0D5tb-1562514621888)(img/jdbc18.png)]
ResultSet获取数据的API

其实ResultSet获取数据的API是有规律的get后面加数据类型。我们统称getXXX()
[外链图片转存失败(img-LrtOP3N8-1562514621888)(img/jdbc19.png)]

​ 例如:

[外链图片转存失败(img-YqokFrvG-1562514621888)(img/结果集.bmp)]

对于上图中的一行数据,我要获取username为zhangsan这列的值,有如下2种写法:

  1. rs.getString(“username”); 通过列名获取该列的值。

  2. rs.getString(2); 通过username列所在的第二个位置获取该列的值。

使用JDBC查询数据库中的数据的步骤
  1. 注册驱动
  2. 获取连接
  3. 获取到Statement
  4. 使用Statement执行SQL
  5. ResultSet处理结果
  6. 关闭资源
案例代码
public class Demo04 {
	public static void main(String[] args) throws Exception {
		Class.forName("com.mysql.jdbc.Driver");
		
		Connection conn = DriverManager.getConnection("jdbc:mysql:///day04_db", "root", "1234");
		Statement stmt = conn.createStatement();
		
		SString sql = "select * from user";
		ResultSet rs = stmt.executeQuery(sql);
		
		// 内部有一个指针,只能取指针指向的那条记录
        while(rs.next()){// 指针移动一行,有数据才返回true
				int id = rs.getInt("id");
				String name = rs.getString(2);
				String pwd= rs.getString(3);
				System.out.println(id+"+++"+name+"++++"+pwd);
			}
		
		// 关闭资源
		rs.close();
		stmt.close();
		conn.close();
	}
}

小结

其实我们使用JDBC操作数据库的步骤都是固定的。不同的地方是在编写SQL语句

  1. 注册驱动
  2. 获取连接
  3. 获取到Statement
  4. 使用Statement执行SQL
  5. ResultSet处理结果
  6. 关闭资源

ResultSet如何获取数据?

  1. 调用next方法, ResultSet内部指针会移动到下一行数据
  2. 我们可以通过ResultSet得到一行数据 getXxx得到某列数据

9、JDBC事务

目标

能够掌握JDBC操作事务

讲解

之前我们是使用MySQL的命令来操作事务。接下来我们使用JDBC来操作银行转账的事务。

准备数据
# 创建一个表:账户表.
create database day05_db;
# 使用数据库
use day05_db;
# 创建账号表
create table account(
	id int primary key auto_increment,
	name varchar(20),
	money double
);
# 初始化数据
insert into account values (null,'a',1000);
insert into account values (null,'b',1000);
JDBC操作事务

[外链图片转存失败(img-agj65RfU-1562514621889)(img/JDBC控制事务.bmp)]

API介绍

Connection接口中与事务有关的方法

  1. void setAutoCommit(boolean autoCommit) throws SQLException;
    false:开启事务, true:关闭事务
    
  2. void commit() throws SQLException;
    提交事务
    
  3. void rollback() throws SQLException;
    回滚事务
    

说明:

注意:在jdbc事务操作中,事务的控制都是通过Connection对象完成的,当一个完整的业务操作前,我们首先使用conn.setAutoCommit(false)来开启事务。默认情况下是true的,表示关闭事务,那么一条sql语句就是一个事务,默认提交事务。如果设置为false,那么表示开启事务,所有的sql语句就会都在一个事务中。

当业务操作完成之后,如果整个操作没有问题,我们需要使用conn.commit()来提交事务。当然了,如果出现了异常,我们需要使用conn.rollback()撤销所有的操作,所以出现异常,需要进行事务的回滚。

使用步骤
  1. 注册驱动
  2. 获取连接
  3. 开启事务
  4. 获取到Statement
  5. 使用Statement执行SQL
  6. 提交或回滚事务
  7. 关闭资源
案例代码

如下是使用jdbc操作事务的转账案例代码。

需求:a转给b 100元。

分析:

a用户 money=money-100

b用户 money=money+100

@Test
	public void demo2() throws SQLException {
		// 需求: 完成转账
		Connection conn = null;
		PreparedStatement stmt = null;

		try {
			// 1 获取连接
            Class.forName("com.mysql.jdbc.Driver");
			conn = DriverManager.getConnection("jdbc:mysql:///day04_db", "root", "1234");
			// 2 开启事务
			conn.setAutocnmit(false);
			// 3 执行一组sql语句...
			// 3.1 完成 a-100
			/*String sql = "update account set money=money-? where name=?";
			stmt = conn.prepareStatement(sql);
			stmt.setDouble(1, 100);
			stmt.setString(2, "a");
			stmt.executeUpdate();*/
            String sql = "update account set money=money-100 where name=’a’";
            stmt = conn.prepareStatement(sql);
            stmt.executeUpdate();
			// 6 模拟断电 发生异常
			int j = 1 / 0;

			// 3.2 完成 b+100
			/*String sql2 = "update account set money=money+? where name=?";
			stmt = conn.prepareStatement(sql2);
			stmt.setDouble(1, 100);
			stmt.setString(2, "b");
			stmt.executeUpdate();*/
            String sql2 = "update account set money=money+100 where name=’b’";
            stmt = conn.prepareStatement(sql2);
            stmt.executeUpdate();

			// 4.1 如果一切正常 提交事务
			System.out.println("一切正常 提交事务");
			conn.commit();
		} catch (Exception e) {
			// 4.2 如果出现异常 回滚事务
			System.out.println("出现异常 回滚事务");
			if (conn != null) {
				conn.rollback();
			}
		} finally {
			// 5 释放资源
			if (stmt != null) {
				stmt.close();
			}

			if (conn != null) {
				conn.close();
			}
		}
	}

小结

JDBC中与事务相关的API?Connection接口中setAutoCommit,commit,rollback

JDBC操作事务的步骤?

  1. 注册驱动
  2. 获取连接
  3. 获取到Statement
  4. 开启事务
  5. 使用Statement执行SQL
  6. 提交或回滚事务
  7. 关闭资源

10、编写JDBC工具类

目标

能够编写JDBC获取连接与关闭连接工具类

讲解

​ 在上面的学习过程中,我们发现我们有很多重复的操作。那么这样一方面来说对我们开发带来了不便,更多的时候是当我遇到如下的问题:

数据库的用户名发生了变化,这时候我们发现,我们需要修改每处获取连接的用户名参数。这样是对于我们后期的维护是非常繁琐的。所以我们需要对jdbc操作数据库的步骤的一些常用的方法抽出来,放到一个外部的工具类中。

获得连接的初步抽取

首先创建一个JDBCUtils 工具类:然后将jdbc中获取连接的方法抽取到工具类中。

public class JDBCUtils {
	// 获得连接
	public static Connection getConnection(){
Connection con = null;
		try {
             // 注册驱动
			Class.forName("com.mysql.jdbc.Driver");
			// 创建连接
		    String url = "jdbc:mysql://localhost:3306/day04_db";
		    String user = "root";
		    String password = "123";
		    con = DriverManager.getConnection(url, user, password);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return con;
	}
}
获得连接第二次优化

紧接着,将刚刚获取连接的方法中所用的参数 都以变量的形式抽离出来,这样方便这些参数的统一管理。

public class JDBCUtils {
	static String driverClass = null;
	static String url = null;
	static String user = null;
	static String password = null;

	static {
		driverClass = "com.mysql.jdbc.Driver";
		url = "jdbc:mysql://localhost:3306/day04_db";
		user = "root";
		password = "123";
		// 注册驱动
		try {
			Class.forName(driverClass);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	// 获得连接
	public static Connection getConnection() {
Connection con = null;
		  try {
		    con = DriverManager.getConnection(url, user, password);
		   } catch (Exception e) {
			e.printStackTrace();
		   }
		   return con;
	}
}
在项目day04目录下创建jdbc.properties

问题:上面的操作已经完成了我们工具类获取连接的方法的抽取。但是如果说当数据库的用户名,或者说密码,或者说数据库的地址放生变化的时候,

我们发现我们需要修改java代码,这也就意味着我们的.class文件需要重新编译。并且每次修改java代码有可能还会带来没有必要的风险。

那么针对这样的问题我们该如何进行优化呢?

显然,我们不能将这些配置参数放在java代码中,只能将这些参数存放在外部文件中,而我们在java代码中通过io流的方式将文件读取出来就行了。当我们需要修改这些参数的时候,只需要修改配置文件中的值,java代码并不需要编译,只需要将应用程序重新启动一下,io重新读取一下。这样就行了。所以接下来我们需要将jdbc获取连接中需要的参数存放在外部的.properties文件中。

创建properties文件的步骤:

第一步:选中项目day04,右键----》new-----》File

[外链图片转存失败(img-1L1TuObW-1562514621889)(img/抽取工具类.bmp)]

第二步:将文件以properties为后缀名进行保存。

[外链图片转存失败(img-2CTi5Izm-1562514621889)(img/抽取工具类1.bmp)]

jdbc.properties文件中的配置信息:

driverClass=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/day04_db
user=root
password=123

第三步:如何读取外部文件的内容呢?

分析:

使用Properties集合和字节流读取可以实现。

具体的测试代码如下所示:

public static void main(String[] args) {
		// 需求: 通过properties对象读取 外部配置的内容
		Properties prop = new Properties();
		try {
            //对于FileInputStream流相对的路径是当前模块
             FileInputStream in=new FileInputStream("jdbc.properties");
			// 加载外部的配置文件
			prop.load(in);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		// 读取外部配置文件的内容
		String driverClass = prop.getProperty("driverClass");
		String url = prop.getProperty("url");
		String user = prop.getProperty("user");
		String password = prop.getProperty("password");

		System.out.println(driverClass);
	}
获得连接的最终优化版
public class JDBCUtils {
	static String driverClass = null;
	static String url = null;
	static String user = null;
	static String password = null;

	static {
		// 需求: 通过properties对象读取 外部配置的内容
		Properties prop = new Properties();

		try {
			 FileInputStream in=new FileInputStream("jdbc.properties");
			// 加载外部的配置文件
			prop.load(in);
			// 读取外部配置文件的内容
		    driverClass = prop.getProperty("driverClass");
		    url = prop.getProperty("url");
		    user = prop.getProperty("user");
		    password = prop.getProperty("password");
			// 注册驱动
			Class.forName(driverClass);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
// 获得连接
	public static Connection getConnection() {
		Connection con = null;
		  try  {
		          con = DriverManager.getConnection(url, user, password);
		        } catch (Exception e) 
				{
			        e.printStackTrace();
		         }
         return con;
	}
}
关闭资源
// 释放资源
	public static void release(Connection conn, Statement stmt, ResultSet rs) {
		// 释放资源
		try {
			if (rs != null) {
				rs.close();
			}
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		try {
			if (stmt != null) {
				stmt.close();
			}
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		try {
			if (conn != null) {
				conn.close();
			}
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
优化后的delete 方法

需求: 删除id=3的记录。

@Test
	public void delete() {
		// 需求: 删除id=3的记录
		Connection conn = null;
		Statement stmt = null;

		try {
			// 获得连接
			conn = JDBCUtils.getConnection();
			// 获得发送sql的对象
			stmt = conn.createStatement();
			// 执行sql 获得结果
			String sql = "delete from user where id=3";
			int sum = stmt.executeUpdate(sql);
			// 处理结果
			System.out.println(sum);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			// 释放资源
			JDBCUtils.release(conn, stmt, null);
		}
	}

11、JDBC实现登录案例

目标

模拟用户输入账号和密码登录网站

  1. 输入正确的账号,密码,显示登录成功
  2. 输入错误的账号,密码,显示登录失败

讲解

案例分析
  1. 使用数据库保存用户的账号和密码
  2. 使用SQL根据用户的账号和密码去数据库查询数据
  3. 如果查询到数据,说明登录成功
  4. 如果查询不到数据,说明登录失败
实现步骤

1.使用SQL根据用户的账号和密码去数据库查询数据.

@Test
	public void login() {
		// 需求: 根据用户名和密码 查询用户信息
		Connection conn = null;
		Statement stmt = null;
		ResultSet rs = null;

		try {
			// 获得连接
			conn = JDBCUtils.getConnection();
			// 获得发送sql的对象
			stmt = conn.createStatement();
			// 执行sql 获得结果
			String uname = "zhangsan";
			String upwd = "1234";
			String sql = "select * from user where username='" + uname + "' and password='" + upwd + "'";
			System.out.println(sql);
			rs = stmt.executeQuery(sql);
			// 处理结果
			if (rs.next()) {
				int id = rs.getInt("id");
				String username = rs.getString("username");
				String pwd = rs.getString("password");
				System.out.println(id + ":::" + username + "===" + pwd);
                System.out.println("登录成功");
			} else {
				System.out.println("登录失败");
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			// 释放资源
			JDBCUtils.release(conn, stmt, rs);
		}
}

小结

登录案例步骤

  1. 使用数据库保存用户的账号和密码
  2. 让用户输入账号和密码
  3. 使用SQL根据用户的账号和密码去数据库查询数据
  4. 如果查询到数据,说明登录成功
  5. 如果查询不到数据,说明登录失败
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值