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数据库为例 的相关文章

  • 使用数据库进行日志记录

    大多数日志似乎都是纯文本形式 而不是放入 MySQL 其他类型的数据库中 这是否有原因 在我看来 将它们放入数据库将使分析变得非常非常容易 但这会以牺牲速度还是其他什么为代价 我不太关心可移植性 显然你会有数据库连接的文本日志 我能想到两大
  • 如何使用sql脚本更改列的属性

    如何使用 sql 脚本更改列的属性 这是我尝试过但出现错误的方法 ALTER TABLE dbo tblBiometricPattern COLUMN BiometricPatternID TINYINT NOT NULL IDENTITY
  • 每个数据库多个/单个 *.edmx 文件

    我有一个通过 ADO net 数据服务与数据库交互的项目 数据库很大 近 150 个具有依赖关系的表 该项目几年前开始 当时使用的是数据集 现在我们正在转向实体模型关系 由于我们添加了更多需要使用的表 该模型正在不断增长 这是管理这一切的正
  • 如何根据条件删除结果以计算平均值

    我有下面的架构 对其的快速解释是 鲍勃评分为 5 5 詹姆斯评分 1 5 梅西百货评分高达 5 5 逻辑 如果我是 A 请查找我屏蔽的所有人 查阅所有电影评论 任何留下电影评论且 personA 已屏蔽的人 请将其从计算中删除 计算电影的平
  • 如何确保与 sqlite 和 NFS 的文件安全同步

    我最近将应用程序的工作区文件格式转换为 sqlite 为了确保 NFS 上的稳健操作 我使用了通用更新策略 对本地硬盘上临时位置中存储的副本进行了所有修改 仅在保存时 我才会通过使用临时文件复制原始文件来修改原始文件 可能在 NFS 上 我
  • SQL 按计数排序

    如果我有一个表和这样的数据 ID Name Group 1 Apple A 2 Boy A 3 Cat B 4 Dog C 5 Elep C 6 Fish C 我希望根据 Group 的总和从小到大进行排序 例如 A 2条记录 B 1条记录
  • 使用 sqlite 离线存储数据的 Web 表单应用程序

    我有一个 asp net Web 表单应用程序 它在远程服务器上使用 sql server 2005 所有控件均使用 linq to sql 绑定 我正在尝试提供完整的离线功能 所以我想知道是否可以像 sql server db 一样创建一
  • Hibernate saveOrUpdate 与更新与保存/持久

    我正在努力理解休眠方法之间的细微差别 saveOrUpdate update save persist 我知道网站上有一些类似的问题 Hibernate中不同的保存方式有什么区别 https stackoverflow com questi
  • 打印表数据mysql php

    我在尝试打印表格的一些数据时遇到问题 我是 php mysql 的新手 但我认为我的代码是正确的 这里是 h1 Lista de usu rios h1
  • 如何使用 C# 查询远程 MS ACCESS .mdb 数据库

    我正在尝试使用 C 查询 mote MS ACCESS 数据库 mdb 文件 将文件复制到本地计算机时可以成功查询它 我只想远程放置文件 所以我的客户端程序不包含原始数据 static string m path http www xyz
  • Django 中从 sqlite 迁移到 postgresql

    我想迁移自sqlite to PostgreSQL db 我安装了 postgresql 并在其 shell 上创建数据库 然后配置我的 django 设置如下 default ENGINE django db backends postg
  • Windows 7 x64 上的 Ruby on Rails SQLite 问题

    当我尝试做的时候db create使用 Windows 7 x64 在具有此数据库配置的 sqlite 数据库上 development adapter sqlite3 database db development sqlite3 tim
  • SQLite 返回错误的 2013 年周数?

    我有一个简单的 SQL 来计算 SQLite 报告中的周数 SELECT STRFTIME W date column 2009 2012 年的数据是正确的 2013 年我总是得到错误的周数 例如 SELECT STRFTIME W 201
  • 从对象定义生成数据库表

    我知道有几种 自动 方法可以创建数据访问层来操作现有数据库 LINQ to SQL Hibernate 等 但我有点厌倦了 我相信应该有更好的做事方式 比如 在 Visio 中创建 更改表 使用 Visio 的 更新数据库 创建 更改数据库
  • dbms_xmlgen.getxml - 如何设置日期格式

    我们使用 dbms xmlgen getxml 实用程序通过 SQL 查询生成 xml 该查询从几乎 10 15 个相关表中获取数据 默认情况下 日期格式生成于dd MMM yy格式 有什么方法可以在 dbms xmlgen getxml
  • 插入具有只读主键列的表

    我正在使用一个使用 sql server 数据库的应用程序 我试图在表中插入一行 如下所示 该表有一个主键 prodNum 这是自动生成的密钥 当我尝试向表中插入一行时 如下所示 在行中intResult oSglProdTableAdap
  • ALTER TABLE 语句与 FOREIGN KEY 约束冲突

    为什么要添加外键tblDomare表导致此错误 ALTER TABLE 语句与 FOREIGN KEY 约束 FK tblDomare PersN 5F7E2DAC 冲突 冲突发生在数据库 almu0004 表 dbo tblBana 列
  • 如何在 sqlite 中将 2 列合并为新列

    我有一个包含 3 列的表 我必须将 2 列中的值按降序排列到一列中 A B C z 1 2 f 5 7 s 9 5 使用此示例 输出会将 B 列和 C 列中的值放入其中 如下所示 A B s 9 f 7 f 5 s 5 z 2 z 1 我当
  • SQLite 仅当值不为空时更新列

    Query UPDATE item table SET field1 field1 spanish field2 field2 spanish 问题 我怎样才能更新field1 with field1 spanish ONLY if fie
  • MySQL 概念:会话与连接

    我对 MySQL 的概念有点困惑 会话与连接 当谈论连接到 MySQL 时 我们使用连接术语 连接池等 然而在 MySQL 在线文档中 http dev mysql com doc refman 4 1 en server system v

随机推荐

  • 【数据库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