-
JDBC常见API详解
-
DriverManager类
- 驱动管理器
- 作用
- 注册和管理驱动程序
-
//1.注册驱动 DriverManager.registerDriver(new Driver()); /* * 下面的加载类的时候也会加载驱动,这个其实是Driver源码中静态代码块执行的. * 推荐使用下面这个,因为上面的注册驱动代码实际上是注册了两次,使用下面的第二种方法就需要知道驱动的全限定名称 */ Class.forName("com.mysql.jdbc.Driver"); -
获取连接对象
-
Connection con = DriverManager.getConnection(String url,String user,String password);
-
Connection(接口)
-
代表与数据库服务的连接
-
作用
-
作为数据传输的通道
-
创建Statement对象
-
-
常见方法--上面我们已经通过DriverManager拿到了Connection的对象,变量名为con
-
设置事务相关
-
//设置事务自动提交 con.setAutoCommit(autoCommit); //提交事务 con.commit(); //回滚 con.rollback();
-
-
创建Statement的实现类对象
-
//创建Statement对象 con.createStatement(); con.prepareStatement(String sql);//返回值是 PreparedStatement con.prepareCall(String sql);//返回值是 CallableStatement 存储程序相关
-
-
得到连接的元数据..元数据:解释数据的数据
-
DatabaseMetaData md = con.getMetaData(); String dpn = md.getDatabaseProductName(); //数据库产品名 String driverName = md.getDriverName(); //驱动名 String url = md.getURL(); //URL String userName = md.getUserName(); //用户名我们可以看到,所有和连接相关的信息,我们都可以从连接的元数据中获取
-
-
-
Statement(接口)
-
作用
-
发送sql指令
-
-
子接口
-
PreparedStatment
-
CallabldStatement
-
-
常见方法
-
execute:发送任意sql命令,返回值boolean类型
-
executeQuery:发送查询sql命令,返回值是ResultSet
-
executeUpdate:发送增删改和ddl语句,返回值影响的行数int类型
-
executeBatch:发送批处理命令,返回值int[]
-
这里我们介绍的都是Statement这个接口自己的命令,它子接口的方法后面介绍
-
-
-
ResultSet(接口)
-
结果集,底层封装指向结果集的游标
-
常见方法
-
next():用于移动游标
-
getX():获取字段值
-
***注意了: getMetaData()--返回一个ResultSetMetaData,获得和结果集游标对应记录的相关元数据
-
//得到结果集元数据 ResultSetMetaData rsmd = rs.getMetaData(); //得到结果集的列数 int columnNum = rsmd.getColumnCount(); //获取列名 String columnName = rsmd.getColumnName(int column); //参数传入的是第几列
-
-
-
-
-
增删改的代码实现
-
前面我入门案例是演示的查询的代码实现,下面我们介绍一下增删改的代码实现
-
向dept表中添加一条数据
-
首先我们先创建一个dept的类来封装向dept表中添加的每一条记录的各个字段的信息,这个类作为参数传入到我们定义的insert方法中.
-
package jdbc_01r; public class Dept { private int deptno; private String dname; private String loc; public int getDeptno() { return deptno; } public void setDeptno(int deptno) { this.deptno = deptno; } public String getDname() { return dname; } public void setDname(String dname) { this.dname = dname; } public String getLoc() { return loc; } public void setLoc(String loc) { this.loc = loc; } @Override public String toString() { return "Dept [deptno=" + deptno + ", dname=" + dname + ", loc=" + loc + "]"; } public Dept(int deptno, String dname, String loc) { super(); this.deptno = deptno; this.dname = dname; this.loc = loc; } public Dept() { super(); // TODO Auto-generated constructor stub }接下来在测试类中,我们创建一个插入的insert方法,来实现数据的插入添加
-
package jdbc_01; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import com.mysql.jdbc.Driver; public class Version01_zengshangai { /* * 入门案例2:连接数据库,并向dept表中插入一条记录 */ public static void main(String[] args) { insert(new Dept(5, "Ali", "HangZhou")); } //添加记录的方法 public static void insert(Dept dept){ Connection con = null; Statement st = null; try { //注册驱动 Class.forName("com.mysql.jdbc.Driver"); //获取连接 con = DriverManager.getConnection( "jdbc:mysql:///db1808?useSSL=true", "root", "root"); //发送sql命令 String sql = "insert into dept(deptno,dname,loc) " + "values("+dept.getDeptno()+",'"+dept.getDname()+"','"+ dept.getLoc()+"')"; //创建Statement对象发送sql st = con.createStatement(); int rows = st.executeUpdate(sql); System.out.println(rows); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); }finally{ //释放资源 try { if(con !=null ){ con.close(); } if(st !=null ){ st.close(); } } catch (SQLException e) { e.printStackTrace(); } } } }通过上面的介绍,我想大家对查询,和添加记录的大致方法都掌握了,那删除和修改就是轻而易举的了.只要我们将插入方法中的sql语句修改了就可以了.因为增删改方法的sql语言的返回值都是int,即影响数据的记录数目.三者都是DML语言,所以删除和修改希望大家自行完成.
-
-
-
用户登录的案例
- 我们来简单的模拟一下登录某个应用的场景.我们可以理解为将用户输入的用户名和密码作为sql语句的查询条件,看看是否能通过DQl语句从数据库的用户表中查询到该信息.查询到了即代表登录成功.
- 这里我们有张存储用户信息的表格userinfo,作为我们的参照
uid username password 1 zs 123 2 ls 123 看一下下面的实现代码:
-
package test; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; public class Test { public static void main(String[] args) { login2("zs", "123"); } //用户的登录 public static void login(String username,String password){ Connection conn = null; Statement stmt = null; ResultSet rs = null; try { Class.forName("com.mysql.jdbc.Driver"); conn = DriverManager.getConnection( "jdbc:mysql:///db1808?useSSL=true", "root", "root"); stmt = conn.createStatement(); String sql = "select * from userinfo where username = '"+username +"' and password = '"+password+"'"; rs = stmt.executeQuery(sql); if(rs.next()){ System.out.println("登录成功"); }else{ System.out.println("登录失败"); } } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); }finally{ try { if(rs!=null){ rs.close(); } if(stmt != null){ stmt.close(); } if(conn != null){ conn.close(); } } catch (SQLException e) { e.printStackTrace(); } } } }这里我们将用户名和密码作为参数传入到方法中,来进行判断查询.大家可以思考一下,上面的代码会出现什么问题呢?
-
假如我们在调用上面的login()方法的时,向里面传入的是这样一行代码
login("' or 1=1 or username = '","");我们发现,我们也是登录成功了.这是为什么呢?
-
这是因为,我们最终是要执行的sql语句来从数据库的表中查找数据,上面的参数传到定义的sql语句中是
select * from userinfo where username = '' or 1=1 or username = '' and password = '123';我们发现,这段语句利用了逻辑运算符的特性,绕过了用户信息的判断(因为1=1返回true),所以也可以登录数据库,像不像黑客的技术? 这就是所谓的sql注入攻击.(利用检验的不严格,不充分绕过了验证--这里的原因就是sql采用了拼接),那如何解决这个问题呢?就用下面的PreparedStatement这个接口来解决
- PreparedStatement接口
-
Statement 的子接口
-
采用占位符以及赋值方式解决sql注入问题,类似前面出现的printf方法
-
采用预编译方式,效率高于Statement
-
下面我们来看一下实现的代码
package test; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.DriverManager; import java.sql.SQLException; import java.sql.Statement; public class Test { public static void main(String[] args) { login2("zs", "123"); } //用户登录2 public static void login2(String username,String password){ Connection conn = null; PreparedStatement ps = null; ResultSet rs = null; try { Class.forName("com.mysql.jdbc.Driver"); conn = DriverManager.getConnection("jdbc:mysql:///db1808?useSSL=true", "root", "root"); //用?占位 String sql = "select * from userinfo where username = ? and password = ?"; //预编译(语法语义等检查) ps = conn.prepareStatement(sql); //赋值 ps.setString(1, username);//给第一个占位符?的位置赋值 ps.setString(2, password); rs = ps.executeQuery(); if(rs.next()){ System.out.println("登录成功"); }else{ System.out.println("登录失败"); } } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); }finally{ try { if(rs!=null){ rs.close(); } if(ps != null){ ps.close(); } if(conn != null){ conn.close(); } } catch (SQLException e) { e.printStackTrace(); } } } }这样如果我们再传入 ("' or 1=1 or username = '","")这样的参数,就会返回登录失败了.
-
-
上面就是关于JDBC的一些基础讲解和案例分析.但有的朋友肯定会发现,以上我们讲的JDBC的增删改查还有一些问题,代码冗余的问题,那关于其优化我们后面再说
数据库:mysql基础(十)--JDBC中API详解,和增删改代码实现,登录案例
最新推荐文章于 2025-08-04 23:47:20 发布
本文详细介绍了JDBC中的DriverManager、Connection、Statement接口及其常用方法,包括创建连接、发送SQL命令。同时,通过示例展示了如何实现数据的增删改操作,并提出用户登录场景中可能遇到的SQL注入问题,强调了PreparedStatement接口在防止SQL注入方面的优势。
467

被折叠的 条评论
为什么被折叠?



