数据库:mysql基础(十)--JDBC中API详解,和增删改代码实现,登录案例

本文详细介绍了JDBC中的DriverManager、Connection、Statement接口及其常用方法,包括创建连接、发送SQL命令。同时,通过示例展示了如何实现数据的增删改操作,并提出用户登录场景中可能遇到的SQL注入问题,强调了PreparedStatement接口在防止SQL注入方面的优势。
  • 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,作为我们的参照
      uidusernamepassword
      1zs123
      2ls123

      看一下下面的实现代码:

    •  

      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的增删改查还有一些问题,代码冗余的问题,那关于其优化我们后面再说

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值