什么是JDBC?
Java连接数据库!

需要jar包支持:
- java.sql
- javax.sql
- mysql-connter-java......连接驱动(必须要导入)
实验-Mysql数据库
MySQL数据插入表中数据

sql
CREATE TABLE users(
`id` INT PRIMARY KEY,
`name` VARCHAR(40),
`password` VARCHAR(40),
`email` VARCHAR(2222),
`birthday` DATE
);
INSERT INTO users(`id`,`name`,`password`,`email`,`birthday`)
VALUES(1,'admin','123456','admin@gmail.com','1998-06-18');
INSERT INTO users(`id`,`name`,`password`,`email`,`birthday`)
VALUES(2,'system','000000','system@gmail.com','1999-06-18');
INSERT INTO users(`id`,`name`,`password`,`email`,`birthday`)
VALUES(3,'sa','00000000','sa@gmail.com','1992-06-18');
INSERT INTO users(`id`,`name`,`password`,`email`,`birthday`)
VALUES(4,'web','0123456789','web@gmail.com','1991-06-18');
SELECT * FROM users;
导入数据库依赖
xml
<dependencies>
<!--MySQL驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
</dependencies>
idea连接数据库

jdbc连接七部曲
- 获取配置信息&解决中文乱码
- 加载驱动
显式加载:
* Class.forName("..."):这是最经典的方式,在代码中显式地加载驱动类。例如,Class.forName("com.mysql.cj.jdbc.Driver")。
* 优点:兼容老版本,建议写、兼容性强。
* 缺点:需要手动编写代码,在一些情况下(如 JDBC 4.0 之后),可能显得冗余。
隐示加载:
spl模式
* SPI ,全称为 Service Provider Interface,是一种服务发现机制。
* 它通过在ClassPath路径下的META-INF/services文件夹查找文件,自动加载文件里所定义的类。
* 这一机制为很多框架扩展提供了可能,比如在Dubbo、JDBC中都使用到了SPI机制。
jdbc4.0后 可以自动扫描jar包下面的这个文件

- 连接数据库,代表数据库
- 向数据库发送SQL的对象 Statement 用它来做(CRUD)增删改查
- 编写SQL
- 执行查询SQL语句
- 关闭连接,释放资源
增删改查
java
//受影响的行数,CRUD都是用executeUpdate即可
int i = preparedStatement.executeUpdate();
完整代码
java
public static void main(String[] args) throws ClassNotFoundException, SQLException {
//1.获取配置信息
// serverTimezone=UTC 解决中文乱码
String url = "jdbc:mysql://localhost:3306/jdbc?useUnicode=true&characterEncoding=UTF-8";
String user = "root";
String password = "123456";
// 2.加载驱动
// Class.forName("com.mysql.jdbc.Driver");
// 3.连接数据库,代表数据库
Connection connection = DriverManager.getConnection(url, user, password);
// 4.向数据库发送SQL的对象,Statement :用它来做(CRUD)增删改查
Statement statement = connection.createStatement();
// 5.编写SQL
String sql = "select * from users;";
// 6.执行查询SQL语句,返回一个ResultSet对象
ResultSet resultSet = statement.executeQuery(sql);
while (resultSet.next()){// 如果还有数据
System.out.println("id="+resultSet.getObject("id"));
System.out.println("name="+resultSet.getObject("name"));
System.out.println("password="+resultSet.getObject("password"));
System.out.println("email="+resultSet.getObject("email"));
System.out.println("birthday="+resultSet.getObject("birthday"));
}
// 7.关闭连接,释放资源(一定要做)先开后关
statement.close();
connection.close();
resultSet.close();
}
}
预编译SQL
更加安全
java
public class TestJdbc2 {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
// 1.配置信息
String url = "jdbc:mysql://localhost:3306/jdbc?useUnicode=true&characterEncoding=UTF-8";
String user = "root";
String password = "123456";
// 2.加载驱动
Class.forName("com.mysql.jdbc.Driver");
// 3.连接数据库
Connection connection = DriverManager.getConnection(url, user, password);
// 4.编写SQL
String sql = "insert into users(`id`,`name`,`email`,`password`,`birthday`) values (?,?,?,?,?);";
// 5.预编译
PreparedStatement preparedStatement = connection.prepareStatement(sql);
//设置?的值
preparedStatement.setInt(1,5); //给第一个占位符,赋值id为5
preparedStatement.setString(2,"test"); //给第二个占位符,赋值name为test
preparedStatement.setString(3,"test@gmail.com"); //给第三个占位符,赋值email为test@gmail.com
preparedStatement.setString(4,"123456"); //给第四个占位符,赋值password为123456
preparedStatement.setDate(5,new Date(new java.util.Date().getTime())); //给第五个占位符,赋值birthday为当前时间
// 5. 执行SQL
int i = preparedStatement.executeUpdate();
//增删改查的判断
if (i > 0){
System.out.println("插入成功");
}else{
System.out.println("插入失败");
}
// 6.关闭连接,释放资源
connection.close();
preparedStatement.close();
}
}
事务
要么都成功,要么都失败
ACID原则(原子性、一致性、隔离性、持久性):保证数据的安全。
- 开启事务
- 事务提交 commit()
- 事务回滚 rollback()
- 关闭事务
转账:
A:1000
B:1000
A(900) --100-->B(1100)
如果服务器崩溃了怎么办?我们不应该让这100块钱凭空的消失
Junit单元测试
测试数据经常使用,不需要new类什么的
导入依赖
pom.xml
xml
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>

java
public class TestJdbc3 {
@Test
public void test(){
System.out.println("test");
}
}
添加@Test注解

可以看见运行键不再是灰色了,可以直接输出

@Test注解只有在方法上有效,只要加了这个注解的方法,就可以直接运行!
事务
常用通常有以下:
- start transaction ;
- rollback ;
- commit ;
sql
start transaction ; #开启事务
update jdbc.account set money = money- 100 where id = '1';
# update jdbc.account set money = money+ 100 where id = '1';
rollback ; # 回滚事务,如果中间崩溃了怎么样,就会回滚,不进行提交
commit ; # 提交事务
可以选中这两行执行

就会只执行这两行

回滚
一定要添加这一行,这个引擎支持回滚
sql
ALTER TABLE jdbc.account ENGINE=InnoDB;
案例代码:
java
public class TestJdbc3 {
@Test
public void test() {
//配置信息
String url = "jdbc:mysql://localhost:3306/jdbc?useUnicode=true&characterEncoding=UTF-8";
String user = "root";
String password = "123456";
Connection connection = null;
try {
// 加载驱动
Class.forName("com.mysql.jdbc.Driver");
// 连接数据库
connection = DriverManager.getConnection(url, user, password);
// 检查自动提交状态
System.out.println("自动提交状态: " + connection.getAutoCommit());
// 开启事务
connection.setAutoCommit(false);
System.out.println("事务已开启");
// 执行第一条SQL
String sql = "update jdbc.account set money = money - 100 where id = 2;";
PreparedStatement pstmt1 = connection.prepareStatement(sql);
int count1 = pstmt1.executeUpdate();
System.out.println("第一条SQL影响行数: " + count1);
pstmt1.close();
// 检查当前数据状态
checkAccountBalance(connection);
// 制造错误 - 这会触发回滚
int i = 1/0;
// 执行第二条SQL
String sql1 = "update jdbc.account set money = money + 100 where id = 3;";
PreparedStatement pstmt2 = connection.prepareStatement(sql1);
int count2 = pstmt2.executeUpdate();
System.out.println("第二条SQL影响行数: " + count2);
pstmt2.close();
// 提交事务
connection.commit();
System.out.println("事务提交成功!");
} catch (Exception e) {
System.out.println("捕获到异常: " + e.getMessage());
// 发生异常时回滚事务
if (connection != null) {
try {
connection.rollback();
System.out.println("事务已回滚!所有操作已撤销");
// 回滚后再次检查数据状态
checkAccountBalance(connection);
} catch (SQLException ex) {
System.out.println("回滚失败: " + ex.getMessage());
ex.printStackTrace();
}
}
e.printStackTrace();
} finally {
// 恢复自动提交并关闭连接
if (connection != null) {
try {
connection.setAutoCommit(true); // 恢复自动提交
connection.close();
System.out.println("连接已关闭");
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
// 辅助方法:检查账户余额
private void checkAccountBalance(Connection conn) throws SQLException {
String checkSql = "SELECT id, money FROM jdbc.account WHERE id IN (2, 3)";
PreparedStatement pstmt = conn.prepareStatement(checkSql);
ResultSet rs = pstmt.executeQuery();
System.out.println("当前账户余额:");
while (rs.next()) {
System.out.println("账户 " + rs.getInt("id") + ": " + rs.getDouble("money"));
}
rs.close();
pstmt.close();
}
}