Hibernate学习(三)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
	 *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单利模式
,以便于您获取更多的相关知识。

时间: 2024-09-17 04:46:23

Hibernate学习(三)Hibernate给表和字段设置前后缀及分隔符的相关文章

一口一口吃掉Hibernate(三)——Hibernate给表和字段设置前后缀及分隔符

       在<一口一口吃掉Hibernate(一)--使用SchemaExport生成数据表>中介绍了如何生成数据表.但是这只是最基本的.Hibernate在生成或者操作数据库时,会受一些限制.比如一开始设计表的时候,直接写成了user(id,name,password,createTime)  这种格式的.但是客户后来要求表名称要以"t_"开头,字段名要以"stu_"开头,可以是一些数据库的关键字,单词之间以"_"隔开,方便他们

Hibernate学习之hibernate.cfg.xml

<?xml version='1.0' encoding='UTF-8'?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"> <!-- 正文开始 --> <

织梦dedecms自定义表单中字段设置为必填项方法

方法一,修改dedecms源码 下面这段段php代码是用来判断验证必选项的: 1.我们先在plus/diy.php 文件中的的第40行下加上一下代码  代码如下 复制代码  //增加必填字段判断 if($required!=''){ if(preg_match('/,/', $required))     {         $requireds = explode(',',$required);         foreach($requireds as $field){           

oracle表,字段名有“/”在做hibernate映射时怎么做?

问题描述 oracle表,字段名有"/"在做hibernate映射时怎么做?<propertyname="bev2edUser"type="java.lang.String"><columnname="/BEV2/ED_USER"length="12"></column></property>这样会报错ORA-00904::标识符无效咋办啊? 解决方案 解决方

数据库-hibernate创建了两个相同的表,字段都一样,大小写不一样

问题描述 hibernate创建了两个相同的表,字段都一样,大小写不一样 应该是第一次启动工程,hibernate生成一次表,这一次是正常的,之后修改了某些实体类 再重新启动工程,数据库里的表就多了一份,比如表bt_study表下面多了个bt_Study的表 ,然后导致外键的一些错误. 解决方案 解决方案二: 解决方案三: 你修改了实体类,那么你的hbernate的配置文件也要改,删除之前的那张表,如果用到hibernate一般建议实体类不要改动

Hibernate学习(一)使用SchemaExport生成数据表

Hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,使得Java程序员可以随心所欲的使用对象编程思维来操纵数据库. 今天就来演示一下Hibernate最初级的操作,使用SchemaExport创建数据表. 1.首先建立POJO类 package com.bjpowernode.hibernate; import java.util.Date; /** * 用户 * @author Longxuan * */ public class User { pri

关于Java Hibernate 插入与更新同一张MySQL表不同字段,出现锁没被释放

问题描述 关于Java Hibernate 插入与更新同一张MySQL表不同字段,出现锁没被释放 关于Java Hibernate 插入与更新同一张MySQL表不同字段,出现锁没被释放,这个有可能是数据还没插入完或者插完了锁没有被释放,导致下一个更新操作不能执行,等待超时,这个情况出现在操作数据量大的时候!这个情况有哪几种解决方式? [http-bio-8080-exec-3] [SQLErrorCodesFactory.:126] SQLErrorCodes loaded: [DB2 Derb

大神们,oracle表,字段名有“/”在做hibernate映射时怎么做?

问题描述 oracle表,字段名有"/"在做hibernate映射时怎么做?<propertyname="bev2edUser"type="java.lang.String"><columnname="/BEV2/ED_USER"length="12"></column></property>这样会报错ORA-00904::标识符无效咋办啊? 解决方案 解决方

Hibernate学习大全

第1课 课程内容. 6 第2课Hibernate UML图. 6 第3课 风格. 7 第4课 资源. 7 第5课 环境准备. 7 第6课 第一个示例HibernateHelloWorld 7 第7课 建立Annotation版本的HellWorld 9 第8课 什么是O/RMapping 11 一.     定义:. 11 二.     Hibernate的创始人:. 11 三.     Hibernate做什么:. 12 四.     Hibernate存在的原因:. 12 五.     Hi