1 零丁应用hibernate处理惩罚事物
底本只用hibernate开辟,从而可以省了DAO层实现数据库接见和跨数据库,也可以对代码进行更好的封装,当我们web中零丁应用hibernate时,我们须要零丁的处理惩罚hibernate的事务,我是应用filter来对事务进行把握的:
零丁应用hibernate应用filter进行事务把握:
HibernateSessionFilter.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
|
public
class
HibernateSessionFilter
implements
Filter {
public
void
destroy() {
}
public
void
doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws
IOException,
ServletException {
Session session = HibernateUtils.openSession();
Transaction tx =
null
;
try
{
tx = session.beginTransaction();
chain.doFilter(request, response);
tx.commit();
}
catch
(Exception e) {
if
(tx !=
null
) {
tx.rollback();
}
throw
new
RuntimeException(e);
}
finally
{
HibernateUtils.closeAndRemoveSession();
}
}
public
void
init(FilterConfig arg0)
throws
ServletException {
}
}
|
web.xml
1
2
3
4
5
6
7
8
9
10
|
<filter>
<filter-name>hibernateSessionFilter</filter-name>
<filter-
class
> syx.jpkc.filter.HibernateSessionFilter</filter-
class
>
</filter>
<filter-mapping>
<filter-name>hibernateSessionFilter</filter-name>
<url-pattern>*.syx</url-pattern>
<url-pattern>*.jsp</url-pattern>
<url-pattern>*.eve</url-pattern>
</filter-mapping>
|
&#160;
我首要在servlet(*.syx,*.eve)和jsp页面(没用struts)须要和数据库操纵,所以须要应用事务处理惩罚。
上方我们还用到了一个 HibernateUtils的小对象类,首要为了获取Session对象和一点优化:
HibernateUitls.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
|
public
class
HibernateUtils {
private
static
Map<Thread, Session> sessionMap;
private
static
SessionFactory sessionFactory;
static
{
sessionMap =
new
HashMap<Thread, Session>();
sessionFactory =
new
Configuration().configure().buildSessionFactory();
}
/**
* can only use in web filter, beause it should remove and clear resources
* @return
*/
public
static
Session openSession() {
System.out.println(Thread.currentThread().getStackTrace()[
1
] +
" run in "
+
new
Date());
Session session = sessionMap.get(Thread.currentThread());
if
(session ==
null
) {
session = sessionFactory.openSession();
sessionMap.put(Thread.currentThread(), session);
}
return
session;
}
public
static
Session getCurrentSession() {
return
sessionMap.get(Thread.currentThread());
}
public
static
void
closeAndRemoveSession() {
System.out.println(Thread.currentThread().getStackTrace()[
1
]+
" run in "
+
new
Date());
//
Session session = sessionMap.remove(Thread.currentThread());
if
(session !=
null
) {
session.close();
}
}
}
|
&#160;
2 hibernate整合进spring后的事物处理惩罚
spring事物处理惩罚的体式格式有很多,详见:http://www.blogjava.net/robbie/archive/2009/04/05/264003.html
介绍常用的:
spring annotation声明式的事务经管
1) 事物处理惩罚层?
比如保存一个User,可以在Service层和DAOImpl层实现:
1
2
3
4
5
6
7
8
9
10
11
12
|
public
void
save(User u) {
userDAO.save(u);
}
public
void
save(User u) {
System.out.println(
"save user :"
+
this
);
Session s = sessionFactory.openSession();
s.beginTransaction();
s.save(u);
s.getTransaction().commit();
s.close();
}
|
假如我们还有个日记记录,没保存一个User对象,要写入日记进入数据库。
而save(log) 和 save(user)必须处在同一事务中,所以不克不及放在DAOImpl层,事务处理惩罚在Service层。
2) 一般的事务处理惩罚
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
Session sess = factory.openSession();
Transaction tx;
try
{
tx = sess.beginTransaction();
//do some work
//save(user);
//save(log);
...
tx.commit();
}
catch
(Exception e) {
if
(tx!=
null
) tx.rollback();
throw
e;
}
finally
{
sess.close();
}
|
并且要在实现层中的save()办法中也要参加事务处理惩罚,若是出呈现异常要throws给上级处理惩罚!
并且实现层中的session必须应用openCurrentSession()获得。
1
2
|
Session s = sessionFactory.getCurrentSession();
s.save(u);
|
3) spring annotation事务处理惩罚
Beans.xml中引入响应的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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
|
xmlns:tx=
"http://www.springframework.org/schema/tx"
http:
//www.springframework.org/schema/tx
http:
//www.springframework.org/schema/tx/spring-tx-3.0.xsd
<tx:annotation-driven transaction-manager=
"txManager"
/>
<bean id=
"txManager"
class
=
"org.springframework.orm.hibernate3.HibernateTransactionManager"
>
<property name=
"sessionFactory"
ref=
"sessionFactory"
/>
</bean>
<bean id=
"dataSource"
class
=
"org.apache.commons.dbcp.BasicDataSource"
destroy-method=
"close"
>
<property name=
"driverClassName"
value=
"¥{jdbc.driverClassName}"
/>
<property name=
"url"
value=
"¥{jdbc.url}"
/>
<property name=
"username"
value=
"¥{jdbc.username}"
/>
<property name=
"password"
value=
"¥{jdbc.password}"
/>
</bean>
<bean id=
"sessionFactory"
class
=
"org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"
>
<property name=
"dataSource"
ref=
"dataSource"
/>
<property name=
"annotatedClasses"
>
<list>
<value>com.syx.model.User</value>
<value>com.syx.model.Log</value>
</list>
</property>
<property name=
"hibernateProperties"
>
<props>
<prop key=
"hibernate.dialect"
>org.hibernate.dialect.MySQLDialect</prop>
<prop key=
"hibernate.show_sql"
>
true
</prop>
<prop key=
"current_session_context_class"
>thread</prop>
</props>
</property>
</bean>
Save办法:
public
void
save(User u) {
Session s = sessionFactory.getCurrentSession();
s.save(u);
}
public
void
save(Log log) {
Session s = sessionFactory.getCurrentSession();
s.save(log);
}
Service层处理惩罚:
@Component(
"userService"
)
public
class
UserService {
UserDAO userDAO =
null
;
LogDAO logDAO =
null
;
public
LogDAO getLogDAO() {
return
logDAO;
}
@Resource(name=
"logDAOMySQLImpl"
)
public
void
setLogDAO(LogDAO logDAO) {
this
.logDAO = logDAO;
}
@Transactional
public
void
save(User u) {
userDAO.save(u);
Log log =
new
Log();
log.setMsg(u.getName() +
" saved in "
+
new
Date());
logDAO.save(log);
}
public
UserDAO getUserDAO() {
return
userDAO;
}
@Resource(name=
"userDAOMySQLImpl"
)
public
void
setUserDAO(UserDAO userDAO) {
this
.userDAO = userDAO;
}
}
|
4) @Transactional详解
什么时辰rollback
运行期异常,非运行期异常不会触发rollback
必须uncheck (没有catch)
不管什么异常,只要你catch了,spring就会放弃经管
事务传播特点:propagation_required
propagation 默认是 REQUIRED ,意思是有我们就用现成的,没的我们就发明一个,其他具体见文档
spring xml声明式的事务经管
设备景象和annotation版本一致,只是在用@Transactional处注释调用,在beans.xml中参加如下设备:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
<!-- spring tranception xml config -->
<
aop:config
>
<
aop:pointcut
id="serviceOperation"
expression="execution(* com.syx.service..*.*(..))" />
<
aop:advisor
pointcut-ref="serviceOperation" advice-ref="txAdvice" />
</
aop:config
>
<
tx:advice
id="txAdvice" transaction-manager="txManager">
<
tx:attributes
>
<
tx:method
name="getUser" read-only="true" />
<
tx:method
name="save" />
<!-- 相当于在上方切面pointcut@Transactional结果 -->
</
tx:attributes
>
</
tx:advice
>
|
1
|
<
span
style="font-size: medium; font-weight: bold;">3 hibernateTemplate.getSessionFactory().getCurrentSession()</
span
>
|
我们应用spring和hibernate连络,操纵数据库最常用可能是HibernateTemplate,HibernateTemplate中集成了很多应用的办法,可惜的是没的createQuery办法,也许我们应用hibernate的时辰喜好应用Query,我们可能会封装hibernateTemplate.getSessionFactory().getCurrentSession()办法获得Session,session创建Query,这是一个办法,但你应当会获得异常 “createQuery without an active transaction”,因为应用hibernateTemplate.getSessionFactory().getCurrentSession(),你是应用的hibernate的事务经管,而你指望spring经管的事物是hibernateTemplate,所以你会提示没有打开事务的异常,解决办法:1)应用hibernate事务处理惩罚,就像上方零丁应用hibernate一样,但这也许不是你想要的。2)应用hibernateTemplate的HibernateCallBack回调:
1
2
3
4
5
6
7
8
|
return hibernateTemplate.executeWithNativeSession(
new HibernateCallback<
List
<T>>() {
public List<
T
> doInHibernate(Session session)
throws HibernateException, SQLException {
return session.createQuery
("FROM " + entityClass.getName() + " WHERE id IN (:ids)")//
.setParameterList("ids", idList).list();
}
|
&#160;
实际上hibernateTemplate中封装的find办法也很强大,若是谙练应用完全可以调换createQuery的。
备注:
若是呈现异常:对同一个凑集处理惩罚不克不及应用2个session,这是因为getCurrentSession办法失足,导致打开一个新的session,搜检设备文件,若是应用tomcat+spring+hibernate 设备hibernate.current_session_context_class 最好为thread,固然支撑jta,设备斗劲麻烦,并且jta支撑多个sessionFactory,即可以跨数据库,斗劲强大!
若是hibernate+spring呈现session没有提友情况,应当是你让spring负责事务处理惩罚,而你有应用了hibernate的session,从而离开spring事务处理惩罚,即没的begintransaction和commit之类的操纵了。
本文转自农夫山泉别墅博客园博客,原文链接:http://www.cnblogs.com/yaowen/archive/2013/02/26/2933102.html,如需转载请自行联系原作者