博客
关于我
把 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/

    你可能感兴趣的文章
    Mysql5.7版本单机版my.cnf配置文件
    查看>>
    mysql5.7的安装和Navicat的安装
    查看>>
    mysql5.7示例数据库_Linux MySQL5.7多实例数据库配置
    查看>>
    Mysql8 数据库安装及主从配置 | Spring Cloud 2
    查看>>
    mysql8 配置文件配置group 问题 sql语句group不能使用报错解决 mysql8.X版本的my.cnf配置文件 my.cnf文件 能够使用的my.cnf配置文件
    查看>>
    MySQL8.0.29启动报错Different lower_case_table_names settings for server (‘0‘) and data dictionary (‘1‘)
    查看>>
    MYSQL8.0以上忘记root密码
    查看>>
    Mysql8.0以上重置初始密码的方法
    查看>>
    mysql8.0新特性-自增变量的持久化
    查看>>
    Mysql8.0注意url变更写法
    查看>>
    Mysql8.0的特性
    查看>>
    MySQL8修改密码报错ERROR 1819 (HY000): Your password does not satisfy the current policy requirements
    查看>>
    MySQL8修改密码的方法
    查看>>
    Mysql8在Centos上安装后忘记root密码如何重新设置
    查看>>
    Mysql8在Windows上离线安装时忘记root密码
    查看>>
    MySQL8找不到my.ini配置文件以及报sql_mode=only_full_group_by解决方案
    查看>>
    mysql8的安装与卸载
    查看>>
    MySQL8,体验不一样的安装方式!
    查看>>
    MySQL: Host '127.0.0.1' is not allowed to connect to this MySQL server
    查看>>
    Mysql: 对换(替换)两条记录的同一个字段值
    查看>>