2015-06-09

為什麼 LocalSessionFactoryBean 回傳的是 SessionFactoryImpl?

我習慣使用 org.hibernate.tool.hbm2ddl.SchemaExport 來產出 SQL。
Configuration cfg = new Configuration();
cfg.configure(); // 預設讀取 hibernate.cfg.xml
SchemaExport export = new SchemaExport(cfg);
export.setOutputFile("src/main/database/all.sql");
export.setDelimiter(";");
export.setFormat(true);
export.create(true, false);
但這種作法有一個前提,就是要有 hibernate.cfg.xml,可是隨著 Spring 的不斷滲透,hibernate.cfg.xml 慢慢的已經不見了,其設定值都進到 Spring XML 設定檔裡了。

之前為了產出 SQL,還特地為此建立 hibernate.cfg.xml,但這又會造成與 Spring XML 不同步的困擾。

今天想想,那能從 Spring 裡擠出 org.hibernate.cfg.Configuration 嗎?如果可以,那就可以用 org.hibernate.tool.hbm2ddl.SchemaExport 來讀 Spring XML 裡有關 Hibernate 的設定,這樣就可以完全擺脫 hibernate.cfg.xml 了。

看看 Spring XML 裡的設定,距離 Hibernate 最近的就是由 org.springframework.orm.hibernate3.LocalSessionFactoryBean 所產生的 SessionFactory 了。

但是 SessionFactory 拿不回 org.hibernate.cfg.Configuration,因為沒有提供這樣的 API,而 LocalSessionFactoryBean 卻有 getConfiguration() 這樣的 API,第一時間,以為 LocalSessionFactoryBean 是 SessionFactory 的子類別,所以就...
SessionFactory sf = (SessionFactory) ctx.getBean("sessionFactory");
LocalSessionFactoryBean lsf = (LocalSessionFactoryBean) sf; // Class cast error
LocalSessionFactoryBean lsf = (LocalSessionFactoryBean) ctx.getBean("sessionFactory"); // Class cast error
才發現,LocalSessionFactoryBean 不是 SessionFactory 子類別,那那那,為何 LocalSessionFactoryBean 可以回傳 SessionFactory(事實上是 SessionFactoryImpl)呢?

原來 LocalSessionFactoryBean 是 Factory Bean,專門用來產出 SessionFactoryImpl 的,長見識了。

但是,我要怎麼拿到 LocalSessionFactoryBean 呢?沒有 LocalSessionFactoryBean 就沒有 Configuration。

沒想到,Spring 居然有這一招,只要在 getBean() 的 id 名稱前加上 & 就可以拿到 Factory Bean,而不是 Factory Bean 產出的 SessionFactoryImpl。
LocalSessionFactoryBean lsf = (LocalSessionFactoryBean) ctx.getBean("&sessionFactory");
新版的 SchemaExport 如下。
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
LocalSessionFactoryBean lsf = (LocalSessionFactoryBean) ctx.getBean("&sessionFactory");
SchemaExport export = new SchemaExport(lsf.getConfiguration());
export.setOutputFile("src/main/database/all.sql");
export.setDelimiter(";");
export.setFormat(true);
export.create(true, false);
ctx.close();
---
---
---

沒有留言:

張貼留言