zoukankan      html  css  js  c++  java
  • 黑马程序员—创建JDBC框架及原理分析

    对于Java数据库的连接,由最初学习的每次全部手工代码,到后面的不断利用知识简化代码量;这是不断学习的过程,就像人类由原始社会的钻木取火到当代的文明,都是一步步过来的!

    本文不从最开始的JDBC入门开始总结,只总结被很多人忽略的地方:自己写框架,或者更确切说是框架的原理!

    先说使用框架的好处,也可以说是使用工具的好处,就如同使用记事本编程和eclipse之间的区别,很明显使用工具大大的提高了我们的编程效率,使我们在编程时候可以几乎避免垃圾代码或重复代码的痛苦!

    但是这样做其实也有不好的地方:不少的程序员,尤其是初学者,贪恋短时间出成果的短暂虚荣,学习不求原理,只求方便。也就造成了很多有识之士口中所说的:离开SSH框架,你还能做出来什么?诚然编程工具可以促进我们的学习,但是如果我们沉溺于简单的皮毛,一辈子也就是碌碌无为的码农!其实一句话:向往高处走,底层必须学!

    本文总结:自己如何编写JDBC框架,实现重复代码的简化?

    本文默认使用C3P0连接池,从用C3P0连接池写过增删改查四个操作分析比较后开始!

    之前我们写的CRUD操作,可以看到重复了很多的代码,我们想我们能否提炼这三个方法使其成为一个方法,只是根据不同的参数来确定去执行什么操作?

    实现这一设想,我们首先来学习一些必备的知识:就是说我们如何知道我们数据库中的表的信息,当然如果你是表的创始人你知道,但是假如现在我们是框架师,我们对sql,对表一无所知,(或者说我们了解SQL知识,但是对数据库内容根本无法知晓)我们只是使用一些技术实现对数据库的操作,所以如何得到数据库相关信息的呢?

    通过元数据!

    先了解元数据

    所谓元数据就是指数据库、表、列的定义信息,(描述数据的数据)如何获得元数据呢?

    DataBaseMetaData(数据库元数据)

    使用connection.getDatabasemetaData()方法,那这个DataBaseMetaData对象到底有什么属性或者方法呢?

    数据库的元数据

    getURL():返回一个String类对象,代表数据库的URL。

    getUserName():返回连接当前数据库管理系统的用户名。

    getDatabaseProductName():返回数据库的产品名称。

    getDatabaseProductVersion():返回数据库的版本号。

    getDriverName():返回驱动驱动程序的名称。

    getDriverVersion():返回驱动程序的版本号。

    isReadOnly():返回一个boolean值,指示数据库是否只允许读操作。

    ParameterMetaData(获取参数元数据)

    可用于获取关于PreparedStatement 对象中每个参数标记的类型和属性信息的对象。使用PreparedStatement.getParameterMetaData()方 法 获 得 代 表PreparedStatement元 数 据 的ParameterMetaData对象。

    它有两个最重要的方法:

    getParameterCount() 获得指定参数的个数

    getParameterType(intparam) 获得指定参数的sql类型(MySQL驱动不支持该方法)

    ResultSetMetaData(获取结果集元数据)

    可用于获取关于ResultSet对象中列的类型和属性信息的对象。有关 ResultSet 中列的名称和类型的信息。 

    那么如果是向把返回的结果遍历一下封装到bean当中我们如何设置呢,我们又不知道keyvalue,这个时候我们就需要另外一个元数据了,ResultSetMetaData它可以获得使用ResultSet对象元数据的对象,主要方法包括:

    getColumnCount() 返回resultset对象的列数

    getColumnName(intcolumn) 获得指定列的名称

    getColumnTypeName(intcolumn) 获得指定列的类型

    实例:(我们的框架)

    CUD操作,我们集成到一个update方法去,根据参数的不同,进行不同的操作!

    //利用元数据+反射优化CRUD操作!这个的原理和DBUtils的几乎一样!

    创建JavaBean,用来封装数据。(查询时候用的上)

    package com.itheima.domain;

    public class User {

    private int id;

    private String username;

    private String password;

    private java.util.Date birthday;

    private float salary;

    public int getId() {

    return id;

    }

    public void setId(int id) {

    this.id = id;

    }

    public String getUsername() {

    return username;

    }

    public void setUsername(String username) {

    this.username = username;

    }

    public String getPassword() {

    return password;

    }

    public void setPassword(String password) {

    this.password = password;

    }

    public java.util.Date getBirthday() {

    return birthday;

    }

    public void setBirthday(java.util.Date birthday) {

    this.birthday = birthday;

    }

    public float getSalary() {

    return salary;

    }

    public void setSalary(float salary) {

    this.salary = salary;

    }

    }

    package com.itheima.dao;

    import java.sql.Connection;

    import java.sql.ParameterMetaData;

    import java.sql.PreparedStatement;

    import java.sql.ResultSet;

    import java.sql.ResultSetMetaData;

    import java.sql.SQLException;

    import org.apache.commons.beanutils.BeanUtils;

    import com.itheima.domain.User;

    import com.itheima.util.JdbcUtil;

    public class Demo2 {

    public static void main(String[] args) throws Exception {

    /*//这是Insert

    String sql = "insert into user (username,password,birthday,salary)values(?,?,?,?)";

    Object params[] = {"zhangsan","125","2012-8-25",6000};

    update(sql,params);*/

    /*//尝试Update

    String sql = "update user set username = ? where username = ?";

    Object params[] = {"lisi","zhangsan"};

    update(sql,params);

    //此时就可以感受到好处:对某类操作(CUD)等只需要简单的sql语句变换(就是说很少的变化),减轻了代码量

    */

    //尝试Delete

    /*String sql = "delete from user where id = ?";

    update(sql,new Object[]{2});

    假如update也不是你写的,这样的话代码量就大大的减少了!这样就引出了框架

    */

    /*

     * 进行的是查询操作

     * 查询为什么需要javabean?因为查询需要返回数据,不然怎么显示

     */

    String sql = "select * from user where id = ?";

    User user = (User)query(sql, new Object[]{1}, User.class);

    System.out.println("用户名:" + user.getUsername());

    System.out.println("密码:" + user.getPassword());

    System.out.println("生日:" + user.getBirthday().toLocaleString());

    System.out.println("薪水:" + user.getSalary());

    }

    private static Object query(String sql, Object[] params ,Class clazz) throws Exception {

    Object obj = clazz.newInstance();

    Connection conn = JdbcUtil.getMySqlConnection();

    PreparedStatement pstmt = conn.prepareStatement(sql);

    //获取参数元数据

    ParameterMetaData psmd = pstmt.getParameterMetaData();

    int size = psmd.getParameterCount();

    //循环绑定

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

    pstmt.setObject(i+1, params[i]);

    }

    ResultSet rs = pstmt.executeQuery();

    if(rs.next()){

    //取得结果集元数据

    ResultSetMetaData rsmd = rs.getMetaData();

    //取得结果集列数目

    size = rsmd.getColumnCount();

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

    //获取列名

    String columnName = rsmd.getColumnName(i+1);

    //取得结果集元数据之后通过BeanUtils框架为JavaBean设置值

    BeanUtils.setProperty(obj, columnName, rs.getObject(i+1));

    }

    }

    JdbcUtil.close(rs);

    JdbcUtil.close(pstmt);

    JdbcUtil.close(conn);

    return obj;

    }

    //CUD操作(通用做法)

    private static void update(String sql, Object[] params) throws SQLException {

    Connection conn = JdbcUtil.getMySqlConnection();

    PreparedStatement pstmt = conn.prepareStatement(sql);

    ParameterMetaData psmd = pstmt.getParameterMetaData();

    int size = psmd.getParameterCount();

    System.out.println(size);

    //循环绑定对象的值(就是将?与实际的传入参数绑定)绑定第一个,第二个...

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

    pstmt.setObject(i+1, params[i]);

    }

    //执行

    pstmt.executeUpdate();

    JdbcUtil.close(pstmt);

    JdbcUtil.close(conn);

    }

    }

    总结:此时我们可以看到,使用元数据确实很大程度上减少了重复代码量。但是针对我们自己的框架,肯定还有不完美的小问题。

    这时候注意:java是一门开源的语言,这是java保持强大生命力的根本所在,既然我们能想到自己写一个框架来简化操作,那么肯定有开源组织也注意到了,而且做得更好!

    再总结一个知识点:

    O-R-Mapping  object-relative-mapping

    对象关系映射。把关系型数据映射为对象(只要能将传统的关系数据库的操作,映射为面向对象方式操作的框架都可以称为OR-Mapping

    常用O-R Mapping映射工具

    Hibernate

    Ibatis

    Commons DbUtils(只是对JDBC简单封装)

    ApacheDBUtils框架

    简介:

    commons-dbutils 是 Apache 组织提供的一个开源 JDBC工具类库,它是对JDBC的简单封装,学习成本极低,并且使用dbutils能极大简化jdbc编码的工作量,同时也不会影响程序的性能。因此dbutils成为很多不喜欢hibernate的公司的首选。

    API介绍:

    org.apache.commons.dbutils.QueryRunner 

    org.apache.commons.dbutils.ResultSetHandler

    工具类

    org.apache.commons.dbutils.DbUtils。   

    QueryRunner类 

    该类简单化了SQL查询,它与ResultSetHandler组合在一起使用可以完成大部分的数据库操作,能够大大减少编码量。

    QueryRunner类提供了两个构造方法:

    默认的构造方法(无参)

    另一个需要一个 javax.sql.DataSource 来作参数的构造方法。

    ResultSetHandler 接口的实现类

    ArrayHandler:把结果集中的第一行数据转成对象数组。

    ArrayListHandler:把结果集中的每一行数据都转成一个数组,再存放到List中。

    BeanHandler:将结果集中的第一行数据封装到一个对应的JavaBean实例中。

    BeanListHandler:将结果集中的每一行数据都封装到一个对应的JavaBean实例中,存放到List里。

    ColumnListHandler:将结果集中某一列的数据存放到List中。

    KeyedHandler(name):将结果集中的每一行数据都封装到一个Map<列名,列值>里,再把这些map再存到一个map里,其key为指定的key

    MapHandler:将结果集中的第一行数据封装到一个Map里,key是列名,value就是对应的值。

    MapListHandler:将结果集中的每一行数据都封装到一个Map里,然后再存放到List

    利用DButils框架进行操作:(使用相当简单,但是注意理解原理)

    package com.itheima.dao;

    import java.sql.SQLException;

    import org.apache.commons.dbutils.QueryRunner;

    import org.apache.commons.dbutils.handlers.BeanHandler;

    import com.itheima.domain.User;

    import com.itheima.util.JdbcUtil;

    public class Demo3 {

    public static void main(String[] args) throws Exception {

    //使用DButil框架

    QueryRunner runner = new QueryRunner(JdbcUtil.getDataSource());

    //String sql = "update user set username = ? where username = ?";

    String sql = "insert into user (username,password,birthday,salary)values(?,?,?,?)";

    //runner.update(sql, new Object[]{"wangwu","lisi"});

    runner.update(sql, new Object[]{"zhangzetian","2356","2012-02-11",6000});

    sql = "select * from user where id = ?";

    User user = (User) runner.query(sql, 1, new BeanHandler(User.class));

    System.out.println("用户名:" + user.getUsername());

    }

    }

    这样的写法是不是相当的简单呢!

    备注:配置文件,数据库,Utils工具类等已经提前准备好。

    本文章只是自己学西过程中的总结,并不是讲解类型的博文,所以这些东西没有面面俱到的写出!

  • 相关阅读:
    Flush the AOS cache from code
    EntityConnectionStringBuilder 构造EF连接字符串
    AX中文转拼音
    AX2012 AOT中Web部署显示二级以上菜单
    clearCompanyCache
    AX2009 打印到PDF优化
    AX ODBC读取其他SQL数据库服务器数据
    AX2009报表打印固定长度Barcode条码
    Create Product Variant
    Rename AOT Object
  • 原文地址:https://www.cnblogs.com/jiangu66/p/3241398.html
Copyright © 2011-2022 走看看