JDBC
- jdbc:Java DataBase Connectivity
- 作用:可以为多种关系型数据库DBMS提供统一的访问方式,用java来操作数据库库
JDBC API
JDBC DriverManager
JDBC DriverManager:管理不同数据的驱动
数据库驱动
数据库驱动由各种数据库厂商提供的(第三方提供):连接\直接操作数据库
数据 | 驱动jar包 | 具体驱动类 | 驱动字符串 |
---|---|---|---|
Oracle | ojdbc-version.jar | oracle.jdbc.OracleDriver | jdbc:oracle:thin:@localhost:1521:ORCL |
MySQL | mysql-connector-java-version.jar | com.mysql.jdbc.Driver | jdbc:mysql://localhost:3306/数据库实例名?serverTimezone=GMT%2B8 |
SqlServer | sqljdbc-version.jar | com.microsoft.sqlserver.jdbc.SQLServerDriver | jdbc:sqlserver://localhost:1433;DatabaseName=数据库实例名 |
JDBC接口
JDBC API:提供各种操作访问数据库的接口(Connection、statement、PreparedStatement、ResultSet)
主要功能
- DriverManager:管理/加载数据库驱动
- Connection:连接数据库(通过DriverManger产生)
- 产生Statement对象:Connection.createStatement()
- 产生PreparedStatement对象:Connection.createPrepareStatement()
- 产生CallableStatement对象:Connection.prepareCall()
- Statement:增删改查数据库(通过Connection产生)
- 操作数据库
- 增删改查:executeUpdate()
- 查询:executeQuery()
- 操作数据库
- PrepareStatement(Statement的之接口):增删改查数据库(通过Connection产生)
- 操作数据库
- 增删改查:executeUpdate()
- 查询:executeQuery()
- 复制操作:setXxxx()
- 优点
- sql可以存在占位符
?
- 在创建perparedStement对象使后对SQL语句进行预编译
- 可以通过set方法替换占位符
- sql可以存在占位符
- 操作数据库
- CallableStatement:调用数据库中的存储过程/存储函数(通过Connection产生)
- ResultSet:结果集(通过Statement等产生)
- next():光标下移,判断是否有下一个数据
- previous():光标上移,判断是否有下一个数据
- getXxxx():获取具体的字段名的值(可以写字段名或者下标)
JDBC操作数据库步骤
- 导入jar包、加载具体的驱动类(驱动程序)
- 与数据库建立连接
- 发送/执行SQL语句
- 处理结果集
操作数据库java代码:
package jdbc.test;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class Oracle {
//oracle数据库
private final String URL = "jdbc:oracle:thin:@localhost:1521:ORCL";
private final String NAME = "scott";
private final String PWD = "tiger";
private final String PWD = "1022";
private final String CSNA = "oracle.jdbc.OracleDriver";
//mysql数据库
/*
private final String URL = "jdbc:mysql://localhost:3306/test?serverTimezone=GMT%2B8";
private final String NAME = "root";
private final String PWD = "1022";
private final String CSNA = "com.mysql.cj.jdbc.Driver";
*/
//SQLserver数据库
/*
private final String URL = "jdbc:sqlserver://localhost:1433;DatabaseName=test";
private final String NAME = "sa";
private final String PWD = "1022";
private final String CSNA = "com.microsoft.sqlserver.jdbc.SQLServerDriver";
*/
public static void main(String[] args) {
Oracle ora = new Oracle();
ora.insert();
ora.query();
}
//插入数据
public void insert() {
Connection conn = null;
Statement stmt = null;
try {
Class.forName(CSNA);
conn = DriverManager.getConnection(URL,NAME,PWD);
stmt = conn.createStatement();
String sql = "insert into test values ('010','test10','Oracle插入数据')";
int count = stmt.executeUpdate(sql);
if(count>0) {
System.out.println("添加成功!");
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}catch (SQLException e) {
e.printStackTrace();
}finally {
try {
if(stmt != null) {
stmt.close();
}
if(conn != null) {
conn.close();
}
} catch (SQLException ex) {
ex.printStackTrace();
}
}
}
//删除数据
public void delete() {
Connection conn = null;
Statement stmt = null;
try {
Class.forName(CSNA);
conn = DriverManager.getConnection(URL,NAME,PWD);
stmt = conn.createStatement();
String sql = "delete test where id = '02'";
int count = stmt.executeUpdate(sql);
if(count>0) {
System.out.println("添加成功!");
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}catch (SQLException e) {
e.printStackTrace();
}finally {
try {
if(stmt != null) {
stmt.close();
}
if(conn != null) {
conn.close();
}
} catch (SQLException ex) {
ex.printStackTrace();
}
}
}
//更新数据
public void update() {
Connection conn = null;
Statement stmt = null;
try {
Class.forName(CSNA);
conn = DriverManager.getConnection(URL,NAME,PWD);
stmt = conn.createStatement();
String sql = "update test set name = '垃圾' where id = '01'";
int count = stmt.executeUpdate(sql);
if(count>0) {
System.out.println("添加成功!");
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}catch (SQLException e) {
e.printStackTrace();
}finally {
try {
if(stmt != null) {
stmt.close();
}
if(conn != null) {
conn.close();
}
} catch (SQLException ex) {
ex.printStackTrace();
}
}
}
//查询数据库
public void query() {
Connection conn = null;
Statement stmt = null;
ResultSet etqy = null;
try {
Class.forName(CSNA);
conn = DriverManager.getConnection(URL,NAME,PWD);
stmt = conn.createStatement();
String sql = "SELECT * FROM test";
etqy = stmt.executeQuery(sql);
while(etqy.next()) {
System.out.printf("%s --- %s --- %s",etqy.getString("id"),etqy.getString("test"),etqy.getString("name"));
System.out.println();
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}catch (SQLException e) {
e.printStackTrace();
}finally {
try {
if(etqy != null) {
etqy.close();
}
if(stmt != null) {
stmt.close();
}
if(conn != null) {
conn.close();
}
} catch (SQLException ex) {
ex.printStackTrace();
}
}
}
}
使用更加安全的PrepareStatement操作数据库:
public void insert() {
Connection conn = null;
PreparedStatement pstmt = null;
try {
Class.forName(CSNA);
conn = DriverManager.getConnection(URL,NAME,PWD);
String sql = "insert into test values (?,?,?)";
pstmt = conn.prepareStatement(sql);
pstmt.setString(1, "012");
pstmt.setString(2, "test012");
pstmt.setString(3, "preparedStement插入数据");
int count = pstmt.executeUpdate(sql);
if(count>0) {
System.out.println("添加成功!");
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}catch (SQLException e) {
e.printStackTrace();
}finally {
try {
if(pstmt != null) {
pstmt.close();
}
if(conn != null) {
conn.close();
}
} catch (SQLException ex) {
ex.printStackTrace();
}
}
}
Statement和preparedStatement的区别
操作sql | 安全性 | 性能 | |
---|---|---|---|
Statement | 需要字符串拼接添加变量,较麻烦 | 安全性较低,存在SQL注入 | 性能较低(每执行一次就会编译一次SQL语句) |
PreparedStatement | 使用? 作为占位符,不用字符串拼接,较方便 | 安全性较高,天然防止SQL注入 | 性能较高,因为存在SQL语句的自编译(只用编译一次) |
JDBC总结
jdbc类似一个模板、八股文,模式都一样
步骤:
- 导入驱动包、加载驱动包
Class.forName("具体驱动类");
- 与数据库建立连接,获取一个connection对象,传入连接字符串,用户名和密码(
Connection conn = DriverManager.getConnection(URL,NAME,PWD);
) - 通过connection对象获取操作数据库的对象(Statement、preparedStement、callableStatement):
PreparedStatement pstmt = pstmt = conn.prepareStatement(sql);
sql
:SQL语句 - 增删改查
- 查询需要处理结果集
ResultSet exqy = stmt.executeQuery(sql);
while(exqy.next()) {
exqy.getXxxx("col");//col为字段名
}
- 处理异常
- 关闭资源(先打开资源后关闭,后打开资源先关闭)
CallableStatement:调用存储过程,存储函数
- connection. prepareCall (参数:存储过程或存储函数名)
- 参数格式:
- 存储过程(无返回值return, 用0ut参数替代) :
{call存储过程名(参数列表)} - 存储函数(有返回值return):{ ? = call 存储函数名(参数列表) }
- 调用存储过程步骤:
a.产生调用存储过程的对象(Cal lableStatement) cstmt = connect ion. prepareCall ("…”);
b.通过setXxx()处理输出参数值cstmt. setInt(1, 30) ;
c.通过registerOutParameter(… )处理输出参数类型
d. cstmt. execute()执行
e. 接受输出值(返回值) getXxx()
示例:
- 创建存储过程(以oracle为例):
CREATE or replace PROCEDURE addTwoNum ( num1 in number, num2 in number, result out number)
AS
BEGIN
result := num1 + num2;
end;
/
- java代码调用存储过程
package jdbc.test;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Types;
public class CallableStatements {
private final String URL = "jdbc:oracle:thin:@localhost:1521:ORCL";
private final String NAME = "scott";
private final String PWD = "tiger";
private final String CSNA = "oracle.jdbc.OracleDriver";
public static void main(String[] args) {
CallableStatements ca = new CallableStatements();
ca.callable();
}
public void callable() {
Connection conn = null;
java.sql.CallableStatement cstmt = null;
try {
Class.forName(CSNA);
conn = DriverManager.getConnection(URL,NAME,PWD);
cstmt = conn.prepareCall("{ call addTwoNum(?,?,?) }");
// 设置输入值
cstmt.setInt(1, 10);
cstmt.setInt(2, 10);
// 设置输出参数的类型
cstmt.registerOutParameter(3, Types.INTEGER);
// 调用存储过程,execute()之前处理的是输入参数以及输出参数的类型,之后是处理输出参数
cstmt.execute();
// 获取计算结果
int result = cstmt.getInt(3);
System.out.println(result);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}catch (SQLException e) {
e.printStackTrace();
}finally {
try {
if(cstmt != null) {
cstmt.close();
}
if(conn != null) {
conn.close();
}
} catch (SQLException ex) {
ex.printStackTrace();
}
}
}
}
调用存储函数
示例:
- 创建存储过程(以oracle为例):
CREATE or replace function addTwoNumFunction ( num1 in number, num2 in number)
return number
AS
result number;
BEGIN
result := num1 + num2;
return result;
end;
/
- jdbc调用存储函数:
public class CallableStatements {
private final String URL = "jdbc:oracle:thin:@localhost:1521:ORCL";
private final String NAME = "scott";
private final String PWD = "tiger";
private final String CSNA = "oracle.jdbc.OracleDriver";
public static void main(String[] args) {
CallableStatements ca = new CallableStatements();
ca.callable();
ca.callablefunction();
}
public void callablefunction() {
Connection conn = null;
java.sql.CallableStatement cstmt = null;
try {
Class.forName(CSNA);
conn = DriverManager.getConnection(URL,NAME,PWD);
cstmt = conn.prepareCall("{ ? = call addTwoNumFunction(?,?) }");
// 设置输入值
cstmt.setInt(2, 20);
cstmt.setInt(3, 10);
// 设置输出参数的类型
cstmt.registerOutParameter(1, Types.INTEGER);
// 调用存储过程,execute()之前处理的是输入参数以及输出参数的类型,之后是处理输出参数
cstmt.execute();
// 获取计算结果
int result = cstmt.getInt(1);
System.out.println(result);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}catch (SQLException e) {
e.printStackTrace();
}finally {
try {
if(cstmt != null) {
cstmt.close();
}
if(conn != null) {
conn.close();
}
} catch (SQLException ex) {
ex.printStackTrace();
}
}
}
}
jsp访问数据库
-
JSP就是在html中嵌套的java代码,因此java代码可以写在jsp中(<% … %>)
-
导包操作:
- java项目:
- Jar复制到工程中
- 右键该Jar :build path ->add to build Path
-Web项目: jar 复制到WEB- INF/lib
- java项目:
-
小示例:
index.jsp页面:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<form action="check.jsp" method="post">
<div>
<label for="uNam">用户名:</label>
<input type="text" id="uName" name="uName"/>
</div>
<div>
<label for="uPWD">密码:</label>
<input type="password" id="uPWD" name="uPWD"/>
</div>
<div>
<input type="submit" value="登录" />
</div>
</form>
</body>
</html>
check.jsp页面:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ page import="java.sql.*" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<%
String URL = "jdbc:oracle:thin:@localhost:1521:ORCL";
String NAME = "scott";
String PWD = "tiger";
String CSNA = "oracle.jdbc.OracleDriver";
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet etqy = null;
try {
Class.forName(CSNA);
conn = DriverManager.getConnection(URL,NAME,PWD);
String sql = "SELECT * FROM users";
pstmt = conn.prepareStatement(sql);
etqy = pstmt.executeQuery(sql);
etqy.next();
if(etqy.getString(1).equals(request.getParameter("uName")) && etqy.getString(2).equals(request.getParameter("uPWD"))){
out.print("登录成功!");
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}catch (SQLException e) {
e.printStackTrace();
}finally {
try {
if(etqy != null) {
etqy.close();
}
if(pstmt != null) {
pstmt.close();
}
if(conn != null) {
conn.close();
}
} catch (SQLException ex) {
ex.printStackTrace();
}
}
%>
</body>
</html>
JavaBean
将jsp中登录操作的代码转移到JDBCDao. java; 其中JDBCDao类就称之为JavaBean。.
- JavaBean的作用:
- 减轻的jsp复杂度
- 提高代码复用
- JavaBean (就是一一个Java类)的定义:满足一下2点,就可以称为JavaBean
- public修饰的类, public无参构造
- 所有属性都是private, 并且提供set/get (如果boolean则get可以替换成is)
- 使用层面,Java分为2大类:
- 封装业务逻辑的JavaBean (JDBCDao. java,封装了操作数据库逻辑)
- 用于操作一个封装数据的JavaBean
- 封装数据的JavaBean (实体类,Student. java Person. java )
- 对应数据库中的一张表
mvc设计模式
全写 | 名称 | 作用 | |
---|---|---|---|
M | Model | 模型 | 一个功能模块,用javaBean实现 |
V | View | 视图 | 用于展示以及与用户的交互,可以使用html\css\jsp\js等实现 |
C | contorller | 控制器 | 接收请求,将请求跳转到模型(Model层)进行处理,模型处理完毕后将结果返回给控制器,控制器将结果返回给请求处。可以使用jsp、servlet、spring等实现 |