一般在項目開發(fā)過程中,使用比較多的就是先建好表,再利用hibernate反向工程生成*.hbm.xml文件跟POJO類,個人認(rèn)為由于目前所使用的數(shù)據(jù)庫都是關(guān)系數(shù)據(jù)庫,而hibernate作為一個ORM,把對數(shù)據(jù)庫的操作都對象化了,更應(yīng)當(dāng)從對象出發(fā),生成數(shù)據(jù)庫里面相關(guān)表,這樣更加符合人認(rèn)知事物的習(xí)慣。
由于hibernate3提供了自帶的工具hbm2ddl,建立根據(jù)你的對象建立數(shù)據(jù)庫是一件非常簡單的事情。
SchemaExport工具:Hibernate的hbm2dll提供SchemaExport工具,給定一個連接字符串和映射文件,不需輸入其他東西就可以按照持久化類和映射文件自動生成數(shù)據(jù)庫架構(gòu),現(xiàn)在SchemaExport工具還不是很強(qiáng)大,但是一般應(yīng)用足夠了,它還是一個相當(dāng)原始的API還在不斷改進(jìn)。SchemaExport工具就是把DDL腳本輸出到標(biāo)準(zhǔn)輸出,同時/或者執(zhí)行DDL語句。SchemaExport工具提供了三個方法,分別是Drop()、Create()、Execute(),前兩個方法實質(zhì)是調(diào)用Execute()方法。通常使用Execute()方法來生成數(shù)據(jù)庫架構(gòu)的。
SchemaUpdate工具:在Hibernate2.0中新添加SchemaUpdate工具,可以用來更新數(shù)據(jù)庫架構(gòu)。但是我覺得沒有什么作用,因為它不能Drop現(xiàn)有的表或列,也不能更新現(xiàn)有的列,只能添加新的表和列。如果我需要刪除表或者列或者修改其中列,SchemaUpdate工具就顯得無能為力了。
SchemaValidator工具:SchemaValidator工具,可以用來檢查數(shù)據(jù)庫架構(gòu)。通過映射文件中配置的相關(guān)數(shù)據(jù)庫表及各自的字段屬性來檢查數(shù)據(jù)庫中對應(yīng)表結(jié)構(gòu)是否存在或正確,如果不存在表或字段不一致,則拋出異常。
對于單純的Hibernate,配置有hibernate.cfg.xml數(shù)據(jù)庫配置文件,或是其它SSH整合版本中也配置有相關(guān).cfg.xml文件的工程來說,這種類型的情況下使用Hibernate的SchemaExport實現(xiàn)正向工程比較簡單。如下例:
public boolean createTableByBean(String mappingFile) {
Configuration cfg = new Configuration().configure(cfgFile);
cfg.addFile(mappingFile);
boolean flag = true;
SchemaExport dbExport = new SchemaExport(cfg);
try {
dbExport.create(true, true);
} catch (Exception e) {
flag = false;
}
return flag;
}
而我所做的數(shù)據(jù)遷移工具中使用的是Spring+Hibernate整合框架,而且在數(shù)據(jù)庫配置中沒有使用hibernate.properties和hibernate.cfg.xml文件來配置,
因為在使用Hibernate的SchemaExport/SchemaUpdate/SchemaValidator工具時,構(gòu)建對象時需要Hibernate的Configuration對象實例作為參數(shù)。如:
var export = new SchemaExport(cfg); 其中cfg參數(shù)由
Configuration cfg = new Configuration().configure(cfgFile);建立,configure默認(rèn)讀取hibernate.cfg.xml配置文件(configure無參函數(shù)),
也可以通過傳遞參數(shù)指定自己定義的.cfg.xml文件。我的SessionFactory是借助于Spring提供的
org.springframework.orm.hibernate3.LocalSessionFactoryBean來實現(xiàn)的:
<bean id="targetSessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
……
</bean>
在沒有配置.cfg.xml文件的情況下,可以通過配置的數(shù)據(jù)源的SessionFactory中獲取,如下:
public class DaoUtil extends HibernateDaoSupport {
private Configuration cfg;
private Settings settings;
public void init() {
String webRootPath = CommonMethod.getWebRootPath();
ApplicationContext dataSource_ctx = new FileSystemXmlApplicationContext(webRootPath + "/WEB-INF/datatransferConf/applicationContext-targetDataSource.xml");
SessionFactoryImplementor sessionFactoryImpl = (SessionFactoryImplementor) dataSource_ctx.getBean("targetSessionFactory");
LocalSessionFactoryBean localSessionFactory = (LocalSessionFactoryBean) dataSource_ctx.getBean("&targetSessionFactory");
SessionFactory sessionFactory = (SessionFactory) dataSource_ctx.getBean("targetSessionFactory");
this.cfg = localSessionFactory.getConfiguration();
this.settings = sessionFactoryImpl.getSettings();
super.setSessionFactory(sessionFactory);
}
public void createTableFromCfg() {
if (settings.isAutoCreateSchema()) {
new SchemaExport(cfg, settings).create(true, true);
} else if (settings.isAutoUpdateSchema()) {
new SchemaUpdate(cfg, settings).execute(true, true);
} else if (settings.isAutoDropSchema()) {
new SchemaExport(cfg, settings).drop(true, true);
} else if (settings.isAutoValidateSchema()) {
new SchemaValidator(cfg).validate();
}
}
public void createTableFromMapFile(String mappingFile) {
Resource mappingLocation = new ClassPathResource(mappingFile);
try {
cfg.addInputStream(mappingLocation.getInputStream());
} catch (MappingException e1) {
e1.printStackTrace();
} catch (IOException e1) {
e1.printStackTrace();
}
createTableFromCfg();
}
}
SchemaExport 的create(script,export)方法根據(jù)持久類和映射文件先刪除架構(gòu)后創(chuàng)建刪除數(shù)據(jù)庫架構(gòu)。有兩個參數(shù),第一個為True就是把DDL語句輸出到控制臺,第二個為True就是根據(jù)持久類和映射文件先執(zhí)行刪除再執(zhí)行創(chuàng)建操作,經(jīng)過調(diào)試可以發(fā)現(xiàn)這個方法其實質(zhì)是執(zhí)行execute(script,export, false, true)方法。execute(script, export, justDrop, format)方法根據(jù)持久類和映射文件先刪除架構(gòu)后創(chuàng)建刪除數(shù)據(jù)庫架構(gòu)。有四個參數(shù),第一個為True就是把DDL語句輸出到控制臺;第二個為True就是根據(jù)持久類和映射文件在數(shù)據(jù)庫中先執(zhí)行刪除再執(zhí)行創(chuàng)建操作;第三個為false表示不是僅僅執(zhí)行Drop語句還執(zhí)行創(chuàng)建操作,這個參數(shù)的不同就擴(kuò)展了上面兩個方法;第四個參數(shù)為false表示不是格式化輸出DDL語句到控制臺,是在一行輸出的。
Spring配置文件中所定義的LocalSessionFactoryBean實現(xiàn)了org.springframework.beans.factory.FactoryBean接口,在使用ApplicationContext對象讀取的時候可以自動轉(zhuǎn)型為多種不同類型的SessionFactory,spring在裝配的時候, 如果發(fā)現(xiàn)實現(xiàn)了org.springframework.beans.factory.FactoryBean接口,就會使用
FactoryBean#getObject() 方法返回的對象裝配,具體的可以看下文檔。如果你想拿到LocalSessionFactoryBean實例, 在id前面加個'&'就可以了,在你的配置文件中BeanFactory.getBean('&sessionFactory')拿到的就是LocalSessionFactoryBean的實例。