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 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,表示有多少条数据受到了影响。