JDBC操作数据库的三种方式比较

JDBC(java Database Connectivity)java数据库连接,是一种用于执行上sql语句的javaAPI,可以为多种关系型数据库提供统一访问接口。我们项目中经常用到的MySQL、oracle、DB2等关系型数据库均是通过JDBC来访问的,现在主流的ORM框架Hibernate、Mybatis等均是在JDBC的基础上做的进一步封装、优化。一般小型的项目,可以直接用JDBC来访问数据库,简单方便。我在进过几个项目后,总结了三总JDBC的基本用法,对这几种用法做一个总结。

第一种、连接池+ JDBC

连接池通过将已经建立好的连接保存在连接池中,当有请求的时候,直接使接对数据库进行访问,从而节省了创建连接和关闭连接的时间,性能得到了提高,总之一句话,连接池就是为了提升性能。常用的连接池有DBCP、c3p0、DRUID等,原理都一样。下面是实例:

首先创建连接池:

public class ConnDBUtil{       

private static final Log logger = LogFactory.getLog(ConnDBUtil.class);

       private static Properties JDBCPOP = new PropertiesUtil().getProperties("jdbc.properties");

       private static ComboPooledDataSource cpds;

       static{

              try {

                     cpds = new ComboPooledDataSource();

                     cpds.setDriverClass(JDBCPOP.getProperty("driverName"));

                     cpds.setJdbcUrl(JDBCPOP.getProperty("url"));

                     cpds.setUser(JDBCPOP.getProperty("user"));

                     cpds.setPassword(JDBCPOP.getProperty("drowssap"));

                     cpds.setAcquireIncrement(Integer.parseInt(JDBCPOP.getProperty("acquireIncrement")));

                     cpds.setInitialPoolSize(Integer.parseInt(JDBCPOP.getProperty("initialPoolSize")));

                     cpds.setMinPoolSize(Integer.parseInt(JDBCPOP.getProperty("minPoolSize")));

                     cpds.setMaxPoolSize(Integer.parseInt(JDBCPOP.getProperty("maxPoolSize")));

                     cpds.setIdleConnectionTestPeriod(Integer.parseInt(JDBCPOP

                                   .getProperty("idleConnectionTestPeriod")));

              } catch (PropertyVetoException e) {

                     logger.error("c3p0连接异常:"+e.getMessage(),e);

              }

       }

       /**

        * 获得c3p0连接

        * @return Connection

        */

       public Connection getConnection(){

              Connection conn = null;

              try {

                     conn= cpds.getConnection();

              } catch (SQLException e) {

                     logger.error(e.getMessage(),e);

                     e.fillInStackTrace();

              }

              return conn;

       }

       public  void c3p0Static(ComboPooledDataSource cpds){

              try {

                     logger.info("c3p0总连接数:"+cpds.getNumConnections());

                     logger.info("c3p0正在使用连接数:"+cpds.getNumBusyConnections());

                     logger.info("c3p0空闲连接数:"+cpds.getNumIdleConnections());

              } catch (SQLException e) {

                     logger.error(e.getMessage(),e);

              }

       }

接下来获取连接,jdbc操作数据库,以一个简单的查询为例:

public class Dao{

public String queryHtable(String username) {

              Connection conn=null;

              PreparedStatement ps=null;

              ResultSet rs=null;

              String HTable=null;

              try {

                     String sql="select tab_name FROM table_user "

                                   + "WHERE USER_NAME=‘"+username+"‘";

                     conn=ConnDBUtil.getConnection();

                     ps=conn.prepareStatement(sql);

                     rs=ps.executeQuery();

                     while(rs.next()){

                            HTable=rs.getString("USE_HTABLE");

                     }

              } catch (SQLException e) {

                     logger.error(e.getMessage(),e);

                     e.fillInStackTrace();

              }finally{

                     closeAll(rs, ps, conn);

              }

              return HTable;

       }

//关闭资源

       private static void closeAll(ResultSet rs, PreparedStatement ps, Connection conn) {

              if(rs != null){

                     try {

                            rs.close();

                     } catch (SQLException e) {

                            logger.error(e.getMessage(),e);

                            e.fillInStackTrace();

                     }

              }

              if(ps != null){

                     try {

                            ps.close();

                     } catch (SQLException e) {

                            logger.error(e.getMessage(),e);

                            e.fillInStackTrace();

                     }

              }

              if(conn != null){

                     try {

                            conn.close();

                     } catch (SQLException e) {

                            logger.error(e.getMessage(),e);

                            e.fillInStackTrace();

                     }

              }

       }

以上就是一种非常简单的JDBC操作数据库的例子,缺点是代码耦合度非常高。

第二种、ThreadLocal+JDBC

ThreadLocal,线程局部变量,作用非常简单就是为每一个使用该变量的线程提供一个变量值的副本,这样,每一个线程都可以独立改变自己的副本而不受其他线程的影响,也不会和其他线程副本冲突,从而提高线程安全性,也就是说,每一个线程完全拥有该变量。从源码我们可以看到ThreadLocal是如何维护线程变量副本的,思路很简单,ThreadLocal类中存在一个Map,Map中存储的就是变量副本。

public class GetConnectionType {
    public static Connection getConnection() throws SQLException, ClassNotFoundException {
        String url = "jdbc:mysql://localhost:3306/test";
        String driver = "com.mysql.jdbc.Driver";
        String username = "root";
        String password = "123456";
        Class.forName(driver);
        Connection connection = DriverManager.getConnection(url, username, password);
        return connection;
    }
}

public class GetConnection {

    private static ThreadLocal<Connection> local = new ThreadLocal<>();
    //获取连接
    public static Connection getConnection() throws ClassNotFoundException, SQLException {
        Connection conn = local.get();
        if (conn == null) {
            conn = GetConnectionType.getConnection();
            conn.setAutoCommit(false);
            local.set(conn);
        }
        return conn;
    }
    //提交事务
    public static void commit() {
        try {
            if (local.get() != null) {
                local.get().commit();
                local.get().close();
                local.set(null);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
    //回滚
    public static void rollback() {
        try {
            if (local.get() != null) {
                local.get().rollback();
                local.get().close();
                local.set(null);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

public List<Bookinfo> getAllBookinfo() throws SQLException, ClassNotFoundException {
        List listBookinfo = new ArrayList();
        String sql = "select * from bookinfo order by id asc";
        Connection conn = GetConnection.getConnection();
        PreparedStatement ps = conn.prepareStatement(sql);
        ResultSet rs = ps.executeQuery();
        while (rs.next()) {
            int idDB = rs.getInt("id");
            String booknameDB = rs.getString("bookname");
            double bookpriceDB = rs.getDouble("bookprice");
            Bookinfo bookinfo = new Bookinfo();
            bookinfo.setId(idDB);
            bookinfo.setBookname(booknameDB);
            bookinfo.setBookprice(bookpriceDB);
            listBookinfo.add(bookinfo);
        }
        rs.close();
        ps.close();
        return listBookinfo;
    }

第三种、通过反射连接JDBC

什么是反射?反射就是对于任何一个类,,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够任意调用它的任何方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。(来自:百度百科)。代码如下:

public class ConnUtil {

private static Log logger = LogFactory.getLog(ConnUtil.class);

       private static String  sqlDriver;

       private static String  url;

       private static String username;

       private static String password;

       private static Properties JDBCP = new PropertiesUtil().getProperties("jdbc.properties");

       static{

              try {

                     sqlDriver=JDBCP.getProperty("driverName");

                     url=JDBCP.getProperty("url");

                     username=JDBCP.getProperty("user");

                     password=JDBCP.getProperty("drowssap");

                     Class.forName(sqlDriver);

              } catch (ClassNotFoundException e) {

                     logger.error("mysql注册驱动出错:"+e.getMessage(),e);

              }

       }

       /**

        * 获取数据库连接

        * @return Connection

        */

       public static Connection getConn(){

              Connection connection=null;

              try {

                     connection= DriverManager.getConnection(url, username, password);

              } catch (SQLException e) {

                     logger.error("数据库建立连接出错:"+e.getMessage(),e);

              }

              return connection;

       }

       /**

        * 关闭连接

        * @param objects

        */

       public static void close(Object...objects){

              try {

                     if(objects!=null){

                            for(Object obj:objects){

                                   if(obj instanceof Connection){

                                          ((Connection) obj).close();

                                   }else if(obj instanceof PreparedStatement){

                                          ((PreparedStatement) obj).close();

                                   }else if(obj instanceof ResultSet){

                                          ((ResultSet) obj).close();

                                   }

                            }

                     }

              } catch (SQLException e) {

                     logger.error("数据库连接关闭异常:"+e.getMessage(),e);

              }

       }

}

数据库连接,操作数据库:

public class Dao {

       private static Log logger = LogFactory.getLog(Dao.class);

       /**

        * 查询所有

        * @param sql

        * @param c

        * @return

        */

       public static<T> List<T> queryAll(String sql,Class<T> c){

              Connection connection=null;

              PreparedStatement pStatement=null;

              ResultSet rSet=null;

              List<T> list=new ArrayList<T>();

              try {

                     connection=ConnUtil.getConn();

                     pStatement=connection.prepareStatement(sql);

                     rSet=pStatement.executeQuery();

                     while(rSet.next()){

                            //通过反射赋值

                            T t=c.newInstance();

                            //获取所有属性

                            Field[] fields=c.getDeclaredFields();

                            //便利属性并赋值

                            for(Field f:fields){

                                   //获取属性名

                                   String fName=f.getName();

                                   //获取属性值

                                   Object objValue=rSet.getObject(fName);

                                   //给属性设置值

                                   Method method=c.getMethod(setter(fName), f.getType());

                                   method.invoke(t, objValue);

                            }

                            list.add(t);

                     }

              } catch (SQLException  e) {

                     logger.error("数据库异常:"+e.getMessage(),e);

              }catch (InstantiationException | IllegalAccessException e1 ){

                     logger.error("反射异常:"+e1.getMessage(),e1);

              } catch (NoSuchMethodException e) {

                     logger.error("方法错误:"+e.getMessage(),e);

              } catch (SecurityException e) {

                     logger.error("安全异常:"+e.getMessage(),e);

              } catch (IllegalArgumentException e) {

                     logger.error("非法转换异常:"+e.getMessage(),e);

              } catch (InvocationTargetException e) {

                     logger.error("InvocationTargetException异常:"+e.getMessage(),e);

              }finally{

                     ConnUtil.close(rSet,pStatement,connection);

              }

              return list;

       }

       /**

        * 条件查询

        * @param sql

        * @param c

        * @return

        */

       public static<T> List<T> queryByCondition(String sql,Class<T> c,Object...objects){

              Connection connection=null;

              PreparedStatement pStatement=null;

              ResultSet rSet=null;

              List<T> list=new ArrayList<T>();

                     try {

                            connection=ConnUtil.getConn();

                            pStatement=connection.prepareStatement(sql);

                            if(objects!=null){

                                   for(int i=0;i<objects.length;i++){

                                          pStatement.setObject(i+1, objects[i]);

                                   }

                            }

                            rSet=pStatement.executeQuery();

                            ResultSetMetaData resultSetMetaData=rSet.getMetaData();

                            int count=resultSetMetaData.getColumnCount();

                            while(rSet.next()){

                                   //通过反射赋值

                                   T t=c.newInstance();

                                   for (int i = 0; i < count; i++) {

                                          //获取属性名

                                          String fName=resultSetMetaData.getColumnName(i);

                                          //获取所有属性

                                          Field field=c.getDeclaredField(fName);

                                          //给属性设置值

                                          Method method=c.getMethod(setter(fName), field.getType());

                                          //获取属性值

                                          Object objValue=rSet.getObject(fName);

                                          method.invoke(t, objValue);

                                   }

                                   list.add(t);

                            }

                     } catch (InstantiationException e) {

                            e.printStackTrace();

                     } catch (IllegalAccessException e) {

                            e.printStackTrace();

                     } catch (NoSuchFieldException e) {

                            e.printStackTrace();

                     } catch (SecurityException e) {

                            e.printStackTrace();

                     } catch (NoSuchMethodException e) {

                            e.printStackTrace();

                     } catch (IllegalArgumentException e) {

                            e.printStackTrace();

                     } catch (InvocationTargetException e) {

                            e.printStackTrace();

                     } catch (SQLException e) {

                            e.printStackTrace();

                     }finally{

                            ConnUtil.close(rSet,pStatement,connection);

                     }

              return list;

       }

       /**

        * 更新操作,包括 insert delete update

        * @param sql

        * @param objects

        * @return flag

        */

       public static boolean update(String sql,Object...objects){

              Connection connection=null;

              PreparedStatement pStatement=null;

              boolean flag=false;

              try {

                     connection=ConnUtil.getConn();

                     pStatement=connection.prepareStatement(sql);

                     if(objects!=null){

                            for(int i=0;i<objects.length;i++){

                                   pStatement.setObject(i+1, objects[i]);

                            }

                     }

                     flag=pStatement.execute();

              } catch (SQLException e) {

                     e.printStackTrace();

              }finally{

                     ConnUtil.close(pStatement,connection);

              }

              return flag;

       }

       private static String setter(String name){

              return "set"+name.substring(0,1).toUpperCase()+name.substring(1);

       }  

}

 总结

JDBC操作数据库,看似简单,但是细节很多,需要我们自己管理数据连接,稍不小心会出现连接未关闭的情况,这样会浪费系统的资源,为了避免我们自己管理JDBC,所以出现了很多框架,如Mybatis、hibernate这种ORM持久性框架,他们对JDBC做了很好的封装,另外有Spring框架的支持,不需要我们去额外维护数据库的连接,我们可以把全部精力放在业务的实现上面,但是JDBC是我们必须会的一个非常重要的知识点,熟悉了JDBC的原理,才能更好的理解框架的应用。以上是在学习和做项目过程中总结的几种JDBC用法各有优缺点,希望能对大家的学习有所帮助。

原文地址:https://www.cnblogs.com/10158wsj/p/8428221.html

时间: 2024-08-06 07:37:07

JDBC操作数据库的三种方式比较的相关文章

[PHP]PHP编程操作Mysql数据库的三种方式

当我开始去接触PHP的时候,真切的感受到其所具有的魅力,本着学习的态度和打破固有的语言和模式的想法,开始了PHP之旅,总的来说,走的还是比较顺利,在其中能够看到C,Java,Perl影子,学习曲线不大,但是做好产品仍然有着一条漫漫长路. 多余的话不说了,慢慢感受和领悟,本文主要讲述PHP操作数据库的三种扩展. 如下图是PHP访问数据库的三种扩展方式: 下面举出三种方式访问数据库并查询数据的实例代码: 1.mysql扩展 <?php //1:获取数据库连接 $connection = @ mysq

Jdbc注册驱动的三种方式

Jdbc注册驱动的三种方式 分类: [Java 基础] 2012-05-17 07:34 2558人阅读 评论(0) 收藏 举报 jdbc数据库javavectorurljar 关于驱动包 jdbc中注册驱动,首先导入对应的包,例如mysql-connector-java-5.0.8-bin.jar.驱动包是java和具体数据库之间的连接桥梁,由数据库厂商开发.每一种数据库对应一款驱动jar,甚至每一个版本的数据库都有自己对应版本的驱动jar. 关于java.sqlDriverManger类 J

使用DataSet Datatable 更新数据库的三种方式

1:自动生成命令的条件 CommandBuilder 方法a)动态指定 SelectCommand 属性b)利用 CommandBuilder 对象自动生成 DataAdapter 的 DeleteCommand.InsertCommand 和 UpdateCommand.c)为了返回构造 INSERT.UPDATE 和 DELETE .SQL CommandBuilder 必须执行 SelectCommand.即:必须额外经历一次到数据源的行程,这可能会降低性能.这也是自动生成命令的缺点.d)

Android开发之使用sqlite3工具操作数据库的两种方式

使用 sqlite3 工具操作数据库的两种方式 请尊重他人的劳动成果,转载请注明出处:Android开发之使用sqlite3工具操作数据库的两种方式 http://blog.csdn.net/fengyuzhengfan/article/details/40193123 在Android SDK的tools目录下提供了一"sqlite3.exe工具,它是一个简单的SQLite数据库管理工具,类似于MySQL提供的命令行窗口在有些时候,开发者利用该工具来査询. 管理数据库. 下面介绍两种方式: 第

Jdbc注册驱动的三种方式 (转)

关于驱动包   jdbc中注册驱动,首先导入对应的包,例如mysql-connector-java-5.0.8-bin.jar.驱动包是java和具体数据库之间的连接桥梁,由数据库厂商开发.每一种数据库对应一款驱动jar,甚至每一个版本的数据库都有自己对应版本的驱动jar. 关于java.sqlDriverManger类   Java的驱动管理类.管理一组 JDBC 驱动程序. javax.sql.DataSource 接口是 JDBC 2.0 API 中的新增内容,它提供了连接到数据源的另一种

Code First03---CodeFirst根据配置同步到数据库的三种方式

上一节我们说到使用Fluent API对实体的配置,但是有一个问题了,在业务中我们可以用到的实体很多,那是不是每个都需要这样去配置,这样就造成我们重写的OnModelCreating方法很庞大了.所以我们需要更好的组织Fluent API的配置. 我们知道modelBuilder的Entity<T>泛型方法的返回值是EntityTypeConfiguration<T>泛型类. 所以我们可以定义一个继承自EntityTypeConfiguration<T>泛型类的类来定义

java连接access数据库的三种方式以及远程连接

连接access数据库,网上的内容很多,尝试的过程中也会遇到各种问题,没有特别好的介绍,所以自己想总结一下,日后备用. 这里需要提前说明下,win7系统32bit和64bit默认安装的access都是32bit的,但是如果是64bit的系统连接access数据库时需要安装64bit的office软件,下面会说到. 以64bit操作系统为列 第一种:电脑上配置结合java代码实现 a.打开目录C:\Windows\System32找到odbcad32.exe文件,双击打开 b.点击右侧添加按钮,在

PHP连接MySQL数据库的三种方式(mysql、mysqli、pdo)

PHP与MySQL的连接有三种API接口,分别是:PHP的MySQL扩展 .PHP的mysqli扩展 .PHP数据对象(PDO) ,下面针对以上三种连接方式做下总结,以备在不同场景下选出最优方案. PHP的MySQL扩展是设计开发允许php应用与MySQL数据库交互的早期扩展.MySQL扩展提供了一个面向过程的接口,并且是针对MySQL4.1.3或者更早版本设计的.因此这个扩展虽然可以与MySQL4.1.3或更新的数据库服务端进行交互,但并不支持后期MySQL服务端提供的一些特性.由于太古老,又

EF Codefirst生成数据库的三种方式

1.写在前头 不是什么高大上的东西,也不是完全原创的,大多是自己学习时去网上查的各种资料.只是发现学东西还是要写点东西,不然前边写着后边忘了,花的时间都浪费了,写写增加记忆吧.如果是有人刚开始学看到这个相信会有帮助的. 2.开搞 前几天写了篇小文章搞了下EF生成数据库时获取连接字符串的方式,发布时不小心勾选了发布到首页,秒秒钟就被管理员给撤销了( ⊙ o ⊙ ),确实太低端了,博客园锅锅撤销也是可以理解的,废话不多说,今天继续搞一搞获取完连接字符串后EF怎么生成数据库呢,有哪些方式呢? 第一种: