【简介】: 持久化指的是把内存中的数据存储到可掉电存储设备中以供之后使用。
【简介】: JDBC是一种用于执行SQL语句的Java API,可以为多种关系型数据库提供统一的访问。
【JDBC本质】: 其实就是Java官方提供的一套规范,帮助开发人员快速实现不同关系型数据库的连接。
【图解JDBC作用】:


CREATE DATABASE demo;
CREATE TABLE t_student(
id BIGINT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(20),
age INT,
email VARCHAR(20)
);
public class JdbcInsert {public static void main(String[] args) {try {// 1、加载数据库驱动Class.forName("com.mysql.jdbc.Driver");// 2、获取数据库连接Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/student", "root", "admin");// 3、创建语句对象Statement statement=connection.createStatement();// 4、执行sqlString sql="INSERT INTO student(name,age,email)VALUES('张三',18,'15651321@qq.com')";statement.execute(sql);// 5、释放资源statement.close();connection.close();} catch (ClassNotFoundException | SQLException e) {e.printStackTrace();}}
}
【DriverManager】: 驱动管理对象,主要用于加载注册关系型数据库的Driver类以及获取关系型数据库的连接对象。
【加载数据库驱动】:
public static void registerDriver(java.sql.Driver driver)throws SQLException {registerDriver(driver, null);}
/**
* 参数:
* url:指定连接某一个数据库的路径
* username:连接数据库的账号
* password:连接数据库的密码
**/public static Connection getConnection(String url,String user, String password) throws SQLException {java.util.Properties info = new java.util.Properties();if (user != null) {info.put("user", user);}if (password != null) {info.put("password", password);}return (getConnection(url, info, Reflection.getCallerClass()));}
【简介】: 关系型数据库连接对象,相当于Java程序和数据的通信桥梁。
【获取执行语句对象】:
Statement createStatement() throws SQLException;
PreparedStatement prepareStatement(String sql) throws SQLException;
【简介】: 静态SQL语句执行对象,用于执行字符串的SQL语句。
/**
* 返回值:受影响行数
* 参数:insert、update、delete、create语句
*/
int executeUpdate(String sql) throws SQLException;
ResultSet executeQuery(String sql) throws SQLException;
// 关闭Statement对象
void close() throws SQLException;

没有dao的时候我们会存在大量的代码重复。
【简介】: DAO(数据库访问对象)是一个面向对象的数据库接口。将所有对数据源访问操作抽象封装在一个公共API中。
【设计图解】:

【命名规范】:
package cn.simplelife.daodemo.domain;import lombok.*;import java.math.BigDecimal;/*** @ClassName Student* @Description* @Author simplelife* @Date 2022/10/3 18:21* @Version 1.0*/@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
@ToString
public class Student {private Long id;private String name;private Integer age;private String email;
}
package cn.simplelife.daodemo.dao;import cn.simplelife.daodemo.domain.Student;import java.util.List;/*** @ClassName IStudentDao* @Description* @Author simplelife* @Date 2022/10/3 18:25* @Version 1.0*/public interface IStudentDAO {/*** 插入一个学生信息* @param student 要插入的学生信息*/void insert(Student student);/*** 根据id删除一个学生信息* @param id 要删除的学生id*/void delete(Long id);/*** 根据学生id修改学生id* @param student 要修改学生的id和新的信息*/void update(Student student);/*** 根据学生的id查询学生的信息* @param id 要查询的学生id* @return 返回一个学生信息*/Student selectOne(Long id);/*** 查询所有的学生信息* @return 返回所有的学生信息列表*/List selectList();
}
package cn.simplelife.daodemo.dao.impl;import cn.simplelife.daodemo.dao.IStudentDAO;
import cn.simplelife.daodemo.domain.Student;import java.sql.*;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;/*** @ClassName StudentDaoImpl* @Description* @Author simplelife* @Date 2022/10/3 18:24* @Version 1.0*/public class StudentDAOImpl implements IStudentDAO {@Overridepublic void insert(Student student) {Connection connection = null;PreparedStatement preparedStatement = null;try {Class.forName("com.mysql.jdbc.Driver");connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/student", "root", "XING0710");String sql = "INSERT INTO student(name,age,email)VALUES(?,?,?)";preparedStatement = connection.prepareStatement(sql);preparedStatement.setString(1, student.getName());preparedStatement.setInt(2, student.getAge());preparedStatement.setString(3, student.getEmail());preparedStatement.execute();} catch (ClassNotFoundException | SQLException e) {e.printStackTrace();} finally {try {if (preparedStatement != null) {preparedStatement.close();}} catch (SQLException e) {e.printStackTrace();}try {if (connection != null) {connection.close();}} catch (SQLException e) {e.printStackTrace();}}}@Overridepublic void delete(Long id) {Connection connection = null;PreparedStatement preparedStatement = null;try {Class.forName("com.mysql.jdbc.Driver");connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/student", "root", "XING0710");String sql = "DELETE FROM student WHERE id=?";preparedStatement = connection.prepareStatement(sql);preparedStatement.setLong(1, id);preparedStatement.execute();} catch (ClassNotFoundException | SQLException e) {e.printStackTrace();} finally {try {if (preparedStatement != null) {preparedStatement.close();}} catch (SQLException e) {e.printStackTrace();}try {if (connection != null) {connection.close();}} catch (SQLException e) {e.printStackTrace();}}}@Overridepublic void update(Student student) {Connection connection = null;PreparedStatement preparedStatement = null;try {Class.forName("com.mysql.jdbc.Driver");connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/student", "root", "XING0710");String sql = "UPDATE student SET name=?, age=?, email=? WHERE id=?";preparedStatement = connection.prepareStatement(sql);preparedStatement.setString(1, student.getName());preparedStatement.setInt(2, student.getAge());preparedStatement.setString(3, student.getEmail());preparedStatement.setLong(4, student.getId());preparedStatement.execute();} catch (ClassNotFoundException | SQLException e) {e.printStackTrace();} finally {try {if (preparedStatement != null) {preparedStatement.close();}} catch (SQLException e) {e.printStackTrace();}try {if (connection != null) {connection.close();}} catch (SQLException e) {e.printStackTrace();}}}@Overridepublic Student selectOne(Long id) {Connection connection = null;PreparedStatement preparedStatement = null;ResultSet resultSet = null;Student student = new Student();try {Class.forName("com.mysql.jdbc.Driver");connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/student", "root", "XING0710");String sql = "SELECT * FROM student WHERE id=?";preparedStatement = connection.prepareStatement(sql);preparedStatement.setLong(1, id);resultSet = preparedStatement.executeQuery();if (resultSet.next()) {long resultId = resultSet.getLong("id");String name = resultSet.getString("name");int age = resultSet.getInt("age");String email = resultSet.getString("email");student.setId(resultId);student.setName(name);student.setAge(age);student.setEmail(email);}} catch (ClassNotFoundException | SQLException e) {e.printStackTrace();} finally {try {if (resultSet != null) {resultSet.close();}} catch (SQLException e) {e.printStackTrace();}try {if (preparedStatement != null) {preparedStatement.close();}} catch (SQLException e) {e.printStackTrace();}try {if (connection != null) {connection.close();}} catch (SQLException e) {e.printStackTrace();}}return student;}@Overridepublic List selectList() {Connection connection = null;PreparedStatement preparedStatement = null;ResultSet resultSet = null;List list = new ArrayList<>();Student student = null;try {Class.forName("com.mysql.jdbc.Driver");connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/student", "root", "XING0710");String sql = "SELECT * FROM student";preparedStatement = connection.prepareStatement(sql);resultSet = preparedStatement.executeQuery();while (resultSet.next()) {long resultId = resultSet.getLong("id");String name = resultSet.getString("name");int age = resultSet.getInt("age");String email = resultSet.getString("email");student = new Student(resultId, name, age, email);list.add(student);}} catch (ClassNotFoundException | SQLException e) {e.printStackTrace();} finally {try {if (resultSet != null) {resultSet.close();}} catch (SQLException e) {e.printStackTrace();}try {if (preparedStatement != null) {preparedStatement.close();}} catch (SQLException e) {e.printStackTrace();}try {if (connection != null) {connection.close();}} catch (SQLException e) {e.printStackTrace();}}return list;}
}
package cn.simplelife.daodemo.test;import cn.simplelife.daodemo.dao.IStudentDAO;
import cn.simplelife.daodemo.dao.impl.StudentDAOImpl;
import cn.simplelife.daodemo.domain.Student;
import org.junit.Test;import java.util.List;/*** @ClassName StudentDAOTest* @Description* @Author simplelife* @Date 2022/10/3 18:40* @Version 1.0*/public class StudentDAOTest {private IStudentDAO studentDAO = new StudentDAOImpl();@Testpublic void insert() {studentDAO.insert(new Student(null, "王五", 52, "6521@qq.com"));}@Testpublic void delete() {studentDAO.delete(2L);}@Testpublic void update() {Student student = new Student();student.setId(4L);student.setName("李四");student.setAge(18);student.setEmail("156321@qq.com");studentDAO.update(student);}@Testpublic void selectOne() {Student student = studentDAO.selectOne(4L);System.out.println(student);}@Testpublic void selectList() {List students = studentDAO.selectList();System.out.println(students);}
}
【简介】: PrepareStatement接口:是Statement接口的子接口,享有Statement中的方法。使用预编译语句对象,sql语句中使用?做占位符。
PreparedStatement conn对象的.prepareStatement(String sql);
//设置第几个占位符的真正参数值. Xxx 表示数据类型,比如 String,int,long,Date等.
void setXxx(int parameterIndex,Xxx value); //设置第几个占位符的真正参数值.
void setObject(int parameterIndex, Object x); //执行DDL/DML语句. 注意:没有参数 // 若当前 SQL是 DDL语句,则返回 0.// 若当前 SQL是 DML语句,则返回受影响的行数.
int executeUpdate(); //执行DQL语句,返回结果集.
ResultSet executeQuery(); //释放资源
close();
【举例】:
public void insert(Student student) {Connection connection = null;PreparedStatement preparedStatement = null;try {Class.forName("com.mysql.jdbc.Driver");connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/student", "root", "XING0710");String sql = "INSERT INTO student(name,age,email)VALUES(?,?,?)";preparedStatement = connection.prepareStatement(sql);preparedStatement.setString(1, student.getName());preparedStatement.setInt(2, student.getAge());preparedStatement.setString(3, student.getEmail());preparedStatement.execute();} catch (ClassNotFoundException | SQLException e) {e.printStackTrace();} finally {try {if (preparedStatement != null) {preparedStatement.close();}} catch (SQLException e) {e.printStackTrace();}try {if (connection != null) {connection.close();}} catch (SQLException e) {e.printStackTrace();}}}
package cn.simplelife.homework.utils;import java.io.IOException;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;/*** 与操作数据库相关的工具*/
public class JDBCUtils {/*** 私有化构造器防止外部创建对象*/private JDBCUtils() {}/*** 私有化静态的Properties对象*/private static Properties properties;static {// 1、获取类加载器ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();// 2、获取文件并将其转为输入流InputStream resourceAsStream = contextClassLoader.getResourceAsStream("db.properties");try {// 3、判断输入流是否为空if (resourceAsStream != null) {// 4、加载流文件properties = new Properties();properties.load(resourceAsStream);}// 5、加载数据库驱动Class.forName(properties.getProperty("driverClassName"));} catch (IOException | ClassNotFoundException e) {e.printStackTrace();}}/*** 获取数据库连接对象** @return 返回获取的连接对象*/public static Connection getConnection() {try {return DriverManager.getConnection(properties.getProperty("url"), properties.getProperty("username"), properties.getProperty("password"));} catch (SQLException e) {e.printStackTrace();}return null;}/*** 关闭资源** @param connection 关闭获取的连接* @param statement 关闭静态sql执行资源* @param resultSet 关闭结果集资源*/public static void close(Connection connection, Statement statement, ResultSet resultSet) {if (resultSet != null) {try {resultSet.close();} catch (SQLException e) {e.printStackTrace();}}if (statement != null) {try {statement.close();} catch (SQLException e) {e.printStackTrace();}}if (connection != null) {try {connection.close();} catch (SQLException e) {e.printStackTrace();}}}
}
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/student
username=root
password=????
【简介】: 事务是指将一组操作括为一个单元,为确保数据库中数据的一致性,数据操作是成组的单元,当单元中的一部分操作失败,整个事务应全部视为错误,所有从起始点以后的操作应全部回退到开始状态。
try{
//取消事务自动提交机制,设置为手动提交
connection对象.setAutoCommit(false);
//操作1
//操作2
//异常
//操作3
//....
//所有操作成功则 手动提交事务
connection对象.commit();
}catch(Exception e){
//处理异常
//出现异常 回滚事务
connection对象.rollback();
}
package cn.simplelife.work.domain;import lombok.*;import java.math.BigDecimal;/*** @ClassName Account* @Description* @Author simplelife* @Date 2022/10/4 20:16* @Version 1.0*/
@NoArgsConstructor
@AllArgsConstructor
@Getter
@Setter
@ToString
public class Account {private Long id;private String name;private BigDecimal balance;
}
package cn.simplelife.work.dao;import cn.simplelife.work.domain.Account;import java.math.BigDecimal;/*** @ClassName IAccountDAO* @Description* @Author simplelife* @Date 2022/10/4 20:38* @Version 1.0*/public interface IAccountDAO {/*** 转账** @param sourceAccount 源账户* @param targetAccount 目标账户* @param money 转账金额*/void transfer(Account sourceAccount, Account targetAccount, BigDecimal money);
}
package cn.simplelife.work.dao.Impl;import cn.simplelife.work.dao.IAccountDAO;
import cn.simplelife.work.domain.Account;
import cn.simplelife.work.utils.JDBCUtils;import java.math.BigDecimal;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;/*** @ClassName IAccountDAOImpl* @Description* @Author simplelife* @Date 2022/10/4 20:43* @Version 1.0*/public class IAccountDAOImpl implements IAccountDAO {@Overridepublic void transfer(Account sourceAccount, Account targetAccount, BigDecimal money) {Connection connection = JDBCUtils.getConnection();PreparedStatement preparedStatement = null;ResultSet resultSet = null;try {if (connection != null) {// 1、判断是否有足够的余额String sql = "SELECT * FROM account WHERE id=? AND balance>=1000";preparedStatement = connection.prepareStatement(sql);preparedStatement.setLong(1, sourceAccount.getId());resultSet = preparedStatement.executeQuery();// 2、余额不足开启提醒if (!resultSet.next()) {System.out.println("账户余额不足!请充值!");return;}// 3、余额充足开始转账sql = "UPDATE account SET balance = balance-? WHERE id=?";preparedStatement = connection.prepareStatement(sql);preparedStatement.setBigDecimal(1, money);preparedStatement.setLong(2, sourceAccount.getId());preparedStatement.executeUpdate();// 模拟停电int i = 10 / 0;// 4、账户价钱sql = "UPDATE account SET balance = balance+? WHERE id=?";preparedStatement = connection.prepareStatement(sql);preparedStatement.setBigDecimal(1, money);preparedStatement.setLong(2, targetAccount.getId());preparedStatement.executeUpdate();}} catch (SQLException e) {e.printStackTrace();} finally {JDBCUtils.close(connection, preparedStatement, resultSet);}}
}
package cn.simplelife.work.dao.test;import cn.simplelife.work.dao.IAccountDAO;
import cn.simplelife.work.dao.Impl.IAccountDAOImpl;
import cn.simplelife.work.domain.Account;
import cn.simplelife.work.utils.DataSourceUtils;
import org.junit.Test;import java.math.BigDecimal;
import java.sql.Connection;import static org.junit.Assert.*;/*** @ClassName IAccountDAOImplTest* @Description* @Author simplelife* @Date 2022/10/4 21:15* @Version 1.0*/public class IAccountDAOImplTest {private IAccountDAO accountDAO = new IAccountDAOImpl();@Testpublic void transfer() {Account sourceAccount = new Account();Account targetAccount = new Account();sourceAccount.setId(1L);targetAccount.setId(2L);accountDAO.transfer(sourceAccount, targetAccount, new BigDecimal("1000"));}
}
【简介】: 普通的 JDBC 数据库连接(Connectiond对象)使用 DriverManager 来获取,每次向数据库建立连接的时候都要将 Connection 加载到内存中,再验证用户名和密码得花费 0.05s~1s 的时间, 时间成本比较大 。
【图解】:

【基本属性】: 连接池存了连接对象,而连接对象依赖四要素,所以四要素是基本要求。
【其他属性】:
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/student
username=root
password=????
package cn.simplelife.work.utils;import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.pool.DruidDataSourceFactory;import javax.sql.DataSource;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;/*** @ClassName DataSourceUtils* @Description* @Author simplelife* @Date 2022/10/14 9:34* @Version 1.0*/public class DataSourceUtils {private DataSourceUtils() {}private static DataSource dataSource = null;static {InputStream resourceAsStream = Thread.currentThread().getContextClassLoader().getResourceAsStream("db.properties");try {if (resourceAsStream != null) {Properties properties = new Properties();properties.load(resourceAsStream);// 调用工厂中的方法创建连接池对象dataSource = DruidDataSourceFactory.createDataSource(properties);}} catch (Exception e) {e.printStackTrace();}}/*** 获取数据库连接对象** @return 返回一个数据库连接对象*/public static Connection getConnection() {try {return dataSource.getConnection();} catch (SQLException e) {e.printStackTrace();}return null;}public static void close(Connection connection, Statement statement, ResultSet resultSet){if (resultSet!=null){try {resultSet.close();} catch (SQLException e) {e.printStackTrace();}}if (statement!=null){try {statement.close();} catch (SQLException e) {e.printStackTrace();}}if (connection!=null){try {connection.close();} catch (SQLException e) {e.printStackTrace();}}}
}
下一篇:富人的“求爱”法则