1.什么是JDBC?
Java DataBase Connectivity 在java语言中编写sql语句,对mysql数据库中的数据进行CRUD操作。增加(Create)、读取查询(Retrieve)、更新(Update)和删除(Delete)
2.JDBC的本质
第一波:SUN公司,负责制定JDBC接口。这些接口已经写好了,在java.sql.*;
第二波:java.sql.*下面的所有接口都要有实现类,这些实现类是数据库厂家编写的。
我们连接的是mysql数据库,mysql数据库厂家的实现类在哪里呢?
mysql-connector-java-5.1.23-bin.jar
jar包中很多.class字节码文件,这是mysql数据库厂家写的接口实现!
注意:如果连接的是oracle数据库,你需要从网上下载oracle的jar包。
mysql-connector-java-5.1.23-bin.jar 这个jar包有一个专业的术语,
大家记住就行:mysql的驱动。
如果是oracle的jar,被称为oracle的驱动。
第三波:我们java程序员,面向JDBC接口写代码就行!
3.JDBC开发前的准备工作
将mysql的驱动jar包配置到classpath当中。
如果使用的是IDEA则不需要配置,只需要创建lib文件夹并把jar包粘贴进去,然后
右键选择add Libraries添加进去即可。
4.JDBC编程的六步
1.注册驱动 2.获取连接 3.获取数据库操作对象 4.执行sql语句 5.处理查询结果 6.释放资源
Connection conn=null
Statement stmt=null
ResultSet rs=null
//注册驱动(jdk8适用,jdk5去掉cj即可)
//这是注册驱动的第一种写法
//DriverManager.registerDriver(new com.mysql.cj.jdbc.Driver());
//注册驱动的第二种方式:常用的
//为什么这种方式常用?因为参数是一个字符串,字符串可以写到xxx.properties文件中。
//以下方法不需要接收返回值,因为我们只想用它的类加载动作。
class.forName("com.mysql.cj.jdbc.Driver")
//获取连接
conn=DriverManger.getConnection("jdbc:mysql://localhost:3306/数据库名","用户名","密码")
//获取 数据库操作对象
stmt=conn.createStatement()
//执行sql语句
String sql="。。";
rs=stmt.executeQuery(sql);
//处理查询结果集
while(rs.next()){}
//释放资源
。。。.close();
import java.sql.*;
/*
使用idea开发第一个JDBC程序
*/
public class JDBCTest03 {
public static void main(String[] args) {
Connection conn=null;
Statement stmt=null;
ResultSet rs=null;
try {
//注册驱动
DriverManager.registerDriver(new com.mysql.cj.jdbc.Driver());
//获取连接
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/db1","root","root");
//System.out.println(conn);
//获取数据库操作对象
stmt=conn.createStatement();
//执行SQL
String sql="select sage,classid from student where sname='张三'";
rs=stmt.executeQuery(sql);
//处理查询结果集
while(rs.next()){
String sage=rs.getString("sage");
String classid=rs.getString("classid");
System.out.printf(sage+","+classid);
}
} catch (SQLException e) {
e.printStackTrace();
}finally {
//释放资源
if (rs != null){
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (stmt!=null){
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (conn!=null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
}
5.从属性资源文件中读取连接数据库信息
(1)先在src下创建resources文件夹,然后在其下创建db.properties文件。文件内容为
#####mysql connectivity configuration######
driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/数据库名
user=用户名
password=密码
(2)在代码中引用资源绑定器,调用db.properties文件,使代码更灵活。
import java.sql.*;
import java.util.ResourceBundle;
public class JDBCTest05 {
public static void main(String[] args) {
//资源绑定器
ResourceBundle bundle=ResourceBundle.getBundle("resources/db");
//通过属性配置文件拿到信息
String driver=bundle.getString("driver");
String url=bundle.getString("url");
String user=bundle.getString("user");
String password=bundle.getString("password");
Connection conn=null;
Statement stmt=null;
ResultSet rs=null;
try {
//以下的driver,url,user,password都是调用的db.properties文件中的值,使代码更灵活了。
Class.forName(driver);
conn = DriverManager.getConnection(url,user,password);
stmt=conn.createStatement();
String sql="select sage from student where sname='王五'";
rs=stmt.executeQuery(sql);
while (rs.next()){
String a=rs.getString("sage");
System.out.println(a);
}
} catch (Exception e) {
e.printStackTrace();
}finally {
if(rs!=null){
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (stmt!=null){
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (conn!=null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
}
6.解决sql注入问题
怎么避免sql注入?
sql注入的根本原因是,先进行了字符串的拼接,然后在进行的编译。
java.sql.Statement接口的特点,先进行字符串的拼接。然后再进行sql语句的编译。
优点:使用Statement可以进行sql语句的拼接。
缺点:因为拼接的存在,导致可能给不法分子机会。
java.sql.PreparedStatement接口的特点,先进行sql语句的编译,然后在进行sql语句的传值。
优点:避免sql注入。
缺点:没有办法进行sql语句的拼接,只能给sql语句传值。
PreparedStatement预编译的数据库操作对象
import java.sql.*;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
public class JDBCTest07 {
public static void main(String[] args) {
//初始化一个界面,可以让用户输入用户名和密码
Map<String,String> userLoginInfo=initUI();
//连接数据库验证用户和密码是否正确
boolean ok=checkNameAndPwd(userLoginInfo.get("loginName"),userLoginInfo.get("loginPwd"));
System.out.println(ok?"登陆成功":"登陆失败");
}
private static boolean checkNameAndPwd(String loginName, String loginPwd) {
boolean ok=false;//默认登录是失败的,
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
// 1、注册驱动
try {
Class.forName("com.mysql.cj.jdbc.Driver");
// 2、获取连接
conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/db1", "root", "root");
// 3、获取预编译的数据库操作对象
//一个问号是一个占位符,一个占位符只能接收一个值/数据
String sql = "select * from t_user where login_name=? and login_pwd=?";
stmt=conn.prepareStatement(sql);//此时会发送sql给DBMS,进行sql语句的编译
//给占位符?传值
//怎么解决sql注入的?即使用户信息中有sql关键字,但是不参加编译就没事。
//stmt.setInt(1,100);//这样必须是填数字,↓下面那个必须填字符串。
stmt.setString(1,loginName);//给第一个占位符传值
stmt.setString(2,loginPwd);//给第二个占位符传值
// 4、执行sql语句
rs = stmt.executeQuery();//这个方法不需要将sql语句传递进去,不能是这样:rs = stmt.executeQuery(sql);因为上面已经把sql传过去了。
if(rs.next()){//此条件如果成立,表示登录成功
ok=true;
}
// 5、处理结果集
} catch (Exception e) {
e.printStackTrace();
}finally {
// 6、释放资源
if (rs != null) {
try {
rs.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if (stmt != null) {
try {
stmt.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if (conn!= null) {
try {
conn.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
return ok;
}
private static Map<String, String> initUI(){
System.out.println("欢迎使用该系统,请输入用户名和密码进行身份认证");
Scanner s=new Scanner(System.in);
System.out.print("用户名:");
String loginName=s.nextLine();
System.out.print("密码:");
String loginPwd=s.nextLine();
//将用户名和密码放在map集合中
Map<String,String> useLoginInfo=new HashMap<>();
useLoginInfo.put("loginName",loginName);
useLoginInfo.put("loginPwd",loginPwd);
//返回map
return useLoginInfo;
}
}