JDBC是什么?
jdbc是一个由sun公司(Oracle)提出的规范(一套接口),jdbc指的就是java语言连接数据库
jdbc就是一套面向所有数据库厂家的接口
每一个数据库厂家都希望可以通过java语言连接到自己开发的数据库,
这个时候,厂家肯定要写一套程序,java语言连接数据库的具体实现,这个实现类必须要实现JDBC接口
例如:java语言连接 Mysql
mysql的厂家就必须要实现jdbc这个接口
JDBC的驱动类型
JDBC的用途
保证mysql服务是开启的
将java包导入到工程lib下,并且添加到类路径下(保证版本对应)
注册驱动,使用Class类下的一个静态方法forName,使得类加载
获取数据库连接 DriverManager类提供了getConnection方法 (需要传入数据源信息)
获取数据库操作对象 createStatement方法
编写sql语句
按照sql语句的类别调用不同方法,获取到返回的结果
关闭数据库资源(放在finally语句块中)
xxxxxxxxxx1171package com.os467.test;2
3import java.sql.*;4
5/**6 * JDBC编程六步:7 * 1.注册驱动8 * 2.获取数据库连接9 * 3.获取数据库操作对象10 * 4.执行sql11 * 5.返回记录条数/获取结果集对象12 * 6.关闭资源13 */14
15public class JdbcTest01 {16
17 public static void main(String[] args) {18
19 //使三个实例作为成员变量存在在类中,使得finally语句块中可以读取到20 Connection connection = null;21
22 Statement statement = null;23
24 ResultSet resultSet = null;25
26 try{27
28 //1.注册驱动29 Class.forName("com.mysql.cj.jdbc.Driver");30
31 //2.获取数据库链接32 /**33 * String url 链接数据库的地址34 * String user 数据库的用户名 root35 * String password 数据库密码 root36 * jdbc:mysql:// 协议37 * localhost 本地的ip地址38 * 3306 默认端口号39 * os467test 需要使用的数据库40 * ?serverTimezone=GMT 设置时区41 */42
43 String url = "jdbc:mysql://localhost:3306/os467test?serverTimezone=GMT";44
45 String user = "root";46
47 String password = "root";48
49 connection = DriverManager.getConnection(url, user, password);50
51 System.out.println(connection);52
53 //3.获取数据库操作对象54 statement = connection.createStatement();55
56 //4.编写sql语句,执行sql57 String sql = "select * from emp";58
59 //5.执行sql,获取返回的结果集对象,遍历结果集60 resultSet = statement.executeQuery(sql);61
62 while(resultSet.next()){63
64 //取出结果集中的数据65 int empno = resultSet.getInt("EMPNO");66
67 String ename = resultSet.getString("ENAME");68
69 System.out.println("员工的编号为"+empno+" 员工的姓名为"+ename);70
71 }72
73
74 }catch (Exception e){75
76 e.printStackTrace();77
78 }finally {79
80 //6.关闭数据库资源,先进行非空校验,对close()可能发生的异常进行处理81 if (resultSet != null){82
83 try {84 resultSet.close();85 } catch (SQLException throwables) {86 throwables.printStackTrace();87 }88
89 }90
91 if (statement != null){92
93 try {94 statement.close();95 } catch (SQLException throwables) {96 throwables.printStackTrace();97 }98
99 }100
101 if (connection != null){102
103 try {104 connection.close();105 } catch (SQLException throwables) {106 throwables.printStackTrace();107 }108
109 }110
111 }112
113 }114
115
116}117
注意:在为字符集添加中文数据时,在url后面用&拼接characterEncoding=utf-8来设置字符集
并且数据库校对中每个字段的字符集也要设置为utf-8
xxxxxxxxxx841package com.os467.test;2
3import javax.swing.*;4import java.sql.*;5
6/**7 * 往学生表中添加数据8 */9public class JdbcTest03 {10
11 public static void main(String[] args) {12
13 Connection connection = null;14
15 Statement statement = null;16
17 try {18
19 //加载jdbc驱动20 Class.forName("com.mysql.cj.jdbc.Driver");21
22 String url = "jdbc:mysql://localhost:3306/os467test?serverTimezone=GMT&characterEncoding=utf-8";23
24 String user = "root";25
26 String password = "root";27
28 //链接数据库29 connection = DriverManager.getConnection(url, user, password);30
31 //获取操作对象32 statement = connection.createStatement();33
34 String sql = "insert into tb_student(name,age,hobby)" +35 "value('Tom',18,'打篮球')";36
37 int num = statement.executeUpdate(sql);38
39 if (num != 0){40
41 System.out.println("添加成功");42 }else{43
44 System.out.println("添加失败");45
46 }47
48 }catch (Exception e){49
50 e.printStackTrace();51
52 }finally {53 54 //关闭数据库资源,避免占用系统资源55 if (statement != null){56
57 try {58 statement.close();59 } catch (SQLException throwables) {60 throwables.printStackTrace();61 }62
63 }64
65 if (connection != null){66
67 try {68 connection.close();69 } catch (SQLException throwables) {70 throwables.printStackTrace();71 }72
73 }74
75
76
77 }78
79
80 }81
82
83}84
//模拟用户登入
xxxxxxxxxx981package com.os467.test;2
3import java.sql.*;4import java.util.Scanner;5
6public class UserJDBCTest02 {7
8 public static void main(String[] args) {9
10 //创建控制台打印对象11 Scanner scanner = new Scanner(System.in);12
13 System.out.println("请输入用户名:");14
15 String username = scanner.next();16
17 System.out.println("请输入密码:");18
19 String password = scanner.next();20
21
22 Connection connection = null;23
24 Statement statement = null;25
26 ResultSet resultSet = null;27
28 try{29
30 //注册驱动31 Class.forName("com.mysql.cj.jdbc.Driver");32
33 String url = "jdbc:mysql://localhost:3306/web_test?serverTimezone=GMT&characterEncoding=utf-8";34
35 //获取数据库对象36 connection = DriverManager.getConnection(url,"root","root");37
38 //获取数据库操作对象39 statement = connection.createStatement();40
41 resultSet = statement.executeQuery("select * from tb_user where username = '" + username + "' and password = '" + password + "'");42
43 //判断结果集是否为空和集合中是否有元素44 if(resultSet != null && resultSet.next()){45
46 System.out.println("登入成功");47
48 }else{49
50 System.out.println("登入失败");51
52 }53
54 }catch (Exception e){55
56 e.printStackTrace();57
58 }finally {59
60 if (resultSet != null){61
62 try {63 resultSet.close();64 } catch (SQLException throwables) {65 throwables.printStackTrace();66 }67
68 }69
70 //关闭数据库资源71 if (statement != null){72
73 try {74 statement.close();75 } catch (SQLException throwables) {76 throwables.printStackTrace();77 }78
79 }80
81 if (connection != null){82
83 try {84 connection.close();85 } catch (SQLException throwables) {86 throwables.printStackTrace();87 }88
89 }90
91 }92
93
94
95 }96
97}98
数据库中创建的每一张表 在java中都有一个实体与之对应
table中的字段对应的是实体beans中的属性
tb_user User
uid uid
username username
password password
通过jdbc来读取数据,这些数据也是以对象的形式被封装在结果集容器中ResultSet
resultSet !=null && resultSet.next()
第一个条件保证容器对象不为空,判断容器中是否有元素
我们会将读取的数据封装成对象,然后将对象装进集合中(ArrayList/HashMap)
后面学习了前端之后,我们会将集合对象传到前端,在前端取出集合中的数据,渲染数据!
java事务
实际上,一个Java应用系统,如果要操作数据库,则通过JDBC来实现的。增加、修改、删除都是通过相应方法间接来实现的,事务的控制也相应转移到java程序代码中。因此,数据库操作的事务习惯上就称为Java事务。
通俗的理解,事务是一组原子操作单元,从数据库角度说,就是一组SQL指令,要么全部执行成功,若因为某个原因其中一条指令执行有错误,则撤销先前执行过的所有指令。更简单的说就是:要么全部执行成功,要么撤销不执行。
事务的原子性:表示事务执行过程中的任何失败都将导致事务所作的任何修改失败
事务的一致性:表示当事务执行失败时,所有被该事务影响的数据都应该恢复到事务执行前的状态
事务的隔离性:表示在事务执行过程中对数据的修改,在事务提交之前对其他事务不可见
事务的持久性:表示已提交的数据在事务执行失败时,数据的状态都应该正确
案例:
银行存钱
银行取钱
转账方法 A B
假设有一个转账的场景:A账户转账给B账户,这个时候我们需要在A账户上扣钱,在B账户上加钱
所以我们需要去写两条sql来完成这样的需求,但是我们要开启事务的支持,因为这两条sql是在一条事务线上的,所以要么同时执行成功,要么同时失败,要满足事务的原子性和一致性。
事务案例代码:
jdbc默认状态下是自动提交的
connection.setAutoCommit();
然后在sql都执行成功的情况下我们要进行一个事务提交的操作connection.commit();connection.rollback()是一个回滚的方法,是为了让事务回到执行之前的状态xxxxxxxxxx861/**2 * A账户向B账户转账10003 *4 * 模拟一个异常5 *6 * 开启对事务的支持7 *8 * 在jdbc中如何开启对事务的支持9 *10 * jdbc默认是关闭事务的,如果想开启事务的话需要 connection.setAutoCommit();11 */12public class JdbcDemo02 {13
14 public static void main(String[] args) {15
16 Connection connection = null;17
18 Statement statement = null;19
20 try{21
22 Class.forName("com.mysql.cj.jdbc.Driver");23
24 connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/web_test?serverTimezone=GMT&characterEncoding=utf-8", "root", "root");25
26 //将自动提交设置为手动提交27 connection.setAutoCommit(false);28
29 statement = connection.createStatement();30
31 //A账户扣钱32 int num = statement.executeUpdate("update tb_account set balance_A = balance_A - 1000 where id = 1");33
34 System.out.println(num==1 ? "扣钱成功" : "扣钱失败");35
36 //模拟一个异常37 int i = 1 / 0;38
39 //B账户加钱40 num = statement.executeUpdate("update tb_account set balance_B = balance_B + 1000 where id = 1");41
42 System.out.println(num==1?"转账成功":"转账失败");43
44 //提交事务45 connection.commit();46
47 } catch (Exception e) {48
49 e.printStackTrace();50
51 }finally{52
53 if (statement != null){54
55 try {56 statement.close();57 } catch (SQLException throwables) {58
59 //事务回滚60 try {61 connection.rollback();62 } catch (SQLException e) {63 e.printStackTrace();64 }65
66 throwables.printStackTrace();67 }68
69 }70
71 if (connection != null){72
73 try {74 connection.close();75 } catch (SQLException throwables) {76 throwables.printStackTrace();77 }78
79 }80
81 }82
83 }84
85}86
sql注入:指的就是通过在sql中加入数据库的关键字,导致最终sql执行的结果是错误的
PreparedStatement 这个对象可以防止sql注入 因为这个对象在执行sql的时候
是分为两个步骤: 1.先预编译sql,先把sql的架子给搭建出来,但是没有赋值,2.给sql中注入具体的数据,执行sql
Statement对象没有预编译的过程,直接就是执行sql
考虑到安全性我们以后不会直接使用Statement而是使用PreparedStatement
xxxxxxxxxx151 //获取数据库操作对象并且预编译sql2 PreparedStatement preparedStatement = connection.prepareStatement("select * from tb_user where username = ? and password = ? ");3
4 //给占位符?赋值,占位符从1开始5 preparedStatement.setString(1,"jack001");6 preparedStatement.setString(2,"123456");7
8 //执行sql9 resultSet = preparedStatement.executeQuery();10
11 if (resultSet != null && resultSet.next()){12
13 System.out.println("登录成功");14
15 }
关于数据库的悲观锁和乐观锁(都是跟事务有关的):
乐观锁:假设在多线程场景下,多个线程同时对数据库中的一个表进行操作
如果多个线程会去修改同一条数据,乐观锁的思想就是觉得这种情况不可能发生
乐观锁:乐观锁可以不用去开启事务的支持(采用的是自动提交的策略)
xxxxxxxxxx11update tb_user set username = 'tom' where id = 1 and version = "影响记录条数只要大于等于1,这个 版本号就会改变"悲观锁:针对于以上描述的情况,悲观锁思想就会觉得这种情况一定会发生,然后要提前去解决这个问题
悲观锁一定要去开启对事务的支持,采用手动提交的策略来解决问题,行级锁,在sql后面加上 for update
xxxxxxxxxx11select * from tb_account where id = 1 for update;当一个线程在对某一条记录进行查询的时候,那么别的线程只能等待
工具类不能实例化对象,构造函数被private修饰
所有的方法都要被static修饰
xxxxxxxxxx801package com.os467.utils;2
3import java.sql.*;4
5/**6 * 封装工具类的步骤:7 *8 * 1.构造方法私有化9 * 2.所有的方法都得是静态方法10 *11 */12
13public class JdbcUtils {14
15 //私有化构造方法16 private JdbcUtils(){17
18 }19
20 //注册驱动21 static {22
23 try {24 Class.forName("com.mysql.cj.jdbc.Driver");25 } catch (ClassNotFoundException e) {26 e.printStackTrace();27 }28
29 }30
31 /**32 * 获取数据库链接方法33 */34 public static Connection getConnection() throws SQLException{35
36 return DriverManager.getConnection("jdbc:mysql://localhost:3306" +37 "/web_test?serverTimezone=GMT&characterEncoding=utf-8",38 "root", "root");39
40 }41
42 /**43 * 用于关闭资源的方法44 */45 public static void getClose(ResultSet resultSet, Statement statement,Connection connection){46
47 if (resultSet != null){48
49 try {50 resultSet.close();51 } catch (SQLException throwables) {52 throwables.printStackTrace();53 }54
55 }56
57 if (statement != null){58
59 try {60 statement.close();61 } catch (SQLException throwables) {62 throwables.printStackTrace();63 }64
65 }66
67 if (connection != null){68
69 try {70 connection.close();71 } catch (SQLException throwables) {72 throwables.printStackTrace();73 }74
75 }76
77 }78
79}80
利用工具类来执行sql
xxxxxxxxxx571package com.os467.demmo;2
3import com.os467.utils.JdbcUtils;4
5import java.sql.Connection;6import java.sql.PreparedStatement;7import java.sql.ResultSet;8import java.sql.SQLException;9
10public class JdbcDemo03 {11
12 public static void main(String[] args) {13
14 PreparedStatement preparedStatement = null;15
16 ResultSet resultSet =null;17
18 Connection connection = null;19
20 try {21 //获取数据库链接对象22 connection = JdbcUtils.getConnection();23
24 //获取数据库操作对象25 preparedStatement = connection.prepareStatement("select * from tb_user");26
27 //执行sql28 resultSet = preparedStatement.executeQuery();29
30 if (resultSet != null){31
32 while (resultSet.next()){33
34 int uid = resultSet.getInt("uid");35
36 String username = resultSet.getString("username");37
38 String password = resultSet.getString("password");39
40 System.out.println(uid+" "+username+" "+password);41
42 }43
44 }45
46 } catch (SQLException throwables) {47 throwables.printStackTrace();48 }finally {49
50 JdbcUtils.getClose(resultSet,preparedStatement,connection);51
52 }53
54 }55
56}57