在網(wǎng)上漫無邊際地搜索了一天,絕大部分都是垃圾信息,只好自己做一遍
好了,下面我就將我所完成的例子程序完整的敘述,希望對讀者有所幫助。
一、開發(fā)環(huán)境
myeclipse6.01GA,mysql。
二、表結(jié)構(gòu)
CREATE TABLE `user` (
`id` int(10) unsigned NOT NULL auto_increment,
`username` varchar(64) NOT NULL,
`password` varchar(64) NOT NULL,
`first_name` varchar(128) NOT NULL,
`last_name` varchar(128) NOT NULL,
`date_created` bigint(20) unsigned NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
三、具體步驟:
1、在myeclipse中建立一個“java project”,工程名為:HibernateSpringProject,這個程序用java應(yīng)用程序就可以實現(xiàn)。
2、右鍵點擊工程文件,然后選擇MyEclipse->Add Spring Capabilities...
第一步選擇需要加載的包,如下圖所示:

其余的選項默認(rèn),點擊 “下一步”,提示是否建立spring配置文件,選擇默認(rèn),然后直接點擊“finish”。
3、右鍵點擊工程文件,然后選擇MyEclipse->Add Hibernate Capabilities...
第一步選擇默認(rèn),點擊“下一步”。
第二步提示你是用hibernate的配置文件還是用spring的配置文件進(jìn)行SessionFactory的配置,選擇使用spring來對hibernate進(jìn)行管理,這樣最后生成的工程里就不包含hibernate.cfg.xml了,好處是在一個地方就可以對hibernate進(jìn)行管理了。
第三步提示你是創(chuàng)建一個新的hibernate配置文件還是使用已有的配置文件,由于我們剛才已經(jīng)生成了spring配置文件,并且要在其中進(jìn)行hibernate的配置,所以選擇復(fù)選框“Existing Spring configuration file”,選擇該項后,下方的“Spring Config:”后的下拉列表框自動填入了剛才生成的spring配置文件路徑。這時候有個錯誤,要求你填寫SessionFactory ID,這個id就是我們要為hibernate注入的一個類的ID,隨便取一個名字,例如“sessionFactory”。點擊“下一步”。
第四步要求選擇數(shù)據(jù)庫連接信息,這個步驟可以參照網(wǎng)上的信息進(jìn)行配置,很簡單。這里需要注意一點,“bean id”處填寫一個數(shù)據(jù)源的名稱,例如“datasource”,下面的單選按鈕選擇“Use Jdbc Driver”就行了,此處沒有用jndi。在“DB Driver”處選擇配置好的數(shù)據(jù)庫連接信息,其他信息自動填入余下的輸入框中,點擊下一步。
第四步提示是否創(chuàng)建“SessionFactory”類,由于本程序用spring替我們注入sessionfactory,此處可以不用創(chuàng)建,勾掉復(fù)選框。然后直接點擊“finish”。
4、建立三個包,分別是com.simon.dao,com.simon.model,com.simon.service。
在用ssh開發(fā)web應(yīng)用時,需要對生成的各個類文件進(jìn)行組織,下面就對一個可行的目錄方案進(jìn)行介紹:
譬如應(yīng)用中有一個用戶管理模塊,則在公共包下建立一個user包,如該公共包可以為com.simon.oa,
在user包下包括如下子包
1、controler包
該包放置各種struts的action。
2、dao包
該包放置各類dao(data access object),也就是放置對數(shù)據(jù)庫訪問的實現(xiàn)類,在用myeclipse中的“Hibernate Reverse Engineering”進(jìn)行反向操作時在某一個目錄中就會生成對應(yīng)某個表的DAO,生成后可將該DAO拖到dao包中。在某些應(yīng)用中將DAO作為接口,在該接口中包括所有對數(shù)據(jù)庫的操作方法,然后在dao包建立一個hibernate包,在hibernate包中放置對DAO接口的實現(xiàn),譬如:UserDAO接口有一個實現(xiàn)類為UserDaoImpl,將該類放置到hibernate包中,實際的開發(fā)傾向于后一種方式,因為對這個DAO接口可以實現(xiàn)spring的IoC操作。(不知道m(xù)yeclipse對此是怎么考慮的,這個問題讓我糾纏了很久,誤將DAO理解成一個能夠進(jìn)行實際操作的類,而不是一個接口,以后開發(fā)要注意)
3、model包
該包中放置hibernate反向工程生成的bean和該bean對應(yīng)的.hbm.xml文件。
4、service包
該包放置業(yè)務(wù)操作類,譬如用戶服務(wù)類,一般情況將該用戶操作類提取一個接口,然后在service包下生成一個impl包,在impl包中才放置用戶操作接口的實現(xiàn)類。該用戶接口實現(xiàn)類中調(diào)用DAO接口對數(shù)據(jù)庫進(jìn)行操作,而調(diào)用該實現(xiàn)類的方法在struts的action中。
5、vo包(value object)
vo包中的中包括struts中使用的POJO及actionform等信息。
VO: Value Object
DTO: Data Transfer Object
個人理解VO和DTO是類似的東西,原則上VO和DTO只有Public Fields,主要用于進(jìn)程之間數(shù)據(jù)傳遞的問題,VO和DTO不會傳遞到表示層,在業(yè)務(wù)層就會被吸收。但看到很多人在建立VO和DTO時,也含有Setter,Getter屬性和一些其它的輔助方法,這也無可厚非,我自己也不能確定這對不對。
實際的結(jié)構(gòu)如下:

5、打開myeclipse的database exployer perspective,右鍵選擇user表,選擇Hibernate reverse engineering
按照下圖所示進(jìn)行設(shè)置

點擊下一步,在“ID generator”中選擇native,如果愿意可以直接點擊finish
這時再觀察applicationContext.xml文件,發(fā)現(xiàn)在sessionFactory定義中增加了如下代碼:
<property name="mappingResources">
<list>
<value>com/simon/model/User.hbm.xml</value>
</list>
</property>
此時在觀察類結(jié)構(gòu):

在model包下生成了三個類和一個映射文件。AbstractUser是User的抽象類,在此需要說明一點的是,在標(biāo)準(zhǔn)的spring應(yīng)用中UserDAO應(yīng)該是一個接口,而不是一個具體的類,而myeclipse將數(shù)據(jù)庫操作方法直接寫到了UserDAO中,另外,按照標(biāo)準(zhǔn)寫法,DAO實現(xiàn)類要實現(xiàn)DAO接口,并且要包括SessionFactory的變量聲明,但是生成的代碼中UserDAO直接實現(xiàn)了HibernateDaoSupport類,需要特別注意。所以,如果你需要標(biāo)準(zhǔn)寫法,可以將UserDAO中的方法提取出來,只保留方法聲明,然后再間一個impl目錄,將該DAO的實現(xiàn)類放在該impl中,按照管理將該類命名為UserDAOImpl,另外一點最好將DAO和它的實現(xiàn)類移到dao包中,結(jié)構(gòu)和model包中的相同。
在這個例子中暫且將生成的文件都放到model中。
此時我們可以寫一個測試程序?qū)⒁粭l記錄插入到user表中,當(dāng)然這個測試程序并沒有用事務(wù)控制,后面我們還會介紹,測試程序如下:
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.simon.model.UserDAO;
import com.simon.model.User;
public class TestWithoutTx {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
User user=new User();
user.setFirstName("first name");
user.setLastName("last name");
user.setUsername("user name");
user.setPassword("password");
user.setDateCreated(new Long(111111));
ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml");
UserDAO userdao=(UserDAO)context.getBean("UserDAO");
userdao.save(user);
}
}
現(xiàn)在的問題是增加事務(wù)處理功能,跟我繼續(xù),這時候源程序不需要修改,只需要修改applicationContext.xml配置文件,首先增加事務(wù)管理器,因為事務(wù)管理器也需要使用數(shù)據(jù)庫,所以需要引入sessionFactory
如下:
<bean id="myTransactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory">
<ref bean="sessionFactory" />
</property>
</bean>
繼續(xù)增加如下配置信息:
<bean id="userDAOProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="proxyTargetClass">
<value>true</value>
</property>
<property name="transactionManager">
<ref bean="myTransactionManager" />
</property>
<property name="target">
<ref local="UserDAO" />
</property>
<property name="transactionAttributes">
<props>
<!-- 這里的方法簽名可以精確到方法, 先懶惰一下全配置上 -->
<prop key="*">PROPAGATION_REQUIRED</prop>
</props>
</property>
</bean>
注意以上紅色部分: 注意這個屬性,必須為 true, 使用CGLIB時才不用強(qiáng)制編寫DAO接口,也就是由于myeclipse并沒有為我們生成DAO接口,而是生成了一個數(shù)據(jù)庫實現(xiàn)類,為了使spring不強(qiáng)迫我們必須定義一個DAO接口,只需要將這個proxyTargetClass屬性定義為true,這點非常重要,程序出錯很有可能和這個屬性設(shè)置錯誤有關(guān)。
下面再寫一個測試程序,和上面的測試程序基本相同,唯一不同是將上面的
UserDAO userdao=(UserDAO)context.getBean("userDAO");
換成
UserDAO userdao=(UserDAO)context.getBean("userDAOProxy");
執(zhí)行,一切ok,數(shù)據(jù)正確的插入到數(shù)據(jù)庫中。