目录

  • jpacomment-spring-boot-starter
    • 需求说明
    • 思路说明

jpacomment-spring-boot-starter

JPA创建或修改数据库的表注释和字段注释

jpacomment-spring-boot-starter 使用非常简单,目前支持三种主流关系型数据库:

  1. Mysql
  2. Sqlserver
  3. Oracle

后期可以增加其他数据库。

GitHub 地址,使用查看README.md
https://github.com/dwhgygzt/jpacomment-spring-boot-starter

需求说明

JPA 比较方便,让开发免于手动创建表操作,但有一个问题表中字段无注释,虽然JPA有提供方法,但无法适应所有主流数据库。
JPA 自身提供方法如下:

public class MyEntity {@Column(nullable = false,columnDefinition = "int(2) comment '我是年龄注释...'")private Integer age;}

其中 columnDefinition 其实就是写 Native Sql,这样违背了JPA的初衷“屏蔽底层数据库差异”,
因此我们计划自己写一套解决方案。

思路说明

  • 自定义注解 @TableComment@ColumnComment 到实体类和其属性上
  • 通过 JPA EntityManager 获取java 属性对应的数据库表和字段
  • 调用 SQL Alter 语句修改字段和表注释

自定义注解 @TableComment@ColumnComment 到实体类和其属性上

@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface ColumnComment {/*** 字段注释** @return String*/String value() default "";
}
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface TableComment {/*** 字段注释** @return String*/String value() default "";
}
@Data
@Entity
@Table(name = "T_SYS_PEOPLE")
@TableComment("普通人员表")
public class SysPeopleEntity implements Serializable {private static final long serialVersionUID = 1L;@EmbeddedId@ColumnComment("联合主键 NAME ID_NUMBER")private PeopleKey id;@ColumnComment("年龄")@Column(name = "AGE")private int age;@ColumnComment("地址")@Column(name = "ADDRESS")private String address;@ColumnComment("乐观锁版本号")@Version@Column(name = "RVERSION", nullable = false)private Integer rversion;@ColumnComment("创建时间")@Column(name = "CREATE_DATE", nullable = false)private Date createDate;@ColumnComment("创建人员信息")@Column(name = "CREATE_USER", nullable = false)private String createUser;@ColumnComment("更新时间")@Column(name = "UPADATE_DATE")private Date updateDate;@ColumnComment("更新人员信息")@Column(name = "UPDATE_USER")private String updateUser;@ColumnComment("备注")@Column(name = "REMARK", length = 1024)private String remark;}

通过 JPA EntityManager 获取java 属性对应的数据库表和字段

public Map<String, TableCommentDTO> findAllTableAndColumn() {Map<String, TableCommentDTO> tableCommentMap = new HashMap<>(256);//通过EntityManager获取factoryEntityManagerFactory entityManagerFactory = entityManager.getEntityManagerFactory();SessionFactoryImpl sessionFactory = (SessionFactoryImpl) entityManagerFactory.unwrap(SessionFactory.class);Map<String, EntityPersister> persisterMap = sessionFactory.getMetamodel().entityPersisters();for (Map.Entry<String, EntityPersister> entity : persisterMap.entrySet()) {SingleTableEntityPersister persister = (SingleTableEntityPersister) entity.getValue();Class targetClass = entity.getValue().getMappedClass();TableCommentDTO table = new TableCommentDTO();// 表注释getTableInfo(persister, table, targetClass);//除主键外的属性注释getColumnInfo(persister, table, targetClass);// 主键字段注释getKeyColumnInfo(persister, table, targetClass);tableCommentMap.put(table.getName(), table);}return tableCommentMap;}@SuppressWarnings("rawtypes")private void getTableInfo(SingleTableEntityPersister persister, TableCommentDTO table, Class targetClass) {table.setColumnCommentDTOList(new ArrayList<>(32));table.setName(persister.getTableName());TableComment tableComment = AnnotationUtil.getAnnotation(targetClass, TableComment.class);if (tableComment != null) {table.setComment(tableComment.value());} else {table.setComment("");}}/*** 递归获取所有父类的类对象 包括自己* 最后的子类在第一个** @param targetClass targetClass* @param list        list*/@SuppressWarnings("rawtypes")private void getAllClass(Class targetClass, List<Class> list) {list.add(targetClass);if (!Object.class.equals(targetClass.getSuperclass())) {getAllClass(targetClass.getSuperclass(), list);}}@SuppressWarnings("rawtypes")private void getColumnInfo(SingleTableEntityPersister persister, TableCommentDTO table, Class targetClass) {// 情况比较复杂,必须还要判断是否有父类,存在父类则还要取父类的字段信息,优先取得子类字段为依据List<Class> classList = new ArrayList<>(2);getAllClass(targetClass, classList);Set<String> alreadyDealField = new HashSet<>(32);Set<String> allColumnField = new HashSet<>(32);Iterable<AttributeDefinition> attributes = persister.getAttributes();//属性for (AttributeDefinition attr : attributes) {allColumnField.add(attr.getName());}classList.forEach(classItem -> Arrays.stream(ClassUtil.getDeclaredFields(classItem)).forEach(field -> {if (allColumnField.contains(field.getName())) {// 判断是否已经处理过if (!alreadyDealField.contains(field.getName())) {//对应数据库表中的字段名String[] columnName = persister.getPropertyColumnNames(field.getName());getColumnComment(table, classItem, field.getName(), columnName);alreadyDealField.add(field.getName());}}}));}@SuppressWarnings("rawtypes")private void getKeyColumnInfo(SingleTableEntityPersister persister, TableCommentDTO table, Class targetClass) {String idName = persister.getIdentifierPropertyName();String[] idColumns = persister.getIdentifierColumnNames();getColumnComment(table, targetClass, idName, idColumns);}@SuppressWarnings("rawtypes")private void getColumnComment(TableCommentDTO table, Class targetClass, String propertyName, String[] columnName) {ColumnComment idColumnComment = AnnotationUtil.getAnnotation(ClassUtil.getDeclaredField(targetClass, propertyName), ColumnComment.class);Arrays.stream(columnName).forEach(item -> {ColumnCommentDTO column = new ColumnCommentDTO();column.setName(item);if (idColumnComment != null) {column.setComment(idColumnComment.value());} else {column.setComment("");}table.getColumnCommentDTOList().add(column);});}

调用 SQL Alter 语句修改字段和表注释


public interface AlterCommentService {/*** 获取当前数据库 schema** @return 数据库 schema*/String getSchema();/*** 设置当前的schema*/void setSchema(String schema);/*** 修改表注释** @param tableName    表名称* @param tableComment 表注释*/void alterTableComment(String tableName, String tableComment);/*** 修改表字段注释** @param tableName     表名称* @param columnName    字段名称* @param columnComment 字段注释*/void alterColumnComment(String tableName, String columnName, String columnComment);/*** 获取  jdbcTemplate** @param jdbcTemplate jdbcTemplate*/void setJdbcTemplate(JdbcTemplate jdbcTemplate);
}

各数据具体实现继承该接口实现自己的方法

例如Mysql的

public class MysqlAlterCommentServiceImpl implements AlterCommentService {private String schema;private JdbcTemplate jdbcTemplate;@Overridepublic void setSchema(String schema) {this.schema = schema;}@Overridepublic void setJdbcTemplate(JdbcTemplate jdbcTemplate) {this.jdbcTemplate = jdbcTemplate;}/*** 1注释 2表名称 3字段名称*/String updateTableComment = " ALTER TABLE %s.%s COMMENT = ?";/*** 1注释 2表名称 3字段名称*/String getUpdateColumnComment = " SELECT CONCAT('ALTER TABLE `',a.TABLE_SCHEMA,'`.`',a.TABLE_NAME,'` MODIFY COLUMN `',a.COLUMN_NAME,'` ',a.COLUMN_TYPE,\n" +" (CASE WHEN a.IS_NULLABLE = 'NO' THEN ' NOT NULL ' ELSE\t'' END), \n" +" (CASE WHEN a.COLUMN_DEFAULT IS NOT NULL THEN CONCAT(' DEFAULT ''',a.COLUMN_DEFAULT,''' ') ELSE\t'' END) ,' COMMENT ?') ALTER_SQL\n" +"FROM information_schema.`COLUMNS` a\n" +"WHERE a.TABLE_SCHEMA = ? \n" +"AND a.TABLE_NAME = ?\n" +"AND a.COLUMN_NAME = ? ";@Overridepublic void alterTableComment(String tableName, String tableComment) {jdbcTemplate.update(String.format(updateTableComment, "`" + schema + "`", "`" + tableName + "`"), tableComment);}@Overridepublic void alterColumnComment(String tableName, String columnName, String columnComment) {String updateColumnComment = jdbcTemplate.queryForObject(getUpdateColumnComment, String.class, schema, tableName, columnName);if (StrUtil.isNotBlank(updateColumnComment)) {jdbcTemplate.update(updateColumnComment, columnComment);}}@Overridepublic String getSchema() {return schema;}
}

GitHub 地址,使用查看README.md 十分简单。
https://github.com/dwhgygzt/jpacomment-spring-boot-starter

JPA创建或修改数据库的表注释和字段注释相关推荐

  1. java根据表名取出字MySQL_mysql取得数据库所有表名和字段注释_MySQL

    bitsCN.com mysql取得数据库所有表名和字段注释 1.取字段注释 Java代码 Select COLUMN_NAME 列名, DATA_TYPE 字段类型, COLUMN_COMMENT ...

  2. mysql获取表名及其注释,mysql获得数据库所有表名和字段注释

    1.取字段注释 Select COLUMN_NAME 列名, DATA_TYPE 字段类型, COLUMN_COMMENT 字段注释 from INFORMATION_SCHEMA.COLUMNS W ...

  3. mysql2012更改表名_sql alter table修改数据库的表名字

    SQL基础语句总结 前言: SQL 是用于访问和处理数据库的标准的计算机语言. 什么是 SQL? SQL 指结构化查询语言SQL 使我们有能力访问数据库SQL 是一种 ANSI 的标准计算机语言编者注 ...

  4. mysql创建表格1warning_MySQL:创建、修改和删除表

    在说创建.修改和删除表前,我们还是要进行一个操作的简单说明: 1.登陆数据库系统 在命令行中登陆MySQL数据库管理系统,输入一下内容: mysql -h localhost -u root -p 很 ...

  5. 虚拟机mysql创建一个表_MySQL:创建、修改和删除表

    其实对很多人来说对于SQL语句已经忘了很多,或者说是不懂很多,因为有数据库图形操作软件,方便了大家,但是我们不能忘记最根本的东西,特别是一些细节上的东西,可能你用惯了Hibernate,不用写SQL语 ...

  6. jpa 表注释和字段注释_JPA注释–Hibernate注释

    jpa 表注释和字段注释 JPA annotations are used in mapping java objects to the database tables, columns etc. H ...

  7. MySQL修改数据库、表、字段的字符编码

    备战2022春招或暑期实习,本专栏会持续输出MySQL系列文章,祝大家每天进步亿点点!文末私信作者,我们一起去大厂. 本篇总结的是 <MySQL之流程函数>,后续会每日更新~ 关于< ...

  8. SQL server——sql命令创建、修改、删除表之记录

    目录 学习内容.sql命令创建.修改.删除表 创建表 指定所属文件组 修改表 增加一列number 更改列属性 删除某一列 重命名表 删除表 分区表 创建表 添加文件组 分别为其添加数据文件 创建分区 ...

  9. MySQL常见问题的解决,root用户密码忘记,不是内部或外部命令,修改数据库和表的字符编码,命令行客户端的字符集问题

    文章目录 问题1:root用户密码忘记,重置的操作 问题2:mysql命令报"不是内部或外部命令" 问题3:错误ERROR :没有选择数据库就操作表格和数据 问题4:命令行客户端的 ...

最新文章

  1. 特征筛选(随机森林)
  2. IIS没有.net版本选择标签问题
  3. java整数翻转_Java程序反转数字
  4. Element UI 总结
  5. 解决:PHP Deprecated: Comments starting with '#' are deprecated in ……
  6. 兄弟HL-1118加粉清零
  7. 认识计算机系统授课计划,计算机网络技术基础授课计划.doc
  8. 怎么将图片进行圆角处理?
  9. 郑和下西洋有两个主要目的:
  10. 以太网交换芯片及PHY处理相关
  11. java 写文件filewriter_使用FileReader和FileWriter读取写入文件内容
  12. 学习3ds max—做自行车车轮
  13. matlab光盘映像文件可以删除吗_Mathworks Matlab R2011a 下载 光盘镜像下载
  14. 贪心算法1——找零钱问题
  15. 20155305乔磊2016-2017-2《Java程序设计》第五周学习总结
  16. EMD EEMD CEEMD对应的matlab工具包
  17. unity 设置软件运行分辨率
  18. Storm Cleaner 应用分析
  19. 雕刻机主轴安装注意事项
  20. pwd命令是什么的缩写_Linux中常用的命令都是哪些单词的缩写?

热门文章

  1. Exploiting Shared Representations for Personalized Federated Learning 论文笔记+代码解读
  2. android 模拟器优化,如何设置才能流畅的使用安卓模拟器玩游戏,好坏取决于哪些因素...
  3. 基于硬件方法的“熔断”和“幽灵”CPU 漏洞应对机制!
  4. c语言stdlib h常用函数,c语言中,头文件stdlib.h主要包含什么函数?
  5. Adobe Flash Player 9.0.45.0 简体中文官方下载(本地播放Flash Player播放器, 非插件)...
  6. MCGS触摸屏在运行过程中设置Modbus通讯地址及串口参数的方法
  7. windows 下编译 Ipopt 3.12
  8. Ipopt-3.12.7在ubuntu18.04安装
  9. 【C语言】如何很好的实现复数类型
  10. 如何使用电视或遥控器来控制Apple TV