在《一口一口吃掉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 *URL:http://www.bianceng.cn/Programming/Java/201410/45829.htm */ 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; } }
以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索string
, return
, 方法
, null
, schemaexport
, str
, 分隔符
, 读取分隔符
java单利模式
,以便于您获取更多的相关知识。