zoukankan      html  css  js  c++  java
  • jdbc基础

    TOC

    jdbc基础

    JDBC概述

      JDBC(Java Data Base Connectivity,java数据库连接)是一种用于执行SQL语句的Java API,可以为多种关系数据库提供统一访问(不同数据库是有差异的,用jdbc都可以访问,相当于屏蔽了不同数据库之间的差异),它由一组用Java语言编写的类和接口组成。是Java访问数据库的标准规范
      JDBC提供了一种基准,据此可以构建更高级的工具和接口,使数据库开发人员能够编写数据库应用程序。(JDBC使用者不能自己写实现类,只能使用接口)
      JDBC需要连接驱动(mysql-connector-java-5.1.39-bin.jar),驱动是两个设备要进行通信(的必要软件),满足一定通信数据格式,数据格式由设备提供商规定,设备提供商为设备提供驱动软件,通过软件可以与该设备进行通信。
    驱动程序:是一套实现类,满足sun公司给的接口,满足一定通信数据格式;
    开发的时候,只需要关注接口就行,使用的时候,会自动调用的
    JDBC定义:是一套API,是sun定义类或是接口;

    JDBC原理

    Java提供访问数据库规范称为JDBC,而生产厂商提供规范的实现类称为驱动。
    驱动是类库,实现了sun规定的接口,
    驱动程序类库,实现接口,重写方法

    JDBC是接口,驱动是接口的实现,没有驱动将无法完成数据库连接,从而不能操作数据库!每个数据库厂商都需要提供自己的驱动,用来连接自己公司的数据库,也就是说驱动一般都由数据库生成厂商提供。

    JDBC开发步骤

    1. 注册驱动.
      告知JVM使用的是哪一个数据库的驱动
    2. 获得连接.
      使用JDBC中的类,完成对MySQL数据库的连接(效率低)
    3. 获得语句执行平台
      通过连接对象获取对SQL语句的执行者对象
    4. 执行sql语句
      使用执行者对象,向数据库执行SQL语句
      获取到数据库的执行后的结果
    5. 处理结果
    6. 释放资源.
      一堆close()
    public class jdbcTest {
        public static void main(String[] args) throws Exception {
            Class.forName("com.mysql.jdbc.Driver"); //加载驱动程序
            String connString = "jdbc:mysql://localhost:3306/db_database17";//"jdbc:mysql://localhost:3306/数据库名?useUnicode=true&characterEncoding=utf8"
            Connection conn = DriverManager.getConnection(connString,"root","123456");// 数据库的连接,有时帐号,密码
            Statement stat = conn.createStatement();// 得到一个Statement(不带参数的简单语),将SQL语句发送到数据库
            stat.executeUpdate("create table if not exists people (id char(10), name char(20), age int, gender bit ) ;");//创建表people(字段id...)
            stat.executeUpdate("insert into people values ('001', 'Tom', 18, 1);");//插入内容
            stat.executeUpdate("insert into people values ('002', 'Marry', 20, 0);");
            stat.executeUpdate("insert into people values ('003', 'Peter', 25, 1);");
            stat.executeUpdate("update people set age=age+1 where id='003';");//更新、修改数据
            String sql = "select * from people;";//查询,在people中查询*
            ResultSet rs = stat.executeQuery(sql);//executeQuery执行查询,结果导入result,
            while (rs.next()) {           //循环遍历,得到每一个记录,字段
                String name = rs.getString("name");
                int age = rs.getInt("age");
                boolean gender = rs.getBoolean(4);
                System.out.printf("name = %s; age = %d,gender =%s
    ", name, age, (gender ? "male" : "female"));
            }
            rs.close();//查询结束
            conn.close();
        }
    }

    bit称为位数据类型,长度为1位,有两种取值:0和1,在输入0以外的其他值时,系统均把它们当1看待。这种数据类型常作为逻辑变量使用,用来表示真、假或是、否等二值选择。程序读取数据库出来之后的表现形式是true或者false,但是保存在数据库中的结构类型是0或者1,1表示true,0表示false。
    gender bit ,insert时是0或1,读取时是:(gender?"true":"false"),1—true,0—false

    获得链接

    • 方法1:
    Connection con = DriverManager.getConnection(“jdbc:mysql://localhost:3306/数据库名”,”root”,”root”);
    //有中文的时候,URL是:"jdbc:mysql://localhost:3306/数据库名?useUnicode=true&characterEncoding=utf8"

    获得语句执行平台

    Statement:有sql注入危险

    获取Statement对象,将SQL语句发送到数据库,返回值是 Statement接口的实现类对象,,在mysql驱动程序

    Statement stat = con.createStatement();
    PreparedStatement:防止sql注入:

    登录案例:
    假设有登录案例SQL语句如下:
    SELECT * FROM 用户表 WHERE NAME = 用户输入的用户名 AND PASSWORD = 用户输的密码;
    此时,当用户输入正确的账号与密码后,查询到了信息则让用户登录。但是当用户输入的账号为XXX 密码为:XXX' OR 'a'='a'时,则真正执行的代码变为:
    SELECT * FROM 用户表 WHERE NAME = 'XXX' AND PASSWORD ='XXX' OR 'a'='a';
    此时,上述查询语句时永远可以查询出结果的。那么用户就直接登录成功了,显然我们不希望看到这样的结果,这便是SQL注入问题。
    为此,我们使用PreparedStatement来解决对应的问题。

    //定义
    PreparedStatement pst =  con.prepareStatement(sql);
    • 设置参数:
    setObject();
    setInt();
    setString();
    等...
    String sql = "SELECT * FROM users WHERE uname =? AND uaddress =?";
    //调用Connection接口的方法prepareStatement,获取PrepareStatement接口的实现类
    //方法中参数,SQL语句中的参数全部采用问号占位符
    PreparedStatement pst =  con.prepareStatement(sql);
    //调用pst对象set方法,设置问号占位符上的参数
    pst.setObject(1, user);
    pst.setString(2, pass);
    //调用方法,执行SQL,获取结果集
    ResultSet rs = pst.executeQuery();
    while(rs.next()){
        System.out.println(rs.getString("uname ")+"  "+rs.getString("uaddress "));
    }
    常用方法
    方法 定义
    int executeUpdate(String sql); 执行执行数据库中的SQL语,insert update delete语句
    返回值int,操作成功数据表多少行的行数
    ResultSet executeQuery(String sql); 执行select语句.
    boolean execute(String sql); 执行select返回true 执行其他的语句返回false

    结果处理:ResultSet

    ResultSet实际上就是一张二维的表格,我们可以调用其boolean next()方法指向某行记录,当第一次调用next()方法时,便指向第一行记录的位置,这时就可以使用ResultSet提供的getXXX(int col)方法(与索引从0开始不同个,列从1开始)来获取指定列的数据:

    • 获取一行数据:rs.next();
    • 获取列数据:
    方法 定义(参数是int:第i列,参数是String:根据字段名获取内容)
    Object getObject(int index) / Object getObject(String name) 获得对象
    String getString(int index) / Object getObject(String name) 获得字符串
    int getInt(int index) / Object getObject(String name) 获得整形
    double getDouble(int index) / Object getDouble(String name) 获得双精度浮点型
    其他...

    释放资源

    与IO流一样,使用后的东西都需要关闭!关闭的顺序是先得到的后关闭,后得到的先关闭。

    rs.close();
    stmt.close();
    con.close();

    JDBC工具类

    “获得数据库连接”操作,将在以后的增删改查所有功能中都存在,可以封装工具类JDBCUtils。提供获取连接对象的方法,从而达到代码的重复利用。
    该工具类提供方法:public static Connection getConnection ()。

    /*
     * JDBC工具类
     */
    public class JDBCUtils {
        //构造方法私有,防止别人创建
        private JDBCUtils(){}
        privatestatic Connection con ;
        static{
            try{
                Class.forName("com.mysql.jdbc.Driver");
                String url = "jdbc:mysql://localhost:3306/mybase";
                String username="root";
                String password="123";
                con = DriverManager.getConnection(url, username, password);
            }catch(Exception ex){
                //若连接失败,直接抛出
                throw new RuntimeException(ex+"数据库连接失败");
            }
        }
        /*
        * 定义静态方法,返回数据库的连接对象
        */
        public static Connection getConnection(){//连接数据库
            return con;
        }
        public static void close(Connection con,Statement stat){//关闭数据库
            closeStatement(stat);
            closeConn(conn);
        }
        public static void close(Connection con,Statement stat , ResultSet rs){
            closeResultSet(rs);
            close(con,stat)
        }
         /**
          * 释放连接
          * @param conn 连接
          */
         public static void closeConn(Connection conn){
              if(conn!=null){//空的时候,不用关闭
                   try {
                        conn.close();
                   } catch (SQLException e) {
                        e.printStackTrace();
                   }
                   conn=null;//对象为空的时候,垃圾回收快
              }
         }
         /**
          * 释放语句执行者
          * @param st 语句执行者
          */
         public static void closeStatement(Statement st){
              if(st!=null){
                   try {
                        st.close();
                   } catch (SQLException e) {
                        e.printStackTrace();
                   }
                   st=null;
              }
         }
         /**
          * 释放结果集
          * @param rs 结果集
          */
         public static void closeResultSet(ResultSet rs){
              if(rs!=null){
                   try {
                        rs.close();
                   } catch (SQLException e) {
                        e.printStackTrace();
                   }
                   rs=null;
              }
         }
    
    }
    • 测试使用
    public class JDBCDemo {
        public static void main(String[] args) throws Exception{
            //创建集合对象
            List<Sort> list = new ArrayList<>();//包是util下的
            try{
                //使用JDBC工具类,直接获取数据库连接对象(必须在同一个工程中)
                Connection con = JDBCUtils.getConnection();//JDBCUtils是工具类
                //连接获取数据库SQL语句执行者对象
                PreparedStatement pst = con.prepareStatement("SELECT * FROM sort");
                //调用查询方法,获取结果集
                ResultSet rs = pst.executeQuery();
    
                while(rs.next()){
                    //获取到每个列数据,封装到Sort对象中,封装的内容直接写列名
                    Sort s = new Sort(rs.getInt("sid"),rs.getString("sname"),rs.getDouble("sprice"),rs.getString("sdesc"));
                    //封装的Sort对象,存储到集合中
                    list.add(s);
                }
            }catch(Exception e){
                e.printStackTrace();
            }finally{
                JDBCUtils.close(con, pst, rs);//关闭不用的
            }
    
            //遍历List集合,输出
            for(Sort s : list){
                System.out.println(s);
            }
        }
    }

    在配置文件properties中设置数据库

    • properties在资源路径下:
    InputStream in = JDBCUtilsConfig.class.getClassLoader().getResourceAsStream("database.properties");
    Properties pro = new Properties();
    pro.load(in);
    String driverClass=pro.getProperty("driverClass");
    String url = pro.getProperty("url");
    String username = pro.getProperty("username");
    String password = pro.getProperty("password");
    • properties在src中:
      在src中新建file,起名jdbc.properties
    driverClass=com.mysql.jdbc.Driver
    url=jdbc:mysql://localhost:3306/day07
    user=root
    password=1234
    ResourceBundle bundle = ResourceBundle.getBundle("jdbc");
    // 获取指定的内容
    String DRIVERCLASS = bundle.getString("driverClass");
    String URL = bundle.getString("url");
    String USER = bundle.getString("user");
    String PASSWORD = bundle.getString("password");
    练习

    判断map中所有的用户名在userinfo表中是否存在存在则输出"该用户已注册",如果不存在将该用户名及对应的密码存入到userinfo表中

    public class TestJdbc {
        public static void main(String[] args) throws Exception {
            HashMap<String, String> hm=new HashMap<>();
            hm.put("liuyan", "123456");
            hm.put("wangbaoqiang", "123321");
            hm.put("fangbian", "123abc321");
            Set<String> set=hm.keySet();
            //功能1:
            for(String key:set){
                String value=hm.get(key);
                System.out.println(key+"--"+value);
            }
            //功能2
            Class.forName("com.mysql.jdbc.Driver");
            Connection con=DriverManager.getConnection("jdbc:mysql://localhost:3306/stdb","","");
            PreparedStatement pst =null;
            ResultSet rs =null;
            for(String key:set){
                String value=hm.get(key);
                pst = con.prepareStatement("SELECT upassword FROM userinfo where uname='"+key+"'");
                rs =pst.executeQuery() ;
                if(rs.next()){
                    if(value.equals(rs.getString("upassword"))){
                        System.out.println(key+"在数据库中已存在");
                    }else{
                        pst = con.prepareStatement("INSERT into userinfo (uname,upassword ) values (?,?)");
                        pst.setString(1, key);
                        pst.setString(2, value);
                        pst.executeUpdate();
                    }
                }else{
                    pst = con.prepareStatement("INSERT into userinfo (uname,upassword ) values (?,?)");
                    pst.setString(1, key);
                    pst.setString(2, value);
                    pst.executeUpdate();
                }
            }
            JdbcDemo.close(con, pst, rs);
        }
    }




  • 相关阅读:
    python读写操作(txt, mat, xls, etc文件)
    开发linux版QQ就是支持未来的国产操作系统
    为知笔记linux绿色版的快速调用
    数学物理中的常见误区
    markdown语法小结
    信息爆炸时代的知识获取
    matlab: 数据的读写
    APS期刊投稿准备: REVTex格式
    markdown基本语法
    常见的数学关系
  • 原文地址:https://www.cnblogs.com/ziyue7575/p/11593458.html
Copyright © 2011-2022 走看看