Hibernate给表和字段设置前后缀及分隔符
在《一口一口吃掉Hibernate(一)——使用SchemaExport生成数据表》中介绍了如何生成数据表。但是这只是最基本的。hibernate在生成或者操作数据库时,会受一些限制。比如一开始设计表的时候,直接写成了user(id,name,password,createTime) 这种格式的。但是客户后来要求表名称要以“t_”开头,字段名要以“stu_”开头,可以是一些数据库的关键字,单词之间以“_”隔开,方便他们维护.例如:T_User(stu_Id,stu_Name,stu_Create_Time)。
对于上面的问题,常规的方法就是去修改Hibernate_cfg.xml中的表,为每个表添加“t_”,或者写table属性,字段也重新使用column属性来修改。如果你有100张表,每个表平均有10个字段,你还会去一个一个修改么?还有可能漏掉或者改错。最“可恶”的是,如果客户再让你改成其他的呢,是不是还要全部修改一次?
有没有一种方法,不修改原先的配置,添加并配置一下表和字段的前后缀及分隔符等等,既可以完成呢??经过尝试,终于被我拿下了,现在拿出来与大家分享。
针对上述问题,我主要用的是NamingStrategy接口。这个接口很有意思,可以作为业务类规范和数据库表规范的桥梁,它可以表和列的映射关系的转变和处理。例如一个数据对象User,对应数据库表是T_USER,如果所有映射关系都是这样的情况,可以使用NamingStrategy做为一个桥梁衔接,而不用再hbm.xml映射文件中指定class对应的物理table。
先说一下Hibernate读取映射文件的简要过程:循环读取class标签,判断class标签的table属性值是否为null,若为null,则调用NamingStrategy接口的classToTableName方法将class值转换并处理(按命名策略NamingStrategy处理)的表名。若不为null,则说明设置了table,那么调用NamingStrategy接口的tableName方法获取处理过的表名。循环遍历property,判断property标签的column属性值是否为null,若为null,则首先调用propertyToColumnName方法,将属性值转化为列名,再调用logicalColumnName方法。若不为null,则直接调用NamingStrategy接口的logicalColumnName方法,再调用columnName方法进行处理(按命名策略NamingStrategy处理)。
了解了上面说的这个过程,只要我们实现NamingStrategy这个接口,就可以随心所欲的修改表映射了。不多说了,直接上代码吧:
【MyNamingStrategy】自定义的命名策略,可对表、字段进行统一处理。
- package com.tgb.hibernate.neatlyDB;
- import org.hibernate.cfg.Configuration;
- import org.hibernate.cfg.NamingStrategy;
- import org.hibernate.util.StringHelper;
- /**
- * 数据库命名策略,可定制表、字段等的前后缀
- *
- * @author Longxuan
- *
- */
- public class MyNamingStrategy implements NamingStrategy {
- /**
- * 数据库命名策略单一实例
- */
- private static MyNamingStrategy instance = null;
- /**
- * 数据库配置信息类
- */
- private static DatabaseConfiguration dbcfg = null;
- /**
- * 私有化构造方法
- */
- private MyNamingStrategy() {
- }
- /**
- * 使用单利模式,获取数据库命名策略的唯一实例
- *
- * @return
- */
- public static synchronized MyNamingStrategy getInstance() {
- // 默认读取hibernate.cfg.xml文件
- Configuration cfg = new Configuration().configure();
- return getInstance(cfg);
- }
- /**
- * 使用单利模式,获取数据库命名策略的唯一实例,同时使用默认Hibernate.cfg.xml更新命名策略信息
- *
- * @param cfg
- * 配置文件信息
- * @return
- */
- public static synchronized MyNamingStrategy getInstance(Configuration cfg) {
- if (instance == null) {
- instance = new MyNamingStrategy();
- }
- MyNamingStrategy.dbcfg = new DatabaseConfiguration(cfg);
- return instance;
- }
- /**
- * 使用单利模式,获取数据库命名策略的唯一实例,同时更新命名策略信息
- *
- * @param cfg
- * 配置文件信息
- * @return
- */
- public static synchronized MyNamingStrategy getInstance(
- DatabaseConfiguration dbcfg) {
- if (instance == null) {
- instance = new MyNamingStrategy();
- }
- MyNamingStrategy.dbcfg = dbcfg;
- return instance;
- }
- /**
- * 设置或更新数据库配置信息
- *
- * @param dbcfg
- */
- public void setDBConfig(DatabaseConfiguration dbcfg) {
- MyNamingStrategy.dbcfg = dbcfg;
- }
- /**
- * 转化为物理表名
- *
- * @param className hbm.xml中的对应表的class值
- */
- @Override
- public String classToTableName(String className) {
- if(className == null ) return null;
- //改变大小写
- String str =UpdateStyle(className,dbcfg.getTableStyle().name());
- //添加前后缀
- str = addPrefixORStuffix(str, dbcfg.getTablePrefix(),dbcfg.getTableSuffix());
- //添加分隔符
- str = addSeparator(str,dbcfg.getTableSeparator());
- return str;
- }
- @Override
- public String collectionTableName(String ownerEntity,
- String ownerEntityTable, String associatedEntity,
- String associatedEntityTable, String propertyName) {
- return null;
- }
- /**
- * 将读取到的列名传递过来进行加工处理,变为物理表的字段名
- *
- * @param columnName logicalColumnName方法读取到的列名
- */
- @Override
- public String columnName(String columnName) {
- //先调用logicalColumnName方法,拿到处理过的值,
- //再传递到该方法中,所以可以在这两个方法中任一选择修改。
- //return columnName;
- if(columnName == null ) return null;
- //改变大小写
- String str =UpdateStyle(columnName,dbcfg.getColumnTyle().name());
- //添加前后缀
- str = addPrefixORStuffix(StringHelper.unqualify(str), dbcfg.getColumnPrefix(),dbcfg.getColumnSuffix());
- //添加分隔符
- str = addSeparator(str,dbcfg.getColumnSeparator());
- return str;
- }
- /**
- * 处理外键列名
- *
- */
- @Override
- public String foreignKeyColumnName(String propertyName,
- String propertyEntityName, String propertyTableName,
- String referencedColumnName) {
- if(referencedColumnName == null ) return null;
- //改变大小写
- String str =UpdateStyle(referencedColumnName,dbcfg.getColumnTyle().name());
- //添加前后缀
- str = addPrefixORStuffix(StringHelper.unqualify(str), dbcfg.getColumnPrefix(),dbcfg.getColumnSuffix());
- //添加分隔符
- str = addSeparator(str,dbcfg.getColumnSeparator());
- return str;
- }
- /**
- * 关联键的名称
- */
- @Override
- public String joinKeyColumnName(String joinedColumn, String joinedTable) {
- if(joinedColumn == null ) return null;
- //改变大小写
- String str =UpdateStyle(joinedColumn,dbcfg.getColumnTyle().name());
- //添加前后缀
- str = addPrefixORStuffix(StringHelper.unqualify(str), dbcfg.getColumnPrefix(),dbcfg.getColumnSuffix());
- //添加分隔符
- str = addSeparator(str,dbcfg.getColumnSeparator());
- return str;
- }
- @Override
- public String logicalCollectionColumnName(String columnName,
- String propertyName, String referencedColumn) {
- return null;
- }
- @Override
- public String logicalCollectionTableName(String tableName,
- String ownerEntityTable, String associatedEntityTable,
- String propertyName) {
- return null;
- }
- /**
- * 处理逻辑列名
- * <b>若设置了column属性,会直接调用调用该方法</b>
- *
- * @param columnName 列名
- * @param propertyName 实体列名
- */
- @Override
- public String logicalColumnName(String columnName, String propertyName) {
- //name值对应propertyName,column值对应columnName
- //判断columnName是否设置,若设置了,则返回column值,否则返回propertyName值
- return columnName == null || columnName =="" ? propertyName:columnName;
- }
- /**
- * 处理逻辑列名
- * <b>若未设置column属性,则先调用该方法,再调用logicalColumnName方法</b>
- *
- * @param propertyName 实体列名
- */
- @Override
- public String propertyToColumnName(String propertyName) {
- if(propertyName == null ) return null;
- //改变大小写
- String str =UpdateStyle(propertyName,dbcfg.getColumnTyle().name());
- //添加前后缀
- str = addPrefixORStuffix(StringHelper.unqualify(str), dbcfg.getColumnPrefix(),dbcfg.getColumnSuffix());
- //添加分隔符
- str = addSeparator(str,dbcfg.getColumnSeparator());
- return str;
- }
- /**
- * 处理表名
- * <b>若设置了table属性,才会调用该方法</b>
- */
- @Override
- public String tableName(String tableName) {
- if(tableName == null ) return null;
- //改变大小写
- String str =UpdateStyle(tableName,dbcfg.getTableStyle().name());
- //添加前后缀
- str = addPrefixORStuffix(StringHelper.unqualify(str), dbcfg.getTablePrefix(),dbcfg.getTableSuffix());
- //添加分隔符
- str = addSeparator(str,dbcfg.getTableSeparator());
- return str;
- }
- /**
- * 单词分隔符
- *
- * @param name
- * @return
- */
- private String addSeparator(String str, String flag) {
- StringBuffer buf = new StringBuffer(str.substring(str.lastIndexOf(".")+1));
- for (int i = 1; i < buf.length() - 1; i++) {
- if ('_' != buf.charAt(i - 1)
- && Character.isUpperCase(buf.charAt(i))
- && !Character.isUpperCase(buf.charAt(i + 1))) {
- // buf.insert(i++, '_');
- buf.insert(i++, flag);
- }
- }
- return buf.toString();
- }
- /**
- * 添加前后缀
- *
- * @param str
- * 字符串
- * @param prefix
- * 前缀
- * @param suffix
- * 后缀
- * @return
- */
- private String addPrefixORStuffix(String str, String prefix, String suffix) {
- StringBuffer buf = new StringBuffer(str.substring(str.lastIndexOf(".")+1));
- buf.insert(buf.length(), suffix).insert(0, prefix);
- return buf.toString();
- }
- /**
- * 更新样式
- * @param str
- * @param style
- * @return
- */
- private String UpdateStyle(String str, String style) {
- if ("AU".equals(style)) {
- str = str.toUpperCase();
- } else if ("AL".equals(style)) {
- str = str.toLowerCase();
- } else if ("FU".equals(style)) {
- StringBuffer buf = new StringBuffer(str.substring(str.lastIndexOf(".")+1));
- String upper =buf.substring(0,1).toUpperCase();
- buf.delete(0, 1).insert(0, upper);
- str = buf.toString();
- } else if ("FL".equals(style)) {
- StringBuffer buf = new StringBuffer(str.substring(str.lastIndexOf(".")+1));
- String lower =buf.substring(0,1).toLowerCase();
- buf.delete(0, 1).insert(0, lower);
- str = buf.toString();
- } else{
- }
- return str;
- }
- }
【DatabaseConfiguration】数据库样式配置,包括前后缀、分隔符、大小写等
- package com.tgb.hibernate.neatlyDB;
- import org.hibernate.cfg.Configuration;
- /**
- * 数据库模式配置
- * @author Longxuan
- *
- */
- public final class DatabaseConfiguration {
- /**
- * 列名样式
- * AU-all upper case
- * AL-all lower case
- * FU-first upper case per word
- * FL-first lower case ,Other first letter upper case
- */
- public static enum ColumnTyle {
- AU,AL,FU,FL;
- }
- /**
- * 表名称样式
- * AU-all upper case
- * AL-all lower case
- * FU-first upper case per word
- * FL-first lower case ,Other first letter upper case
- */
- public static enum TableStyle{
- AU,AL,FU,FL;
- }
- /**
- * 列名样式
- * AU-all upper case
- * AL-all lower case
- * FU-first upper case per word
- * FL-first lower case ,Other first letter upper case
- */
- private ColumnTyle columnTyle = ColumnTyle.FL;
- /**
- * 表名称样式
- * AU-all upper case
- * AL-all lower case
- * FU-first upper case per word
- * FL-first lower case ,Other first letter upper case
- */
- private TableStyle tableStyle = TableStyle.FU;
- /**
- * 表名称前缀
- */
- private String tablePrefix = "";
- /**
- * 表名称后缀
- */
- private String tableSuffix = "";
- /**
- * 表名称分隔符
- */
- private String tableSeparator = "";
- /**
- * 列名前缀
- */
- private String columnPrefix = "";
- /**
- * 列名后缀
- */
- private String columnSuffix = "";
- /**
- * 列名分隔符
- */
- private String columnSeparator = "";
- public ColumnTyle getColumnTyle() {
- return columnTyle;
- }
- public void setColumnTyle(ColumnTyle columnTyle) {
- this.columnTyle = columnTyle;
- }
- public TableStyle getTableStyle() {
- return tableStyle;
- }
- public void setTableStyle(TableStyle tableStyle) {
- this.tableStyle = tableStyle;
- }
- public String getTablePrefix() {
- return tablePrefix;
- }
- public void setTablePrefix(String tablePrefix) {
- this.tablePrefix = tablePrefix;
- }
- public String getTableSuffix() {
- return tableSuffix;
- }
- public void setTableSuffix(String tableSuffix) {
- this.tableSuffix = tableSuffix;
- }
- public String getTableSeparator() {
- return tableSeparator;
- }
- public void setTableSeparator(String tableSeparator) {
- this.tableSeparator = tableSeparator;
- }
- public String getColumnPrefix() {
- return columnPrefix;
- }
- public void setColumnPrefix(String columnPrefix) {
- this.columnPrefix = columnPrefix;
- }
- public String getColumnSuffix() {
- return columnSuffix;
- }
- public void setColumnSuffix(String columnSuffix) {
- this.columnSuffix = columnSuffix;
- }
- public String getColumnSeparator() {
- return columnSeparator;
- }
- public void setColumnSeparator(String columnSeparator) {
- this.columnSeparator = columnSeparator;
- }
- /**
- * 初始化,读取配置参数,默认读取Hibernate.cfg.xml
- * @param cfg
- */
- public DatabaseConfiguration(){
- ReadConfig(new Configuration().configure());
- }
- /**
- * 初始化,读取配置文件
- * @param cfg
- */
- public DatabaseConfiguration(Configuration cfg){
- ReadConfig(cfg);
- }
- /**
- * 自动读取配置信息
- * @param cfg
- */
- private void ReadConfig(Configuration cfg){
- tableStyle = cfg.getProperty("tablestyle")==""?TableStyle.FU:TableStyle.valueOf(cfg.getProperty("tablestyle"));
- tablePrefix = cfg.getProperty("tablePrefix");
- tableSuffix = cfg.getProperty("tablesuffix");
- tableSeparator = cfg.getProperty("tableseparator");
- columnTyle = cfg.getProperty("columntyle")==""?ColumnTyle.FL:ColumnTyle.valueOf(cfg.getProperty("columntyle"));
- columnPrefix = cfg.getProperty("columnPrefix");
- columnSuffix = cfg.getProperty("columnsuffix");
- columnSeparator = cfg.getProperty("columnseparator");
- }
- }
【hibernate.cfg.xml】设置数据库样式配置信息
- <!DOCTYPE hibernate-configuration PUBLIC
- "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
- "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
- <hibernate-configuration>
- <session-factory name="foo">
- <!--
- name: 配置的名称
- style: 类型 枚举AU-all upper case
- AL-all lower case
- FU-first letter upper case per word
- FL-first letter lower case ,Other first letters upper case
- befix: 前缀
- suffix: 后缀
- separator: 分隔符
- -->
- <property name="tablestyle">FU</property>
- <property name="tablePrefix" >T_</property>
- <property name="tablesuffix" ></property>
- <property name="tableseparator" >_</property>
- <property name="columntyle">FU</property>
- <property name="columnPrefix">[stu_</property>
- <property name="columnsuffix">]</property>
- <property name="columnseparator">_</property>
- <property name="hibernate.dialect" >org.hibernate.dialect.MySQLDialect</property>
- <property name="hibernate.show_sql">true</property><!-- 设置是否显示生成sql语句 -->
- <property name="hibernate.format_sql">false</property><!-- 设置是否格式化sql语句-->
- <mapping resource="com/bjpowernode/hibernate/User.hbm.xml" />
- </session-factory>
- </hibernate-configuration>
【User.hbm.xml】映射文件可以比较随意的修改或者设定了
- <?xml version="1.0"?>
- <!DOCTYPE hibernate-mapping PUBLIC
- "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
- "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
- <hibernate-mapping>
- <class name="com.bjpowernode.hibernate.User" table="Users">
- <id name="id" column="pid">
- <generator class="uuid" />
- </id>
- <property name="name" column="userName"></property>
- <property name="password" column="pwd"></property>
- <property name="createTime"></property>
- <property name="expireTime"></property>
- </class>
- </hibernate-mapping>
最后修改一下【ExportDB】,主要是修改必须先设置NamingStrategy,在调用configure方法
- package com.bjpowernode.hibernate;
- import org.hibernate.cfg.Configuration;
- import org.hibernate.tool.hbm2ddl.SchemaExport;
- import com.tgb.hibernate.neatlyDB.DatabaseConfiguration;
- import com.tgb.hibernate.neatlyDB.MyNamingStrategy;
- /**
- * 将hbm生成ddl
- * @author Longxuan
- *
- */
- public class ExportDB {
- /**
- * @param args
- */
- public static void main(String[] args) {
- //默认读取hibernate.cfg.xml文件,并按照命名策略修改表、字段的名称
- //Configuration cfg = new Configuration().configure();
- //注意,必须先设置NamingStrategy,在调用configure方法
- Configuration cfg = new Configuration().setNamingStrategy(MyNamingStrategy.getInstance()).configure();
- SchemaExport export = new SchemaExport(cfg);
- //true 在控制台打印ddl语句,true 导入ddl语句到数据库,即可执行
- export.create(true, true);
- }
- }
看一下结果图吧:表名,字段名都已经修改过了。
上面演示的是生成数据表。在对数据库的增删改查时,只要同样设置NamingStrategy即可。
为了大家更为方便的使用,已经做成jar包分享给大家了,点这里下载。
Hibernate给表和字段设置前后缀及分隔符的更多相关文章
- django 重写User表增加字段设置
models中: from django.contrib.auth.models import AbstractUser lass User(AbstractUser): mobile = model ...
- mysql表时间戳字段设置
创建时间 修改时间
- Hibernate 3中如何获得库表所有字段的名称
15问:Hibernate 3中如何获得库表所有字段的名称 答:可以使用以下的程序获得. Configuration conf = new Configuration(); conf.configur ...
- 在高并发、高负载的情况下,如何给表添加字段并设置DEFAULT值?
在高并发.高负载的情况下,如何给表添加字段并设置DEFAULT值? 在Oracle 12c之前,当Oracle表数据量上亿时,对表执行“ALTER TABLE XXX ADD COLUMN_XX VA ...
- MySQL 创建表时,设置时间字段自己主动插入当前时间
MySQL 创建表时,设置时间字段自己主动插入当前时间 DROP TABLE IF EXISTS `CONTENT`; CREATE TABLE `CONTENT` ( `ID` char(20) N ...
- 如何更精准地设置 C# / .NET Core 项目的输出路径?(包括添加和删除各种前后缀)
原文:如何更精准地设置 C# / .NET Core 项目的输出路径?(包括添加和删除各种前后缀) 我们都知道可以通过在 Visual Studio 中设置输出路径(OutputPath)来更改项目输 ...
- OneThink学习笔记02----数据字典(即OneThink项目数据库里的表及其字段)
action 字段 类型 注释 id int(11) unsigned 自增主键 name char(30) 行为唯一标识 title char(80) 行为说明 remark char(140) 行 ...
- Hibernate学习笔记(三)Hibernate生成表单ID主键生成策略
一. Xml方式 <id>标签必须配置在<class>标签内第一个位置.由一个字段构成主键,如果是复杂主键<composite-id>标签 被映射的类必须定义对应数 ...
- Ecshop 表结构 字段说明
ecs_account_log 用户帐号情况记录表,包括资金和积分等 log_id mediumint 自增ID号user_id mediumint 用户登录后保存在session中的id号,跟use ...
随机推荐
- 单点登录实现机制:桌面sso
参考链接,感谢作者:https://zm10.sm-tc.cn/?src=l4uLj8XQ0IiIiNGckZ2TkJiM0ZyQktCZlo2Mi5uNmp6S0I/QysrJyszPztGXi5K ...
- 两款不同应用场景的Wpf分页控件
简介 今天给大家分享两个Wpf分页控件,本篇博客主要介绍一些实现思路和使用方法,具体实现和应用代码请参考文末的Demo链接 废话不多说,先看一下效果~ (两款控件显示效果是一样的) 实现思路 一款控件 ...
- Tomcat NIO
说起Tomcat的NIO,不得不提的就是Connector这个Tomcat组件.Connector是Tomcat的连接器,其主要任务是负责处理收到的请求,并创建一个Request和Response的对 ...
- MongoDB的安装和使用指南
什么是MongoDB MongoDB 是一个基于分布式文件存储的数据库.由 C++ 语言编写.旨在为 WEB 应用提供可扩展的高性能数据存储解决方案. MongoDB 是一个介于关系数据库和非关系 ...
- MySQL 如何使用 PV 和 PVC?- 每天5分钟玩转 Docker 容器技术(154)
本节演示如何为 MySQL 数据库提供持久化存储,步骤为: 创建 PV 和 PVC. 部署 MySQL. 向 MySQL 添加数据. 模拟节点宕机故障,Kubernetes 将 MySQL 自动迁移到 ...
- jacascript 立即执行函数(IIFE)与闭包
前言:这是笔者学习之后自己的理解与整理.如果有错误或者疑问的地方,请大家指正,我会持续更新! 一直没搞清楚立即执行函数和闭包之间的关系,总结一下: 闭包有很多种理解:访问不到内部作用域,函数就是这样, ...
- 在CentOS 7+ 安装Kubernetes入门
TL;DR; 科学上网,科学上网,科学上网,重要的事情说三次.如果不会科学上网,这篇文章就没有看下去的意义.作为一个技术人员如果不愿意折腾,很难有所作为.作为一个单纯的技术人员,最好把心思放在技术上, ...
- 扩展第二屏幕发生Out Of Range及扩展后耳机没声音解决方案
新年好\(^o^)/~ 拓展屏幕这种事情.其实很简单的.无非就分辨率跟刷新频率.有时候一接好就可以了.有时候怎么也弄不出来.我也是搞了蛮久.昨天突然弄通了.小记一下说不定能帮到同需求人. [设备] 主 ...
- .NET Core Community 首个千星项目诞生:CAP
项目简介 在我们构建 SOA 或者 微服务系统的过程中,我们通常需要使用事件来对各个服务进行集成,在这过程中简单的使用消息队列并不能保证数据的最终一致性, CAP 采用的是和当前数据库集成的本地消息表 ...
- 发布你的程序包到Nuget
1.新建一个.NET Standard 的类库项目 2.选择项目熟悉,在 package 栏目下填写我们的nuget包信息 3.选择我们的项目,点击"Pack" 打包 主要注意的是 ...