博客
关于我
把 jdbc返回的数据 装进对象里 (分析DBUtils源码)
阅读量:643 次
发布时间:2019-03-14

本文共 8986 字,大约阅读时间需要 29 分钟。

JDBC 数据库开发实践指南

在 Java 开发中,JDBC 是连接数据库的重要工具。通过 JDBC,我们可以通过 Java 程序与各种关系型数据库进行交互。本文将介绍 JDBC 的基本使用方法,并结合实例展示如何将 JDBC 返回值直接包装到实体类中。


JDBC 的基本使用

JDBC 提供了标准化的接口,使开发者能够通过 Java 程序访问各种数据库。以下是 JDBC 的基本使用步骤:

  • 注册驱动程序:需要加载数据库的驱动程序。常用的数据库如 MySQL、Oracle、PostgreSQL 等都有对应的 JDBC 驱动程序。
  • 获取连接:使用 DriverManager.getConnection() 获取数据库连接。
  • 执行查询:通过 StatementPreparedStatement 对数据库进行查询。
  • 处理结果集:根据结果集 (ResultSet) 将数据转换为 Java 对象。

  • 实体类字段与 JDBC 返回值的对应关系

    在实际开发中,数据库查询的结果通常以字段形式返回,而我们需要将这些字段映射到 JavaBean 对应的属性中。本文提供了一个简单的 Student 实体类:

    package cn.dbutils.analyze;public class Student {    private Integer id;    private String name;    private Date time;    public Student() {        super();    }    public Integer getId() {        return id;    }    public void setId(Integer id) {        this.id = id;    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    public Date getTime() {        return time;    }    public void setTime(Date time) {        this.time = time;    }    @Override    public String toString() {        return "Student [id=" + id + ", name=" + name + ", time=" + time + "]";    }}

    QueryRunner 工具类

    为了简化 JDBC 的复杂性,我们开发了一个 QueryRunner 工具类。以下是工具类的核心逻辑:

    public class QueryRunner {    private Connection con;    public QueryRunner(Connection con) {        this.con = con;    }    public 
    T query(String sql, Class
    type) throws SQLException, InstantiationException, IllegalAccessException, IntrospectionException { Statement stmt = con.createStatement(); ResultSet rs = stmt.executeQuery(sql); if (rs.next()) { return toBean(rs, type); } return null; } public
    List
    queryList(String sql, Class
    type) throws SQLException, InstantiationException, IllegalAccessException, IntrospectionException { Statement stmt = con.createStatement(); ResultSet rs = stmt.executeQuery(sql); List
    list = new ArrayList<>(); while (rs.next()) { list.add(toBean(rs, type)); } return list; } private
    T toBean(ResultSet rs, Class
    type) throws IntrospectionException, SQLException, InstantiationException, IllegalAccessException { BeanInfo beanInfo = Introspector.getBeanInfo(type); PropertyDescriptor[] props = beanInfo.getPropertyDescriptors(); ResultSetMetaData rsmd = rs.getMetaData(); int[] columnToProperty = mapColumnsToProperties(rsmd, props); return createBean(rs, type, props, columnToProperty); } private
    T createBean(ResultSet rs, Class
    type, PropertyDescriptor[] props, int[] columnToProperty) throws SQLException, InstantiationException, IllegalAccessException { T bean = type.newInstance(); for (int i = 1; i < columnToProperty.length; i++) { int propertyIndex = columnToProperty[i]; if (propertyIndex == -1) { continue; } PropertyDescriptor prop = props[propertyIndex]; Class
    propType = prop.getPropertyType(); Object value = processColumn(rs, i, propType); if (propType != null && value == null && propType.isPrimitive()) { value = primitiveDefaults.get(propType); } callSetter(bean, prop, value); } return bean; } protected int[] mapColumnsToProperties(ResultSetMetaData rsmd, PropertyDescriptor[] props) throws SQLException { int cols = rsmd.getColumnCount(); int[] columnToProperty = new int[cols + 1]; Arrays.fill(columnToProperty, -1); for (int col = 1; col <= cols; col++) { String columnName = rsmd.getColumnName(col); for (int i = 0; i < props.length; i++) { if (columnName.equalsIgnoreCase(props[i].getName())) { columnToProperty[col] = i; break; } } } return columnToProperty; } private Object processColumn(ResultSet rs, int index, Class
    propType) throws SQLException { if (!propType.isPrimitive() && rs.getObject(index) == null) { return null; } if (propType.equals(String.class)) { return rs.getString(index); } else if (propType.equals(Integer.TYPE) || propType.equals(Integer.class)) { return Integer.valueOf(rs.getInt(index)); } else if (propType.equals(Boolean.TYPE) || propType.equals(Boolean.class)) { return Boolean.valueOf(rs.getBoolean(index)); } else if (propType.equals(Long.TYPE) || propType.equals(Long.class)) { return Long.valueOf(rs.getLong(index)); } else if (propType.equals(Double.TYPE) || propType.equals(Double.class)) { return Double.valueOf(rs.getDouble(index)); } else if (propType.equals(Float.TYPE) || propType.equals(Float.class)) { return Float.valueOf(rs.getFloat(index)); } else if (propType.equals(Short.TYPE) || propType.equals(Short.class)) { return Short.valueOf(rs.getShort(index)); } else if (propType.equals(Byte.TYPE) || propType.equals(Byte.class)) { return Byte.valueOf(rs.getByte(index)); } else if (propType.equals(Timestamp.class)) { return rs.getTimestamp(index); } else { return rs.getObject(index); } } private void callSetter(Object target, PropertyDescriptor prop, Object value) throws SQLException { Method setter = prop.getWriteMethod(); if (setter == null) { return; } Class
    [] params = setter.getParameterTypes(); try { if (value != null) { if (value instanceof java.util.Date) { if (params[0].getName().equals("java.sql.Date")) { value = new java.sql.Date(((java.util.Date) value).getTime()); } else if (params[0].getName().equals("java.sql.Time")) { value = new java.sql.Time(((java.util.Date) value).getTime()); } else if (params[0].getName().equals("java.sql.Timestamp")) { value = new java.sql.Timestamp(((java.util.Date) value).getTime()); } } } if (isCompatibleType(value, params[0])) { setter.invoke(target, new Object[]{value}); } else { throw new SQLException("Cannot set " + prop.getName() + ": incompatible types."); } } catch (IllegalArgumentException e) { throw new SQLException("Cannot set " + prop.getName() + ": " + e.getMessage()); } catch (IllegalAccessException e) { throw new SQLException("Cannot set " + prop.getName() + ": " + e.getMessage()); } catch (InvocationTargetException e) { throw new SQLException("Cannot set " + prop.getName() + ": " + e.getMessage()); } } private boolean isCompatibleType(Object value, Class
    type) { if (value == null || type.isInstance(value)) { return true; } else if (type.equals(Integer.TYPE) && Integer.class.isInstance(value)) { return true; } else if (type.equals(Long.TYPE) && Long.class.isInstance(value)) { return true; } else if (type.equals(Double.TYPE) && Double.class.isInstance(value)) { return true; } else if (type.equals(Float.TYPE) && Float.class.isInstance(value)) { return true; } else if (type.equals(Short.TYPE) && Short.class.isInstance(value)) { return true; } else if (type.equals(Byte.TYPE) && Byte.class.isInstance(value)) { return true; } else if (type.equals(Character.TYPE) && Character.class.isInstance(value)) { return true; } else if (type.equals(Boolean.TYPE) && Boolean.class.isInstance(value)) { return true; } return false; }}

    工具类 DBUtil

    为了简化数据库连接的管理,我们开发了一个 DBUtil 工具类:

    package com.zzzy.book.manage.util;import java.sql.Connection;import java.sql.DriverManager;import java.sql.PreparedStatement;import java.sql.ResultSet;import java.sql.SQLException;public final class DBUtil {    private DBUtil() {    }    public static Connection getConn() {        String url = "jdbc:mysql://localhost:3306/test?characterEncoding=utf-8";        String user = "root";        String password = "1913599913";        Connection connection = null;        try {            Class.forName("com.mysql.jdbc.Driver");            connection = DriverManager.getConnection(url, user, password);        } catch (ClassNotFoundException e) {            e.printStackTrace();        } catch (SQLException e) {            e.printStackTrace();        }        return connection;    }    public static void closeConn(Connection conn) {        try {            if (conn != null && !conn.isClosed()) {                conn.close();            }        } catch (Exception e) {            e.printStackTrace();        }    }    public static void closeResource(Connection conn, PreparedStatement ps) {        try {            if (ps != null && !ps.isClosed()) {                ps.close();            }            if (conn != null && !conn.isClosed()) {                conn.close();            }        } catch (Exception e) {            e.printStackTrace();        }    }    public static void closeResource(Connection conn, PreparedStatement ps, ResultSet rs) {        try {            if (ps != null && !ps.isClosed()) {                ps.close();            }            if (rs != null && !rs.isClosed()) {                rs.close();            }            if (conn != null && !conn.isClosed()) {                conn.close();            }        } catch (Exception e) {            e.printStackTrace();        }    }}

    使用效果

    通过 QueryRunner 工具类和 DBUtil 类,开发者可以快速完成数据库操作。以下是一个简单的使用示例:

    Connection conn = DBUtil.getConn();Student student = new QueryRunner(conn).query("SELECT id, name, time FROM student WHERE id=1", Student.class);System.out.println(student);

    总结

    通过以上方法,开发者可以轻松地将 JDBC 返回值映射到对应的 JavaBean 实体类中。 QueryRunner 工具类提供了从数据库到 Java 对象的自动转换功能,使开发过程更加高效和简便。

    转载地址:http://pmulz.baihongyu.com/

    你可能感兴趣的文章
    mysql_secure_installation初始化数据库报Access denied
    查看>>
    MySQL_西安11月销售昨日未上架的产品_20161212
    查看>>
    Mysql——深入浅出InnoDB底层原理
    查看>>
    MySQL“被动”性能优化汇总
    查看>>
    MySQL、HBase 和 Elasticsearch:特点与区别详解
    查看>>
    MySQL、Redis高频面试题汇总
    查看>>
    MYSQL、SQL Server、Oracle数据库排序空值null问题及其解决办法
    查看>>
    mysql一个字段为空时使用另一个字段排序
    查看>>
    MySQL一个表A中多个字段关联了表B的ID,如何关联查询?
    查看>>
    MYSQL一直显示正在启动
    查看>>
    MySQL一站到底!华为首发MySQL进阶宝典,基础+优化+源码+架构+实战五飞
    查看>>
    MySQL万字总结!超详细!
    查看>>
    Mysql下载以及安装(新手入门,超详细)
    查看>>
    MySQL不会性能调优?看看这份清华架构师编写的MySQL性能优化手册吧
    查看>>
    MySQL不同字符集及排序规则详解:业务场景下的最佳选
    查看>>
    Mysql不同官方版本对比
    查看>>
    MySQL与Informix数据库中的同义表创建:深入解析与比较
    查看>>
    mysql与mem_细说 MySQL 之 MEM_ROOT
    查看>>
    MySQL与Oracle的数据迁移注意事项,另附转换工具链接
    查看>>
    mysql丢失更新问题
    查看>>