JDBC
一.简介:
1.定义
JDBC是java DataBase Connectivity
的缩写。它是Sun的Javasoft公司制定的Java数据库连接技术,是一套标准接口
java.sql包中提供了JDBC API,通过它连接到各种数据库系统,编写访问数据库的程序。
JDBC API不能直接访问数据库,它依赖于数据库厂商提供的JDBC Driver(JDBC驱动程序)
2.JDBC编程涉及的三个部分:
- 应用程序:开发人员编写的客户端程序。在应用程序中调用JDBC API,将SQL语句发送到数据库并检索结果。
- 驱动程序管理器:JDBC将驱动程序管理器负责使用正确的JDBC驱动程序和连接信息访问数据库,在Java应用程序和数据库系统之间建立连接。
- 驱动程序:驱动程序由数据库厂商提供,实现数据库驱动接口,能够把SQL指令正确的发送的数据库服务器。
二、Java.SQL包
、Driver接口和DriverManager类, Connection, Statement或者PreparedStatement, ResultSet
Java.SQL包中常用的接口和类包括:
-
Driver接口和DriverManager类
1.所有的JDBC驱动程序都必须实现Driver接口,JDBC驱动程序由数据库厂商提供,所以必须把JDBC驱动程序加入到项目中
2.
DriverManager
用来建立和数据库的连接以及管理JDBC驱动程序。常用方法:方法 描述 registerDriver(Driver driver) 在DriverManager中注册JDBC驱动程序 getConnection(String url, String user, String password) 建立到给定数据库 URL 的连接,返回Connection对象 setLoginTimeout(int seconds) 设定等待数据库连接的最长时间 setLogWriter(PrintWriter out) 设定输出数据库日志的PrintWriter对象 -
Connection
Connection
代表java程序和数据库的连接。在连接上下文中执行 SQL 语句并返回结果. 常用方法:方法 说明 createStatement() 创建并返回Statement对象 preparedStatement(String sql) 创建并返回PreparedStatement对象 -
Statement或者PreparedStatement
- Statement : Statement接口定义了一组数据库操作的方法,可以通过这个接口的实现类对象执行指定的SQL命令
Statement 对象的方法:
方法 说明 示例 executeUpdate() 用来创建和更新表 stmt.executeUpdate(query); executeQuery() 对于SELECT 语句 stmt.executeQuery(query); execute() 返回布尔值,用于执行任何 SQL 语句 stmt.execute(); -
PreparedStatement: PreparedStatement表示预编译的 SQL 语句的对象,是Statement的子接口,扩展了Statement的功能
- PreparedStatement接口使我们可以使用占位符(?)作为参数定义一条SQL语句。
- 占位符是在SQL语句中出现的标记符,在SQL语句执行之前会被替换成实际的值。
- 通过调用connection.preparedStatement()方法来生成PreparedStatement对象
设置查询参数:
setAsciiStream() setBigDecimal() setBinaryStream() setBoolean() setByte() setBytes() setDate() setDouble() setFloat() setInt() setLong() setNull() setObject() setShort setString() setTime() setTimestamp() setUnicodeStream() -
Statement 和 PrepareStatement 的区别:
Statement 执行每一条SQL语句时,都是编译+执行,相当于静态SQL;SQL语句每次都是重新编译执行的,这就导致你传进去的参数和SQL语句是有联系,可以改变原先SQL的功能结构(Sql注入的问题);
PrepareStatement执行的SQL语句,会进行预编译,SQL中可以包含动态参数"?“,在执行时可以为”?"动态设置参数值,当下次执行相同类型的SQL语句时,可以解析并直接执行编译好的SQL语句,从而减少编译次数提高数据库的性能,相当于动态SQL;SQL的参数会被强制类型转换成表中的列属性值,由于SQL语句已经实现被编译过,参数和原来SQL语句不会有交集,也就避免了这种情况的发送;
-
ResultSet
ResultSet表示select语句查询得到的结果集。
- ResultSet中记录的行号从1开始,一个Statement对象在同一时刻只能打开一个ResultSet对象。
- 调用ResultSet的next()方法,可以使游标定位到下一条记录。
- 调用ResultSet的getXXX()方法,可以取得某个字段的值。
ResultSet的常用方法:
目录 描述 getString(int index) 返回指定字段的String类型的值,参数index代表字段的序号。 getString(String indexName) 返回指定字段的String类型的值,参数indexName代表字段的名字。 getInt(int index) 返回指定字段的int类型的值,参数index代表字段的序号。 getInt(String indexName) 返回指定字段的int类型的值,参数indexName代表字段的名字。 getFloat(int index) 返回指定字段的float类型的值,参数index代表字段的序号。 getFloat(String indexName) 返回指定字段的float类型的值,参数indexName代表字段的名字。
、SQL到Java的数据类型
从一个JDBC数据源检索数据的时候,ResultSet实现了把SQL数据类型映射到Java数据类型上
SQL数据类型 | Java数据类型 |
---|---|
CHAR | String |
VARCHAR | String |
LONGVARCHAR | String |
NUMERIC | java.math.BigDecimal |
DECIMAL | java.math.BigDecimal |
BIT | boolean |
TINYINT | byte |
SMALLINT | short |
INTEGER | int |
BIGINT | long |
REAL | float |
FLOAT | double |
DOUBLE | double |
BINARY | byte[] |
VARBINARY | byte[] |
LONGVARBINARY | byte[] |
DATE | java.sql.Date |
TIME | java.sql.Time |
TIMESTAMP | java.sql.Timestamp |
三、JDBC访问数据库
1.步骤1
通过pom.XML文件装载并注册数据库的驱动程序:
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.29</version>
</dependency>
//点击内容区域复制,刷新xml文件,加载完成;
2.步骤2
建立数据库的连接
Connection conn = DriverManager.getConnection(url,user,pwd)
//其中url表示连接数据库的JDBC URL,user和pwd表示连接数据库的用户名和口令。
//url格式:2种
jdbc:mysql://localhost:3306/hrms?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false&allowPublicKeyRetrieval=true
jdbc:mysql://localhost:3306/hrms?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai
//在XXX.properties文件中配置
driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/hrms?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false&allowPublicKeyRetrieval=true
user=root
password=123456
3.步骤3
创建Statement | PreparedStatement对象,准备调用sql语句
Statement stm = conn.createStatement();
PreparedStatement pstm = conn.preparedStatement(sql);
4.步骤4
执行SQL语句,2种获取结果集(select操作):
ResultSet rs = stm.executeQuery(sql);
ResultSet rs = pstm.executeQuery();
Connection conn = DBUtil.getConn();
//?占位符
sql = "insert into employee(emp_id,emp_name,age) values (?,?,?)";
//创建预编译语句,根据sql语句生成ps对象
PreparedStatement ps = conn.prepareStatement(sql);
//为占位符设置值(共三个占位符),通过employee对象获得相应属性值
ps.setInt(1, employee.getId());
ps.setString(2, employee.getName());
ps.setInt(3, employee.getAge());
int i = ps.executeUpdate();
5.步骤5
访问ResultSet中的记录集
While(rs.next()){
String col1 = rs.getString(1);
String col2 = rs.getString(2);
int col3 = rs.getInt(3);
…
}
//...........................
list = new ArrayList<>();//创建list集合存储Employee对象
Connection conn = DBUtil.getConn();//通过工具类DBUtil的方法获取数据库连接对象Connection,用于建立数据库通信
sql = "select emp_id,emp_name,age from employee";//定义一个sql语句
ps = conn.prepareStatement(sql);//创建ps预处理语句接受sql语句,执行数据库数据库查询
rs = ps.executeQuery();//sql查询获得结果集rs对象
//遍历结果集每一行数据,依序获得sql查询语句的每一个字段
while (rs.next()) {//如果数据存在,调用数据
int emp_id = rs.getInt(1);
String emp_name = rs.getString(2);
Integer age = rs.getInt(3);
//从每一行数据种后的属性值付给Employee对象
Employee employee = new Employee(emp_id, emp_name, age);
list.add(employee);
}
//关闭数据库连接conn、预处理语句对象ps和结果集对象rs,释放数据库资源
DBUtil.realze(conn, ps, rs);//释放内存
6.步骤6
依次关闭ResultSet、Statement/PrearedStatement和Connection对象
finally {
try{
if(rs != null) rs.close();
if(stmt != null) stmt.close();
if(con != null) con.close();
}catch(SQLException e){
System.out.println(e.toString());
}
}
//通过工具类释放内存
public static void realze(Connection conn, PreparedStatement ps, ResultSet rs) throws SQLException {
if (conn != null) {
conn.close();
}
if (ps != null) {
ps.close();
}
if (rs != null) {
rs.close();
}
}
//.....................................
DBUtil.realze(conn, ps, rs);//释放内存
conn.close();
}
if (ps != null) {
ps.close();
}
if (rs != null) {
rs.close();
}
}
//…
DBUtil.realze(conn, ps, rs);//释放内存