zoukankan      html  css  js  c++  java
  • 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】自定义的命名策略,可对表、字段进行统一处理。

    1. package com.tgb.hibernate.neatlyDB;  
    2.   
    3. import org.hibernate.cfg.Configuration;  
    4. import org.hibernate.cfg.NamingStrategy;  
    5. import org.hibernate.util.StringHelper;  
    6.   
    7. /** 
    8.  * 数据库命名策略,可定制表、字段等的前后缀 
    9.  *  
    10.  * @author Longxuan 
    11.  *  
    12.  */  
    13. public class MyNamingStrategy implements NamingStrategy {  
    14.   
    15.     /** 
    16.      * 数据库命名策略单一实例 
    17.      */  
    18.     private static MyNamingStrategy instance = null;  
    19.   
    20.     /** 
    21.      * 数据库配置信息类 
    22.      */  
    23.     private static DatabaseConfiguration dbcfg = null;  
    24.   
    25.     /** 
    26.      * 私有化构造方法 
    27.      */  
    28.     private MyNamingStrategy() {  
    29.   
    30.     }  
    31.   
    32.     /** 
    33.      * 使用单利模式,获取数据库命名策略的唯一实例 
    34.      *  
    35.      * @return 
    36.      */  
    37.     public static synchronized MyNamingStrategy getInstance() {  
    38.         // 默认读取hibernate.cfg.xml文件  
    39.         Configuration cfg = new Configuration().configure();  
    40.         return getInstance(cfg);  
    41.     }  
    42.   
    43.     /** 
    44.      * 使用单利模式,获取数据库命名策略的唯一实例,同时使用默认Hibernate.cfg.xml更新命名策略信息 
    45.      *  
    46.      * @param cfg 
    47.      *            配置文件信息 
    48.      * @return 
    49.      */  
    50.     public static synchronized MyNamingStrategy getInstance(Configuration cfg) {  
    51.         if (instance == null) {  
    52.             instance = new MyNamingStrategy();  
    53.         }  
    54.         MyNamingStrategy.dbcfg = new DatabaseConfiguration(cfg);  
    55.         return instance;  
    56.     }  
    57.   
    58.     /** 
    59.      * 使用单利模式,获取数据库命名策略的唯一实例,同时更新命名策略信息 
    60.      *  
    61.      * @param cfg 
    62.      *            配置文件信息 
    63.      * @return 
    64.      */  
    65.     public static synchronized MyNamingStrategy getInstance(  
    66.             DatabaseConfiguration dbcfg) {  
    67.         if (instance == null) {  
    68.             instance = new MyNamingStrategy();  
    69.         }  
    70.         MyNamingStrategy.dbcfg = dbcfg;  
    71.         return instance;  
    72.     }  
    73.   
    74.     /** 
    75.      * 设置或更新数据库配置信息 
    76.      *  
    77.      * @param dbcfg 
    78.      */  
    79.     public void setDBConfig(DatabaseConfiguration dbcfg) {  
    80.         MyNamingStrategy.dbcfg = dbcfg;  
    81.     }  
    82.   
    83.     /** 
    84.      * 转化为物理表名 
    85.      *  
    86.      * @param className hbm.xml中的对应表的class值 
    87.      */  
    88.     @Override  
    89.     public String classToTableName(String className) {  
    90.           
    91.         if(className == null ) return null;  
    92.           
    93.         //改变大小写  
    94.         String str =UpdateStyle(className,dbcfg.getTableStyle().name());  
    95.               
    96.         //添加前后缀  
    97.         str = addPrefixORStuffix(str, dbcfg.getTablePrefix(),dbcfg.getTableSuffix());  
    98.           
    99.         //添加分隔符  
    100.         str = addSeparator(str,dbcfg.getTableSeparator());  
    101.           
    102.         return str;  
    103.     }  
    104.   
    105.     @Override  
    106.     public String collectionTableName(String ownerEntity,  
    107.             String ownerEntityTable, String associatedEntity,  
    108.             String associatedEntityTable, String propertyName) {  
    109.         return null;  
    110.     }  
    111.   
    112.       
    113.     /** 
    114.      * 将读取到的列名传递过来进行加工处理,变为物理表的字段名 
    115.      *  
    116.      * @param columnName logicalColumnName方法读取到的列名 
    117.      */  
    118.     @Override  
    119.     public String columnName(String columnName) {  
    120.         //先调用logicalColumnName方法,拿到处理过的值,  
    121.         //再传递到该方法中,所以可以在这两个方法中任一选择修改。         
    122.         //return columnName;  
    123.           
    124.         if(columnName == null ) return null;  
    125.           
    126.         //改变大小写  
    127.         String str =UpdateStyle(columnName,dbcfg.getColumnTyle().name());  
    128.               
    129.         //添加前后缀  
    130.         str = addPrefixORStuffix(StringHelper.unqualify(str), dbcfg.getColumnPrefix(),dbcfg.getColumnSuffix());  
    131.           
    132.         //添加分隔符  
    133.         str = addSeparator(str,dbcfg.getColumnSeparator());  
    134.           
    135.         return str;  
    136.           
    137.     }  
    138.   
    139.       
    140.     /** 
    141.      * 处理外键列名 
    142.      *  
    143.      */  
    144.     @Override  
    145.     public String foreignKeyColumnName(String propertyName,  
    146.             String propertyEntityName, String propertyTableName,  
    147.             String referencedColumnName) {  
    148.           
    149.         if(referencedColumnName == null ) return null;  
    150.           
    151.         //改变大小写  
    152.         String str =UpdateStyle(referencedColumnName,dbcfg.getColumnTyle().name());  
    153.               
    154.         //添加前后缀  
    155.         str = addPrefixORStuffix(StringHelper.unqualify(str), dbcfg.getColumnPrefix(),dbcfg.getColumnSuffix());  
    156.           
    157.         //添加分隔符  
    158.         str = addSeparator(str,dbcfg.getColumnSeparator());  
    159.           
    160.         return str;  
    161.     }  
    162.   
    163.     /** 
    164.      * 关联键的名称 
    165.      */  
    166.     @Override  
    167.     public String joinKeyColumnName(String joinedColumn, String joinedTable) {  
    168.           
    169.         if(joinedColumn == null ) return null;  
    170.           
    171.         //改变大小写  
    172.         String str =UpdateStyle(joinedColumn,dbcfg.getColumnTyle().name());  
    173.               
    174.         //添加前后缀  
    175.         str = addPrefixORStuffix(StringHelper.unqualify(str), dbcfg.getColumnPrefix(),dbcfg.getColumnSuffix());  
    176.           
    177.         //添加分隔符  
    178.         str = addSeparator(str,dbcfg.getColumnSeparator());  
    179.           
    180.         return str;  
    181.     }  
    182.   
    183.     @Override  
    184.     public String logicalCollectionColumnName(String columnName,  
    185.             String propertyName, String referencedColumn) {  
    186.         return null;  
    187.     }  
    188.   
    189.     @Override  
    190.     public String logicalCollectionTableName(String tableName,  
    191.             String ownerEntityTable, String associatedEntityTable,  
    192.             String propertyName) {  
    193.         return null;  
    194.     }  
    195.   
    196.     /** 
    197.      * 处理逻辑列名 
    198.      * <b>若设置了column属性,会直接调用调用该方法</b> 
    199.      *  
    200.      * @param columnName    列名 
    201.      * @param propertyName  实体列名 
    202.      */  
    203.     @Override  
    204.     public String logicalColumnName(String columnName, String propertyName) {  
    205.           
    206.         //name值对应propertyName,column值对应columnName  
    207.         //判断columnName是否设置,若设置了,则返回column值,否则返回propertyName值  
    208.         return columnName == null || columnName =="" ? propertyName:columnName;  
    209.           
    210.     }  
    211.   
    212.     /** 
    213.      * 处理逻辑列名 
    214.      * <b>若未设置column属性,则先调用该方法,再调用logicalColumnName方法</b> 
    215.      *  
    216.      * @param propertyName  实体列名 
    217.      */  
    218.     @Override  
    219.     public String propertyToColumnName(String propertyName) {  
    220.   
    221.         if(propertyName == null ) return null;  
    222.           
    223.         //改变大小写  
    224.         String str =UpdateStyle(propertyName,dbcfg.getColumnTyle().name());  
    225.               
    226.         //添加前后缀  
    227.         str = addPrefixORStuffix(StringHelper.unqualify(str), dbcfg.getColumnPrefix(),dbcfg.getColumnSuffix());  
    228.           
    229.         //添加分隔符  
    230.         str = addSeparator(str,dbcfg.getColumnSeparator());  
    231.           
    232.         return str;  
    233.     }  
    234.   
    235.       
    236.     /** 
    237.      * 处理表名 
    238.      * <b>若设置了table属性,才会调用该方法</b> 
    239.      */  
    240.     @Override  
    241.     public String tableName(String tableName) {  
    242.           
    243.         if(tableName == null ) return null;  
    244.           
    245.         //改变大小写  
    246.         String str =UpdateStyle(tableName,dbcfg.getTableStyle().name());  
    247.               
    248.         //添加前后缀  
    249.         str = addPrefixORStuffix(StringHelper.unqualify(str), dbcfg.getTablePrefix(),dbcfg.getTableSuffix());  
    250.           
    251.         //添加分隔符  
    252.         str = addSeparator(str,dbcfg.getTableSeparator());  
    253.           
    254.         return str;  
    255.     }  
    256.   
    257.     /** 
    258.      * 单词分隔符 
    259.      *  
    260.      * @param name 
    261.      * @return 
    262.      */  
    263.     private String addSeparator(String str, String flag) {  
    264.         StringBuffer buf = new StringBuffer(str.substring(str.lastIndexOf(".")+1));  
    265.         for (int i = 1; i < buf.length() - 1; i++) {  
    266.             if ('_' != buf.charAt(i - 1)  
    267.                     && Character.isUpperCase(buf.charAt(i))  
    268.                     && !Character.isUpperCase(buf.charAt(i + 1))) {  
    269.                 // buf.insert(i++, '_');  
    270.                 buf.insert(i++, flag);  
    271.             }  
    272.         }  
    273.         return buf.toString();  
    274.     }  
    275.   
    276.     /** 
    277.      * 添加前后缀 
    278.      *  
    279.      * @param str 
    280.      *            字符串 
    281.      * @param prefix 
    282.      *            前缀 
    283.      * @param suffix 
    284.      *            后缀 
    285.      * @return 
    286.      */  
    287.     private String addPrefixORStuffix(String str, String prefix, String suffix) {  
    288.         StringBuffer buf = new StringBuffer(str.substring(str.lastIndexOf(".")+1));  
    289.         buf.insert(buf.length(), suffix).insert(0, prefix);  
    290.         return buf.toString();  
    291.     }  
    292.   
    293.     /** 
    294.      * 更新样式 
    295.      * @param str 
    296.      * @param style 
    297.      * @return 
    298.      */  
    299.     private String UpdateStyle(String str, String style) {        
    300.         if ("AU".equals(style)) {  
    301.             str = str.toUpperCase();  
    302.         } else if ("AL".equals(style)) {  
    303.             str = str.toLowerCase();  
    304.         } else if ("FU".equals(style)) {  
    305.             StringBuffer buf = new StringBuffer(str.substring(str.lastIndexOf(".")+1));  
    306.             String upper =buf.substring(0,1).toUpperCase();  
    307.             buf.delete(0, 1).insert(0, upper);  
    308.             str = buf.toString();  
    309.         } else if ("FL".equals(style)) {  
    310.             StringBuffer buf = new StringBuffer(str.substring(str.lastIndexOf(".")+1));  
    311.             String lower =buf.substring(0,1).toLowerCase();  
    312.             buf.delete(0, 1).insert(0, lower);  
    313.             str = buf.toString();  
    314.         }  else{  
    315.               
    316.         }         
    317.         return str;  
    318.     }  
    319.       
    320.       
    321. }  

    【DatabaseConfiguration】数据库样式配置,包括前后缀、分隔符、大小写等

    1. package com.tgb.hibernate.neatlyDB;  
    2.   
    3. import org.hibernate.cfg.Configuration;  
    4.   
    5.   
    6. /** 
    7.  * 数据库模式配置 
    8.  * @author Longxuan 
    9.  * 
    10.  */  
    11. public final class DatabaseConfiguration {  
    12.   
    13.   
    14.     /** 
    15.      * 列名样式 
    16.      * AU-all upper case 
    17.      * AL-all lower case 
    18.      * FU-first upper case per word 
    19.      * FL-first lower case ,Other first letter upper case 
    20.      */  
    21.     public static enum ColumnTyle {  
    22.         AU,AL,FU,FL;          
    23.     }  
    24.       
    25.     /** 
    26.      * 表名称样式 
    27.      * AU-all upper case 
    28.      * AL-all lower case 
    29.      * FU-first upper case per word 
    30.      * FL-first lower case ,Other first letter upper case 
    31.      */  
    32.     public static enum TableStyle{  
    33.         AU,AL,FU,FL;  
    34.     }  
    35.   
    36.     /** 
    37.      * 列名样式 
    38.      * AU-all upper case 
    39.      * AL-all lower case 
    40.      * FU-first upper case per word 
    41.      * FL-first lower case ,Other first letter upper case 
    42.      */  
    43.     private ColumnTyle columnTyle = ColumnTyle.FL;  
    44.       
    45.     /** 
    46.      * 表名称样式 
    47.      * AU-all upper case 
    48.      * AL-all lower case 
    49.      * FU-first upper case per word 
    50.      * FL-first lower case ,Other first letter upper case 
    51.      */  
    52.     private TableStyle tableStyle = TableStyle.FU;  
    53.       
    54.     /** 
    55.      * 表名称前缀 
    56.      */  
    57.     private String tablePrefix = "";  
    58.       
    59.     /** 
    60.      * 表名称后缀 
    61.      */  
    62.     private String tableSuffix = "";  
    63.       
    64.     /** 
    65.      * 表名称分隔符 
    66.      */  
    67.     private String tableSeparator = "";  
    68.       
    69.     /** 
    70.      * 列名前缀 
    71.      */  
    72.     private String columnPrefix = "";  
    73.       
    74.     /** 
    75.      * 列名后缀 
    76.      */  
    77.     private String columnSuffix = "";  
    78.       
    79.     /** 
    80.      * 列名分隔符 
    81.      */  
    82.     private String columnSeparator = "";  
    83.       
    84.     public ColumnTyle getColumnTyle() {  
    85.         return columnTyle;  
    86.     }  
    87.   
    88.     public void setColumnTyle(ColumnTyle columnTyle) {  
    89.         this.columnTyle = columnTyle;  
    90.     }  
    91.   
    92.     public TableStyle getTableStyle() {  
    93.         return tableStyle;  
    94.     }  
    95.   
    96.     public void setTableStyle(TableStyle tableStyle) {  
    97.         this.tableStyle = tableStyle;  
    98.     }  
    99.   
    100.     public String getTablePrefix() {  
    101.         return tablePrefix;  
    102.     }  
    103.   
    104.     public void setTablePrefix(String tablePrefix) {  
    105.         this.tablePrefix = tablePrefix;  
    106.     }  
    107.   
    108.     public String getTableSuffix() {  
    109.         return tableSuffix;  
    110.     }  
    111.   
    112.     public void setTableSuffix(String tableSuffix) {  
    113.         this.tableSuffix = tableSuffix;  
    114.     }  
    115.   
    116.     public String getTableSeparator() {  
    117.         return tableSeparator;  
    118.     }  
    119.   
    120.     public void setTableSeparator(String tableSeparator) {  
    121.         this.tableSeparator = tableSeparator;  
    122.     }  
    123.   
    124.     public String getColumnPrefix() {  
    125.         return columnPrefix;  
    126.     }  
    127.   
    128.     public void setColumnPrefix(String columnPrefix) {  
    129.         this.columnPrefix = columnPrefix;  
    130.     }  
    131.   
    132.     public String getColumnSuffix() {  
    133.         return columnSuffix;  
    134.     }  
    135.   
    136.     public void setColumnSuffix(String columnSuffix) {  
    137.         this.columnSuffix = columnSuffix;  
    138.     }  
    139.   
    140.     public String getColumnSeparator() {  
    141.         return columnSeparator;  
    142.     }  
    143.   
    144.     public void setColumnSeparator(String columnSeparator) {  
    145.         this.columnSeparator = columnSeparator;  
    146.     }  
    147.       
    148.   
    149.     /** 
    150.      * 初始化,读取配置参数,默认读取Hibernate.cfg.xml 
    151.      * @param cfg 
    152.      */  
    153.     public DatabaseConfiguration(){  
    154.         ReadConfig(new Configuration().configure());   
    155.     }  
    156.       
    157.     /** 
    158.      * 初始化,读取配置文件 
    159.      * @param cfg 
    160.      */  
    161.     public DatabaseConfiguration(Configuration cfg){  
    162.         ReadConfig(cfg);   
    163.     }  
    164.       
    165.   
    166.     /** 
    167.      * 自动读取配置信息 
    168.      * @param cfg 
    169.      */  
    170.     private void ReadConfig(Configuration cfg){  
    171.         tableStyle = cfg.getProperty("tablestyle")==""?TableStyle.FU:TableStyle.valueOf(cfg.getProperty("tablestyle"));  
    172.         tablePrefix = cfg.getProperty("tablePrefix");  
    173.         tableSuffix = cfg.getProperty("tablesuffix");  
    174.         tableSeparator = cfg.getProperty("tableseparator");  
    175.           
    176.         columnTyle = cfg.getProperty("columntyle")==""?ColumnTyle.FL:ColumnTyle.valueOf(cfg.getProperty("columntyle"));  
    177.         columnPrefix = cfg.getProperty("columnPrefix");  
    178.         columnSuffix = cfg.getProperty("columnsuffix");  
    179.         columnSeparator = cfg.getProperty("columnseparator");  
    180.           
    181.     }  
    182.       
    183. }  



    【hibernate.cfg.xml】设置数据库样式配置信息

    1. <!DOCTYPE hibernate-configuration PUBLIC  
    2.     "-//Hibernate/Hibernate Configuration DTD 3.0//EN"  
    3.     "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">  
    4.   
    5. <hibernate-configuration>  
    6.     <session-factory name="foo">        
    7. <!--   
    8.     name:       配置的名称  
    9.     style:      类型 枚举AU-all upper case  
    10.                       AL-all lower case  
    11.                       FU-first letter upper case per word  
    12.                       FL-first letter lower case ,Other first letters upper case  
    13.       
    14.     befix:      前缀  
    15.     suffix:     后缀  
    16.     separator:  分隔符  
    17.  -->  
    18.         <property name="tablestyle">FU</property>  
    19.         <property name="tablePrefix" >T_</property>  
    20.         <property name="tablesuffix" ></property>  
    21.         <property name="tableseparator" >_</property>         
    22.         <property name="columntyle">FU</property>  
    23.         <property name="columnPrefix">[stu_</property>  
    24.         <property name="columnsuffix">]</property>  
    25.         <property name="columnseparator">_</property>  
    26.           
    27.           
    28.       
    29.         <property name="hibernate.dialect" >org.hibernate.dialect.MySQLDialect</property>  
    30.         <property name="hibernate.show_sql">true</property><!-- 设置是否显示生成sql语句 -->  
    31.         <property name="hibernate.format_sql">false</property><!-- 设置是否格式化sql语句-->  
    32.           
    33.         <mapping resource="com/bjpowernode/hibernate/User.hbm.xml" />  
    34.           
    35.     </session-factory>  
    36.       
    37. </hibernate-configuration>  


    【User.hbm.xml】映射文件可以比较随意的修改或者设定了

    1. <?xml version="1.0"?>  
    2. <!DOCTYPE hibernate-mapping PUBLIC   
    3.     "-//Hibernate/Hibernate Mapping DTD 3.0//EN"  
    4.     "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">  
    5. <hibernate-mapping>  
    6.     <class name="com.bjpowernode.hibernate.User" table="Users">  
    7.         <id name="id" column="pid">  
    8.             <generator class="uuid" />  
    9.         </id>  
    10.         <property name="name" column="userName"></property>  
    11.         <property name="password" column="pwd"></property>  
    12.         <property name="createTime"></property>  
    13.         <property name="expireTime"></property>  
    14.           
    15.     </class>  
    16. </hibernate-mapping>  


    最后修改一下【ExportDB】,主要是修改必须先设置NamingStrategy,在调用configure方法

    1. package com.bjpowernode.hibernate;  
    2.   
    3. import org.hibernate.cfg.Configuration;  
    4. import org.hibernate.tool.hbm2ddl.SchemaExport;  
    5.   
    6. import com.tgb.hibernate.neatlyDB.DatabaseConfiguration;  
    7. import com.tgb.hibernate.neatlyDB.MyNamingStrategy;  
    8.   
    9.   
    10.   
    11. /** 
    12.  * 将hbm生成ddl 
    13.  * @author Longxuan 
    14.  * 
    15.  */  
    16. public class ExportDB {  
    17.   
    18.     /** 
    19.      * @param args 
    20.      */  
    21.     public static void main(String[] args) {  
    22.   
    23.         //默认读取hibernate.cfg.xml文件,并按照命名策略修改表、字段的名称  
    24.         //Configuration cfg = new Configuration().configure();   
    25.           
    26.         //注意,必须先设置NamingStrategy,在调用configure方法  
    27.         Configuration cfg = new Configuration().setNamingStrategy(MyNamingStrategy.getInstance()).configure();  
    28.                           
    29.         SchemaExport export = new SchemaExport(cfg);  
    30.           
    31.         //true 在控制台打印ddl语句,true 导入ddl语句到数据库,即可执行  
    32.         export.create(true, true);  
    33.     }  
    34.   
    35. }  


          看一下结果图吧:表名,字段名都已经修改过了。

          上面演示的是生成数据表。在对数据库的增删改查时,只要同样设置NamingStrategy即可。

          为了大家更为方便的使用,已经做成jar包分享给大家了,点这里下载。

  • 相关阅读:
    sql server 分页
    省市区
    省市
    sql server 中英混合排序
    C# 添加大量sql
    小程序小数的输入判定
    C# Files 的值“<<<<<<< .mine”无效。路径中具有非法字符。
    vagrant安装遇到的问题
    vagrant安装使用
    tp6 session问题
  • 原文地址:https://www.cnblogs.com/KingIceMou/p/7100979.html
Copyright © 2011-2022 走看看