Java-JDBC
资源下载
- MySQL驱动:https://dev.mysql.com/downloads/
获取数据库连接方式
方式一
idea如何加载MySQL驱动jar包?
- 在要加载的工程目录下新建lib目录,将下载好的jar包放入该目录中
- 右击要加载的工程目录
- Open Module Settings
- Libraries
- 点击“+”
- Java
- 选择jar包
驱动:Interface Driver
- Driver driver = new com.mysql.jdbc.Driver();
连接地址:url
- String url = "jdbc:mysql://localhost:3306/jdbc_test";
账号密码:info
Properties info = new Properties(); info.setProperty("user", "root"); info.setProperty("password", "root");
获取Connection对象
- Connection con = driver.connect(url, info);
方式二
获取驱动方式的升级
Class driverClass = Class.forName("com.mysql.jdbc.Driver"); Driver driver = (Driver) driverClass.newInstance();
- 优点是不含有任何第三方的api,程序更好的可移植性
方式三
使用DriverManager
DriverManager.registerDriver(driver); Connection connection = DriverManager.getConnection(url, user, password);
方式四
使用DriverManager精简版
- 省略注册驱动的操作
方式五
使用配置文件方式(final版)
- 也就是将上一种方式中个的声明连接参数的方式改为读取配置文件
核心代码
InputStream is = Index.class.getClassLoader().getResourceAsStream("jdbc.properties"); Properties properties = new Properties(); properties.load(is);
好处
- 实现了数据和代码分离,实现了解耦
- 如果要修改配置信息,可以避免重新打包程序
Statement
弊端
- 需要拼接SQL语句,存在SQL注入风险
PreparedStatement
作用
- 用来解决StatementSQL注入问题的
核心要点
- 预编译SQL语句
核心代码
String sql = "insert into customer (name, email, created_at)values(?,?,?)"; String s = String.valueOf(System.currentTimeMillis() / 1000); Integer time = Integer.parseInt(s); ps = con.prepareStatement(sql); ps.setString(1, "jack"); ps.setString(2, "jack@test.com"); ps.setInt(3, time); ps.execute();
JDBCUtils
说白了就是把公共逻辑按照方法分离出来
- 获取连接方法
- 关闭资源方法
- 通用update方法
通用查询方法
核心知识点
- 获取结果集的元数据:ResultSetMetaData
- 通过ResultSetMetaData获取结果集中的列数
- 通过ResultSetMetaData获取结果集中的列名(不推荐)
- 通过ResultSetMetaData获取结果集中的列名的别名(推荐)
- 通过反射给表字段赋值
核心代码
// 执行SQL,获取结果接 rs = ps.executeQuery(); // 获取元数据 ResultSetMetaData rsmd = rs.getMetaData(); // 获取结果集列数 int columnCount = rsmd.getColumnCount(); // 遍历结果集列 if (rs.next()) { Customer customer = new Customer(); for (int i = 0; i < columnCount; i++) { Object columnValue = rs.getObject(i + 1); // 获取结果集中的列名(不推荐) // String columnName = rsmd.getColumnName(i + 1); // 获取结果集中的列名的别名(推荐) String columnLabel = rsmd.getColumnLabel(i + 1); // 给customer对象赋值,通过反射 // Field field = Customer.class.getDeclaredField(columnName); Field field = Customer.class.getDeclaredField(columnLabel); field.setAccessible(true); field.set(customer, columnValue); } return customer;
通用查询操作流程
针对不同表统一查询单条数据
核心思想
- 定义方法返回类型为泛型
- 使用泛型实例填充数据
- 返回泛型实例
核心代码
public static <T> T getOne(Class<T> clazz, String sql, Object... args) {//...} T t = clazz.newInstance(); Field field = t.getClass().getDeclaredField(columnLabel); field.setAccessible(true); field.set(t, columnValue); return t;
针对不同表查询多条数据
核心思想
- 参考返回单条数据逻辑,最后把返回泛型实例改为返回泛型实例数组
核心代码
public static <T> List<T> getList(Class<T> clazz, String sql, Object... args) {//...} ArrayList<T> list = new ArrayList<>(); list.add(t); return list;
Blob类型数据操作
批量插入数据
方式一
- 循环使用Statement一条一条执行insert,效率差,代码复杂
方式二
- 循环使用PrepareStatement一条一条执行insert,效率差,代码相对较复杂
方式三
循环使用PrepareStatement
- addBatch()
- executeBatch()
- clearBatch()
- 该方式效率极高
数据库事务
ACID属性
- A:原子性(Automatic)
- C:一致性(Consistency)
- I:隔离性(Isolation)
- D:持久性(Durability)
MySQL事务隔离级别
并发问题
- 脏读
- 不可重复读
- 幻读
隔离级别
- 未提交读(Read uncommitted)
- 已提交读(Read committed)
- 可重复读(Repeatable read
- 可串行化(Serializable )
BaseDAO
数据库连接池
分类
- c3p0
- dbcp
- druid
DBUtils类关闭资源
- DBUtils是Apache提供的一套通用工具类
- 基本使用:QueryRunner
- DBUtils类关闭资源