一、JDBC的用途
- 加载对应的数据库驱动(Load Driver)
- 与数据库建立连接(connection)
- 大宋操作数据库语句(createStatement)
- 执行并处理返回结果(executeQuery)
二、JDBC
2.1 什么是JDBC
- java语言连接数据库(mysql、DB2)
- 一套规范,所有数据库厂家都需要实现;
2.2 通过jdbc连接数据库
- 注册驱动;
- 获取数据库链接;
- 获取数据库操作对象;
- 编写sql,执行sql;
- 根据返回值,如果是增删改查,返回影响记录条数,如果查询返回查询结果集;
- 关闭资源;
2.2.2详细操作:
- 注册驱动:Driver
Driver驱动: ```java package com.mysql.cj.jdbc;//1、注册驱动
Class.forName("com.mysql.cj.jdbc.Driver");
/**
* jdbc:mysql : jdbc协议,类似于http协议
* localhost 本地的ip地址 127.0.0.1
* 3306 :mysql服务默认的端口号
*/
//连接数据的地址
String url = "jdbc:mysql://localhost:3306/eagls?characterEncoding=utf8&serverTimezone=GMT%2B8";
//用户名
String username = "root";
//密码
String password = "root";
import java.sql.DriverManager; import java.sql.SQLException;
public class Driver extends NonRegisteringDriver implements java.sql.Driver { public Driver() throws SQLException { } //try catch 添加快捷键方式ctrl +alt+t static { try { DriverManager.registerDriver(new Driver()); } catch (SQLException var1) { throw new RuntimeException(“Can’t register driver!”); } } }
> 创建Driver的实例对象,完成Driver中的static的类加载(类加载只加载一次不是很占用内存);
> class.forName(" com.mysql.cj.jdbc.Driver")可以使得driver类加载。
> 权限定类名 com.mysql.cj.jdbc.Driver 全类名 注意点上包结构。
String url="jdbc:mysql://localhost:3306/eagls?characterEncoding=utf8&serverTimezone=GMT%2B8";
> 字符集设置,防止字符乱码以及时区设置;
> characterEncoding=utf8&serverTimezone=GMT%2B8
2. 获取数据库链接;
```java
//2、获取数据库连接对象
Connection connection = DriverManager.getConnection(url, username, password);
获取数据库操作对象;
//3、获取数据库操作对象
Statement statement = connection.createStatement();
编写sql,执行sql;
//4、编写sql、执行sql
String sql = "insert into user(username,password)values('jack','123456')";
根据返回值,如果是增删改查,返回影响记录条数,如果查询返回查询结果集;
//执行sql
int num = statement.executeUpdate(sql);
System.out.println(num == 1 ? "添加成功" : "添加失败");
关闭资源;
//关闭资源
statement.close();
connection.close();
2.3 JDBC的完整写法;
1. 按照六部写法;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
/**
* jdbc编程六步
*/
public class JDBCTest02 {
public static void main(String[] args) {
try {
//1、注册驱动
Class.forName("com.mysql.cj.jdbc.Driver");
/**
* jdbc:mysql : jdbc协议,类似于http协议
* localhost 本地的ip地址 127.0.0.1
* 3306 :mysql服务默认的端口号
*/
//连接数据的地址
String url = "jdbc:mysql://localhost:3306/eagls?characterEncoding=utf8&serverTimezone=GMT%2B8";
//用户名
String username = "root";
//密码
String password = "root";
//2、获取数据库连接对象
Connection connection = DriverManager.getConnection(url, username, password);
//3、获取数据库操作对象
Statement statement = connection.createStatement();
//4、编写sql、执行sql
String sql = "insert into user(username,password)values('jack','123456')";
//执行sql
int num = statement.executeUpdate(sql);
System.out.println(num == 1 ? "添加成功" : "添加失败");
//关闭资源
statement.close();
connection.close();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
2. 改进写法
常用写法以及注意事项:
首先,数据库连接对象、数据库获取对象、以及用以存放数据库查询结果的对象需要在主函数内声明并赋初值为null。不放在try语句块的内部申明,这样方便后面再finally语句块内关闭资源;
关闭资源的时候需要做判空判断,并添加try-catch语句捕获异常;
注意sql语句的写法与执行; ```java import java.sql.*;
public interface JdbcTest2 { public static void main(String[] args) { //2、获取数据库连接对象 Connection connection = null;
//3,获取数据库操作对象
Statement statement = null;
//获取数据库对象,用以存放查询结果;
ResultSet resultSet = null;
try {
Class.forName("com.mysql.cj.jdbc.Driver");
//连接数据的地址
// String url = "jdbc:mysql://localhost:3306/test1?characterEncoding=utf8&serverTimezone=GMT%2B8";
/* //用户名
String username = "root";
//密码
String password = "root";*/
//2、获取数据库连接对象
connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/test1?characterEncoding=utf8&serverTimezone=GMT%2B8", "root", "root");
//3,获取数据库操作对象
statement = connection.createStatement();
//4. 编写sql
//String sql = "insert into user(username,password)values('jack','123456')";
//String sql1 = "UPDATE user set username = 'jack12', password = '12345678' where id = 1";
String sql2 = "select * from user";
//5. 执行sql
//int num1 = statement.executeUpdate(sql1);
//int num = statement.executeUpdate(sql);
resultSet = statement.executeQuery(sql2);
//System.out.println(num == 1 ? "数据添加成功" : "数据添加失败失败");
//System.out.println(num1 == 1 ? "数据修改成功" : "数据修改失败失败");
while(resultSet.next()){
int id = resultSet.getInt("id");
String username = resultSet.getString("username");
String password = resultSet.getString("password");
System.out.println(id+ " "+username+" "+password);
}
} catch (ClassNotFoundException | SQLException e) {
e.printStackTrace();
}
finally {
if(statement != null){
try {
statement.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if(connection != null){
try {
connection.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if(resultSet != null){
try {
resultSet.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
}
}
<a name="TnHwQ"></a>
##### 3. 几个案例:
将数据添加到数据库,并把数据库内的表创建对应的类,将每条数据创建对应实例对象并存入集合。
```java
public class Student {
private Integer id;
private String name;
private String sex;
private String birth;
private String department;
private String Address;
public Student(Integer id, String name, String sex, String birth, String department, String address) {
this.id = id;
this.name = name;
this.sex = sex;
this.birth = birth;
this.department = department;
Address = address;
}
public Student() {
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String getBirth() {
return birth;
}
public void setBirth(String birth) {
this.birth = birth;
}
public String getDepartment() {
return department;
}
public void setDepartment(String department) {
this.department = department;
}
public String getAddress() {
return Address;
}
public void setAddress(String address) {
Address = address;
}
@Override
public String toString() {
return "Student{" +
"id=" + id +
", name='" + name + '\'' +
", sex='" + sex + '\'' +
", birth='" + birth + '\'' +
", department='" + department + '\'' +
", Address='" + Address + '\'' +
'}';
}
}
import javax.xml.crypto.Data;
import java.sql.*;
import java.util.ArrayList;
public interface JdbcTest03 {
public static void main(String[] args) {
//定义数据库的几个操作对象;
//数据库连接对象
Connection connection = null;
//数据库操作对象
Statement statement = null;
//数据库的数据获取的集合对象
ResultSet resultSet =null;
try {
Class.forName("com.mysql.cj.jdbc.Driver");
connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/test1?characterEncoding=utf8&serverTimezone=GMT%2B8","root","root");
statement = connection.createStatement();
ArrayList<Student> students = new ArrayList<>();
String sql1 = "select * from student";
resultSet = statement.executeQuery(sql1);
while(resultSet.next()){
int id = resultSet.getInt("id");
String name =resultSet.getString("name");
String sex = resultSet.getString("sex");
String birth = resultSet.getString("birth");
String department = resultSet.getString("department");
String Address = resultSet.getString("Address");
Student student = new Student();
student.setId(id);
student.setName(name);
student.setSex(sex);
student.setBirth(birth);
student.setDepartment(department);
student.setAddress(Address);
students.add(student);
}
for (Student student : students) {
System.out.println(student);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
finally {
if(statement != null){
try {
statement.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if(connection != null){
try {
connection.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
}
}
案例:写一个用户登陆部分:
注意sql语句中变量添加的位置:
String sql = “select * from user where username =’”+username+ “‘and password = ‘“+password+”‘“;
import java.sql.*;
import java.util.ArrayList;
import java.util.Scanner;
public interface JdbcTest04 {
public static void main(String[] args) {
//定义数据库的几个操作对象;
//数据库连接对象
Connection connection = null;
//数据库操作对象
Statement statement = null;
//数据库的数据获取的集合对象
ResultSet resultSet =null;
try {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入登陆用户名:");
String username = scanner.next();
System.out.println("请输入登陆用户密码:");
String password = scanner.next();
//注册驱动
Class.forName("com.mysql.cj.jdbc.Driver");
//获取数据库连接对象
connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/test1?characterEncoding=utf8&serverTimezone=GMT%2B8","root","root");
//获取数据操作对象
statement = connection.createStatement();
//编写sql语句
String sql = "select * from user where username ='"+username+ "'and password = '"+password+"'";
resultSet = statement.executeQuery(sql);
if(resultSet.next()) {
System.out.println("登陆成功");
}
else
System.out.println("登陆失败");
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
finally {
if(statement != null){
try {
statement.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if(connection != null){
try {
connection.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
}
}
三、preparedStatemen
1.Statement操作对象
- 可能会出现sql注入,就是通过扭曲sql语句的本来意思来窃取数据库数据。
- 但是preparedStatement操作对象就不会出现这种问题。
- preparedStatemen
需要先传入一个sql的’框架’语句,框架中变量用占位符,再传入变量。防止SQL注入。
注意占位符的使用以及赋值操作;
- 获取操作对象,预编译sql
preparedStatement = connection.prepareStatement(“insert into user(username,password) values (?,?)”);
- 获取操作对象,预编译sql
- 给占位符赋值
preparedStatement.setString(1,”tom”); preparedStatement.setString(2,”112233”);
- 给占位符赋值
- 执行sql语句
int num = preparedStatement.executeUpdate();
- 执行sql语句
四、JDBC工具类
4.1 jdbc工具类的封装
- 由于jdbc的六部操作相对于复杂,可以把jdbc中相对固定的代码的组件封装成一个工具类;
- jdbc对应的都是对应的静态方法,没有普通方法,直接用类名点上就可以使用。
- 封装步骤:
- 先将当前类的构造方法私有化,把六步放在静态代码块中。
- 获取数据库连接对象 注意异常捕获或者异常抛出。
- 关闭数据库资源 ```java import java.sql.; /*
- 封装jdbcUtils
1、先将当前类构造方法私有化 */ public class JDBCUtils {
private JDBCUtils(){ } /**
将注册驱动的步骤放进代码块中,在类加载的时候就会加载,而且只执行一次,提高程序的执行效率 */ static {
try {
//注册驱动
Class.forName("com.mysql.cj.jdbc.Driver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
} }
/**
- 获取数据库连接对象
- @return
@throws SQLException */ public static Connection getConnection() throws SQLException {
return DriverManager.getConnection(“jdbc:mysql://localhost:3306/eagls?” +
"characterEncoding=utf8&serverTimezone=GMT%2B8","root","root");
} /**
- 关闭数据库资源
- @param connection
- @param statement
@param resultSet */ public static void close(Connection connection, Statement statement, ResultSet resultSet){
if (resultSet != null){
try {
resultSet.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if (statement != null){
try {
statement.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if (connection != null){
try {
connection.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
} } } ```
五、事物处理
java事物
事物必须服从ACID原则;
ACID原则:原子性、一致性、隔离性、持久性; 通常认为:事物仅于数据库相关
事物是一组原子操作单元,从数据库角度上来书哦就是一组sql语句,要么全部执行成功要么全部执行失败(撤销不执行)
Jdbc事物是用Connection对象控制的;
jdbc Connection 接口:
jdbc默认情况下是没有开启事物的,需要手动开启;
jdbc默认情况下采用自动提交策略;(每次执行完sql之后,java只要
一提交,那么会通知mysql修改数据)
如果要开启事物:要自动提交改为手动提交;开启事物: connection.setAutoCommit(false);
- 提交事物: connection.commit();
- 回滚事物:让事物回到执行之前的状态; connection.rollback();
事物案例:
import com.eagleslab.utils.JDBCUtils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
/**
* 关于jdbc的事务操作:
* -场景:模拟A账户给B账户转账,如果中途发生异常,我们希望事务能满足一致性
* -jdbc默认情况下是没有开启事务的,事务需要我们手动开启
* -jdbc默认情况下采用的是自动提交的策略(当每次执行完sql之后,jdbc会自动提交sql,sql只要一提交,那么就会通知mysql,修改对应的数据)
* -如果要开启事务的话,要将自动提交改为手动提交
*/
public class JdbcTest03 {
public static void main(String[] args) {
Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
try {
//获取数据库连接对象
connection = JDBCUtils.getConnection();
//开启事务,将自动提交改为手动提交
connection.setAutoCommit(false);
//获取数据库操作对象
preparedStatement = connection.prepareStatement("update tb_account set account_A = account_A - ? where id = ?");//给A账户扣钱
//给占位符赋值
preparedStatement.setDouble(1,1000.0);
preparedStatement.setInt(2,1);
//执行sql语句
int num = preparedStatement.executeUpdate();
System.out.println(num == 1 ? "扣钱成功" : "扣钱失败");
//模拟异常
int i = 1 / 0;
preparedStatement = connection.prepareStatement("update tb_account set account_B = account_B + ? where id = ?");
//给占位符赋值
preparedStatement.setDouble(1,1000.0);
preparedStatement.setInt(2,1);
num = preparedStatement.executeUpdate();
System.out.println(num == 1 ? "转账成功" : "转账失败");
//提交事务
connection.commit();
} catch (Exception e) {
try {
//回滚事务,让事务回到执行之前的状态
connection.rollback();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
e.printStackTrace();
}finally {
//关闭资源
JDBCUtils.close(connection,preparedStatement,resultSet);
}
}
}
结束