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

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

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/

    你可能感兴趣的文章
    NN&DL4.3 Getting your matrix dimensions right
    查看>>
    NN&DL4.8 What does this have to do with the brain?
    查看>>
    No 'Access-Control-Allow-Origin' header is present on the requested resource.
    查看>>
    No fallbackFactory instance of type class com.ruoyi---SpringCloud Alibaba_若依微服务框架改造---工作笔记005
    查看>>
    No module named cv2
    查看>>
    No module named tensorboard.main在安装tensorboardX的时候遇到的问题
    查看>>
    No qualifying bean of type XXX found for dependency XXX.
    查看>>
    No resource identifier found for attribute 'srcCompat' in package的解决办法
    查看>>
    Node.js 文件系统的各种用法和常见场景
    查看>>
    node.js 配置首页打开页面
    查看>>
    node.js+react写的一个登录注册 demo测试
    查看>>
    Node.js安装与配置指南:轻松启航您的JavaScript服务器之旅
    查看>>
    nodejs libararies
    查看>>
    nodejs-mime类型
    查看>>
    nodejs中Express 路由统一设置缓存的小技巧
    查看>>
    Node入门之创建第一个HelloNode
    查看>>
    NotImplementedError: Cannot copy out of meta tensor; no data! Please use torch.nn.Module.to_empty()
    查看>>
    npm run build 失败Compiler server unexpectedly exited with code: null and signal: SIGBUS
    查看>>
    npm WARN deprecated core-js@2.6.12 core-js@<3.3 is no longer maintained and not recommended for usa
    查看>>
    npm和yarn的使用对比
    查看>>