JDBC 概述
咱们学习了数据库,数据库实现了数据的长久化,但咱们最终要在程序里解决数据啊,那 java 代码中怎么去拜访数据库读写数据呢?
这就要用到 sun 公司设定的一套数据库规范了,这套规范就是 JDBC(Java Database Connectivity)。但它只是标准,不做具体实现。于是数据库厂商又依据 JDBC 规范,实现自家的驱动 Driver。如:mysql 驱动 com.mysql.cj.jdbc.Driver,Oracle 的驱动 oracle.jdbc.OracleDriver。有了这套解决方案,java 就能够拜访数据库中的数据了。
public interface Connection extends Wrapper, AutoCloseable {}
public interface Statement extends Wrapper, AutoCloseable {}
public interface PreparedStatement extends Statement {}
public interface CallableStatement extends PreparedStatement {}
public interface ResultSet extends Wrapper, AutoCloseable {}
调用形式有三种:
Statement 语句、PreparedStatement 预处理语句、CallableStatement 存储过程,举荐应用第二种 PreparedStatement,避免 SQL 注入,其也是预编译性能高。
JDBC 的三种调用
Statement 语句:
步骤:
1. 加载驱动
2. 创立数据库连贯 connection
3. 创立 sql 语句对象(statement 语句,preparestatement 预编译语句,call 存储过程 X)
4. 执行查问语句, 返回后果集 ResultSet
5. 利用查问到的后果集对象进行数据处理
package test;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
public class Test3JDBC {public static void main(String[] args) throws Exception {
// 根本查问语句
method();}
public static void method() throws Exception {
// 第一步,须要加载驱动
String driver = "com.mysql.jdbc.Driver";
// 第二步,增加链接,用户名,明码
String url = "jdbc:mysql://localhost:3306/jtdb2007";
String usename="root";
String password="1234";
// 创立 driver 申明的类的全门路的 Class 类对象
Class.forName(driver);
// 第三步,创立一个数据库链接 connection
Connection cn = DriverManager.getConnection(url,usename,password);
// 第四步,创立语句对象(statement 语句,preparestatement 预编译语句,call 存储过程 X)Statement state = cn.createStatement();// 创立 Statement 对象,该对象来将 sql 发送到数据库。// 第五步,执行查问语句, 返回后果集 ResultSet
String sql = "select * from emp";
ResultSet rs = state.executeQuery(sql);
int cols = rs.getMetaData().getColumnCount();// 获取列的数量
for (int i = 1; i <=cols ; i++) {
// 第六步,获取列名,元数据
System.out.print(rs.getMetaData().getColumnName(i)+"t");//ResultSetMetaData 接口,获取指定列的名称
}
// 第七步,for 循环打印表字段内容
while(rs.next()){System.out.println();
for (int i = 1; i <=cols ; i++) {System.out.print(rs.getString(i)+"t");
}
}
}
}
PreparedStatement 预处理语句:
package test;
import org.junit.Test;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
public class Test2JDBC {
@Test // 预编译查问语句
public <PrepareStatement> void prepareStatement() throws Exception {
String driver = "com.mysql.jdbc.Driver"; // 驱动
String url = "jdbc:mysql://localhost:3306/jtdb2007"; // 连贯
// 预编译 sql 中用?作为占位符,未来会被实在值替换掉
String sql = "select * from dept where deptno = ?";
Class.forName(driver);
Connection cn = DriverManager.getConnection(url, // 获取链接
"root","1234");
// 带参数
PreparedStatement ps=cn.prepareStatement(sql); // 返回预编译对象
ps.setString(1,"2");//?地位,参数值
// 查问
ResultSet rs = ps.executeQuery();
// 打印列题目
int cols = rs.getMetaData().getColumnCount(); // 列的总数
for (int i = 1; i <=cols ; i++) {
// 打印列的名称
System.out.print(rs.getMetaData().getColumnName(i)+"t");
}
// 打印数据
while(rs.next()){ // 每次向下取一条,直到结尾
System.out.println(); // 换行
for (int i = 1; i <=cols ; i++) {System.out.print(rs.getString(i)+"t");
}
}
}
}
Procedure 存储过程:
package jdbc;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
public class TestProcedure {public static void main(String[] args) throws ClassNotFoundException, SQLException {
String driver = "oracle.jdbc.OracleDriver";
String url = "jdbc:oracle:thin:@localhost:1521:xe"; // 留神 SID
String sql = "{call paging_cursor(?,?,?,?,?,?)}";
String user = "ht";
String password = "ht";
Class.forName(driver);
Connection cn = DriverManager.getConnection(url, user, password);
CallableStatement cs = cn.prepareCall(sql);
// 给 in? 赋值
cs.setString(1, "emp");// 传表名
cs.setInt(2, 3); // 传入 pagesize,每页显示多少条记录
cs.setInt(3, 2); // 传入 pagenow,显示第几页。// 给 out? 注册
cs.registerOutParameter(4, oracle.jdbc.OracleTypes.CURSOR);
cs.registerOutParameter(5, oracle.jdbc.OracleTypes.INTEGER);
cs.registerOutParameter(6, oracle.jdbc.OracleTypes.INTEGER);
// 执行
cs.execute();
// 这里是关键所在,java 没有接管后果集的 get 办法,所以只能用 getObject 来接管后果集,接管到后须要应用 ResultSet 强转才能够
ResultSet rs = (ResultSet) cs.getObject(4);
// 循环取出
while (rs.next()) {System.out.println(rs.getString("ename") + "" + rs.getString("sal"));
}
// 取出总记录数
int rowCount = cs.getInt(5);
// 取出总页数
int pageCount = cs.getInt(6);
System.out.println("共有记录:" + rowCount + "条!" + "共有记录:" + pageCount + "页!");
}
}
Statement 和 PreparedStatement 的异同
同:两者都可创立执行 sql 语句的对象
异:PreparedStatement 能够设置占位符,预编译,编译效率高,它可能通过设置参数,指定相应的值;
Statement 应用的是字符串拼接的形式,具备注入攻打的危险。
execute 和 executeUpdate 的区别
相同点:都可能执行减少、删除、批改等操作。
不同点:
1、execute 能够执行查问语句,而后通过 getResult 把后果取出来。executeUpdate 不能执行查问语句。
2、execute 返回 Boolean 类型,true 示意执行的是查问语句,false 示意执行的 insert、delete、update 等。executeUpdate 的返回值是 int,示意有多少条数据受到了影响。