flea-frame-db使用之基于EntityManager实现JPA分表的数据库操作【旧】

2023-11-12

引言

本文采用 EclipseLink的JPA实现,相关JPA接入使用请移步我的另外几篇博文

首先还是讨论一下,实现JPA分表的增删改查操作,我们需要做什么:

  • 分表规则定义(即从主表到分表的转换实现)
  • 分表操作实现(即EntityManager根据分表规则操作具体分表)

1. EntityManager持久化操作

常用接口方法如下:

	// 新增
	void persist(Object var1);
	// 更新
    <T> T merge(T var1);
	// 删除
    void remove(Object var1);
	// 查找
    <T> T find(Class<T> var1, Object var2);

下面来分析一下上述增删改查的接口方法实现:

org.eclipse.persistence.internal.jpa.EntityManagerImpl

  • persist
    入参 : 实体对象实例
    出参 : 无
    在这里插入图片描述
    org.eclipse.persistence.internal.sessions.UnitOfWorkImpl
    在这里插入图片描述

  • merge
    入参 : 实体对象实例
    出参 : 实体对象实例
    在这里插入图片描述在这里插入图片描述

  • remove
    入参 : 实体对象实例
    出参 : 无
    在这里插入图片描述在这里插入图片描述

  • find
    入参 : 实体类Class, 实体类主键
    出参 : 实体对象实例
    在这里插入图片描述

然后我们需要了解下getDescriptor方法的具体实现 :

org.eclipse.persistence.internal.sessions.AbstractSession
在这里插入图片描述
在这里插入图片描述
ClassDescriptor 最后都会被缓存到 lastDescriptorAccessed 变量。

最后切到debug视图,查看一下 ClassDescriptor,从中可以看到 与实际表名相关的 DatabaseTable
在这里插入图片描述
到了这一步,我们已经知道了表名存储在DatabaseTable中,要想实现分表操作,势必需要动态改变这里的值。

下面给出上述我们需要做的事情的解决方案:

2. 分表规则定义

实体类中定义的表名,我们可以理解为主表名;分表名的命名规则首先需要确定一下,定义如下配置:

<?xml version="1.0" encoding="UTF-8"?>
<tables>

	<!-- 定义分表配置
		name : 分表对应的主表名
		exp  : 分表名表达式 (FLEA_TABLE_NAME)_(列名大写)_(列名大写)
	-->
	<table name="flea_login_log" exp="(FLEA_TABLE_NAME)_(CREATE_DATE)" desc="Flea登录日志表分表规则">
		<splits>
			<!-- 定义分表后缀
				key : 分表类型关键字 (可查看 com.huazie.frame.db.common.table.split.TableSplitEnum )
				column : 分表属性列字段名
				implClass : 分表后缀转换实现类
			-->
			<split key="yyyymm" column="create_date" implClass="com.huazie.frame.db.common.table.split.impl.YYYYMMTableSplitImpl"/>
		</splits>
	</table>

</tables>

分表规则相关实现代码,可以移步 GitHub 查看 TableSplitHelper

3. 分表操作实现

在上述分表规则定义中, 我们可以看到分表名表达式exp是由 主表名 和 分表字段 组成,分表字段的转换实现规则由split定义。
分表处理者实现 EclipseLinkTableSplitHandler

	@Override
    public void handle(EntityManager entityManager, Object entity, boolean isRead) throws Exception {

        if (ObjectUtils.isEmpty(entityManager) || ObjectUtils.isEmpty(entity)) {
            return;
        }

        // 获取分表信息(包括主表名 和 分表名 【如果存在分表返回】)
        SplitTable splitTable = EntityUtils.getSplitTable(entity);

        // 存在分表,则需要操作具体分表
        if (StringUtils.isNotBlank(splitTable.getSplitTableName())) {
            // 获取可用的数据库会话对象
            AbstractSession session;
            if (isRead) {
                session = entityManager.unwrap(AbstractSession.class);
            } else {
                session = entityManager.unwrap(RepeatableWriteUnitOfWork.class);
            }
            // 重新设置 查询的分表表名
            session.getDescriptor(entity.getClass()).setTableName(splitTable.getSplitTableName());
        }
    }

JPA分表的增删改查操作相关代码可以 移步 GitHub 查看 AbstractFleaJPADAOImplEclipseLinkTableSplitHandler

4. 自测

自测类可以查看 LoginLogAuthTest

4.1 新增数据

	@Test
    public void testFleaLoginLogInsert() {
        try {
            IFleaLoginLogSV fleaLoginLogSV = (IFleaLoginLogSV) applicationContext.getBean("fleaLoginLogSV");
            FleaLoginLog fleaLoginLog = new FleaLoginLog();
            fleaLoginLog.setAccountId(1000000L);
            fleaLoginLog.setSystemAccountId(2000L);
            fleaLoginLog.setLoginIp4("127.0.0.1");
            fleaLoginLog.setLoginState(1);
            fleaLoginLog.setLoginTime(DateUtils.getCurrentTime());
            fleaLoginLog.setCreateDate(DateUtils.getCurrentTime());
            Long fleaLoginId = fleaLoginLogSV.getFleaNextValue(fleaLoginLog);
            fleaLoginLog.setLoginLogId(fleaLoginId);
            // 保存至分表
            fleaLoginLogSV.save(fleaLoginLog);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

4.2 查询数据

	@Test
    public void testFleaLoginLogQuery() {
        try {
            IFleaLoginLogSV fleaLoginLogSV = (IFleaLoginLogSV) applicationContext.getBean("fleaLoginLogSV");
            FleaLoginLog fleaLoginLog = new FleaLoginLog();
            fleaLoginLog.setCreateDate(DateUtils.getCurrentTime());
            fleaLoginLog = fleaLoginLogSV.queryNew(1L, fleaLoginLog);
            LOGGER.debug("FleaLoginLog = {}", fleaLoginLog);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

4.3 更新数据

	@Test
    public void testFleaLoginLogUpdate() {
        try {
            IFleaLoginLogSV fleaLoginLogSV = (IFleaLoginLogSV) applicationContext.getBean("fleaLoginLogSV");
            FleaLoginLog fleaLoginLog = new FleaLoginLog();
            fleaLoginLog.setCreateDate(DateUtils.getCurrentTime());
            fleaLoginLog = fleaLoginLogSV.queryNew(1L, fleaLoginLog);
            LOGGER.debug("FleaLoginLog = {}", fleaLoginLog);
            // 更新记录(分表)
            fleaLoginLog.setLogoutTime(DateUtils.getCurrentTime());
            fleaLoginLog.setDoneDate(DateUtils.getCurrentTime());
            fleaLoginLog.setLoginState(2);
            fleaLoginLog.setRemarks("用户退出登陆");
            fleaLoginLogSV.update(fleaLoginLog);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

4.4 删除数据

    @Test
    public void testFleaLoginLogDelete() {
        try {
            IFleaLoginLogSV fleaLoginLogSV = (IFleaLoginLogSV) applicationContext.getBean("fleaLoginLogSV");
            FleaLoginLog fleaLoginLog = new FleaLoginLog();
            fleaLoginLog.setCreateDate(DateUtils.getCurrentTime());
            fleaLoginLogSV.removeNew(1L, fleaLoginLog);
        } catch (Exception e) {
        	e.printStackTrace();
        }
    }

更新

这一版本存在并发的问题,目前已经重构,详见笔者后续的 flea-db使用之JPA分库分表实现,也可至GitHub查看笔者的 flea-framework 中的 flea-db 模块。

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

flea-frame-db使用之基于EntityManager实现JPA分表的数据库操作【旧】 的相关文章

  • 我们用4行代码节省了100万 相见恨晚的PCDN

    我们公司主要做视频在线点播 还有少量视频下载 比较关心网络加速 首先就是价格 其次是首播时间 流畅率这几个核心性能指标 目前使用阿里云PCDN也有几个月了 整体结果是超预期 值得安利的 写这篇文章 希望能通过选型对比 接入过程 效果实现几个
  • torchserve使用-注册模型设置参数(二)

    目录 1 自定义处理程序 2 托管多个模型 3 模型接口 3 1 添加注册新模型 3 2 查看是否注册成功 3 3 查看注册模型基本信息 3 4 设置注册模型参数 3 5 使用以下代码注销模型 3 6 模型版本控制 4 记录和指标 1 自定
  • xxl-job-admin多数据库支持

    记录一下改造过程 针对 xxl job 2 3版本 什么是xxl job 你的系统中有很多定时任务 如果你想统一管理 你需要一个调度系统 XXL JOB是一个分布式任务调度平台 其核心设计目标是开发迅速 学习简单 轻量级 易扩展 githu
  • 机器学习初实践——恶意域名检测

    这次恶意域名检测实践是第一次自己做机器学习而非单纯复现 参考了第一次鸢尾花的代码和GitHub的UrlDetect中的特征提取参数的代码 一 数据处理 首先要实现自动化处理数据 在这里我没有使用urlparser而是直接写脚本提取域名 提取
  • 【南邮操作系统实验】页面置换算法 (FIFO、LRU、OPTP)

    写在前面 操作系统内存管理的页面置换算法 因为懒得看老师给的代码 太长了而且据说好像还有错误 就自己写了一个python版本的 因为比较菜 所以写的一般般 仅供大伙参考一下Orz python版本的 代码如下 import random 生
  • mysql视图基本操作

    mysql视图介绍及如何创建视图请看 一个案例理解mysql视图 本章主要记录视图的修改 删除以及展示视图语法 目录 一 创建视图 二 修改视图 三 删除视图 四 更新视图 五 展示视图 一 创建视图 请看 一个案例理解mysql视图 二
  • Docker 使用网络

    文章目录 外部访问容器 端口绑定 映射所有接口地址 映射到指定地址的指定端口 查看当前端口配置 多个端口绑定 容器互联 配置 DNS 外部访问容器 1 使用 P 标记时 Docker 会随机映射一个 490000 49900 的端口到内部容

随机推荐

  • 应用Cryptopp库实现AES加密【转】

    crypto 自身的wiki上就有一些例子 可以参考 http www cryptopp com wiki Category Sample 本文来源 http ste xidian edu cn bbs a a asp B 5 ID 224
  • DirectX11学习笔记(不定期更新)

    目录 1 DX与HLSL的矩阵 2 创建常量缓冲区的尺寸需要按照16字节对齐 1 DX与HLSL的矩阵 DX的矩阵 DirectX XMMATRIX 按照行主元优先存储 而HLSL的矩阵默认按照列主元优先存储 解决这个问题的方法有两种 1
  • 【STM32 x ESP8266】连接 MQTT 服务器(报文,附部分源码解析)

    MQTT 协议作为物联网非常重要的传输协议 如何使用它十分重要 如果有不理解的同学可以点击这里学习 这里只是简单介绍一下 同时这里附上MQTT 3 1 1协议中文版 pdf 的链接 对协议底层感兴趣的同学可以下载学习一下 同时下面的实现函数
  • Qt Q_UNUSED使用

    以前经常在程序里定义很多局部变量 如果没有使用 Qt Creator就会报 未引用的局部变量 警告 因为不影响程序 一开始也没管 但随着程序代码变多 警告变动还是有点烦 到今天才知道这个Qt的有个消除这个警告的宏 Q UNUSED int
  • Flink系统架构

    Flink 的运行时架构中 最重要的就是两大组件 作业管理器 JobManger 和任务管理器 TaskManager 对于一个提交执行的作业 JobManager 是真正意义上的 管理者 Master 负责管理调度 所以在不考虑高可用的情
  • 如何将java项目部署到Linux服务器上

    博主之前并没有操作过服务器 以及部署项目 记第一次操作心得 仅供参考 在服务器上已经有了mysql的五个rpm安装包 jdk的rpm tomcat的tar gz 博主找了其他的博文说是需要配置java环境但是博主并没有操作到这一步 安装包是
  • ThinkPad开机停留在boot menu界面、进不了系统的解决方法

    方法一 1 开机点击F1进入到bios界面 2 进入Security Secure Boot Disabled 如果不修改Secure boot选项为Disabled 在光驱引导时可能会出现报错 3 进入Startup UEFI Legac
  • C++57个入门知识点_37 虚函数的直接调用与间接调用(函数的调用分为直接调用和间接调用,间接调用是虚函数所具有的的性质;间接调用:运行期通过查找对象的虚表下标来调用函数的方法)

    前面两篇C 57个入门知识点 35 函数覆盖的概念1 函数覆盖条件 父子类继承关系 函数名 参数列表 返回值 调用约定必须相同 有virtual关键字 函数覆盖 类虚表中成员函数从继承自父类变为自己的 C 57个入门知识点 36 函数覆盖的
  • Android中的Loaders机制

    转自 http blog csdn net guoshaobei article details 17451647 Loaders机制在Android 3 0版本后引入 Loaders机制使一个Activity或者一个Fragment更加容
  • 职工管理系统(C++)

    职工管理系统有以下8个功能 增加职工信息 实现批量添加职工功能 将信息录入到文件中 职工信息为 职工编号 姓名 部门编号 显示职工信息 显示公司内部所有职工的信息 删除离职职工 按照编号删除指定的职工 修改职工信息 按照编号修改职工个人信息
  • python笔记-排序函数

    List排序 sort val list 1 7 3 9 5 6 val list sort sort 没有返回值 在原列表上排序 val list sort reverse True 逆序 print val list 使用sort 方法
  • IDEA启动tomcat控制台中文乱码问题

    IntelliJ IDEA是很多程序员必备且在业界被公认为最好的Java开发工具 有很多小伙伴在安装完IDEA并且tomcat之后 启动tomcat会出现控制台中文乱码问题 如下图所示 具体解决步骤 一 修改当前 Web 项目 Tomcat
  • 从用户页面获取作品列表

    最近web端更新比较频繁 所以搞了很多方案来应对更新问题 本文内容是其中一种方案 从用户主页的HTML响应内容中抽取user信息和作品列表数据 下图中出现的内容都是在html名为RENDER DATA的script标签中 以urlencod
  • spring与loc

    loc 是控制反转 是一个概念 当前比较流行的实现方式有两种 一种是依赖查找 第二就是依赖注入 依赖注入是目前最优秀的解耦方式 第一个小程序 所需的jar包 spring beans 4 2jar spring context 4 2 ja
  • 5折交叉验证_交叉验证:评估模型表现

    注明 本文章所有代码均来自scikit learn官方网站 在实际情况中 如果一个模型要上线 数据分析员需要反复调试模型 以防止模型仅在已知数据集的表现较好 在未知数据集上的表现较差 即要确保模型的泛化能力 它指机器学习对新鲜样本的适应能力
  • 重写或替换jar中的类或方法两种方式

    上一篇 还没毕业 我就进了HR的黑名单 目录 序言 重写jar的两种方式 第一种 第二种 序言 在某些特殊场景下 我们需要修改 jar 包中的某些类和方法 jar 我们没有修改权限 那么怎么重写里面的类和方法呢 本文教你两种常用的方法 分享
  • TortoiseGit SSH拉取GitLab代码

    ING 前述 Git获取远端代码的方式主要有两种https和SSH 这两种方式的主要区别在于 1 https url克隆会比较方便 复制https url然后到git Bash里面直接用clone命令克隆到本地就好了 但是每次fetch和p
  • 黑猫带你学eMMC协议第19篇:eMMC RPMB区域详解(重放保护内存块)

    1 前言 1 1 声明 本文依据eMMC JEDEC5 1 网络资料及个人工作经验整理而成 如有错误请留言 本文结合eMMC JEDEC5 1协议手册查看效果更佳 文章为个人辛苦整理 付费内容 禁止私自转载 1 2 内容提要 本文大约一万一
  • 2. Redis持久化、主从哨兵架构详解

    分布式缓存技术Redis 1 Redis持久化 1 1 RDB快照 snapshot 1 1 1 bgsave的写时复制 COW 机制 1 2 AOF append only file 1 2 1 AOF重写 1 3 Redis 4 0 混
  • flea-frame-db使用之基于EntityManager实现JPA分表的数据库操作【旧】

    基于EntityManager实现JPA分表的数据库操作 引言 1 EntityManager持久化操作 2 分表规则定义 3 分表操作实现 4 自测 4 1 新增数据 4 2 查询数据 4 3 更新数据 4 4 删除数据 更新 引言 本文