zoukankan      html  css  js  c++  java
  • JDBC

    JDBC

    jdbc本质就是一套接口,程序员不需要关心数据库的具体品牌,只需要面向jdbc接口写代码。

    驱动

    所有的数据库驱动都是以jar包的形式存在,jar包中有许多.class文件(驱动就是实现jdbc接口的实现类)。

    JDBC编程

    • 注册驱动(告诉java程序,即将连接的是那个品牌的数据库)
    • 获取连接(表示jvm的进程和数据库进程之间的通道打开了。使用完要关闭)
    • 获取数据库操作对象(创建执行数据库的对象)
    • 执行sql语句(DQL,DML。。。)
    • 处理查询结果集
    • 释放资源(使用完资源之后一定要关闭,java和数据库属于进程间的通信,开启之后一定要关闭)
    import java.sql.Driver;
    import java.sql.DriverManager;
    import java.sql.SQLException;
    import java.sql.Connection;
    import java.sql.Statement;
    
    public class JDBCTest{
        
        public static void main(String [] args){
            Connection conn=null;
            Statement stmt=null;
            try{
                //注册驱动
                Driver driver=new com.mysql.jdbc.Driver();//父类型引用指向子类对象
                DriverManager.registerDriver(driver);
                //注册驱动的第二中方法;因为参数是一个字符串,字符串可以写到.properties文件中。不需要接受返回值是因为我们只想用它的类加载动作。
                //Class.forName("com.mysql.jdbc.Driver");
                //获取连接
                String url="jdbc:mysql://192.168.151.80:3306/userDb";
                String user="root";
                String password="root";
                conn=DriverManager.getConnection(url,user,password);
                System.out.println("数据连接对象"+conn);
                //获取数据库操作对象(Statement专门执行SQl语句的)
                stmt=conn.createStatement();
                //执行sql
                String sql="";
                
                
            }
            catch(SQLException e){
                e.printStackTrace();
            }finally{
                //释放资源
                try{
                    if(stmt!=null){
                        stmt.close();
                    }
                }catch(SQLException e){
                        e.printStackTrace();
                    }
                 try{
                    if(conn!=null){
                        conn.close();
                    }
                }catch(SQLException e){
                        e.printStackTrace();
                    }
            }
        }
    }
    
    
    
    //实际开发中会将连接数据库的信息写在配置文件中,不会直接写在java程序代码中
    //使用资源绑定器绑定属性配置文件
    ResourceBundle bundle=ResourceBundle.getBundle("jdbc")
    String driver=bundle.getString("driver");
    String url=bundle.getString("url");
    String user=bundle.getString("user");
    String password=bundle.getString("password");
    //配置文件jdbc.properties
    driver=com.mysql.jdbc.Driver
    url=jdbc:mysql://192.168.151.80:3306/userDb
    user=root
    password=root
    

    SQL注入

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

    解决SQL注入:只要用户提供的信息不参与sql语句的执行就可以了,即使用户提供的信息包括sql关键词但没有参与到编译就不起作用了。

    要想用户提供的信息不参与编译就要使用到java.sql.PreparedStatement;

    PreparedStatement接口继承了Statement;PreparedStatement属于预编译数据库操作对象,在用户提供信息之前将sql语句进行了预编译。即使用户提供的信息含有sql关键字但不参与sql编译所以不起作用。

    PreparedStatement ps=null;
    //在获取数据库操作对象是使用PreparedStantement
    //sql语句,问号代表一个占位符用于接收用户输入的值
    String sql="select * from 表名 where loginName=? and loginPwd=?";
    //程序执行到此处会将sql语句进行预编译,使用的是PrepareStatement方法
    ps.conn.PrepareStatement(sql);
    //给占位符赋值,数字1代表第一个问号;因为jdbc下标是从1开始的。
    ps.setString(1,loginName);
    ps.setString(2,loginPwd);
    

    Statement和PreparStatement对比

    • Statement存在sql注入问题,PreparStatement不存在sql注入问题;
    • Statement是编译一次执行一次,PreparStatement是编译一次可以执行N次,效率较高;
    • PreparStatement在编译阶段会进行类型的安全检查;

    并不是在以后不使用Statement而是在需要进行sql注入时使用Statement

    jdbc事务

    jdbc的事务是自动提交的,只要执行一条sql语句就会自动提交一次;

    解决jdbc事务自动提交:

    //在获取连接后关闭事务自动提交,开启事务
    conn.setAutoCommit(false);
    //执行完sql语句后进行提交,事务的提交
    conn.commit;
    //如果有错进行事务回滚
    conn.rollback();
    

    封装jdbc工具类

    public class DButil{
        
        private DButil(){}
        //静态代码块在类加载时执行,并且只执行一次
        static{
            try{
                //注册驱动
                Class.forName("com.mysql.jdbc.Driver");
            }catch(Exception e){
                e.printStackTrace();
            }
        }
        //获取数据库连接
        public static Connection getConnection() throws SQLexception{
            return DriverManager.getConnection("jdbc:mysqk://localhost:3306/userDb","root","root");
            
        }
        //释放资源
        public static void close(Connection conn,Statement ps,ResultSet rs){
            //结果集
            if(rs!=null){
                try{
                    rs.close();
                }catch(SQLexception e){
                    e.printStackTrace();
                }  
            }
            //数据库操作对象
            if(ps!=null){
                try{
                    ps.close();
                }catch(SQLexception e){
                    e.printStackTrace();
                }  
            }
            //数据库连接对象
            if(conn!=null){
                try{
                    conn.close();
                }catch(SQLexception e){
                    e.printStackTrace();
                }  
            }
            
        }
    }
    

    悲观锁/行级锁:在sql语句后加上for update;将查询的语句进行加锁其它无法进行更改

    乐观锁:指线程1访问后会在数据一个版本号,线程2访问后并进行更改会将版本号更改,当线程1再次访问时数据以被更改太它会回滚到以前的版本;

  • 相关阅读:
    leetcode821
    leetcode872
    leetcode700
    leetcode806
    2019-9-2-win10-uwp-右击浮出窗在点击位置
    2019-9-2-win10-uwp-打包第三方字体到应用
    2019-10-18-dotnet-文件读写务必注意事项
    2018-8-10-win10-uwp-如何创建修改保存位图
    2018-8-9-win10-uwp-装机必备应用-含源代码
    2019-11-1-asp-dotnet-core-简单开发P2P中央服务器
  • 原文地址:https://www.cnblogs.com/wanglong1/p/14227672.html
Copyright © 2011-2022 走看看