日期:2014-05-16  浏览次数:20588 次

一口一口吃掉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
	 */
	public static synchronized MyNamingStrategy getInstance(
			DatabaseConfiguration dbcfg) {