一.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,因此也就不需要进行同步处理。
四.学习总结
学东西要学透,在写代码的时候要找最好方法,不懂的地方要弄明白,为什么这样写,学过的要记录,防止以后会忘。