JDBC《笔记》

JDBC学习

Connection conn = null;
PreparedStatement ps = null;
try{
    //1.注册驱动
    Class.forName("con.mysql.jdbc.Driver");
    
    //2.获取连接
    /*
    jdbc:mysql://127.0.0.1:3306/bjpowernode
    jdbc:mysql://  协议
    127.0.0.1    IP地址
    3306   mysql数据库端口号
    bjpowernode  具体的数据库
    
    说明:localhost和127.0.0.1都是本机IP地址。
    
    什么是通信协议,有什么用?
    	通信协议是通信之前就提前定好的数据传送格式。
    	数据包具体怎么传数据,格式提前定好的。
    */
    String url = "jdbc:mysql://127.0.0.1:3306/bjpowernode";
    String user = "root";
    String passoword = "123456";
    conn = DriverManager.getConnection(url,user,password);
    
    
    //3.获取数据库操作对象(Statement专门执行sql语句的)
    //4.执行sql语句
    String sql = "insert into dept(deptno,dname,loc) values(?,?,?)";
    ps = conn.prepareStatement();
    ps.setString(1,xxx);
	ps.setString(2,xxx);
    ps.setString(3,xxx);
   
    
    
    //专门执行DML语句的(insert delete update)
    //返回值是“影响数据库中的记录条数”
    int count = ps.executeUpdate();
    
    //5.处理查询结果集,如果是select语句
}catch(SQLException e){
    e.printStackTrace();
}finally{
    //6.释放资源
    //为了保证资源一定释放,在finally语句块中关闭资源
    //并且要遵循从小到大依次关闭
    //分别对其try...catch
    try{
        if(ps != null){
        ps.close();
    }}catch(SQLException e){
        e.printStackTrace();
    }
     try{
        if(conn != null){
        conn.close();
    }}catch(SQLException e){
         e.printStackTrace();
    }
}

JDBC中的sql语句不需要提供分号
Class.forName("com.mysql.jdbc.Driver");
conn = DriverManager.getConnection(url,user,password);
stmt = conn.createStatement();
stmt.executeUpdate(sql);

//DriverManager 驱动管理器
//Statement 报告
//executeUpdate 执行更新
//注册驱动的另一种方式(这种方式常用)
//以下方法不需要接收返回值,因为我们指向用它的类加载动作
Class.forName("com.mysql.jdbc.Driver");
/*
	处理查询结果集
*/
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;

try{
	Class.forName("com.mysql.jdbc.Driver");
    String url = "jdbc:mysql://localhost:3306/bjpowernode";
    String user = "root";
    String password = "123456";
    conn = DriverManager.getConnection(url,user,password);
    stmt = conn.createStatement();
    String sql = "select empno,ename,sal from emp";
    //int executeUpdate (insert/delete/update)
    //ResultSet executeQuery(select)
    rs = stmt.executeQuery(sql);//专门执行DQL语句的方法
    
    //5.处理查询结果集,如果是select语句
    while(rs.next()){
        //查询结果最后的列名(要注意重命名的情况)
        int empno = rs.getInt("empno");
        String ename = rs.getString("ename");
        double sal = rs.getDouble("sal");
        System.out.println(empno + "," + ename +"," + sal);
    }
}catch(SQLException e){
		e.printStackTrace();
}finally{
    try{
        if(rs != null){
        rs.close();
    }}catch(SQLException e){
        e.printStackTrace();
    }
    try{
        if(stmt != null){
        stmt.close();
    }}catch(SQLException e){
        e.printStackTrace();
    }
    try{
        if(conn != null){
        conn.close();
    }}catch(SQLException e){
         e.printStackTrace();
    }
}

处理查询结果集,图解

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xuln97Tx-1648281348661)(C:\Users\Lenovo\AppData\Roaming\Typora\typora-user-images\image-20220228100814055.png)]

SQL注入现象(黑客常用)

  • 原因:用户输入的信息中含有sql语句的关键字,并且这些关键字参与sql语句的编译过程,导致sql语句的原意被扭曲,进而达到sql注入。

    String sql = "select * from t_users where user = '"+loginName+"' and password = '"+loginPwd+"'";
    //以上正好完成了sql语句的拼接,一下的代码含义是,发送sql语句给DBMS,DBMS进行sql编译。
    //正好将用户提供的“非法信息”编译进去,导致了原sql语句的含义被扭曲了
    rs = stm.executeQuery(sql);
    
  • 如何解决:

    /*只要用户提供的信息不参与SQL语句的编译过程,问题就解决了。
    要想用户信息不参与SQL语句的编译,那么必须使用java.sql.PreparedStatement
    PreparedStatement接口继承了java.sql.Statement,属于预编译的数据库操作对象。
    其原理是:预先对SQL语句的框架进行编译,然后再给SQL语句传值。
    只能用于条件,表名等不能使用,例如从emp表中查ename,sal>800的名字,只有800可以用?替代
    */
    PreparedStatement ps = null;
    //在3中获取预编译的数据库操作对象
    //SQL语句的框子。其中一个?表示一个占位符,一个?将来接收一个“值”,注意:占位符不能使用单引号括起来。
    String sql = "select * from t_users where user = ? and password = ?";
    //程序执行到此处,会发送sql语句框子给DBMS,然后DBMS进行sql语句的预先编译。
    ps = conn.prepareStatement(sql);
    //给占位符?传值(第一个?下标是1,以此类推,JDBC中所有下标从1开始)
    ps.setString(1,loginName);
    ps.setString(2,loginPwd);
    //4.执行sql语句
    rs = ps.executeQuery();
    
    
    对比Statement和PreparedStatement?
    • Statement存在sql注入问题,PreparedStatement解决了sql注入问题
    • Statement是编译一次执行一次。PreparedStatement是编译一次,可执行N次。PreparedStatement效率较高一些
    • PreparedStatement会在编译阶段做类型的安全检查
    • 什么情况下必须使用Statement?
      • 业务方面要求必须支持SQL注入的时候,凡是业务方面要求是需要进行sql语句拼接的,必须使用Statement
      • 例如:用户在控制台输入desc就是降序,asc就是升序的时候,就需要进行sql语句的拼接,然后就要用Statement

事务

/*JDBC事务机制:
		1.JDBC中的事务是自动提交的,只要执行任意一条DML语句,则自动提交一次。
		
在java中使用代码
*/
conn.setAutoCommit(false);
//在try最后一行手动提交数据
conn.commit();
//在catch中,如果conn不=null,则要回滚
if(conn != null){
    conn.rollback();
}

JDBC工具类的封装

模糊查询

String sql = "select ename from emp where ename like ?";
ps.conn.prepareStatement(sql);
ps.setString(1,"_A%");
ps.executeQuery();

行级锁

//悲观锁(行级锁,for update),在这个事务没有结束之前,emp表中的ename,job,sal三个数据不能进行改变
select ename,job,sal from emp where job = 'MANAGER' for update;

悲观锁:事务必须排队执行,数据锁住了,不允许并发。
乐观锁:支持并发,事务也不需要排队,只不过需要一个版本号。
事务1--》读取到版本号1.1
事务2--》读取到版本号1.1
其中事务1先修改了,修改之后看了版本号是1.1,于是提交修改的数据,将版本号修改为1.2
其中事务2后修改的,修改之后准备提交的时候,发现版本号是1.2,和它最初读的版本号不一致。回滚。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值