JDBC是什么?
Java DataBase Connectivity(java语言连接数据库)
java实现的数据库接口
JDBC的本质是什么
JDBC是sun公司制定的一套接口(interface)
接口都有调用者和实现者
面向接口(调用、实现类)编程
为什么要用面向接口编程?
解耦合:降低程序的耦合度,提高程序的扩展力。
多态机制就是非常典型的:面向抽象编程。(不要面向具体编程)
建议使用。//父类型的应用指向子类型的对象
//面向父类型编程==面向接口编程(抽象
Animal a=new Cat();
Animal a=new Cat();
不建议使用:
Cat c=new Cat();
Dog d=new Dog();
五个步骤
1、注册驱动
Class.forName("com.mysql.cj.jdbc.Driver");
2、连接数据库
String url="jdbc:mysql://localhost:3306/company?useSSL=true&serverTimezone=GMT";
Connection conn= DriverManager.getConnection(url,"root","333");
3、获得数据库操作对象
Statement stmt=conn.createStatement();
//PreparedStatement ps=conn.prepareStatement(sql);
4、执行sql语句
//更新数据库增、删、改,返回更新的行数为int
stmt.executeUpdate();
//查询语句。放回值类型为下方的ResultSet
stmt.executeQuery();
5、处理查询结果集
ResultSet rs=stmt.execteQuery(sql);
6、关闭数据库连接
.close();
Statement和PreparedStatement的区别
Statement,不够安全,存在sql注入的问题 。如下面的例子
package jbcd.test1;
import java.sql.*;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
/**
* 当前程序存在的问题
* 用户名:aaaa
* 密码:aaaa'or'1'='1
* 登录成功!
* 这种现象被称为SQL注入。(黑客经常使用)
*
* 导致SQL注入的原因?
* 用户输入的信息中含有SQL语句的关键字,并且参与sql编译,扭曲了原先的sql语句
*
* 如何解决问题?
* 只要用户提供的信息不参与SQL语句的编译过程,问题就解决了。
* 即,即使用户提供的信息中含有SQL语句的关键字,但是没有参加sql编译,不起作用
* 这里可以使用java.sql.PreparedStatement
* PreparedStatement接口继承java.sql.Statement
* PreparedStatement是属于预编译的数据库操作对象
* PreparedStatement的原理是,预先对sql语句的框架进行编译,然后再给sql语句传值
* 结果:
* 用户名:aaaa
* 密码:aaaa'or'1'='1
* 登录错误!
*/
public class JDBCTest03 {
public static void main(String[] args) {
//初始化一个界面
Map<String,String> userLogInfo=initUI();
//验证用户名和密码
boolean loginSuccess=login(userLogInfo);
if(loginSuccess)
System.out.println("登录成功!");
else
System.out.println("登录错误!");
}
/**
* 用户登录
* @param userLogInfo 用户登录信息
* @return false表示失败,true表示成功
*/
private static boolean login(Map<String, String> userLogInfo) {
boolean loginSuccess=false;
String loginName=userLogInfo.get("loginName");
String loginPwd=userLogInfo.get("loginPwd");
//JDBC 代码
Connection conn=null;
PreparedStatement ps=null;
//Statement stmt=null;
ResultSet rs=null;
try {
//注册驱动
Class.forName("com.mysql.cj.jdbc.Driver");
//获取连接
conn= DriverManager.getConnection("jdbc:mysql://localhost:3306/company2?useSSL=true&serverTimezone=GMT","root","333");
//stmt=conn.createStatement();
//String sql="select * from myuser where name='"+loginName+"'and psw='"+loginPwd+"'";
String sql="select * from myuser where name= ? and psw= ? ";
ps=conn.prepareStatement(sql);
ps.setString(1,loginName);
ps.setString(2,loginPwd);
//处理结构集
rs=ps.executeQuery();
if (rs.next())
loginSuccess=true;
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException throwables) {
throwables.printStackTrace();
} finally {
if (rs != null) {
try {
rs.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if (ps != null) {
try {
ps.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if (conn != null) {
try {
conn.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
return loginSuccess;
}
/**
* 初始化用户界面
* 用户输入的用户名和密码等登陆信息
* @return Map
*/
private static Map<String, String> initUI() {
Scanner s=new Scanner(System.in);
System.out.print("用户名:");
String loginName=s.nextLine();
System.out.print("密码:");
String loginPwd=s.nextLine();
Map<String,String> userLoginInfo=new HashMap<>();
userLoginInfo.put("loginName",loginName);
userLoginInfo.put("loginPwd",loginPwd);
return userLoginInfo;
}
}
PreparedStatement接口继承java.sql.Statement
PreparedStatement是属于预编译的数据库操作对象
PreparedStatement的原理是,预先对sql语句的框架进行编译,然后再给sql语句传值
PreparedStatement,安全,效率高
事务
JDBC中的事务是默认提交的(执行一条语句,则提交一次)
//将自动提交机制改为手动提交(false)表示
conn.setAutoCommit(false);
//手动提交
conn.commit();
//回滚。取消当前事务中的所有更改
conn.rollback();
悲观锁和乐观锁(难点,这里简单了解一下)
悲观锁:事务必须排队执行。数据锁住了,不允许并发
乐观锁:支持并发,事务不需要排队。这里需要一个记录,来记录前面的事务是否对数据发生改变。