目录
一、JDBC概述
二、JDBC搭建
1.注册JDBC驱动程序
2.建立与数据库连接
3.获得Satement执行sql语句
4.关闭与数据库的链接通道
三、PreparedStatement和Statement
1、代码的可读性和可维护性
2、最重要的一点是极大地提高了安全性
四、结果集处理
一、JDBC概述
JDBC(Java DataBase Connectivity)java数据库连接
是一种用于执行SQL语句的Java API,可以为多种关系型数据库提供统一访问, 它由一组用Java语言编写的类和接口组成。
有了JDBC,java开发人员只需要编写一次程序,就可以访问不同的数据库.
JavaAPI中提供了操作数据库的标准接口 , 最终由不同的数据库开发商实现这些标准接口来对数据库操作
.
Java定义者制定了JDBC规范
数据库开发商实现接口
程序员学习使用标准规范
二、JDBC搭建
JDBC API:供程序员调用的接口与类,集成在java.sql包中
DriverManager类作用:管理各种不同的JDBC驱动
Connection 接口 与特定数据库的连接
Statement 接口 执行sql
PreparedStatement接口 执行sql
ResultSet接口 接收查询结果
1.注册JDBC驱动程序
这需要初始化驱动程序,这样就可以打开与数据库的通信信道。
Class.forName(“com.mysql.cj.jdbc.Driver”); //反射实现
或者
DriverManager.registerDriver(new Driver());//手动注册
2.建立与数据库连接
这需要使用DriverManager.getConnection()方法来创建一个Connection对象,它代表一个物理连接的数据库.
Connection conn = DriverManager.getConnection(URL,USER,PASS);
URL:jdbc:mysql://ip(127.0.0.1):端口(3306)/数据库名?serverTimezone=Asia/Shanghai
USER:用户名(root)
PASS:密码
在getConnection方法中url参数是一个字符串,一般格式:
jdbc:subprotocol:subname
jdbc: 表示使用JDBC协议
subprotocol:指定所使用的数据库类型的子协议(例如,mysql,sqlserver,oracle等)。
subname:包含连接数据库所需的其他信息,如主机名、端口号和数据库名称等。
在URL中,还可以添加其他参数,例如用户名、密码、字符集等,通常使用?符号引入查询字符串。例如:
String url="jdbc:mysql://localhost:3306/mydatabase?useSSL=false&serverTimezone=UTC";
以注册和建立连接的示例代码:
package com.jdbcpro;import com.mysql.cj.jdbc.Driver;import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;public class Demo1 {public static void main(String[] args) throws ClassNotFoundException, SQLException {//2.注册驱动//Class.forName("com.mysql.cj.jdbc.Driver");//反射方式加载驱动类DriverManager.registerDriver(new Driver());//3.建立与数据库的连接String url = "jdbc:mysql://127.0.0.1:3306/schooldb?serverTimezone=Asia/Shanghai";String user = "root";String password = "root";//写自己数据库的密码Connection connection = DriverManager.getConnection(url,user,password); //com.mysql.cj.jdbc.ConnectionImpl@25359ed8System.out.println(connection);
3.获得Satement执行sql语句
Statement st = connection.createStatement();
Satement中的方法:
Int executeUpdate(String sql) 用于执行ddl语句和dml(增,删,改)语句 返回
操作的行数
用于执行ddl语句返回0
用于执行dml语句返回操作的行数
ResultSet executeQuery(String sql); 用于执行查询语句返回一个ResultSet 集合
获得PrepareStatement执行sql语句
在sql语句中参数位置使用占位符,使用setXX方法向sql中设置参数
PrepareStatement ps = connection.prepareStatement(sql);
PrepareStatement中的方法:
Int executeUpdate() 用于执行ddl语句和dml(增,删,改)语句 返回操作的行数
用于执行ddl语句返回0
用于执行dml语句返回操作的行数
ResultSet executeQuery(); 用于执行查询语句 返回一个ResultSet 集合
4.关闭与数据库的链接通道
每次操作完成后关闭所有与数据库交互的通道
st.close();
rs.close();
conn.close();
ps.close();
示例(用statement在student表中执行sql语句完成进行DML操作):
package com.jdbcpro;import com.mysql.cj.jdbc.Driver;import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;public class Demo2 {public static void main(String[] args) throws SQLException {Demo2.insert("徐卉","女","2003-3-4","1533555",1.65);Demo2.update(4,"林欣","女","2003-3-4","15333333",1.65);Demo2.delete(7);}public static void insert(String name,String gender,String birthday,String phone,double height) throws SQLException {//注册JDBC驱动程序DriverManager.registerDriver(new Driver());//建立与数据库的连接String url = "jdbc:mysql://127.0.0.1:3306/schooldb?serverTimezone=Asia/Shanghai";String user = "root";String password = "root";Connection connection = DriverManager.getConnection(url,user,password);System.out.println(connection);//用statement执行sql语句Statement statement = connection.createStatement();statement.executeUpdate("insert into student(name,gender,birthday,phone,height)values ('"+name+"','"+gender+"','"+birthday+"','"+phone+"','"+height+"')");//关闭与数据库的连接statement.close();connection.close();};public static void update(int number,String name,String gender,String birthday,String phone,double height) throws SQLException {//注册JDBC驱动程序DriverManager.registerDriver(new Driver());//建立与数据库的连接String url = "jdbc:mysql://127.0.0.1:3306/schooldb?serverTimezone=Asia/Shanghai";String user = "root";String password = "root";Connection connection = DriverManager.getConnection(url,user,password);System.out.println(connection);//用statement执行sql语句Statement statement = connection.createStatement();statement.executeUpdate("update student set name='"+name+"',gender='"+gender+"',birthday='"+birthday+"',phone='"+phone+"',height="+height+" where number="+number);//关闭与数据库的连接statement.close();connection.close();};public static void delete(int number) throws SQLException {//注册JDBC驱动程序DriverManager.registerDriver(new Driver());//建立与数据库的连接String url = "jdbc:mysql://127.0.0.1:3306/schooldb?serverTimezone=Asia/Shanghai";String user = "root";String password = "root";Connection connection = DriverManager.getConnection(url,user,password);System.out.println(connection);//用statement执行sql语句Statement statement = connection.createStatement();statement.executeUpdate("delete from student where number = "+number);//关闭与数据库的连接statement.close();connection.close();};
}
三、PreparedStatement和Statement
用prepared statement执行sql语句:
package com.jdbcpro;import com.mysql.cj.jdbc.Driver;import java.sql.*;public class Demo3 {public static void main(String[] args) throws ClassNotFoundException, SQLException {//2.注册驱动//Class.forName("com.mysql.cj.jdbc.Driver");//反射方式加载驱动类DriverManager.registerDriver(new Driver());//3.建立与数据库的连接String url = "jdbc:mysql://127.0.0.1:3306/schooldb?serverTimezone=Asia/Shanghai";String user = "root";String password = "root";//写自己数据库的密码Connection connection = DriverManager.getConnection(url,user,password); //com.mysql.cj.jdbc.ConnectionImpl@25359ed8//4.发送sqlPreparedStatement ps = connection.prepareStatement("insert into major(name)value(?)"); //?占位符 表示要插入一个参数ps.setObject(1,"智能"); //1箱第一个占位符的位置插入数据ps.executeUpdate();//5.关闭与数据库的连接connection.close();}
}
然而这不是最主要的区别
而是基于以下的原因:
1、代码的可读性和可维护性
虽然用PreparedStatement来代替Statement会使代码多出几行,但这样的代码无论从可读性还是可维护性上来说.都比直接用Statement的代码高很多档次:
//statement
stmt.executeUpdate("insert into tb_name (col1,col2,col2,col4) values
('"+var1+"' , '"+var2+"' , "+var3+" , '"+var4+"')");
//prepared statement
perstmt = con.prepareStatement("insert into tb_name (col1,col2,col2,col4)values (?,?,?,?)");
perstmt.setString(1,var1);//向sql中传参 向占位符传参时,进行验证防止sql注入攻击更安全
perstmt.setString(2,var2);
perstmt.setString(3,var3);
perstmt.setString(4,var4);
perstmt.executeUpdate(); //执行sql
2、最重要的一点是极大地提高了安全性
防止sql注入
String sql= “ delete from user where id = ”+num;
如果我们把[or 1=1]作为id传入进来?
delete from tb_name where id = 1 or 1 = 1;
因为‘1’ = ‘1’肯定成立
而如果你使用预编译语句.你传入的任何内容就不会和原来的语句发生任何匹配的关系.
预编译模式中每个占位符处,只能插入一个值,而会过滤其他语句.
下面是用prepared statement对student表执行sql语句示例:
package com.jdbcpro;import com.mysql.cj.jdbc.Driver;import java.sql.*;public class Demo4 {public static void main(String[] args) throws SQLException {//Demo4.insert("徐卉","女","2003-3-4","1533555",1.65);// Demo4.update(4,"林欣11","女","2003-3-4","153333322",1.65);Demo4.delete("0 or 1=1");}public static void insert(String name,String gender,String birthday,String phone,double height) throws SQLException {//注册驱动DriverManager.registerDriver(new Driver());String url = "jdbc:mysql://127.0.0.1:3306/schooldb?serverTimezone=Asia/Shanghai";String user = "root";String password = "root";//写自己数据库的密码//建立与数据库的连接Connection connection = DriverManager.getConnection(url,user,password);//发送sqlPreparedStatement ps = connection.prepareStatement("insert into student(name,gender,birthday,phone,height)value(?,?,?,?,?)");ps.setObject(1,name);ps.setObject(2,gender);ps.setObject(3,birthday);ps.setObject(4,phone);ps.setObject(5,height);ps.executeUpdate();//关闭与数据库的连接ps.close();connection.close();}public static void update(int number,String name,String gender,String birthday,String phone,double height) throws SQLException {//注册驱动DriverManager.registerDriver(new Driver());String url = "jdbc:mysql://127.0.0.1:3306/schooldb?serverTimezone=Asia/Shanghai";String user = "root";String password = "root";//写自己数据库的密码//建立与数据库的连接Connection connection = DriverManager.getConnection(url,user,password);//发送sqlPreparedStatement ps = connection.prepareStatement("update student set name=?,gender=?,birthday=?,phone=?height=? where number = ?");ps.setObject(1,name);ps.setObject(2,gender);ps.setObject(3,birthday);ps.setObject(4,phone);ps.setObject(5,height);ps.setObject(6,number);ps.executeUpdate();//关闭与数据库的连接ps.close();connection.close();}public static void delete(String number) throws SQLException {//注册驱动DriverManager.registerDriver(new Driver());String url = "jdbc:mysql://127.0.0.1:3306/schooldb?serverTimezone=Asia/Shanghai";String user = "root";String password = "root";//写自己数据库的密码//建立与数据库的连接Connection connection = DriverManager.getConnection(url,user,password);//发送sqlPreparedStatement ps = connection.prepareStatement("delete from student where number = ?");//封装sqlps.setObject(1,number);//向sql中传参 向占位符传参时,进行验证,防止sql注入攻击 更安全ps.executeUpdate();//执行sql//关闭与数据库的连接ps.close();connection.close();}
}
四、结果集处理
PreparedStatement和Statement中的executeQuery()方法中会返回一个ResultSet对象,查询结果就封装在此对象中.
使用ResultSet中的next()方法获得下一行数据
使用getXXX(String name)方法获得值
示例:完成了数据库中根据学号查找单个学生信息的功能,并把信息封装在Student对象中。
//学生类:
package com.jdbcpro;import java.util.Date;public class Student {private int number;private String name;private String gender;private Date birthday;private double height;private String phone;private Date regTime;public int getNumber() {return number;}public void setNumber(int number) {this.number = number;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getGender() {return gender;}public void setGender(String gender) {this.gender = gender;}public Date getBirthday() {return birthday;}public void setBirthday(Date birthday) {this.birthday = birthday;}public String getPhone() {return phone;}public void setPhone(String phone) {this.phone = phone;}public double getHeight() {return height;}public void setHeight(double height) {this.height = height;}public Date getRegTime() {return regTime;}public void setRegTime(Date regTime) {this.regTime = regTime;}@Overridepublic String toString() {return "Student{" +"number=" + number +", name='" + name + '\'' +", gender='" + gender + '\'' +", birthday=" + birthday +", phone='" + phone + '\'' +", height=" + height +", regTime=" + regTime +'}';}
}//实现了查询学生信息:
package com.jdbcpro;import com.mysql.cj.jdbc.Driver;import java.sql.*;public class Demo5 {public static void main(String[] args) throws SQLException {Student student = findStudentByNumber(1);System.out.println(student);}public static Student findStudentByNumber(int number) throws SQLException {//注册JDBC驱动程序DriverManager.registerDriver(new Driver());;//建立连接String url = "jdbc:mysql://127.0.0.1:3306/schooldb?serverTimezone=Asia/Shanghai";String user = "root";String password = "root";Connection connection = DriverManager.getConnection(url, user, password);//用PreparedStatement执行sql语句PreparedStatement ps = connection.prepareStatement("select number,name,gender,birthday,height,phone,reg_time from student where number = ?");ps.setObject(1, number);//执行查询后,将mysql数据封装到ResultSet对象中ResultSet rs = ps.executeQuery();//com.mysql.cj.jdbc.result.ResultSetImpl@4f9a3314//将ResultSet中的数据重新包装到我们自己的对象中,使用起来更方便Student student = null;if(rs.next()) {//结果集中有没有数据,如果有返回true,没有返回falsestudent = new Student();student.setNumber(rs.getInt("number"));student.setName(rs.getString("name"));student.setGender(rs.getString("gender"));student.setBirthday(rs.getDate("birthday"));student.setHeight(rs.getDouble("height"));student.setPhone(rs.getString("phone"));student.setRegTime(rs.getTimestamp("reg_time"));}rs.close();ps.close();connection.close();return student;}
}
结果:
查询多个学生的示例:
package com.jdbcpro;import com.mysql.cj.jdbc.Driver;import java.sql.*;
import java.util.ArrayList;public class Demo5 {public static void main(String[] args) throws SQLException {ArrayList<Student>students = findStudents();System.out.println(students);}public static ArrayList<Student> findStudents() throws SQLException {//注册JDBC驱动程序DriverManager.registerDriver(new Driver());;//建立连接String url = "jdbc:mysql://127.0.0.1:3306/schooldb?serverTimezone=Asia/Shanghai";String user = "root";String password = "root";Connection connection = DriverManager.getConnection(url, user, password);//用PreparedStatement执行sql语句PreparedStatement ps = connection.prepareStatement("select number,name,gender,birthday,height,phone,reg_time from student ");//执行查询后,将mysql数据封装到ResultSet对象中ResultSet rs = ps.executeQuery();//com.mysql.cj.jdbc.result.ResultSetImpl@4f9a3314//将ResultSet中的数据重新包装到我们自己的对象中,使用起来更方便//创建一个集合对象,用来封装多个学生对象ArrayList<Student> students = new ArrayList<>();while(rs.next()) {//结果集中有没有数据,如果有返回true,没有返回falseStudent student = new Student();student.setNumber(rs.getInt("number"));student.setName(rs.getString("name"));student.setGender(rs.getString("gender"));student.setBirthday(rs.getDate("birthday"));student.setHeight(rs.getDouble("height"));student.setPhone(rs.getString("phone"));student.setRegTime(rs.getTimestamp("reg_time"));students.add(student);//把当前学生对象添加到集合中}rs.close();ps.close();connection.close();return students;}
}
结果: