JDBC 的简单封装,以sqlite数据库为例

2023-11-20

* 小驼峰会自动转下划线
* Column 注解会覆盖其他策略,就取name名字作为字段名
* Table 注解可以重新标记表名

1.主要方法就是save和list两个方法,调用实例如下

package xin.tom.esui.db;
import org.junit.Test;
import xin.tom.esui.entity.ConnectionEntity;

import java.util.List;


public class SqliteDataSourceConfigTest
{
    @Test
    public void testSave()
    {
        ConnectionEntity connectionEntity = new ConnectionEntity("爱的色放",
                "127.0.0.1",8866,"root","1234556","notuse");

       SqliteDataSourceConfig.save(connectionEntity);
    }

    @Test
    public void testList()
    {
        List<ConnectionEntity> list = 
        SqliteDataSourceConfig.list("select * from connections", ConnectionEntity.class);
        System.out.println(list);
    }

}

2.核心代码如下,有需要自己改

package xin.tom.esui.db;

import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.pool.DruidPooledConnection;

import javax.persistence.Column;
import javax.persistence.Table;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.*;

import static xin.tom.esui.util.StringUtils.*;

/**
 * @author guolinyuan
 */
public class SqliteDataSourceConfig
{
    // 主配置的数据库地址
    private static final String mainDBUrl = System.getProperty("user.home") + "/Documents//esui/esui.db";
    // 连接数据库的数据源
    private static final DruidDataSource dataSource = new DruidDataSource();

    static
    {
        //检测是否存在数据库文件,若没有,创建新的数据库文件
        createDBIfNotExit();

        // 数据源配置
        dataSource.setUrl("jdbc:sqlite:" + mainDBUrl);
        dataSource.setDriverClassName("org.sqlite.JDBC");
        dataSource.setValidationQuery("select 1");
        // 失败后重连的次数置为0,本地文件不可能失败
        dataSource.setConnectionErrorRetryAttempts(0);
        // 请求失败之后中断
        dataSource.setBreakAfterAcquireFailure(true);
    }

    /**
     * 检测是否存在数据库文件,若没有,创建新的数据库文件
     * todo 应该复制初始化的sqlite文件来处理,而不是创建新的空文件
     */
    @SuppressWarnings("ResultOfMethodCallIgnored")
    private static void createDBIfNotExit()
    {
        File file = new File(mainDBUrl);
        if (!file.exists())
        {
            try
            {
                file.getParentFile().mkdirs();
                file.createNewFile();
            }
            catch (IOException e)
            {
                e.printStackTrace();
            }
        }
    }

    /**
     * 执行sql,将结果存到指定的类型list中,
     * 如果字段匹配不到,则抛弃,支持@Column改变字段名
     *
     * @param sql 要执行的sql
     * @param clazz 指明数据类型
     * @param <T> 指明数据类型
     * @return
     */
    public static <T> List<T> list(String sql, Class<T> clazz)
    {
        List<T> list = new ArrayList<>();
        // 会自动关闭
        try (DruidPooledConnection conn = dataSource.getConnection();
             Statement statement = conn.createStatement())
        {
            //执行sql返回结果
            ResultSet rs = statement.executeQuery(sql);
            while (rs.next())
            {
                //创建对象实例
                T po = clazz.newInstance();
                //查出目标对象所有的属性
                Field[] fields = clazz.getDeclaredFields();
                for (Field field : fields)
                {
                    //目标对象的类型名称,会拼接成类似于getInteger一类的方法名
                    String poTypeName = field.getType().getSimpleName();
                    //目标对象的属性名
                    String poFieldName = field.getName();
                    //目标对象的设置数据的方法名
                    String poSetMethodName = "set" + upperFirst(poFieldName);

                    //sql的对应字段名,@Column注解有的话,按照注解name值,否则就是属性名
                    String dbFieldName = getDbFieldName(field);
                    //ResultSet获取查询结果对象的值的方法名
                    String dbGetMethodName = getDbGetMethodName(poTypeName);

                    //从结果中获取实体字段名的值,如果有注解@Column照注解name值,否则就是属性名
                    //如果实体类型为RS中不存在get方法的类型,比如Hashmap,因为数据库没有hashmap类型对应
                    //但字段又匹配上了,直接抛弃此字段的注入
                    Object value;
                    try
                    {
                        //获取数据库字段值
                        Method rsGetMethod = ResultSet.class.getMethod(dbGetMethodName, String.class);
                        value = rsGetMethod.invoke(rs, dbFieldName);
                        //调用实体的set方法注入
                        //value为null时获取类型会空指针,直接不注入就行
                        if (value != null)
                        {
                            Method method = clazz.getMethod(poSetMethodName, value.getClass());
                            method.invoke(po, value);
                        }
                    }
                    catch (NoSuchMethodException ex)
                    {
                        //此字段无法注入,不处理
                    }
                }
                list.add(po);
            }
        }
        catch (SQLException | InstantiationException | IllegalAccessException | InvocationTargetException throwable)
        {
            throwable.printStackTrace();
        }

        return list;
    }

    /**
     * 按照指定对象插入到数据库,名称为类名
     * 字段为字段名
     * @param object
     */
    public static void save(Object object)
    {
        // 解析实体内容
        Class<?> clazz = object.getClass();
        Field[] fields = clazz.getDeclaredFields();
        String className = clazz.getName();
        String tableName;
        Table clazzAnnotation = clazz.getAnnotation(Table.class);
        if (clazzAnnotation != null)
        {
            tableName = clazzAnnotation.name();
        }
        else
        {
            tableName = lowerFirst(className);
        }
        Map<String, Object> valueMap = new LinkedHashMap<>(fields.length);
        for (Field field : fields)
        {
            String poFieldName = field.getName();
            String dbFieldName = getDbFieldName(field);
            try
            {
                //fixme 这里不处理is的情况
                Method method = clazz.getMethod("get" + upperFirst(poFieldName));
                Object value = method.invoke(object);
                String key;
                Column fieldAnnotation = field.getAnnotation(Column.class);
                if (fieldAnnotation != null)
                {
                    key = fieldAnnotation.name();
                }
                else
                {
                    key = dbFieldName;
                }

                valueMap.put(key, value);
            }
            catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e)
            {
                System.out.println("已忽略字段" + field + e.getMessage());
            }
        }

        //执行sql
        try (DruidPooledConnection conn = dataSource.getConnection();
             Statement statement = conn.createStatement())
        {
            String sql = buildInsertSql(valueMap, tableName);
            System.out.println(sql);
            boolean b = statement.execute(sql);
            System.out.println("rs: " + b);
        }
        catch (SQLException throwable)
        {
            throwable.printStackTrace();
        }
    }

    private static String getDbFieldName(Field field)
    {
        Column fieldAnnotation = field.getAnnotation(Column.class);
        if (fieldAnnotation != null)
        {
            return fieldAnnotation.name();
        }
        else
        {
            return humpToUnderline(field.getName());
        }
    }

    private static String getDbGetMethodName(String poTypeName)
    {
        String typeSuffix;
        if (poTypeName.equals("Integer"))
        {
            typeSuffix = "Int";
        }
        else
        {
            typeSuffix = poTypeName;
        }
        return "get" + typeSuffix;
    }

    private static String buildInsertSql(Map<String, Object> valueMap, String tableName)
    {
        //处理数据为2个StringBuilder,获取tableName,构造sql
        StringBuilder keys = new StringBuilder();
        StringBuilder values = new StringBuilder();
        valueMap.forEach((s, o) ->
        {
            keys.append(s).append(",");
            if (o != null)
            {
                values.append("'").append(o).append("',");
            }
            else
            {
                values.append("'null',");
            }
        });
        keys.deleteCharAt(keys.length() - 1);
        values.deleteCharAt(values.length() - 1);
        return "INSERT INTO " + tableName + " (" + keys + ") VALUES (" + values + ")";
    }
}

3.StringUtils类

package xin.tom.esui.util;

import java.util.Locale;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author guolinyuan
 */
public class StringUtils
{
    public static String upperFirst(String name)
    {
        char[] cs = name.toCharArray();
        cs[0] -= 32;
        return String.valueOf(cs);
    }

    public static String lowerFirst(String name)
    {
        char[] cs = name.toCharArray();
        cs[0] += 32;
        return String.valueOf(cs);
    }
    /**
     * 驼峰转下划线
     * @param str   目标字符串
     * @return: java.lang.String
     */
    public static String humpToUnderline(String str) {
        String regex = "([A-Z])";
        Matcher matcher = Pattern.compile(regex).matcher(str);
        while (matcher.find()) {
            String target = matcher.group();
            str = str.replaceAll(target, "_"+target.toLowerCase());
        }
        return str;
    }

    /**
     * 下划线转驼峰
     * @param str   目标字符串
     * @return: java.lang.String
     */
    public static String underlineToHump(String str) {
        String regex = "_(.)";
        Matcher matcher = Pattern.compile(regex).matcher(str);
        while (matcher.find()) {
            String target = matcher.group(1);
            str = str.replaceAll("_"+target, target.toUpperCase());
        }
        return str;
    }


}

4.引入代码包

 <dependency>
      <groupId>com.alibaba</groupId>
      <artifactId>druid</artifactId>
      <version>1.2.8</version>
    </dependency>
    <dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
      <version>1.18.22</version>
      <scope>provided</scope>
    </dependency>
    <dependency>
      <groupId>javax.persistence</groupId>
      <artifactId>javax.persistence-api</artifactId>
      <version>2.2</version>
    </dependency>

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

JDBC 的简单封装,以sqlite数据库为例 的相关文章

  • Flask 管理数据库连接:内存:

    我有一个烧瓶应用程序 需要存储请求中的一些信息 这些信息的生命周期非常短暂 如果服务器重新启动 我就不再需要它了 所以我真的不需要持久性 我读过了here https stackoverflow com questions 11113903
  • 如何打开sqlite数据库并将其转换为pandas dataframe

    我已经下载了一些数据作为 sqlite 数据库 data db 我想在 python 中打开这个数据库 然后将其转换为 pandas 数据框 这是到目前为止我所做的 import sqlite3 import pandas dat sqli
  • 关于ORA 21000

    我正在与 ORA 21000 作斗争 上面写着ORA 21000 raise application error 的错误号参数 3739 超出范围 此错误间歇性出现 我不知道为什么会发生这种情况 早些时候这工作得很好 但是从 Solaris
  • 同时使用实体框架与 SQL Server 和 SQLite 数据库

    我有一个用于测试目的的 C Net 4 0 控制台应用程序 使用 VS 2012 我的目标是能够创建一个可在 MS SQL Server 数据库和 SQLite 数据库上使用的单个实体框架 edmx 文件 基本上 我想使用相同的实体模型类和
  • Django - 没有名为 _sqlite3 的模块

    我在 rhel 5 上安装了 django 1 4 默认情况下 rhel 5 中有 python 2 4 但要使用 django 1 4 我手动安装了 python 2 7 3 开发服务器运行良好 但是当我创建一个新项目并将 setting
  • 如何将两个django模型(表)合并为一个模型(表)

    我想合并两个 django 模型并创建单个模型 我们假设 我有第一个表表 A 其中包含一些列和数据 Table A col1 col2 col3 col4 x1 x2 x3 x4 y1 y2 y3 y4 我还有另一个表 Table B 其中
  • 如果 db 有主字段,如何将 N 个 SQLite 数据库文件合并为一个?

    我有一堆 SQLite 数据库文件 我需要将它们合并成一个大数据库文件 我怎样才能做到这一点 Added 基于this http old nabble com Attempting to merge large databases td18
  • 数百个别名/同义词与数据库表的完全限定名称

    考虑到多个模式中的数百个数据库表 在创建存储过程和视图时 您是否建议使用别名 同义词或完全限定名称 给定一些 schema table 像这样 Orders OrderHeader Production LineThroughput Sal
  • 时间序列数据的键值存储?

    我一直在使用 SQL Server 存储数十万个对象的历史时间序列数据 每天观察大约 100 次 我发现查询 给我时间 t1 和时间 t2 之间对象 XYZ 的所有值 太慢 对于我的需要 慢超过一秒 我按时间戳和对象 ID 建立索引 我考虑
  • 在 Python 中使用 SQLCipher - 最简单的方法 [重复]

    这个问题在这里已经有答案了 我正在编写一个可以在加密的 SQLite 数据库上运行的 Python 实用程序 最终我会将此类实用程序转换为可执行文件 以便更轻松地交付给团队的其他成员 我读了很多关于 SQLCipher 的页面 但他们都谈论
  • PostgreSQL 中字符串列类型的索引数组

    是否可以在类型为的列上创建索引文本数组 尝试使用GIN索引 但查询似乎没有使用这些索引 Example CREATE TABLE users name VARCHAR 100 groups TEXT Query SELECT name FR
  • 如何使用 Sqlite3 用列表中的值更新整个列

    我有一个数据集本地存储在 sqlite3 数据库中 我提取了一列 执行了一些操作 现在想要替换数据库列中的所有值 我怎样才能做到这一点 保证列和列表的长度相同 我只想用新值更新表 有没有一种简单的方法可以一次性完成这一切 使用Python
  • PHP 中的 MongoDB - 如何将项目插入集合中的数组中?

    这必须很容易 但我似乎无法弄清楚 假设我有一个集合users这是集合中的第一项 id ObjectId 4d8653c027d02a6437bc89ca name Oscar Godson email email protected cdn
  • SQlite 获取最近的位置(带有纬度和经度)

    我的 SQLite 数据库中存储有纬度和经度的数据 我想获取距我输入的参数最近的位置 例如我当前的位置 纬度 经度等 我知道这在 MySQL 中是可能的 并且我已经做了相当多的研究 SQLite 需要一个自定义外部函数来实现半正弦公式 计算
  • Scrapy - 持续从数据库中获取要爬取的url

    我想不断地从数据库中获取要爬行的网址 到目前为止 我成功地从基地获取了 url 但我希望我的蜘蛛继续从该基地读取 因为该表将由另一个线程填充 我有一个管道 一旦爬行 工作 就会从表中删除 url 换句话说 我想使用我的数据库作为队列 我尝试
  • 将 Android 应用程序从 Lite 升级到 Pro 版本时保持相同的 SQLite 数据库

    首先 我已经进行了搜索 但找不到我的问题的具体答案 所以这里是 我正在编写我的第一个 Android 应用程序 并计划拥有 Lite 版本 有限功能 和付费版本 完整功能 Lite 和 Pro 版本将使用相同的 SQLite 数据库结构 如
  • fetchsize和batchsize对Spark的影响

    我想通过以下方式控制 RDB 的读写速度Spark直接 但标题已经透露的相关参数似乎不起作用 我可以得出这样的结论吗fetchsize and batchsize我的测试方法不起作用 或者它们确实会影响阅读和写作方面 因为测量结果基于规模是
  • 如何在 Visual Studio 中更改 Azure 数据库表的列顺序

    我整个下午都在寻找在 MS Visual Studio 2022 中重新排序 Azure 数据库表列的方法 没有运气 在其他应用程序中 可以通过拖动或剪切和粘贴轻松重新排列列 这里无能为力 此时 我什至不确定可以在 VS 中移动列 我只对
  • 如何在不运行 PostgreSQL 服务器的情况下初始化 PostgreSQL 数据库

    在初始化脚本中 我想初始化 PostgreSQL 目录 但在此阶段不需要 也不希望 正在运行的 PostgreSQL 服务器 如果我只是创建集群 作为用户postgres initdb D 但是 我还需要创建 PostgreSQL 角色 创
  • 尝试将 SQLite DB 从数据复制到 SD 卡

    我正在使用以下代码 该代码发布在 Stack Overflow 上的某个位置 并根据我的目的进行了修改 try File sd Environment getExternalStorageDirectory File data Enviro

随机推荐

  • 【数据库MySQL】-- 视图的作用和使用

    首先介绍一下什么是视图 视图 view 是一种虚拟存在的表 视图中的数据并不在数据库中实际存在 行和列数据来自定义视图的查询中使用的表 并且是在使用视图时动态生成的 通俗的讲 视图只保存了查询的SQL逻辑 不保存查询结果 所以我们在创建视图
  • 北森,SaaS风口上的「新范式」

    在单纯的战略表象背后 成立19年 北森在每一个节点做选择的核心驱动力是什么 这家公司是否拥有自己内部的 组织密码 作者 皮爷 出品 产业家 2013年 纪伟国决定要去美国 取取经 和他同行的还有参与了北森A轮融资的经纬等机构投资人 对于北森
  • IDEA关联MySQL数据库时报错 “Server returns invalid timezone. Go to ‘Advanced‘ tab and set ‘server......”

    具体报错 Server returns invalid timezone Go to Advanced tab and set serverTimezone property manually 解决办法参考 https blog csdn
  • 简单又漂亮:小白入门网页制作

    网页大家平时见的非常多 有的网页简约 有的网页很华丽 那么今天我就来分享一下制作网页的基本操作 就以下面这个网页为例 1 制作网页需要用到的工具 写网页不需要很多工具 因为写出来的网页只是一张图片 没有添加与后台的交互 所以只需要使用HTM
  • vue中使用Echarts地理地图并结合高德地图实现一个国、省、市、区的地图下钻功能

    vue中使用Echarts地理地图并结合高德地图实现一个国 省 市 区的地图下钻功能 一 需求 按不同的层级展示不同的内容 1 中国地图 2 省级地图 3 市级地图 4 县和区以下的地图 二 开发 1 Echarts和地图容器的设置 相关代
  • 优化网站DNS域名解析 进一步提升访问速度

    提高网页的打开速度 一般地我们会选择使用CDN 利用 就近原则 让用户在最短的时间内获取到服务器资源 实际应用当中采用CDN的方式提高网站访问速度的效果也是最明显的 这也就是为什么国外的空间打开速度远不及国内的主机的访问速度的原因了 我们知
  • 1、二层交换机VLAN的划分

    目录 1 手动配置主机IP地址 2 创建vlan 在交换机的全局配置模式下进行 3 分配vlan端口 1 逐一添加 2 分组添加 4 查看vlan配置 1 手动配置主机IP地址 PC PT IP SM PC0 192 168 0 11 25
  • Ubuntu20.04部署android版mediapipe踩坑记录(持续更新。。。)

    1 Android SDK 以及NDK版本问题 根据mediapipe官方文档 SDK要求在28 0 3版本及以上 NDK版本要求介于18和21之间 若版本超出范围容易引发未知的问题 导致无效加班到怀疑人生 注意 SDK build too
  • 机器学习最经典算法-SVM支持向量机-【基本解读算法+详细实际案例分部流程】

    支持向量机 SVM SVM算法可谓是最经典的机器学习算法了 具有泛化错误率低 分类速度快 结果易解释等特点多多 在应用领域涉及非常广 比如人像识别 文本分类 手写字符识别 人脸识别 生物信息学等等等 同时算法模型评估效果也是很优秀的 它为何
  • React 单元测试策略及落地

    写好的单元测试 对开发速度 项目维护有莫大的帮助 前端的测试工具一直推陈出新 而测试的核心 原则却少有变化 与产品代码一并交付可靠的测试代码 是每个专业开发者应该不断靠近的一个理想之地 本文就围绕测试讲讲 为什么我们要做测试 什么是好的测试
  • 自然语言处理nltk下载以及nltk_data下载及其所遇问题解决方案

    目录 一 nltk的下载 二 nltk data 下载 三 解压 nltk data 存放目录可能会出现的问题 一 nltk的下载 新建虚拟环境 conda activate n NLP python 3 8 创建虚拟环境方便管理 激活虚拟
  • IC Compiler指南——数据准备

    一 概述 ICC数据设置的文件关系框图如图 后端工具在数据设置阶段需要对两大类数据进行设置 包括从前端设计继承的综合数据 以及后端设计需要的物理数据 综合数据主要包括前端逻辑综合已经设置过的逻辑与时序库文件 设计约束文件sdc以 及综合网表
  • FileZilla尝试连接“ECONNREFUSED - 连接被服务器拒绝”失败。

    考虑是否在ubuntu下开启了FTP服务 执行以下命令开启 sudo apt get install vsftpd 不能远程登陆 mobaxterm等 unbutu 考虑是否开启了SSH 使用以下命令开启 sudo apt get inst
  • 互联网创业项目整合:提高成功率的关键方法

    互联网创业是当前非常火热的话题 但是市场竞争也异常激烈 成功率不高 今天 我来分享一些互联网创业项目整合的方法 帮助大家创造更大的机会 1 选择适合自己的领域 在选择创业项目时 一定要根据自己的专业 兴趣 经验等因素进行选择 才能更好地发挥
  • clion file and code templates

    主要用于 文件命名为 my class 时 生成的类为 MyClass c class header 和 都是被分割的对象 parse C File Header h ifndef INCLUDE GUARD define INCLUDE
  • L1-039 古风排版(C语言)(测试点2)

    题目 L1 039 古风排版 分数 20 作者 陈越 单位 浙江大学 中国的古人写文字 是从右向左竖向排版的 本题就请你编写程序 把一段文字按古风排版 输入格式 输入在第一行给出一个正整数N lt 100 是每一列的字符数 第二行给出一个长
  • Flickr30k图像标注数据集下载及使用方法

    Flickr30k数据集的下载 可在http shannon cs illinois edu DenotationGraph 中填表 获取下载地址http shannon cs illinois edu DenotationGraph da
  • 【深入理解C++】转发、完美转发、std::forward

    文章目录 1 转发 2 完美转发 3 std forward和std move的区别 4 参考资料 前置知识 万能引用 引用折叠 1 转发 include
  • SIM卡相关知识总结

    主题 SIM基本功能和原理 简介 参考 SIM卡工作原理总结 SIM卡插入检测原理 SIM卡的识卡机制 SIM卡基础技术规范 2 3 4 5G UE和网络鉴权流程的演进 作者 ybb 时间 2021年9月9日 1 初识SIM卡 SIM卡的物
  • JDBC 的简单封装,以sqlite数据库为例

    小驼峰会自动转下划线 Column 注解会覆盖其他策略 就取name名字作为字段名 Table 注解可以重新标记表名 1 主要方法就是save和list两个方法 调用实例如下 package xin tom esui db import o