程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> Hibernate學習(三)Hibernate給表和字段設置前後綴及分隔符

Hibernate學習(三)Hibernate給表和字段設置前後綴及分隔符

編輯:關於JAVA

在《一口一口吃掉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;  
    }  
          
          
}

【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 
	 *URL:http://www.bianceng.cn/Programming/Java/201410/45829.htm
     */
    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包分享給大家了:http://pan.baidu.com/share/link?shareid=1107664883&uk=1259218556

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved