Java泛型与数据库应用实例详解

Java泛型与数据库应用实例详解

什么是Java泛型?

Java泛型是Java SE 5中引入的一项语言特性,它提供了一种编写泛化代码的方法,能够提高代码的通用性和复用性,从而提高了代码的可维护性和可扩展性。

Java泛型的语法

Java泛型使用尖括号<>来规定类型参数,语法格式如下:

public class GenericClass<T1, T2, ..., Tn>{
    //泛型类或者接口体
}

泛型类或者接口体可以包含泛型方法,泛型方法的语法格式如下:

public <T> R methodName(T arg1, arg2, ..., argn){
    //泛型方法体
}

Java泛型应用于数据库操作

Java的数据库操作通常需要使用JDBC(Java DataBase Connectivity)的API,JDBC API提供了一组接口和类,可以访问各种不同类型的数据库。在使用JDBC实现数据库操作的时候,需要考虑以下几个问题:

  1. 如何获取数据库连接?
  2. 如何进行SQL操作?
  3. 如何释放数据库连接?

下面将分别讲解这三个问题。

如何获取数据库连接?

Java数据库连接通常需要使用DataSource或DriverManager两种方式获取连接,具体介绍如下:

使用DataSource获取数据库连接

DataSource是Java EE规范中定义的接口,提供了获取数据库连接和释放数据库连接的方法。DataSource编码如下:

// 加载配置文件获取DataSource
DataSource ds = (DataSource)
                new InitialContext().lookup("java:comp/env/jdbc/myDataSource");
// 获取Connection对象
Connection conn = ds.getConnection();

这种方式最大的优点是可以方便地进行数据库连接池配置,提高了数据库连接的复用性和扩展性。

使用DriverManager获取数据库连接

DriverManager是JDBC API提供的一个类,它提供了获取数据库连接的静态方法。DriverManager编码如下:

// 加载数据库驱动
Class.forName("com.mysql.jdbc.Driver");
// 获取数据库连接
Connection conn = DriverManager.getConnection(url, username, password);

这种方式最大的优点是简单方便,便于单独测试和调试。

如何进行SQL操作?

JDBC API提供了大量的接口和类,用于进行SQL操作。以下是使用JDBC API实现数据库插入和查询操作的示例代码:

数据库插入操作

Connection conn = null;
PreparedStatement stmt = null;
try{
    // 获取数据库连接
    conn = getConnection();
    // SQL语句
    String sql = "insert into user(name, age) values(?, ?)";
    // 创建PreparedStatement对象
    stmt = conn.prepareStatement(sql);
    // 设置参数值
    stmt.setString(1, "张三");
    stmt.setInt(2, 20);
    // 执行SQL语句
    int num = stmt.executeUpdate();
    System.out.println("插入" + num + "条记录");
} catch (SQLException e){
    e.printStackTrace();
} finally {
    // 释放资源
    try{
        if(stmt != null){
            stmt.close();
        }
        if(conn != null){
            conn.close();
        }
    } catch(SQLException e){
        e.printStackTrace();
    }
}

数据库查询操作

Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
try{
    // 获取数据库连接
    conn = getConnection();
    // SQL语句
    String sql = "select * from user where age=?";
    // 创建PreparedStatement对象
    stmt = conn.prepareStatement(sql);
    // 设置参数值
    stmt.setInt(1, 20);
    // 执行SQL语句
    rs = stmt.executeQuery();
    // 处理结果集
    while(rs.next()){
        System.out.println(rs.getInt("id") + ":" + rs.getString("name"));
    }
} catch (SQLException e){
    e.printStackTrace();
} finally {
    // 释放资源
    try{
        if(rs != null){
            rs.close();
        }
        if(stmt != null){
            stmt.close();
        }
        if(conn != null){
            conn.close();
        }
    } catch(SQLException e){
        e.printStackTrace();
    }
}

如何释放数据库连接?

JDBC连接是一种稀缺的资源,连接不当会导致系统性能下降。释放数据库连接的方式有两种:

自动释放

JDBC连接池可以根据一定的策略来自动回收链接,释放连接资源。可以使用数据库连接池工具来实现该功能。

手动释放

手动释放数据库连接的方式是在使用完数据库连接后,显式地将连接对象、Statement对象、ResultSet对象的引用置为空,表示不再使用该资源。示例代码如下:

Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
try{
    // 获取数据库连接
    conn = getConnection();
    // SQL语句
    String sql = "select * from user where age=?";
    // 创建PreparedStatement对象
    stmt = conn.prepareStatement(sql);
    // 设置参数值
    stmt.setInt(1, 20);
    // 执行SQL语句
    rs = stmt.executeQuery();
    // 处理结果集
    while(rs.next()){
        System.out.println(rs.getInt("id") + ":" + rs.getString("name"));
    }
} catch (SQLException e){
    e.printStackTrace();
} finally {
    // 释放资源
    try{
        if(rs != null){
            rs.close();
            rs = null;
        }
        if(stmt != null){
            stmt.close();
            stmt = null;
        }
        if(conn != null){
            conn.close();
            conn = null;
        }
    } catch(SQLException e){
        e.printStackTrace();
    }
}

实例一:使用Java泛型批量插入数据

假设有一个用户实体类User,包含id、name、age三个属性。现在需要将一批用户信息插入数据库,可以使用Java泛型来实现。

public class JdbcUtil {

    //加载数据库驱动(使用MySQL数据库)
    private static final String DRIVER = "com.mysql.jdbc.Driver";

    //数据库连接信息
    private static final String URL = "jdbc:mysql://localhost:3306/test?" + "useUnicode=true&characterEncoding=utf8&useSSL=false";
    private static final String USERNAME = "root";
    private static final String PASSWORD = "mypassword";

    /**
     * 批量插入数据
     * @param sql 插入数据的SQL语句
     * @param dataList 数据列表
     * @return 插入成功的行数
     */
    public static <T> int batchInsert(String sql, List<T> dataList) throws SQLException {
        Connection conn = null;
        PreparedStatement stmt = null;
        int result = 0;
        try {
            conn = DriverManager.getConnection(URL, USERNAME, PASSWORD);
            stmt = conn.prepareStatement(sql);
            for (T data : dataList) {
                if (data != null) {
                    setPreparedStatementParameters(stmt, data);
                    stmt.addBatch();
                }
            }
            int[] rows = stmt.executeBatch();
            for (int i : rows) {
                if (i > 0) {
                    result++;
                }
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            closeConnection(conn, stmt, null);
        }
        return result;
    }

    /**
     * 设置PreparedStatement对象的参数值
     * @param stmt PreparedStatement对象
     * @param data 数据对象
     */
    private static <T> void setPreparedStatementParameters(PreparedStatement stmt, T data) throws SQLException {
        if (data instanceof User) {
            User user = (User) data;
            stmt.setString(1, user.getName());
            stmt.setInt(2, user.getAge());
        }
        //其他数据类型类似
    }

    /**
     * 关闭数据库连接和相关资源
     */
    private static void closeConnection(Connection conn, Statement stmt, ResultSet rs) {
        try {
            if (stmt != null) {
                stmt.close();
            }
            if (conn != null) {
                conn.close();
            }
            if (rs != null) {
                rs.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

实例二:使用Java泛型查询数据

假设有一个用户实体类User,包含id、name、age三个属性,现在需要根据用户id查询用户信息,可以使用Java泛型来实现。

public class JdbcUtil {

    //加载数据库驱动(使用MySQL数据库)
    private static final String DRIVER = "com.mysql.jdbc.Driver";

    //数据库连接信息
    private static final String URL = "jdbc:mysql://localhost:3306/test?" + "useUnicode=true&characterEncoding=utf8&useSSL=false";
    private static final String USERNAME = "root";
    private static final String PASSWORD = "mypassword";

    /**
     * 根据ID查找数据
     * @param sql 查询数据的SQL语句
     * @param clazz 被查询的对象类型
     * @param id ID
     * @return 查找到的数据
     */
    public static <T> T selectById(String sql, Class<T> clazz, int id) throws SQLException {
        Connection conn = null;
        PreparedStatement stmt = null;
        ResultSet rs = null;
        T result = null;
        try {
            conn = DriverManager.getConnection(URL, USERNAME, PASSWORD);
            stmt = conn.prepareStatement(sql);
            stmt.setInt(1, id);
            rs = stmt.executeQuery();
            if (rs.next()) {
                result = clazz.newInstance();
                ResultSetMetaData rsmd = rs.getMetaData();
                int columnCount = rsmd.getColumnCount();
                for (int i = 1; i <= columnCount; i++) {
                    String columnName = rsmd.getColumnLabel(i);
                    Object columnValue = rs.getObject(columnName);
                    setFieldValue(result, columnName, columnValue);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            closeConnection(conn, stmt, rs);
        }
        return result;
    }

    /**
     * 设置对象属性的值
     * @param obj 对象
     * @param fieldName 属性名
     * @param fieldValue 属性值
     */
    private static <T> void setFieldValue(T obj, String fieldName, Object fieldValue) throws Exception {
        Field field = obj.getClass().getDeclaredField(fieldName);
        field.setAccessible(true);
        field.set(obj, fieldValue);
    }

    /**
     * 关闭数据库连接和相关资源
     */
    private static void closeConnection(Connection conn, Statement stmt, ResultSet rs) {
        try {
            if (stmt != null) {
                stmt.close();
            }
            if (conn != null) {
                conn.close();
            }
            if (rs != null) {
                rs.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java泛型与数据库应用实例详解 - Python技术站

(0)
上一篇 2023年5月20日
下一篇 2023年5月20日

相关文章

  • Java实现简单学生管理系统

    Java实现简单学生管理系统攻略 1. 设计数据结构 在实现学生管理系统前,需要先考虑需要存储哪些数据。一般而言,学生的基本信息包括学号、姓名、年龄、性别等。我们可以使用一个类 Student 来存储这些信息。在 Student 类中定义需要存储的属性,并为其提供 getter 和 setter 方法。 示例代码: public class Student …

    Java 2023年5月23日
    00
  • SpringBoot配置和切换Tomcat流程详解

    关于SpringBoot配置和切换Tomcat的流程,我来为您详细讲解。 1. SpringBoot 配置 Tomcat 的默认端口 SpringBoot默认使用的Tomcat端口是8080,可以通过在配置文件中配置server.port来修改端口号,例如设置为8090端口,只需要按照以下步骤操作: 打开配置文件application.properties或…

    Java 2023年6月2日
    00
  • 浅谈SpringMVC请求映射handler源码解读

    以下是关于“浅谈SpringMVC请求映射handler源码解读”的完整攻略,其中包含两个示例。 浅谈SpringMVC请求映射handler源码解读 SpringMVC是一个基于MVC模式的Web框架,它的核心是请求映射handler。在本文中,我们将深入了解SpringMVC请求映射handler的源代码。 步骤一:创建Maven项目 打开IntJ ID…

    Java 2023年5月17日
    00
  • Java中常用解析工具jackson及fastjson的使用

    Java中常用解析工具jackson及fastjson的使用攻略 jackson 1. 简介 jackson是一种可以将java对象转换为JSON格式,也可以将JSON格式转换为java对象的工具。它为一个高性能的JSON处理库,是Spring框架的默认JSON格式解析工具,此外也逐渐成为Java领域内最流行的JSON解析器之一。 2. 快速开始 首先我们需…

    Java 2023年5月26日
    00
  • SpringBoot深入分析运行原理与功能实现

    SpringBoot深入分析运行原理与功能实现 什么是SpringBoot SpringBoot是一个开源的、轻量级的框架,用于快速构建基于Spring框架的Web应用程序和微服务。相对于传统的Spring框架,它更加简单方便,提供了自动配置、嵌入式Web服务器等特性,使得开发者可以快速构建可靠的、健壮的Web应用程序。 以下是SpringBoot的一些特性…

    Java 2023年5月15日
    00
  • 使用Spring Boot的原因解析

    使用Spring Boot的原因解析 前言 Spring Boot 是 Spring 家族的一个全新项目,它通过提供自动配置、快速开发等一系列优化,使得 Spring 应用的开发更加简单、快速、便捷。那么为什么我们要选择使用 Spring Boot 呢?下面本文将从以下几个方面为大家详细介绍 Spring Boot 的使用原因。 解析 1. 自动配置 Spr…

    Java 2023年5月15日
    00
  • skywalking自定义插件开发

    skywalking是使用字节码操作技术和AOP概念拦截Java类方法的方式来追踪链路的,由于skywalking已经打包了字节码操作技术和链路追踪的上下文传播,因此只需定义拦截点即可。 这里以skywalking-8.7.0版本为例。关于插件拦截的原理,可以看我的另一篇文章:skywalking插件工作原理剖析 1. 创建插件模块 在 apm-sniffe…

    Java 2023年4月25日
    00
  • Java实现经典游戏2048的示例代码

    以下是“Java实现经典游戏2048的示例代码”的完整攻略: 1. 确定游戏规则和逻辑 在开始编写游戏代码之前,需要先确认游戏规则和逻辑。2048游戏的规则是:玩家通过移动方块,让相同数字的方块叠加在一起,最终得到2048方块。每次移动时,所有方块会向移动的方向靠拢,相同数字的方块叠加在一起,如果四个方向都没有可以移动的方块,则游戏结束。 2. 创建代码框架…

    Java 2023年5月19日
    00
合作推广
合作推广
分享本页
返回顶部