JDBC : Java DataBase Connectivity
可为多种关系型数据库DBMS提供统一的访问方式,用Java来操作数据库
- JDBC API: 提供各种操作访问接口,Connection Statement PreparedStatement ResultSet
- JDBC DriverManager: 管理不同的数据库驱动
- 各种数据库驱动: 相应的数据库厂商提供的连接\直接操作数据库
1.JDBC API 主要功能
- 与数据建立连接(Connection )
- 发送Sql语句(Statement)
- 返回处理结果(.Result)
三件事,具体通过一下类/接口实现
- DriverManager : 管理jdbc驱动
- Connection : 连接(通过DriverManager产生)
- Statement ( PreparedStatement ) : 增删改查(通过Connection产生)
- CallableStatement : 调用数据库中的存储过程/存储函数
- Result : 返回的结果集 (上面的Statement等产生)
2.JBDC访问数据库的具体步骤
1.具体步骤
-
导入驱动,加载具体的驱动类
数据库驱动: 驱动jar包 具体驱动类 连接字符串 Oracle object-版本号.jar oracle.jbbc.OracleDriver jdbc:oracle:thin:@localhost:1521:ORCL MySQL mysql-connector-Java-版本号.jar com.mysql.jdbc.Driver jdbc.MySQL://localhost:3306/数据库实例名 SqlServer sql.jdbc.jar com.microsoft.sqlserver.jdbc.SQLServerDriner jdbc:microsoft:sqlserver:localhost:1433;databasename = 数据库实例名 -
与数据库建立连接
-
发送sql,执行
-
处理结果(查询)
2.Connection产生操作数据库的对象
- Connection产生Statement对象:CreateStatement()
- Connection产生PreparedStatement对象:prepareStatement()
- Connection产生CallsbleStatement对象:prepareCall()
3.Statement操作数据库
- 增删改:executeUpdate()
- 查询:executeQuery()
4.Resultset:保存结果集 eg:select * from XXX
- next():光标下移,判断是否有下一条数据:true/false
- previous():true/false
- getXXX(字段名||位置):获取具体的字段值
5.PreparedStatement 操作数据库:
public interface PreparedStatement extends Statement
因此
- 增删改:executeUpdate()
- 查询:executeQuery()
- 赋值操作:setXxx()
6.PreparedStatement和Statement在使用时区别:
-
Statement
sql
executeUpdate(sql);
-
PreparedStatement:
sql(可能存在占位符“?”)
在创建PreparedStatement对象时,将sql预编译
executeUpdate()
setXxx() 替换占位符“?”
推荐使用PreparedStatement(),原因如下:
-
编码更加简便
-
提高性能(有预编译操作,预编译操作只进行一次)
-
安全:有效的防止sql注入
*注 sql注入:将客户输入的内容和开发人员的sql语句混为一体
3.JDBC总结(模板)
try{
-
导入jar包,加载具体驱动类
Class.forName("com.mysql.jdbc.Driver");
-
与数据库建立连接
connection = DriverManager.getConnection(URL,USERNAME,PWD);
-
通过connection,获取数据库操作对象(Statement / preparedStattement / callableStatement)
stmt = connection.createStatement(); pstmt = connection.prepareStatement(sql);
-
处理结果集,增删改不需要
rs = pstmt.executeQuery(sql); while(rs.next()){ Xxx zz = rs.getXxx("zz"); ......... }
}catch(Exception e) {
e.printStackTrace();}finally{
//打开顺序与关闭顺序相反
if(rs != null) rs.close();**
if(pstmt != null) pstmt.close();
if(connection != null) connection.close();** }
JDBC 中,除了Class.forName(),抛出ClassNotFoundException,其余方法全部抛出SQLWException.
4.CallableStatement
调用存储过程,存储函数
connection.prepareCall(参数:存储过程或存储函数名)
-
参数格式:
存储过程:(无返回值,用Out参数替代)
{call 存储过程名(参数列表)}
存储函数:(有返回值,return)
{? = call 存储过程名(参数列表)}
-
存储过程示例:
create or replace procedure addTwoNum (num1 in number , num2 in number , result out number) -----1+2->3 as begin result := num1 + num2; end;
第三步; cstmt = connection.prepareCall("{call addTwoNUm(?,?,?)}"); cstmt = setInt(1,20); cstmt = setInt(2,10); //设置输出参数的类型 cstmt.registerOutParameter(3,Types.INTEGER); cstmt.execute();//num1+num2,execute()之前处理,输入参数以及输出参数类型,之后接受输出参数值 //获取计算结果 int result = cstmt.getInt(3); System.out.println(result);
*注
如果通过sqlplus 访问数据库,只需要开启:OracleServiceSID
通过navicate,JDBC访问数据,需要开启:OracleServiceSID,XxxvListener
-
存储函数示例
create or replace procedure addTwoNum (num1 in number , num2 in number ) -----1+2->3 return number as result number; begin result := num1 + num2 return result end;
第三步; cstmt = connection.prepareCall("{? = call addTwoNUm(?,?)}"); cstmt = setInt(2,20); cstmt = setInt(3,10); //设置输出参数的类型 cstmt.registerOutParameter(1,Types.INTEGER); cstmt.execute();//num1+num2,execute()之前处理,输入参数以及输出参数类型,之后接受输出参数值 //获取计算结果 int result = cstmt.getInt(3); System.out.println(result);
-
JDBC调用存储函数和存储过程的区别:
在调用时,注意参数
5.处理Text/BLOB类型
处理稍大型数据
-
存储路径(绝对路径)
通过JDBC存储文件路径,然后根据IO操作处理
-
Text:大文本数据(小说->数据)
BLOB:二进制文件,
-
Text
存:
- 先通过pstmt的?代替小说的内容(占位符)
- 再通过pstmt.setCharacterStream(2,reader,(int)file.length()); 将上一步的?替换为小说流,注意第三个参数需要是Int类型
对JDBC第三步进行修改 String sql = "inster into mynovel values(?,?)"; pstmt = connection.prepareStatement(sql);//预编译 pstmt.setInt(1,0001); File file = new FileInputStream(file); Reader reader = new InputStreamReader(in,"UTF-8");//转换流,可以设置编码 pstmt.setCharacterStream(2,reader,(int)file.length()); int count = pstmt.executeUpdate(); reader.colse;
取:
- 通过 Reader resder = rs.getCharacterStream(“NOVEL”); 将cloc类型文件保存到Reader对象中
- 将Reader通过Writer输出即可
对JDBC第三步进行修改 String sql = "select NOVEL from mynovel where id = ?"; pstmt = connection.prepareStatement(sql);//预编译 pstmt.setInt(1,0001); rs = pstmt.executeQuery(); if(rs.next()){ Reader resder = rs.getCharacterStream("NOVEL"); Writer writer = new FileWriter("src/小说.txt"); char[] chs = new char[100]; int len = -1; while((len = reader.read(chs)) != 1){ wrier.write(chs,0,len); } writer.close(); reader.close(); }
6.JSP访问数据库
- JSP就是在html中嵌套的Java代码,因此Java代码可以写在JSP中(<%…%>)
- 导包:web项目:jar包复制到WEB-INF/lib
- 核心:将Java中的JDBC代码,复制到JSP中的<%/…%>
**注:如果JSP出现错误:Xxx cannot be resolved…
解决步骤:
- 如果之前没有包,则将该类加入包中
- (可能是JDK,Tomcat版本问题)右键项目–>build path,将其中的报错libaerty和lib删除后重新导入
- 清空各种缓存,右键项目–>Clean tomcat …clean
- 重启计算机
7.javaBean
将jsp中的登录操作的代码转移到loginDao.java;其中loginDao类称之为JavaBean
-
JavaBean 的作用:
- 减轻Jsp的复杂度
- 提高代码复用(以后任何地方的的登录操作,都可以调用)
-
JavaBean(就是一个Java类)的定义:满足一下两点就是JavaBean
- public 修饰的类,public无参构造
- 如果有属性,必须是private,并且提供set/get(如果是boolean,则将get替换为is)
-
使用层面(分为两类)
-
逻辑: 用于操作一个封装数据的JavaBean
封装业务逻辑的JavaBean(LoginDao.Java封装了登录逻辑)
可及将JSP中的JDBC代码,封装到Login.java 中
-
数据: 对应与数据库中的一张表
封装数据的JavaBean(实体类,Student.java person.java)
Login log = new Login(no,name);//即用Login对象封装了2个数 据(学号姓名)
-