Spring和Hibernate自动管理事务总结(注解方式)

一.Hibernate事务管理

1.bean.xml配置文件的代码

<?xml version="1.0" encoding="utf-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
	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.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop.xsd
    http://www.springframework.org/schema/tx
    http://www.springframework.org/schema/tx/spring-tx.xsd">

	<context:component-scan base-package="com.highgo.holiday.dao,com.highgo.holiday.service,com.highgo.holiday.action" />

	<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
		<property name="driverClassName" value="org.postgresql.Driver" />
		<property name="url" value="jdbc:postgresql://localhost:5432/postgres" />
		<property name="username" value="postgres" />
		<property name="password" value="highgo123" />
	</bean>

	<!-- 注册sessionFactory -->
	<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
		<property name="dataSource" ref="dataSource" /><!-- 引用数据源 -->

		<property name="packagesToScan">
			<list>
				<value>com.highgo.holiday.model</value>
			</list>
		</property>

		<property name="hibernateProperties">
			<props>
				<prop key="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</prop>
				<prop key="hibernate.show_sql">false</prop>
				<prop key="hibernate.format_sql">true</prop>
				<prop key="hibernate.connection.autocommit">true</prop>
			</props>
		</property>
	</bean>
</beans>

2.Dao.java接口文件部分代码

package com.highgo.holiday.dao;

public interface PeopleDao {
//这里写你在Dao实现类里写的方法
}

3.DaoImpl.java实现类的部分代码

package com.highgo.ssh.dao;

import java.util.List;
import javax.annotation.Resource;
import org.hibernate.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import com.highgo.ssh.model.People;

@Repository(value = "peopleDao")
public class PeopleDaoImpl implements PeopleDao {

	@Autowired
	@Resource(name = "sessionFactory")
	private SessionFactory sessionFactory;
	
	//第一种方式,用的是openSession(),需要开启事务,并且session必须手动关闭
	public void insertData(People people) throws Exception {
		session = sessionFactory.openSession();
		transaction = session.beginTransaction();

		session.save(people);

		transaction.commit();
		session.close();
	}

    //第二种方式,用的是getCurrentSession(),必须要开启事务,否则获取不到session,提交完成后不用手动关闭session,会自动关闭。
	public void insertData(People people) throws Exception {
		session = sessionFactory.getCurrentSession();
		transaction = session.beginTransaction();

		session.save(people);

		transaction.commit();
	}
}

如果用getCurrentSession()获取session的话,需要在配置文件加上一句代码:

<property name="current_session_context_class">thread</property>

4.ServiceImpl.java中注入Dao层

    //第一种方式,注入接口类
    @Autowired
	@Resource(name = "peopleDao")
	private PeopleDao peopleDao;
	
   //第二种方式,注入实现类
   @Autowired
	@Resource(name = "peopleDao")
	private PeopleDaoImpl peopleDao;

推荐使用第一种方式,Action注入Service层同上,也是推荐使用注入接口类

二.Spring自动管理事务

1.bean.xml配置文件代码

<?xml version="1.0" encoding="utf-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
	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.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop.xsd
    http://www.springframework.org/schema/tx
    http://www.springframework.org/schema/tx/spring-tx.xsd">

	<context:component-scan base-package="com.highgo.holiday.dao,com.highgo.holiday.service,com.highgo.holiday.action" />

	<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
		<property name="driverClassName" value="org.postgresql.Driver" />
		<property name="url" value="jdbc:postgresql://localhost:5432/postgres" />
		<property name="username" value="postgres" />
		<property name="password" value="highgo123" />
	</bean>

	<!-- 注册sessionFactory -->
	<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
		<property name="dataSource" ref="dataSource" /><!-- 引用数据源 -->

		<property name="packagesToScan">
			<list>
				<value>com.highgo.holiday.model</value>
			</list>
		</property>

		<property name="hibernateProperties">
			<props>
				<prop key="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</prop>
				<prop key="hibernate.show_sql">false</prop>
				<prop key="hibernate.format_sql">true</prop>
				<prop key="hibernate.connection.autocommit">true</prop>
			</props>
		</property>
	</bean>

	<!-- 声明式事务管理 -->
	<bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">

		<property name="sessionFactory" ref="sessionFactory" />

	</bean>

	<tx:annotation-driven transaction-manager="transactionManager" />

</beans>

2.Dao.java接口文件部分代码

package com.highgo.holiday.dao;

public interface PeopleDao {
//这里写你在Dao实现类里写的方法
}

3.DaoImpl.java实现类的部分代码

package com.highgo.ssh.dao;

import java.util.List;
import javax.annotation.Resource;
import org.hibernate.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import com.highgo.ssh.model.People;

@Repository(value = "peopleDao")
public class PeopleDaoImpl implements PeopleDao {

	@Autowired
	@Resource(name = "sessionFactory")
	private SessionFactory sessionFactory;
	
	//第一种方式,用的是openSession(),session必须手动关闭
	public void insertData(People people) throws Exception {
		session = sessionFactory.openSession();
		
		session.save(people);

		session.close();
	}

    //第二种方式,用的是getCurrentSession(),不用手动关闭session,会自动关闭。
	public void insertData(People people) throws Exception {
		session = sessionFactory.getCurrentSession();

		session.save(people);
	}
}

4.因为需要自动管理事务所以需要在ServiceImpl.java中加入注解@Transactional

//放到类上面,该类所有方法都会自动管理,也可以放到方法上
@Transactional
@Service("peopleService")
public class PeopleServiceImpl implements PeopleService {
}

5.ServiceImpl.java中注入Dao层

   @Autowired
	@Resource(name = "peopleDao")
	private PeopleDao peopleDao;

要注入接口类,不然会出错

三.hibernate中session线程安全的实现

在hibernate中session是使用ThreadLocal实现线程安全的。

1.ThreadLocal并不是一个Thread,而是一个线程副本,ThreadLocal为每个使用该变量的线程提供一个变量副本,线程修改自己的变量副本不会影响其他线程的变量副本。

2.ThreadLocal有四个方法:
(1)set():设置当前线程的局部变量的值
(2)get():获取当前线程的局部变量的值
(3)remove():将当前线程局部变量的值删除,此方法不必显示 的调用,因为局部变量自有垃圾回收器去清理
(4)initialValue():返回该局部变量的初始值,只有在线程第一次调用get,set方法时,此方法才会执行。

3.ThreadLocal源码如下:

public class ThreadLocal {
                /*这个集合中以当前线程对象作为键,值就是该线程对象的变量副本的值,也就是
                 * session
                 */
    		Map map = Collections.synchronizedMap(new HashMap());
    		public Object get(){
    			Thread currentThread = Thread.currentThread();
    			Object o = map.get(currentThread);
    			if(o == null && !map.containsKey(currentThread)){
    				o = initialValue();
    				map.put(currentThread, o);
    			}
    			return o;
    		}
    		
    		public void set(Object newValue){
    			map.put(Thread.currentThread(), newValue);
    		}
    		
    		public Object initialValue() {
    			return null;
    		}
    	}

4.hibernate中的getCurrentSession()的底层代码如下:

public class CurrentSession {
	
		public static final ThreadLocal session = new ThreadLocal();
		
		public static final SessionFactory sf;
		static {
			sf = new Configuration().configure().buildSessionFactory();
		}

		public Session getCurrentSession(){
			Session s = (Session) session.get();
			if(s == null){
				s = sf.openSession();
				session.set(s);
			}
			return s;
		}
	}

5.总结:要想让多线程实现对共享资源的操纵,就需要对它进行同步处理,这不是一件容易的事,不仅会降低程序性能,还要小心死锁的产生,而ThreadLocal模式,直接让每一个线程都具有自己的一个session,他仅仅操作自己的session不会影响其它线程的session,因此也就不需要进行同步处理。

四.学习总结

学东西要学透,在写代码的时候要找最好方法,不懂的地方要弄明白,为什么这样写,学过的要记录,防止以后会忘。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值