java database connectivity java 与数据库的连接
JDBC基本流程
JDBC基本流程:
1.加载驱动(选择数据库)
2.获取连接(与数据库建立连接)
3.准备SQL
4.构建处理块(封装发送SQL)
5.发送SQL,得到结果
6.处理结果
7.连接关闭
public class Class001_JDBC {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
//1)加载驱动(选择数据库)利用创建类对象进行加载
Class.forName("oracle.jdbc.driver.OracleDriver");
//2)获取连接(与数据库建立连接)
Connection coon = DriverManager.getConnection(
"jdbc:oracle:thin:@localhost:1521:XE",
"SCOTT",
"TIGER"
);
//准备SQL
String sql="SELECT * FROM DEPT";
//4)构建处理块(封装发送SQL
Statement state=coon.createStatement();
//5)发送SQL得到结果
ResultSet result=state.executeQuery(sql);
//6)处理结果
while(result.next()){
int deptno=result.getInt(1);
String dname=result.getString("dname");
String loc=result.getString(3);
System.out.println(deptno+"--->"+dname+"--->"+loc);
}
//7)连接关闭
coon.close();
}
}
JDBC流程的优化
1.配置properties文件
2.将出现的异常捕获而不是抛出
package jdbc;
import java.io.IOException;
import java.sql.*;
import java.util.Properties;
public class Class002_JDBC {
public static void main(String[] args) {
Properties p=new Properties();
try {
p.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("db.properties"));
} catch (IOException e) {
e.printStackTrace();
}
//1)加载驱动
try {
Class.forName(p.getProperty("driver"));
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
//2)建立连接
Connection coon= null;
try {
coon = DriverManager.getConnection(
p.getProperty("url"),
p.getProperty("user"),
p.getProperty("password")
);
//3)准备SQL
String sql="SELECT * FROM DEPT";
//4)构建处理块
Statement state=coon.createStatement();
//5)发送sql
ResultSet result=state.executeQuery(sql);
//6)处理结果
while(result.next()){
int deptno=result.getInt(1);
String dname=result.getString("dname");
String loc=result.getString(3);
System.out.println(deptno+"--->"+dname+"--->"+loc);
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}finally {
//7)关闭
if(coon!=null){
try {
coon.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
}
}
运行结果
数据库中查询结果
处理块
静态处理块 statement
Statement 是 Java 执行数据库操作的一个重要接口,用于在已经建立数据库连接的基础上,向数据库发 送要执行的 SQL 语句。Statement 对象,用于执行不带参数的简单 SQL 语句。 执行静态 SQL 语句并返回它所生成结果的对象。
创建
连接.Connection.createStatement()
执行
ddl -->execute(dd语句) -- 通常不会在代码中执行 dml -->executeUpdate(dml语句) select -->executeQuery(select)
特点
处理 不变的静态的 sql 语句 优点: 直接查看sql ,方便处理错误 缺点:性能不高 拼接 sql 麻烦 可能存在 sql 注入
SQL注入:其实就是恶意用户通过在表单中填写包含SQL关键字的数据来使数据库执行非常规代码的过程。简单来说,就是数据「越俎代庖」做了代码才能干的事情。例如在输入的用户名中包含了and or等关键字使操作数据库有误。
预处理块 PreparedStatement
创建
连接.prepareStatement(sql)
执行
存在? ,先填充参数再执行 ddl -->execute() dml -->executeUpdate() select -->executeQuery()
特点
处理 不变的静态的 sql 语句 |可变的 sql 语句 带 ? 的 sql 优点:性能高,方便编写sql 不存在sql注入 安全 缺点:不能直接打印sql语句 不方便处理错误
角色分类
服务器
接收SQL
执行SQL
返回结果
客户端
接受数据
组装SQL
发送SQL
分析结果
JDBC实例
1.通过JDBC实现用户注册与登录
用户基本操作:
用户注册 insert
用户登录 select
根据用户名与密码同时查找,找到结果返回true,没找到结果返回false
根据用户名查找,找到密码与用户号输入的密码比较是否相等,返回true|false
修改用户数据 update
注销用户 delete
注意: 事务默认自动提交
/*
JDBC封装工具类
加载驱动
获取连接
资源关闭
*/
public class JDBCUtils {
private static Properties pro = new Properties();
static{
//加载流
try {
pro.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("db.properties"));
} catch (IOException e) {
e.printStackTrace();
}
//加载驱动
try {
Class.forName(pro.getProperty("driver"));
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
//获取连接
public static Connection getConnection() throws SQLException {
Connection conn = null;
conn = DriverManager.getConnection(
pro.getProperty("url"),
pro.getProperty("username"),
pro.getProperty("password")
);
return conn;
}
//关闭资源
public static void close(Connection conn, Statement state){
close(conn,state,null);
}
public static void close(Connection conn, Statement state, ResultSet result){
if(result!=null){
try {
result.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if(state!=null){
try {
state.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if(conn!=null){
try {
conn.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
}
public class Class003_User {
public static void main(String[] args) {
System.out.println(login("zhangsan","1234")?"成功":"失败");;
}
//登录
//预处理块 PreparedStatement
public static boolean login(String username,String password){
boolean flag = false;
Connection conn = null;
PreparedStatement state = null;
ResultSet result = null;
//1.获取连接
try {
conn = JDBCUtils.getConnection();
//2.准备sql
String sql = "select * from t_user where username=? and password =?";
//3.构建预处理块
state = conn.prepareStatement(sql);
//4.为?赋值
state.setString(1,username);
state.setObject(2,password);
//5.执行,得到结果
result = state.executeQuery();
//5.处理结果
if(result.next()){
flag = true;
}
}catch(SQLSyntaxErrorException e){
System.out.println("遇到SQL注入了....");
} catch (SQLException throwables) {
throwables.printStackTrace();
} finally {
//6.关闭资源
JDBCUtils.close(conn,state,result);
}
//7.返回结果
return flag;
}
//静态处理块 Statement,会造成SQL注入
/*public static boolean login(String username,String password){
boolean flag = false;
Connection conn = null;
Statement state = null;
ResultSet result = null;
//1.获取连接
try {
conn = JDBCUtils.getConnection();
//2.准备sql
String sql = "select * from t_user where username='"+username+"' and password = "+password;
//3.封装处理块
state = conn.createStatement();
//4.执行,得到结果
result = state.executeQuery(sql);
//5.处理结果
if(result.next()){
flag = true;
}
} catch (SQLException throwables) {
throwables.printStackTrace();
} finally {
//6.关闭资源
JDBCUtils.close(conn,state,result);
}
//7.返回结果
return flag;
}*/
//注册
public static boolean reg(String username,String password){
boolean flag = false;
Connection conn = null;
Statement state = null;
//1.获取连接
try {
conn = JDBCUtils.getConnection();
//2.准备sql
String sql = "insert into t_user values('"+username+"',"+password+")";
//3.封装处理块
state = conn.createStatement();
//4.执行,得到结果
int rows = state.executeUpdate(sql);
//5.处理结果
if(rows>0){
flag = true;
}
} catch (SQLException throwables) {
throwables.printStackTrace();
} finally {
//6.关闭资源
JDBCUtils.close(conn,state);
}
//7.返回结果
return flag;
}
}
2.实现一个事务内的转账操作
转账操作
A --> SAL-500
B --> SAL+500
需要控制在同一个事务中,设置手动提交,校验之后提交或者回滚
public class Class004_Transfer {
public static void main(String[] args) {
System.out.println(transfer());;
}
//预处理块 PreparedStatement
public static boolean transfer(){
boolean flag = false;
Connection conn = null;
PreparedStatement state1 = null;
PreparedStatement state2 = null;
//1.获取连接
try {
conn = JDBCUtils.getConnection();
//设置手动提交
conn.setAutoCommit(false);
//2.准备sql
String sql1 = "update emp set sal=sal-500 where empno =7499";
String sql2 = "update emp set sal=sal+500 where empno =7369";
//3.构建预处理块
state1 = conn.prepareStatement(sql1);
state2 = conn.prepareStatement(sql2);
//4.为?赋值
//5.执行,得到结果
int rows1 = state1.executeUpdate();
int rows2 = state2.executeUpdate();
//5.处理结果
if(rows1>0 && rows2>0){
flag = true;
conn.commit();
}else{
conn.rollback();
}
}catch(SQLSyntaxErrorException e){
System.out.println("遇到SQL注入了....");
} catch (SQLException throwables) {
throwables.printStackTrace();
}
//7.返回结果
return flag;
}
}
注意:必须要设置手动提交,不然有一方更改失败,另一方的数据任然会发生更改