JAVA基础编程——数据库编程

在当前大数据时代,数据的流量已经越来越大,有时单单依靠内存来进行数据的处理已经不能满足需求了。因此在开发中,会不可避免地使用到数据库技术,JAVA自然也会支持对数据库操作的支持。

JDBC

JDBC(JAVA Database Connective,JAVA数据库连接技术)是由JAVA提供的一组与平台无关的数据库的操作标准,其本身由一组类和接口组成,并且在操作中将按照严格的顺序执行。

这样的表述表明JAVA的这种技术与平台无关,同时该技术规定了4中数据库操作的形式:

  • JDBC-ODBC桥接技术:Windows中的开放数据库连接(Open Database Connectivity, ODBC)是微软提供的数据库编程接口。而JDBC-ODBC桥接技术则是先利用ODBC技术作为数据库的连接方式,然后利用JDBC进行ODBC的连接,以实现数据库操作。该方法使用性能较差,但不需要进行第三方开发包配置,使用较为方便。
  • JDBC本地驱动:JDBC本地驱动是由不同的数据库厂商根据JDBC定义的操作标准实现各自的驱动程序,程序可以直接通过JDBC进行数据库的连接操作。该方法操作性好,但需要针对不同的数据库配置匹配对应的驱动程序。
  • JDBC网络驱动:JDBC网络驱动将利用特定的数据库连接协议进行数据库的网络连接。此方法可以连接任一服务器的数据库,使用灵活,开发方便。
  • JDBC协议驱动:JDBC协议驱动是利用JDBC提供的协议标准,将数据库的操作以特定的网络协议方式进行处理。

连接MySQL数据库

JAVA中数据库的相关操作在java.sql包中,该包中主要包含以下核心类和接口:

  • java.sql.DriverManager类:提供数据库的驱动管理,主要负责获取数据库的连接对象
  • java.sql.Connection接口:用于描述数据库的连接,可以用该接口关闭连接
  • java.sql.Statement接口:数据库的操作接口,通过连接对象打开
  • java.sql.PreparedStatement接口:数据库预处理操作接口,通过连接对象打开
  • java.sql.ResultSet接口:数据查询结果描述,通过该接口获取查询结果

整体看来,JDBC的操作步骤主要分为四个步骤:

加载数据库驱动程序

所有的JDBC都是由各个不同的数据库厂商提供的数据库驱动程序,这些驱动程序都是以jar包的形式给出。而连接MySQL数据库首先要保证本地存在对应的jar包,要提前在官网下载,并将其路径配置到CLASSPATH变量中。

本文使用的MySQL版本为8.0.20。

通过DriverManager类建立连接

操作数据库首先要建立连接,连接需要:

  • 连接地址
  • 用户名
  • 密码

然后使用DriverManager类进行连接:

static Connection getConnection(String url, String user, String password) // Attempts to establish a connection to the given database URL.

从上面定义看出,数据库连接使用Connection接口对象进行封装,因此只要有一个新Connection对象就表示要连接一次数据库。

利用Statement、PreparedStatement、ResultSet接口实现CRUD操作

Statement createStatement() // Creates a Statement object for sending SQL statements to the database.
PreparedStatement prepareStatement(String sql) // Creates a PreparedStatement object for sending parameterized SQL statements to the database.

释放资源

跟IO操作类似,数据库操作后最好显式释放资源。

import java.sql.*;

public class Demo {
	private static final String DBDRIVER = "com.mysql.cj.jdbc.Driver";
	private static final String DBURL = "jdbc:mysql://localhost:3306/myemployees?useSSL=false&serverTimezone=UTC";
	private static final String USER = "root";
	private static final String PASSWORD = "********";
	
	public static void main(String[] args) throws Exception {
        Class.forName(DBDRIVER);
		Connection conn = DriverManager.getConnection(DBURL,USER,PASSWORD);
		System.out.println(conn);

        // CRUD
		
		conn.close();
	}
}

执行结果为:

com.mysql.cj.jdbc.ConnectionImpl@2f943d71

上面的代码先利用反射机制进行驱动程序的加载,然后建立了数据库连接,并进行了关闭,并没有实际的CRUD操作。

Statement

Statement接口主要用来进行数据库的CRUD操作,主要方法有:

ResultSet executeQuery(String sql) // Executes the given SQL statement, which returns a single ResultSet object.
int executeUpdate(String sql) // Executes the given SQL statement, which may be an INSERT, UPDATE, or DELETE statement or an SQL statement that returns nothing, such as an SQL DDL statement.

这里看段代码:

import java.sql.*;

public class Demo {
	private static final String DBDRIVER = "com.mysql.cj.jdbc.Driver";
	private static final String DBURL = "jdbc:mysql://localhost:3306/myemployees?useSSL=false&serverTimezone=UTC";
	private static final String USER = "root";
	private static final String PASSWORD = "********";
	
	public static void main(String[] args) throws Exception {
		Class.forName(DBDRIVER);
		Connection conn = DriverManager.getConnection(DBURL,USER,PASSWORD);
		
		Statement st = conn.createStatement();
		
		String sql = "select * from departments";
		ResultSet res = st.executeQuery(sql);
		while(res.next()) {
		    int depID = res.getInt("department_id");
			String depName = res.getString("department_name");
			int magID = res.getInt("manager_id");
			int locID = res.getInt("location_id");
			
			System.out.println("DepID is:" + depID + ",depName is:" + depName + ",magID is:" + magID + ",locID is:" + locID);
		}
		
		sql = "UPDATE departments SET manager_id = 201 WHERE department_id = 10";
		int len = st.executeUpdate(sql);
		
		st.close();		
		conn.close();
	}
}

数据的增删改其实逻辑都一样,只要sql语句写的没问题就OK。但是数据查询的结果是由ResultSet来接收的,而ResultSet的设计是按照数据类型的方式来保存返回数据的,这就要求需要针对数据库中每一列的属性进行分别获取。

上面的代码便是利用next判断是否截止,然后按照列属性逐个获取属性值,然后打印。

同时上边的代码只是为了说明一下使用方法,写sql语句并不是目的,在实际的开发中:

  • 要避免select *查询,会占用过大的内存
  • 要按照数据库的列顺序逐列获取属性值
  • 每列数据只能按照顺序取一次

上面的代码还可以修改为:

while(res.next()) {
    int depID = res.getInt(1);
	String depName = res.getString(2);
	int magID = res.getInt(3);
	int locID = res.getInt(4);
	
	System.out.println("DepID is:" + depID + ",depName is:" + depName + ",magID is:" + magID + ",locID is:" + locID);
}

这样的写法可以用于select name1,name2...这样的查询语句中,毕竟如果查询和属性值获取都要写重复的字符串有点多余,这样的写法可以按照列顺序进行逐个获取。

PreparedStatement

虽然StateMent能够用于CRUD,但是在进行insert操作时,需要进行字符串拼接操作,这个过程会很容易出错。

而PreparedStatement可以使用占位符sql语句来进行动态设置,这意味着字符串拼接的工作会被省略。

public interface PreparedStatement extends Statement

PreparedStatement prepareStatement(String sql) // Creates a PreparedStatement object for sending parameterized SQL statements to the database.

看下具体使用:

import java.sql.*;

public class Demo {
	private static final String DBDRIVER = "com.mysql.cj.jdbc.Driver";
	private static final String DBURL = "jdbc:mysql://localhost:3306/myemployees?useSSL=false&serverTimezone=UTC";
	private static final String USER = "root";
	private static final String PASSWORD = "********";
	
	public static void main(String[] args) throws Exception {
		Class.forName(DBDRIVER);
		Connection conn = DriverManager.getConnection(DBURL,USER,PASSWORD);
		
		Statement st = conn.createStatement();
		
		String sql = "select * from departments";
		ResultSet res = st.executeQuery(sql);
		while(res.next()) {
		    int depID = res.getInt(1);
			String depName = res.getString(2);
			int magID = res.getInt(3);
			int locID = res.getInt(4);
			
			System.out.println("DepID is:" + depID + ",depName is:" + depName + ",magID is:" + magID + ",locID is:" + locID);
		}
		
		sql = "INSERT INTO departments(department_id, department_name, manager_id) VALUES (?,?,?)";
		PreparedStatement pst = conn.prepareStatement(sql);
		pst.setInt(1,12);
		pst.setString(2,"Tom");
		pst.setInt(3,102);
		
		int len = pst.executeUpdate();
		
		st.close();
		pst.close();
		conn.close();
	}
}

上面的代码就省略了字符串拼接,而是用?作为占位符,并在后续中赋值,执行sql语句,这样的代码就会整洁一点。

另外也不止查询才可以使用PreparedStatement,其它sql语句也可以使用该接口借助占位符实现sql语句。本文也不是主要介绍sql语句的,只是搞清楚JAVA中数据库操作的逻辑接口,复杂的sql就不赘述了。

批处理与事务

批处理

批处理是指一次性向数据库发出多条操作指令,然后一块执行。

在Statement和PreparedStatement接口中有关于批处理的操作:

// Statement
void addBatch(String sql) // Adds the given SQL command to the current list of commands for this Statement object.
int[] executeBatch() // Submits a batch of commands to the database for execution and if all commands execute successfully, returns an array of update counts.

// PreparedStateMent
void addBatch() // Adds a set of parameters to this PreparedStatement object's batch of commands.

下面的代码就实现了批处理:

import java.sql.*;
import java.util.Arrays;

public class Demo {
	private static final String DBDRIVER = "com.mysql.cj.jdbc.Driver";
	private static final String DBURL = "jdbc:mysql://localhost:3306/myemployees?useSSL=false&serverTimezone=UTC";
	private static final String USER = "root";
	private static final String PASSWORD = "********";
	
	public static void main(String[] args) throws Exception {
		Class.forName(DBDRIVER);
		Connection conn = DriverManager.getConnection(DBURL,USER,PASSWORD);
		
		Statement st = conn.createStatement();
		
		st.addBatch("INSERT INTO departments(department_id, department_name, manager_id) VALUES (1001,12,13)");
		st.addBatch("INSERT INTO departments(department_id, department_name, manager_id) VALUES (1002,12,14)");
		st.addBatch("INSERT INTO departments(department_id, department_name, manager_id) VALUES (1003,12,15)");
		
		int res[] = st.executeBatch();
		System.out.println(Arrays.toString(res));
		
		st.close();
		conn.close();
	}
}

事务

事务保证了数据操作的完整性。

JDBC支持事务处理操作,相关方法定义在Connection接口中:

void commit() // Makes all changes made since the previous commit/rollback permanent and releases any database locks currently held by this Connection object.
void rollback() // Undoes all changes made in the current transaction and releases any database locks currently held by this Connection object.
void setAutoCommit(boolean autoCommit) // Sets this connection's auto-commit mode to the given state.

示例代码为:

import java.sql.*;
import java.util.Arrays;

public class Demo {
	private static final String DBDRIVER = "com.mysql.cj.jdbc.Driver";
	private static final String DBURL = "jdbc:mysql://localhost:3306/myemployees?useSSL=false&serverTimezone=UTC";
	private static final String USER = "root";
	private static final String PASSWORD = "********";
	
	public static void main(String[] args) throws Exception {
		Class.forName(DBDRIVER);
		Connection conn = DriverManager.getConnection(DBURL,USER,PASSWORD);
		
		Statement st = conn.createStatement();
		conn.setAutoCommit(false);
		try {
		    st.addBatch("INSERT INTO departments(department_id, department_name, manager_id) VALUES (1004,12,13)");
			st.addBatch("INSERT INTO departments(department_id, department_name, manager_id) VALUES (1005,12,14)");
			st.addBatch("INSERT INTO departments(department_id, department_name, manager_id) VALUES (1006,12,15)");
		
			int res[] = st.executeBatch();
			System.out.println(Arrays.toString(res));
			
			conn.commit();
		} catch (Exception e) {
		    e.printStackTrace();
			conn.rollback();
		}
		
		st.close();
		conn.close();
	}
}

在手动进行事务处理时,首先要取消自动提交,然后在try中执行数据操作,并进行手动提交,而在catch中捕获错误,并进行回滚处理,以保证数据的完整性。

  • 1
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
目录 前言 第1部分 介绍数据库、SQL和JDBC 第1章 关系型数据库 1.1 理解关系型数据库管理系统 1.1.1 关系模型 1.1.2 Codd法则 1.1.3 表、行、列和关键字 1.1.4 主键 1.1.5 外键 1.1.6 关系 1.1.7 视图 1.1.6 范式化 1.2 高级语言 1.2.1 结构化查询语言 1.2.2 数据定义语言 1.2.3 数据处理语言 1.2.4 数据查询语言 1.3 事务管理和事务控制命令 1.3.1 ACID测试 1.3.2 SQL中的事务管理 1.4 数据库安全和数据控制语言 1.4.1 管理数据库用户 1.4.2 用户权限 1.4.3 用户组和角色 1.5 数据库体系结构 1.5.1 Java数据对象 1.5.2 两层模型 1.5.3 三层模型 1.6 小结 第2章 设计数据库 2.1 数据库设计应考虑的事项 2.1.1 项目规范 2.1.2 设计表 2.1.3 生成发票 2.2 引用完整性 2.2.1 通用完整性规则 2.2.2 特定于数据库的完整性规则 2.3 小结 第3章 SQL基础 3.1 SQL语言 3.2 SQL数据类型 3.3 数据定义语言 3.3.1 创建、取消、更改数据库和表 3.3.2 创建、更改和取消视图 3.4 数据处理语言 3.4.1 INSERT语句 3.4.2 UPDATE语句 3.4.3 DELETE语句 3.5 数据查询语言 3.5.1 SELECT语句 3.5.2 WHERE子句 3.5.3 SQL运算符 3.5.4 使用子查询 3.6 对查询结果排序 3.7 将查询结果进行汇总 3.7.1 集合函数 3.7.2 使用HAVING子句来筛选组 3.7.3 使用索引提高SQL查询效率 3.7.4 格式化SQL命令 3.7.5 使用SQL连接 3.7.6 编写SQL的JOIN命令 3.7.7 使用UNION运算符进行组合查询 3.8 数据控制语言 3.8.1 管理用户 3.8.2 授予和取消用户权限 3.9 创建和使用存储过程 3.9.1 在存储过程中使用输入参数 3.9.2 存储过程中使用输出参数 3.10 小结 第4章 JDBC入门 4.1 什么是JDBC 4.2 两层和三层模型 4.2.1 两层模型 4.2.2 三层模型 4.3 SQL的一致性 4.4 JDBC兼容性 4.5 JDBC如何工作 4.5.1 DriverManager 4.5.2 JDBC DataSource 4.5.3 DataSource对象和JNDI 4.5.4 部署和使用DataSource的基本实现 4.6 连接池 4.7 分布式事务处理 4.7.1 分布式事务管理 4.7.2 Connection对象 4.8 SQL语句 4.8.1 Statement对象 4.8.2 PreparedStatement语句 4.8.3 CallableStatement 4.9 事务 4.9.1 事务独立性等级 4.9.2 事务存储点 4.9.3 多线程 4.10 批更新 4.11 ResultSet 4.12 可滚动的ResultSet 4.12.1 创建可滚动的ResultSet 4.12.2 游标控制 4.12.3 将游标移动到指定行 4.12.4 获得游标位置

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值