zoukankan      html  css  js  c++  java
  • 通过jdbc完成单表的curd操作以及对JDBCUtils的封装

    概述:jdbc是oracle公司制定的一套规范(一套接口),驱动是jdbc的实现类,由数据库厂商提供。所以我们可以通过一套规范实现对不同的数据库操作(多态)

    jdbc的作用:连接数据库,发送sql语句,处理结果

    curd操作:它代表创建(Create)、更新(Update)、读取(Retrieve)和删除(Delete)操作

    jdbc操作步骤:

    1.数据库和表

    在这里,用exercise数据库下的student表。

    2.创建一个项目

    由于是在javase版本的ecplise下创建的,lib文件夹是我手动创建的,用来存放导入的驱动jar包。

    3.导入驱动jar包

    记得右键单击jar包,然后点击build path。

    4.编写代码

    首先,采用硬编码的方式进行,注意,以下需要导包的所有类都是java.sql下的包,以下为代码和注释:

        @Test
        public void jdbc1() throws ClassNotFoundException, SQLException{//将类加载到内存中有3种方式
                    //注册驱动
            Class.forName("com.mysql.jdbc.Driver");  
                    //获取连接
            Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/exercise", "root", "123456");
                    //编写sql
            String sql = "select * from student";
                    //创建预编译的语句执行者
            PreparedStatement st = conn.prepareStatement(sql);
                    //执行sql,这里是r操作(读取操作)
            ResultSet rs = st.executeQuery();
            //处理结果,rs.next初始指向第一个。
            while(rs.next()){
                System.out.println(
                        rs.getString("id")+"  "+rs.getString("name")
                        +"   "+rs.getString("score"));
            }
            //后开的先关
            rs.close();
            st.close();
            conn.close();
            
        }
                        

    jdbc-api:所有的包都是java.sql或者javax.sql下的

    DriverManger(驱动管理者):管理了一组jdbc的操作,是一个类。

    常用方法:

      1.注册驱动:static void registerDriver(Driver driver)

    然而为什么注册驱动却用的Class.forName(),而不是拿registerDriver函数注册驱动呢?

    由上文知,执行registerDriver函数,里面需要传入一个Driver类型的对象,查看源码我们发现

     java.mysql.jdbc.Driver类中有一个静态代码块,众所周知,在类加载进内存中时,静态代码块只会运行一次。我们发现,这个静态代码块里也调用了registerDriver函数。

    如果我们代码编写本身用的是registerDriver(Driver driver)函数注册驱动,那么在加载Driver这个类的时候,静态代码块执行,里面的registerDriver函数又会执行一次,相当于注册了两次驱动。这是不被允许的。为了让驱动只被注册一次,我们只需要执行Driver类中的静态代码块即可,所以我们只需要让Driver类加载进内存即可。

    类加载进内存有三种方法:Class.forName("全限定名");     类名.class     对象.getClass();

    这三种方法都能将类加载进内存并成功注册驱动。上面的代码所使用的是第一种。

      2.获取连接:static Connection getConnection(String url, String user, String password)

    url告诉我们连接什么类型的数据库及连接哪个数据库协议:数据库类型:子协议 参数。
    例如:

       mysql: jdbc:mysql://localhost:3306/数据库名称        

      oracle: jdbc:oracle:thin@localhost:1521@实例    thin代表瘦连接

    user就是账户名,password就是密码

    Connection:连接 接口

    常用方法:

      1.获取语句执行者:

    Statement createStatement() :获取普通的语句执行者  会出现sql注入问题

    PreparedStatement prepareStatement(String sql) :获取预编译语句执行者

    CallableStatement prepareCall(String sql):获取调用存储过程的语句执行者。

      2.关于事务的一些方法:

    setAutoCommit(false) 手动开启事务   选择false是因为默认是不开启事务的

    commit()提交事务

    rollback()事务回滚

    Statement:语句执行者 接口

    PreparedStatement:预编译语句执行者 接口

    常用方法:

      1.设置参数

    setXxx(int 第几个问号,Object 实际参数);

      2.执行sql

    ResultSet executeQuery() :执行 r 语句 返回值:结果集

    int executeUpdate() :执行cud 语句 返回值:影响的行数。一般是1,可以通过判断返回的行数来确定sql语句是否执行成功。

    ResultSet:结果集 接口 执行查询语句之后返回的结果

    常用方法:

      1.boolean next();判断是否有下一条记录,若有,返回true,且将光标移到下一行。若无,返回false

    注意:光标一开始处于第一条记录的上面,所以就算结果中只有一条记录,也会返回一个true。

      2.getXxx(int/string);获取具体内容。若参数为Int,获取第几列。若参数为String,获取列名(字段名)。

    getString()也可以获取int值,getObject()可以获取任意。

    以上为jdbc的最基本操作,在实际操作中,当上述代码被编译为.class文件后,改动上面的参数会变得有些困难。为了方便期间,采用xml或properties文件,将里面的所有参数提取出来,封装成一个工具类,即:JDBCUtils工具类,就会方便很多。下面就是封装JDBCUtils工具类的过程。

    在这里我们采用的是properties文件的方式。

    properties文件的内容格式为:key=value,放在src目录下。

    我们可以通过ResourceBundle工具类快速获取里面的配置信息。

    使用步骤:1.获取ResourceBundle 对象:  static ResourceBundle getBundle("文件名称不带后缀名")   返回值是ResourceBundle对象。

         2.通过ResourceBundle 对象获取配置信息  String getString(String key) :通过执行key获取指定的value。

    注意:properties文件不能有多余的空格。

    由于获取参数的配置信息以及注册驱动只需要加载一次,所以将他们放入静态代码块中。

    static{
            ResourceBundle rb = ResourceBundle.getBundle("ha"); //获取properties文件。
            DRIVERCLASS = rb.getString("driverclass");
            URL = rb.getString("url");
            USER = rb.getString("user");
            PASSWORD = rb.getString("password");
                    
        }
    static{
                   //这个是注册驱动
            try {
                Class.forName(DRIVERCLASS);
            } catch (ClassNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }        

    由于获取连接时也需要用到参数的配置信息,所以将这些配置的常量定义再了静态代码块外面,并采用final修饰,表示只赋值一次。

       static final String DRIVERCLASS;
        static final String URL;
        static final String USER;
        static final String PASSWORD;

    将获取连接和释放连接分别定义成静态方法。

    释放连接时传入的是Statement接口,而不是prepareStatement接口。这样可以提高代码的复用性。

    public static Connection getConnection() throws ClassNotFoundException, SQLException{
            Connection conn = DriverManager.getConnection(URL, USER, PASSWORD);
            return conn;    
        }
        
        public static void closeResource(Connection conn,Statement st,ResultSet rs) throws SQLException{
            //注意:这里传入的是statement,不是preparestatement,因为statement是父接口
            closeConn(conn);
            closeSt(st);
            closeRs(rs);
        }
    
        /**
         * 释放连接
         * 
         * @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 closeSt(Statement st) {
            if (st != null) {
                try {
                    st.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
                st = null;
            }
    
        }
    
        /**
         * 释放结果集
         * 
         * @param rs
         *            结果集
         */
        public static void closeRs(ResultSet rs) {
            if (rs != null) {
                try {
                    rs.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
                rs = null;
            }
    
        }

     以上为工具类JDBCUtils的全部代码。

    但是还是存在局限性:

    即:使用jdbc的时候,每操作一次都需要获取连接(创建)用完之后把连接释放掉了(销毁)。

    解决方法:,通过连接池来优化curd操作。

    关于连接池的操作以及如何自定义连接池,详情见下一篇。

  • 相关阅读:
    vue指令(3)v-html
    vue指令(2)v-text
    vue基础(2)模板语法
    Struts2中在Action里面向前端页面传值的方法总结
    MySQL之字符串函数
    搜索关键字描红
    点击超链接执行js代码实现确认操作
    Java之线程同步的三种方法
    Java之线程的控制
    Java之线程的生命周期
  • 原文地址:https://www.cnblogs.com/tonbby/p/9032865.html
Copyright © 2011-2022 走看看