單純Hibernate程序
1、首先是導入hibernate的jar包。
2、 建立用戶和用戶操作記錄實體,Log.Java和User.java。代碼如下所示。
Log.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
import java.util.Date; public class Log { private int id; //日志的類別.日志一般起到一個不可否認性. //操作日志 安全日志 事件日志. private String type; private String detail; private Date time; public int getId() { return id; } public void setId( int id) { this .id = id; } public String getType() { return type; } public void setType(String type) { this .type = type; } public String getDetail() { return detail; } public void setDetail(String detail) { this .detail = detail; } public Date getTime() { return time; } public void setTime(Date time) { this .time = time; } } |
User.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
public class User { private int id; private String name; public int getId() { return id; } public void setId( int id) { this .id = id; } public String getName() { return name; } public void setName(String name) { this .name = name; } } |
3、 并建立與之對應的實體配置文件,Log.hbm.xml和Use.hbm.xml。代碼如下所示。
1
2
3
4
5
6
7
8
9
10
11
12
|
<?xml version= "1.0" ?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" > <hibernate-mapping> < class name= "com.bjpowernode.usermgr.domain.User" table= "t_user" > <id name= "id" > <generator class = "native" /> </id> <property name= "name" /> </ class > </hibernate-mapping> |
Log.hbm.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
<?xml version= "1.0" ?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" > <hibernate-mapping> < class name= "com.bjpowernode.usermgr.domain.Log" table= "t_log" > <id name= "id" > <generator class = "native" /> </id> <property name= "type" /> <property name= "detail" /> <property name= "time" /> </ class > </hibernate-mapping> |
4、Manager層代碼如下所示。
LogManager.java接口
1
2
3
4
|
public interface LogManager { //添加日志.方法 public void addLog(Log log); } |
LogManagerImpl實現
1
2
3
4
5
6
7
|
public class LogManagerImpl implements LogManager { @Override public void addLog(Log log) { HibernateUtils.getSessionFactory().getCurrentSession().save(log); } } |
UserManager接口
1
2
3
4
|
public interface UserManager { public void addUser(User user); } |
UserManagerImpl.java實現
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
public class UserManagerImpl implements UserManager { @Override public void addUser(User user) { Session session = null ; try { //這個session中是放到threadlocal. session = HibernateUtils.getSessionFactory().getCurrentSession(); session.beginTransaction(); // 網用戶表中添加一條同時網日志中添加一條. session.save(user); Log log = new Log(); log.setType( "操作日志" ); log.setTime( new Date()); log.setDetail( "xxx" ); LogManager logManager = new LogManagerImpl(); //添加日志. logManager.addLog(log); session.getTransaction().commit(); } catch (Exception e) { e.printStackTrace(); session.getTransaction().rollback(); } finally { HibernateUtils.closeSession(session); } } } |
5、是通過sessionFactory來創建session,通過session來開啟提交和關閉回滾事務,我們把session的開啟關閉封裝到一個工具類中。HibernateUtils.java代碼如下所示。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
public class HibernateUtils { private static SessionFactory factory; static { try { //讀取hibernate.cfg.xml文件 Configuration cfg = new Configuration().configure(); //建立SessionFactory factory = cfg.buildSessionFactory(); } catch (Exception e) { e.printStackTrace(); } } public static Session getSession() { return factory.openSession(); } public static void closeSession(Session session) { if (session != null ) { if (session.isOpen()) { session.close(); } } } public static SessionFactory getSessionFactory() { return factory; } } |
6、配置hibernate.cfg.xml文件,包括數據庫名稱,數據庫關聯的表,以及用戶名密碼等。代碼如下所示。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
<hibernate-configuration> <session-factory> <property name= "hibernate.connection.driver_class" >com.mysql.jdbc.Driver</property> <property name= "hibernate.connection.url" >jdbc:mysql: //localhost:3306/spring_hibernate_1</property> <property name= "hibernate.connection.username" >root</property> <property name= "hibernate.connection.password" >root</property> <property name= "hibernate.dialect" >org.hibernate.dialect.MySQLDialect</property> <property name= "hibernate.show_sql" > true </property> <property name= "hibernate.hbm2ddl.auto" >update</property> <property name= "hibernate.current_session_context_class" >thread</property> <!-- <property name= "hibernate.current_session_context_class" >jta</property> --> <mapping resource= "com/bjpowernode/usermgr/domain/User.hbm.xml" /> <mapping resource= "com/bjpowernode/usermgr/domain/Log.hbm.xml" /> </session-factory> </hibernate-configuration> |
7、 使用junit進行單元測試,代碼如下所示。
1
2
3
4
5
6
7
8
9
|
import junit.framework.TestCase; public class UserManagerImplTest extends TestCase { public void testAddUser() { UserManager userManager = new UserManagerImpl(); User user = new User(); user.setName( "張三" ); userManager.addUser(user); } } |
在上述操作用,對事物的控制邊界在業務邏輯層,因為在UserManagerImpl中我們調用addUser()這一方法的同時要把這一操作寫入到日志中,也就是調用了addLog()方法,而對于類的方法,一方法一session,一session一事務,那么如果控制事務的呢?我們要執行開啟addUser()事務同時再開啟addLog()事務嗎?在這里我們沒有再用以前的openSession方法,選擇用的HibernateUtils.getSessionFactory().getCurrentSession();
同時在hibernate.cfg.xml中對getCurrentSession()進行配置如下, <propertyname="hibernate.current_session_context_class">thread</property>
表示在當前線程中,與當前線程綁定這樣執行addUser()方法和addLog()方法使用的是同一個事務。
那OpenSession和getCurrentSession的區別呢?
1、 openSession必須關閉,currentSession在事務結束后自動關閉。
2、 openSession沒有和當前線程綁定,currentSession和當前線程綁定。并且使用currentSession需要在我們的hibernate.cfg.xml文件中進行事務的配置,是使用Jdbc事務還是JTA事務。
hibernate和spring結合使用
我們從上述例子中發現,hibernate的事務是獨立于hibernate對數據庫的增刪改查的,并且事務控制在我們的業務邏輯層,對于獨立的東西,像是橫切性問題,自然想到了AOP,實際上SpringAOP封裝了對事務的管理,使用SpringAOP我們不再負責去開啟和關閉事務。
下面用SpringAOP來和hibernate結合。
當然也要導入Spring相關jar。
對于事務管理就是一個橫切性問題,把事務管理模塊化就是我們的aspect,然后再配置文件中進行配置,我們可以把事務單獨放到一個配置文件中。
1、代碼如下,applicationContext-common.xml文件。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
<beans xmlns= "http://www.springframework.org/schema/beans" xmlns:xsi= "http://www.w3.org/2001/XMLSchema-instance" xmlns:aop= "http://www.springframework.org/schema/aop" xmlns:tx= "http://www.springframework.org/schema/tx" xsi:schemaLocation="http: //www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd http: //www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd http: //www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd"> <!-- 配置SessionFactoyr --> <bean id= "sessionFactory" class = "org.springframework.orm.hibernate3.LocalSessionFactoryBean" > <property name= "configLocation" > <value>classpath:hibernate.cfg.xml</value> </property> </bean> <!-- 配置事務管理器 --> <bean id= "transactionManager" class = "org.springframework.orm.hibernate3.HibernateTransactionManager" > <property name= "sessionFactory" > <ref bean= "sessionFactory" /> </property> </bean> <!-- 哪些類哪些方法使用事務. --> <aop:config> <aop:pointcut id= "allManagerMethod" expression= "execution(* com.bjpowernode.usermgr.manager.*.*(..))" /> <aop:advisor pointcut-ref= "allManagerMethod" advice-ref= "txAdvice" /> </aop:config> <tx:advice id= "txAdvice" transaction-manager= "transactionManager" > <tx:attributes> <tx:method name= "add*" propagation= "REQUIRED" /> <tx:method name= "del*" propagation= "REQUIRED" /> <tx:method name= "modify*" propagation= "REQUIRED" /> <tx:method name= "*" propagation= "REQUIRED" read-only= "true" /> </tx:attributes> </tx:advice> </beans> |
首先是配置的是sessionFactory,讓spring拿到hibernate的sessionFactory,以便對hibernate事務控制,通過sessionFactory產生session再訪問。這樣就把把hibernate的sessionFactory注入到Spring中了。通過<property>標簽,告訴SpringHibernate的配置文件在哪里,以便spring可以讀取hibernate的配置文件。
其次是配置事務管理器,把我們的sessionFactory注入給事務管理器,讓事務管理器管理事務。
其次,到底是哪些類哪些方法,開始執行的時候執行事務,<aop:pointcutid="allManagerMethod"
其次,配置AOP,expression="execution(*com.bjpowernode.usermgr.manager.*.*(..))",
到底是哪些類交給spring完成事務管理?我們應用在所有的manager包中的所有方法上,manager所有類所有方法全部參與事務的運行。那在什么地方觸發開啟事務?
再次,定義一個Advice,配置事務的傳播特性,例如addUser()中調用addLog()方法,是在同一個事務還是不在同一個事務。以add開頭,del開頭,modify開頭以及其他,我們配置的事務傳播特性為propagation="REQUIRED",這樣在一個方法中調用另一個方法他們公共一個線程。
2、讓UserManagerImpl繼承spring提供的對hibernateDao支持類。
HibernateDaoSupport,這樣繼承之后我們就能拿到session,其實也就是hibernate中的session,只不過spring為我們封裝了。我們可以這樣拿到sesion:This.getSession().save(user);或者使用spring封裝好的對象:
This.getHibernateTemplate().save(user);這樣都封裝到里面了,我們不管理事務的開啟和關閉。
之前在我們的UserManagerImpl中使用了LogManagerImpl實例,這次我們可以使用Spring的IOC容器,把他們之間的依賴關系注入到Spring中,這樣就看不到實例,面對接口編程,進行了解耦。
接口不變,UserManagerImpl.java代碼如下所示。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
public class UserManagerImpl extends HibernateDaoSupport implements UserManager { private LogManager logManager; public void setLogManager(LogManager logManager) { this .logManager = logManager; } @Override public void addUser(User user) throws Exception { //this.getSession().save(user); //或者用. this .getHibernateTemplate().save(user); Log log = new Log(); log.setType( "操作日志" ); log.setTime( new Date()); log.setDetail( "xxx" ); //LogManager logManager = new LogManagerImpl(); //添加日志. logManager.addLog(log); //運行期的異常,會回滾. 并且是他的子類也會回滾. //throw new RuntimeException(); //throw new Exception(); } } |
LogManagerImpl.java 代碼如下所示。
1
2
3
4
5
6
7
8
|
public class LogManagerImpl extends HibernateDaoSupport implements LogManager { @Override public void addLog(Log log) { //getSession().save(log); this .getHibernateTemplate().save(log); } } |
刪除我們自己建立的HibernateUtils.java類,刪除hibernate.cfg.xml文件中對getCurrentSession()的事務配置。
3、在配置文件中配置依賴關系。
applicationContext-beans.xml代碼如下所示。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
<beans xmlns= "http://www.springframework.org/schema/beans" xmlns:xsi= "http://www.w3.org/2001/XMLSchema-instance" xmlns:aop= "http://www.springframework.org/schema/aop" xmlns:tx= "http://www.springframework.org/schema/tx" xsi:schemaLocation="http: //www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd http: //www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd http: //www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd"> <bean id= "userManager" class = "com.bjpowernode.usermgr.manager.UserManagerImpl" > <property name= "sessionFactory" ref= "sessionFactory" /> <property name= "logManager" ref= "logManager" /> </bean> <bean id= "logManager" class = "com.bjpowernode.usermgr.manager.LogManagerImpl" > <property name= "sessionFactory" ref= "sessionFactory" /> </bean> </beans> |
在Junit中測試程序代碼如下所示。
1
2
3
4
5
6
7
8
9
10
11
12
13
|
public class UserManagerImplTest extends TestCase { public void testAddUser() { BeanFactory factory = new ClassPathXmlApplicationContext( "applicationContext-*.xml" ); UserManager userManager = (UserManager) factory.getBean( "userManager" ); User user = new User(); user.setName( "張三" ); try { userManager.addUser(user); } catch (Exception e) { e.printStackTrace(); } } } |
顯示結果如下圖所示。
這樣就完成了spring和hibernate的結合,主要是利用SpringAOP對hibernate的事務進行控制和在Manager層之間的調用用Spring IOC進行控制。
總結
以上所述是小編給大家介紹的spring結合hibernate示例詳解,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對服務器之家網站的支持!
原文鏈接:http://blog.sina.com.cn/s/blog_9c6852670102wvtw.html