JDBC

92 阅读4分钟

日新计划6月更文 Day 23

  JDBC~~(Java Database Connectivity)~~是一个独立于特定数据库管理系统,通用的数据库存取操作的应用编程接口。

建立连接

  最简单的建立与MySQL数据库连接的方法如下:

Driver driver = new com.mysql.cj.jdbc.Driver();
Properties info = new Properties();
info.setProperty("user", userName);
info.setProperty("password", password);
Connection conn = driver.connect(url, info);

  为了提高程序可移植性,可使用反射创建驱动对象。

  使用驱动管理器可以简化部分操作:

DriverManager.registerDriver(driver);                        // 可省略,会随Driver加载自动完成
Connection conn = DriverManager.getConnection(url, info);

  为实现解耦,通过配置文件获得连接信息,最终代码为:

// 读取配置文件
InputStream is = Main.class.getResourceAsStream("jdbc.cfg");
Properties prop =  new Properties();
prop.load(is);
String url = prop.getProperty("url");
String userName = prop.getProperty("userName");
String password = prop.getProperty("password");
String device = prop.getProperty("device");
// 加载驱动
Class.forName(device);
// 连接
Connection conn = DriverManager.getConnection(url, userName, password);
//断开连接
conn.close();

操作和访问数据库

  操作和访问数据库的方式有以下三种:

  • Statement:用于执行静态SQL语句并返回执行结果对象。

    由于存在SQL注入等安全问题和操作繁琐等缺点,已不再使用

  • PreparedStatement:用于存储预编译的SQL语句,可多次高效地执行这些SQL语句

  • CallableStatement:用于执行SQL存储过程。

PreparedStatement的使用

  与Statement相比,PreparedStatement使用预编译的SQL语句并通过占位符代替变量,具有以下优点:

  • 解决了SQL注入的安全问题
  • 可操作Blob数组
  • 实现更高效的批量操作

  PreparedStatement对数据库的操作(增删改)基本符合以下的步骤:

String sql = "insert into Beauty(Name) values (?);";    // 以“?”作为占位符
PreparedStatement sm = conn.prepareStatement(sql);
sm.setString(1, value);                                 // 填充占位符,从1开始
sm.addBatch();                                          // 暂存待执行的SQL语句
sm.execute();                                           // 执行SQL语句
sm.close();

  如果需要对数据进行查询,可以使用executeQuery()执行SQL语句并获得结果集:

ResultSet rs = sm.executeQuery();
ResultSetMetaData rsMetaData = rs.getMetaData();       // 获取结果集的元数据
rs.close();                                            // 需要手动关闭

  对结果集的访问可以使用迭代器,对结果集数据的存储一般使用ORM(Object Relational Mopping):

  • 数据表<-->Java类
  • 记录<-->对象
  • 字段<-->对象属性

  MySQL数据类型与Java数据类型对应关系

Java数据类型MySQL数据类型
booleanBIT
byteTINYINT
shortSMALLINT
intINTEGER
longBIGINT
StringCHAR,VARCHAR,LONGVARCHAR
byte arrayBINARY,VAR BINARY
java.sql.DateDATE
java.sql.TimeTIME
java.sql.TimestampTIMESTAMP

事务操作

事务:使数据从一种状态转换到另一种状态的一组逻辑操作单元 事务操作:保证所有操作都作为一个工作单元处理。在执行事务的时候,要么所有事务都被提交(commit),要么数据库管理系统放弃所有操作,整个事务回滚(rollback)。

事务的ACID属性

  • Atomicity:原子性,事务为一个不可分割的基本单元
  • Consistency:一致性,事务必须使数据库从一个一致的转台变换到另一个一致的状态
  • Isolation:隔离性,事务的执行相互隔离,并发的各个事务不会相互干扰
  • Durability:持久性,事务被提交后其对数据库的更改为永久性的,后续的操作或数据库故障不会对其产生影响

数据库并发问题

  对于并发的事务,当其操作同一数据且未作相应措施时,会出现一些问题:

  • 脏读:B读取了被A修改但未提交的数据,若A回滚,则B读取的数据有误
  • 不可重复读:A两次读取同一数据之间该数据已被B修改
  • 幻读:A读取某张表的过程中B增/删了部分数据

数据库的隔离级别

  为了在保证隔离性的同时保证一定的并发性,需要在数据库的隔离级别中做出取舍:

  • READ UNCOMMITED:读未提交数据,允许读取未被其他事务提交的数据
  • READ COMMITED:读已提交数据,仅允许读取已被其他事务提交的数据
  • REPEATABLE READ:可重复读,确保事务可多次对同一字段读取到相同的值
  • SERIALIZABLE:串行化,确保一个事务执行期间可在表中读取到相同的数据

  其中 Oracle 仅支持 READ COMMITED 和 SERIALIZABLE,默认为 READ COMMITED;MySQL 支持四种隔离级别,默认为 REPEATABLE READ。

  在JDBC中通过以下方法管理数据库隔离级别:

conn.getTranactionIsolation();  // 获取当前隔离级别
conn.setAutoCommit(false);      // 关闭自动提交
conn.setTranactionIsolation(Connection.);  // 设置隔离级别