最近做toB、toG业务,普遍要去适配各种国产数据库,所以不得不用hibernate,过去这么多年一直都是用mybatis+mysql,现在重拾hibernate,专注跨数据库,感兴趣的加关注。

需求背景:

最近做一个数据库备份还原功能,需要支持跨库同步,比如mysql的数据及表结构整库批量同步到SqlServer(虽然Navicat有此功能,但是Navicat不支持一些新的国产数据库,况且,这个Navicat不能集成到项目里,用户使用不方便)。

功能分析:

1、需要同步表结构,不同的数据库DDL语句不兼容性。但是,hibernate框架中,entity已经定义了表结构,hibernate会帮我们适配各种数据库,所以不用备份表结构(sql: create table xxx ...),直接通过hibernate在数据库生成表;

2、常见的数据备份是备份insert into table ... 这样的sql语句。这样做,备份文件体积大,且不是批量插入,性能一般,特殊格式的字段在不同数据库还存在兼容问题。所以我们可以通过hibernate,只备份数据,将数据转为json格式存储,然后用hibernate将数据入库。

实现思路:

1、通过entityManager获取实体entity;

2、通过entity查询对应表所有数据;

3、解析前端传参,组装新的数据库链接;

4、根据数据库链接和获取到的实体,创建hibernate工厂(通过entity创建表);

5、再次通过遍历实体,组装批量insert sql(ps:hibernate批量插入性能很差,原则是还是saveOrUpdate);

6、从创建的hibernate工厂获取sessionFactory,执行批量插入sql;

关键代码:

1、通过批量jpa备份数据

@Resource
private EntityManager entityManager; //注入entityManager // ---------------------------------
// 通过entityManager获取所有实体
Set<EntityType<?>> entityTypes = entityManager.getMetamodel().getEntities();
// 遍历实体
entityTypes.parallelStream().forEach((EntityType<?> entity) -> {
  // 根据实体创建 JpaRepository
  SimpleJpaRepository simpleJpaRepository = new SimpleJpaRepository(entity.getJavaType(), entityManager);
  // 直接读表数据
  List<?> list = simpleJpaRepository.findAll();
  // 可以将list转为json存储...以下省略...
});

2、通过jpa手动创建表

 private void initEntityManager() {
Map<String, String> settings = new HashMap<>();
settings.put(AvailableSettings.DRIVER, "com.mysql.jdbc.Driver");
settings.put(AvailableSettings.DIALECT, "com.ut.msfw1a.common.core.hibernate.dialect.MsfwMySQLDialect");
        settings.put(AvailableSettings.URL, "jdbc:mysql://127.0.0.1"); // 填入要还原的数据库jdbc信息
settings.put(AvailableSettings.USER, "root");
settings.put(AvailableSettings.PASS, "password");
settings.put(AvailableSettings.ORDER_INSERTS, "true");
settings.put(AvailableSettings.ORDER_UPDATES, "true");
settings.put(AvailableSettings.STATEMENT_BATCH_SIZE, "10000");
settings.put(AvailableSettings.SHOW_SQL, "false");
settings.put(AvailableSettings.BATCH_VERSIONED_DATA, "ture");
settings.put(AvailableSettings.HBM2DDL_AUTO, "update");
settings.put(AvailableSettings.PHYSICAL_NAMING_STRATEGY, "org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy");// 表命名规则
ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().applySettings(settings).build();
MetadataSources metadataSources = new MetadataSources(serviceRegistry);
entityTypes.forEach((EntityType<?> type) -> {//entityTpyes是备份的时候从entity中取到的
metadataSources.addAnnotatedClass(type.getJavaType()); // 添加要还原的entity
});
Metadata metadata = metadataSources.getMetadataBuilder().build(); // 创建hibernate工厂,这一步,会自动生成表
SessionFactory sessionFactory = metadata.buildSessionFactory();
sessionFactory.openSession();
entityManager = sessionFactory.createEntityManager(); // 这样就根据jdbc信息创建了一个自己的entityManager
}

3、还原数据

存数据的时候,json数据文件用表名存储

可以这样根据表名获取到对应的entity

Optional<EntityType<?>> entityTypeOptional = entityTypes.stream().filter(et -> et.getName().equals(tableName)).findFirst();
if (!entityTypeOptional.isPresent()) {
return;
}
EntityType<?> entityType = entityTypeOptional.get();
根据表名,和新创建的entityManager还原数据
SimpleJpaRepository simpleJpaRepository = new SimpleJpaRepository(entity.getJavaType(), entityManager);
simpleJpaRepository.batchSave(list)

通过手动创建hibernate工厂,自动生成表,完成数据库备份还原功能的更多相关文章

  1. hibernate不能自动生成表的原因总结

    1. upate->create <property name="hbm2ddl.auto">create</property> 2. 2.Mappi ...

  2. hibernate如何配置自动生成表

    hibernate自动生成表有两种方法: 1.直接写代码,通过方法来创建数据库表. 2.通过 hibernate.cfg.xml配置标签来创建数据表. 下面依次实现: 1.直接写代码,通过方法来创建数 ...

  3. Hibernate使用自定义脚本替换注解或者xml文件中的自动生成表结构

    本文作者:苏生米沿 本文地址:http://blog.csdn.net/sushengmiyan/article/details/50534361 我们都清楚,可以使用hibernate的metada ...

  4. hibernate.hbm2ddl.auto=update不能自动生成表结构

    在写上篇文章<spring整合springmvc和hibernate>的时候,曾遇到一个问题 INFO: Server startup in 8102 ms Hibernate: inse ...

  5. java自动生成表单简单实例

    数据库表设置 tb_form(form表单) 字段 类型 约束 说明 Id Int 主键 主键 Formid Varchar2(20) 唯一 Form表单id的值 Action Varchar2(20 ...

  6. Eclipse中设置在创建新类时自动生成注释

    方法一:Eclipse中设置在创建新类时自动生成注释 windows-->preference Java-->Code Style-->Code Templates code--&g ...

  7. 基于PHP和mysql的自动生成表单

    开发背景:公司要求管理系统能够由管理员在前台页面管理系统表单,能够对表单进行增删改查基本操作,表单的各个字段都可以被修改.删除,可以添加新的字段,并且不影响系统正常运行,前台表单展示要由系统自动处理, ...

  8. 利用powerDesigner15.1连接oracle数据库并自动生成表结构

    利用powerDesigner15.1连接oracle数据库并自动生成表结构 参考:http://blog.csdn.net/qq_24531461/article/details/76713802 ...

  9. IntelliJ IDEA 创建的文件自动生成 Author 注释 签名

    IntelliJ IDEA 创建的文件自动生成 Author 注释 签名1.打开 File --> Setting2.找到 Editor --> File and Code Templat ...

  10. 用Django自动生成表遇到问题

    因为以前在数据库中已经生成过Django 叫App01下的表,所以无法生成,在数据库中执行这个命令 DELETE FROM django_migrations WHERE app='App01';然后 ...

随机推荐

  1. 【数据结构与算法】希尔排序 python和c++实现

    算法思路 每一次:固定间隔把数据分组,每一组进行排序 每次比上次选取更小的间隔分组,再每组排序,直到间隔为1 代码 c++:(越看越不明白了,后看) int gap = length;//length ...

  2. Qt自带的阴影类、跨线程问题汇总、hover相关、全屏轮子,一些思考。

    一点思考:故事的结局重不重要? 我语文不好,但是我数学不好. 我数学不好,但是我英语不好. 我英语不好,但是我物理不好. 我物理不好,但是我化学不好. 我化学不好,但是我历史不好. 我历史不好,但是我 ...

  3. JavaScript:箭头函数:作为参数进行传参

    之前已经说过,JS的函数,也是对象,而函数名是一个变量,是可以进行传参的,也即函数是可以被传参的. 只要是函数,都可以被传参,但是箭头函数的语法更为灵活,所以更方便进行传参. 如上图所示,fun1是一 ...

  4. ubuntu系统wireshark源码编译与安装

    官网:https://www.wireshark.org/ 官方文档:Wireshark · Documentation 一 介绍 wireshark[1]是一款抓包工具.wireshark的GUI( ...

  5. 2022年7月13日,第四组,周鹏,JS做计算器代码

    代码不难,看了我前面笔记的应该能看懂. 没看?(= ̄ω ̄=)喵了个咪(๑‾᷅^‾᷅๑) 嫌弃你 还看啥,去看啊!要不直接复制代码吧!( ̄へ ̄)( ̄へ ̄)( ̄へ ̄) Document 0 / * - 7 ...

  6. 【转载】SQL SERVER 中各种存储过程创建及执行方式

    一. 什么是存储过程系统存储过程是系统创建的存储过程,目的在于能够方便的从系统表中查询信息或完成与更新数据库表相关的管理任务或其他的系统管理任务.系统存储过程主要存储在master数据库中,以&quo ...

  7. 如何优雅地升级一个Creator 2.x 项目到 3.6.2 ?

    最近,我将之前用 Cocos Creator 2.x 写的一个微信小游戏<球球要回家>移植到了 Cocos Creator 3.6.2 上. 编程语言也从 JavaScript 迁移到了 ...

  8. 1.5万字总结 Redis 常见面试题&知识点

    以下内容来源于于我开源的 JavaGuide (Java学习&&面试指南,Github 130k star,370人共同参与爱完善), 万字总结,质量有保障! 这篇文章最早写于2019 ...

  9. [C#]关于override和new在重写方法时的区别

    规则: 在"运行时"遇到虚方法时,对象会调用虚成员派生得最远的.重写的实现. 如果是用new修饰符实现的方法,它会在基类面前隐藏派生类重新声明的成员,这时候会找到使用new修饰符的 ...

  10. runtime-第一篇

    第一次接触runtime,先介绍下自学的几个runtime方法 1.获取类的属性列表 先导入runtime文件 #import <objc/runtime.h>   我这边创建了一个Per ...