使用如下配置:
<property name="hibernate.current_session_context_class">thread</property>
根据文档,这个是hibernate3.1以后的一个新扩展,目的在于可以让我们在某一个上下文环境(比如说当前线程)中可以通过SessionFactory.getCurrentSession()得到同一个session会话.
该方式Hibernate会自动关闭session,但是事务控制仍然需要手动开始和提交。
public Long createUser(UserVO user) {
Session session = sessionFactory.getCurrentSession();
Transaction tx = session.beginTransaction();
Long id = (Long) session.save(user);
tx.commit();
return id;
}
我们希望通过 Spring 使用声明式事务管理 或使用@Transactional注解进行事务管理。
如果 hibernate.current_session_context_class 属性配置为thread话,会抛一个异常: get is not valid without active transaction。这个错误一般情况是因为由getCurrentSession得到的session中没有获得的transaction,我们一般要手动的调用Transaction tx = session.beginTransaction(); 和 tx.commit() 来控制事务。但是问题是,我们在spring的配置文件中不是已经通过aop,指定了此处由spring来管理事务吗,怎么还要手动处理事务?
解决办法是将 thread 改为 org.springframework.orm.hibernate4.SpringSessionContext。
<property name="hibernate.current_session_context_class">org.springframework.orm.hibernate4.SpringSessionContext</property>
其实这就是默认值,把这段配置去掉,也是可以调用 sessionFactory.getCurrentSession(),以及使用 Spring 进行事务管理。
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.taj.test</groupId>
<artifactId>hibernate-test</artifactId>
<version>0.0.1-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>4.3.11.Final</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.2.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>4.2.4.RELEASE</version>
</dependency>
<!-- AOP -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.7</version>
</dependency>
<!-- AOP -->
<!-- 测试 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<!-- Oracle的驱动包 -->
<dependency>
<groupId>com.oracle</groupId>
<artifactId>ojdbc14</artifactId>
<version>10.2.0.4.0</version>
</dependency>
</dependencies>
</project>
<?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-4.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.2.xsd">
<context:component-scan base-package="com.taj.**.dao" />
<context:component-scan base-package="com.taj.**.service" />
<!-- 数据源配置 -->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" />
<property name="url" value="jdbc:oracle:thin:@localhost:1521:XE" />
<property name="username" value="ssh" />
<property name="password" value="ssh" />
</bean>
<!-- session工厂 -->
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="configLocation" value="classpath:hibernate.cfg.xml" />
<property name="mappingDirectoryLocations">
<list>
<value>classpath:com/taj/**/model</value>
</list>
</property>
</bean>
<!-- 事务管理器 -->
<bean id="txManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<!-- 开启通过注解@Transactional管理事务 -->
<tx:annotation-driven transaction-manager="txManager" proxy-target-class="true" />
<!-- 事务 -->
<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
<tx:method name="query*" read-only="true" propagation="REQUIRED" />
<tx:method name="find*" read-only="true" propagation="REQUIRED" />
<tx:method name="*" propagation="REQUIRED" />
</tx:attributes>
</tx:advice>
<!-- 配置AOP -->
<aop:config proxy-target-class="true">
<aop:pointcut expression="execution(* *..service..*Service*.*(..))" id="serviceMethod" />
<aop:advisor advice-ref="txAdvice" pointcut-ref="serviceMethod" />
</aop:config>
</beans>
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="show_sql">true</property>
<!-- <property name="hibernate.connection.driver_class">oracle.jdbc.driver.OracleDriver</property> <property name="hibernate.connection.username">ssh</property> <property name="hibernate.connection.password">ssh</property> <property name="hibernate.connection.url">jdbc:oracle:thin:@localhost:1521:XE</property> -->
<property name="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</property>
<!-- Hibernate的session管理:自动管理:"jta", "thread", and "managed". -->
<!-- 默认为:org.springframework.orm.hibernate4.SpringSessionContext-->
<!-- 默认时,除了手动管理,还可以交给Spring管理事务和关闭session(aop配置或注解实现) -->
<!-- <property name="hibernate.current_session_context_class">org.springframework.orm.hibernate4.SpringSessionContext</property> -->
<!-- <mapping resource="com/taj/sshall/user/model/UserVO.hbm.xml"/> -->
</session-factory>
</hibernate-configuration>
package com.taj.sshall.user.dao;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.taj.sshall.user.model.UserVO;
@Component(value="userDao")
public class UserDaoSpringHibernateImpl extends UserDaoHibernateImpl {
@Autowired
@Override
public void setSessionFactory(SessionFactory sessionFactory){
super.setSessionFactory(sessionFactory);
}
/** * sessionFactory.getCurrentSession() * 1. Hibernate 自动管理,thread方式实现。session自动关闭,但是需要手动开启和关闭事务。 * <property name="current_session_context_class">thread</property> * 2. Spring 自动管理,通过AOP或注解@Transactional实现。session和事务都自动管理。 * <tx:annotation-driven transaction-manager="txManager" proxy-target-class="true" /> */
@Override
//@Transactional
public Long createUser(UserVO user) {
Session session = sessionFactory.getCurrentSession();
//Transaction tx = session.beginTransaction();
Long id = (Long) session.save(user);
//tx.commit();
return id;
}
}
UserDaoHibernateImpl.java
package com.taj.sshall.user.dao;
import java.util.List;
import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.criterion.Example;
import com.taj.sshall.common.page.PageVO;
import com.taj.sshall.user.model.UserVO;
public class UserDaoHibernateImpl implements IUserDao {
public SessionFactory sessionFactory;
public List<UserVO> findUserPage(UserVO user, PageVO page) {
//q_user_all
Session session = sessionFactory.openSession();
//Query query = session.getNamedQuery("q_user_all");
Criteria criteria = session.createCriteria(UserVO.class);
criteria.add(Example.create(user));
criteria.setFirstResult((page.getPage()-1) * page.getSize());
criteria.setMaxResults(page.getPage() * page.getSize());
@SuppressWarnings("unchecked")
List<UserVO> list = criteria.list();
return list;
}
public List<UserVO> findUsersByName(String userName) {
Session session = sessionFactory.openSession();
String hql = "from UserVO u where u.userName=?1";
Query query = session.createQuery(hql);
query.setString("1", userName);
@SuppressWarnings("unchecked")
List<UserVO> list = query.list();
return list;
}
public UserVO findUserById(Long userId) {
Session openSession = sessionFactory.openSession();
UserVO user = (UserVO)openSession.get(UserVO.class, userId);
openSession.close();
return user;
}
public Long createUser(UserVO user) {
Session openSession = sessionFactory.openSession();
Transaction tx = openSession.beginTransaction();
Long id = (Long) openSession.save(user);
tx.commit();
openSession.close();
return id;
}
public void updateUser(UserVO user) {
Session openSession = sessionFactory.openSession();
Transaction tx = openSession.beginTransaction();
openSession.update(user);
tx.commit();
openSession.close();
}
public void deleteUser(UserVO user) {
Session openSession = sessionFactory.openSession();
Transaction tx = openSession.beginTransaction();
openSession.delete(user);
tx.commit();
openSession.close();
}
public SessionFactory getSessionFactory() {
return sessionFactory;
}
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
}
package com.taj.sshall.user.service;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.taj.sshall.user.dao.IUserDao;
import com.taj.sshall.user.model.UserVO;
@Component("userService")
public class UserServiceSpringImpl implements IUserService {
@Autowired
private IUserDao userDao;
public Long createUser(UserVO user) {
Long createUser = userDao.createUser(user);
return createUser;
}
----------- 省略其他方法 -----------
}
package com.taj.sshall.common;
import java.util.Arrays;
import java.util.Properties;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class SSHUtils {
private static ThreadLocal<SessionFactory> sessionFactoryLocal;
private static ThreadLocal<ApplicationContext> applicationContextLocal;
public static SessionFactory getSessionFactory(){
if(sessionFactoryLocal == null){
Configuration cfg = new Configuration().configure();
Properties settings = cfg.getProperties();
ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder()
.applySettings(settings).build();
SessionFactory sf = cfg.buildSessionFactory(serviceRegistry);
sessionFactoryLocal = new ThreadLocal<SessionFactory>();
sessionFactoryLocal.set(sf);
}
return sessionFactoryLocal.get();
}
public static ApplicationContext getAppContext(){
if(applicationContextLocal == null){
ApplicationContext context = newClassPathXmlApplicationContext("applicationContext.xml");
applicationContextLocal = new ThreadLocal<ApplicationContext>();
applicationContextLocal.set(context);
}
return applicationContextLocal.get();
}
public static void main(String[] args) {
//测试sessionFactory
SessionFactory sessionFactory = getSessionFactory();
Session openSession = sessionFactory.openSession();
System.out.println(openSession);
openSession.close();
//测试appContext
ApplicationContext appContext = getAppContext();
String[] names = appContext.getBeanDefinitionNames();
System.out.println(Arrays.toString(names));
}
}
package com.taj.sshall.user.service;
import static org.junit.Assert.*;
import java.util.Date;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import com.taj.sshall.common.SSHUtils;
import com.taj.sshall.user.model.UserVO;
public class UserServiceSpringImplTest {
private static IUserService userService;
@BeforeClass
public static void setUpBeforeClass() throws Exception {
ApplicationContext appContext = SSHUtils.getAppContext();
userService = (IUserService) appContext.getBean("userService");
}
@Test
public void testCreateUser() {
UserVO user = new UserVO();
user.setUserName("test_");
user.setPassword("1234567");
user.setAge(30);
user.setEmail("[email protected]");
user.setCreateDate(new Date());
user.setLastUpdateDate(new Date());
Long id = userService.createUser(user);
assertTrue(id != null);
}
}
package com.taj.sshall.user.dao;
import static org.junit.Assert.assertTrue;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import com.taj.sshall.common.SSHUtils;
import com.taj.sshall.common.page.PageVO;
import com.taj.sshall.user.model.UserVO;
public class UserDaoHibernateImplTest {
public IUserDao userDao;
public SessionFactory sessionFactory;
@Before
public void before() throws Exception {
UserDaoHibernateImpl dao = new UserDaoHibernateImpl();
dao.setSessionFactory(SSHUtils.getSessionFactory());
this.userDao = dao;
this.sessionFactory = dao.getSessionFactory();
}
@Test
public void testFindUserPage() {
UserVO user = new UserVO();
user.setEmail("[email protected]");
PageVO page = new PageVO();
for (int i = 1; i <= 5; i++) {
page.setPage(i);
List<UserVO> lst = userDao.findUserPage(user, page);
System.out.println(Arrays.toString(lst.toArray()));
System.out.println("----------------------------------------------\n");
}
}
@Test
public void findUsersByName() {
List<UserVO> users = userDao.findUsersByName("test_0");
for (UserVO userVO : users) {
System.out.println("{" + userVO.getUserId() + ", "
+ userVO.getUserName() + ", " + userVO.getEmail() + "}");
}
}
@Test
public void testFindUserById() {
Long userId = 10000L;
UserVO user = userDao.findUserById(userId);
assertTrue("tajun77".equals(user.getUserName()));
assertTrue("123456".equals(user.getPassword()));
assertTrue("[email protected]".equals(user.getEmail()));
assertTrue(27 == user.getAge());
}
@Test
public void testCreateUser() {
for (int i = 0; i < 25; i++) {
UserVO user = new UserVO();
user.setUserName("test_"+i);
user.setPassword("1234567");
user.setAge(30);
user.setEmail("[email protected]");
user.setCreateDate(new Date());
user.setLastUpdateDate(new Date());
Long id = userDao.createUser(user);
assertTrue(id != null);
}
}
@Test
public void testUpdateUser() {
UserVO user = userDao.findUserById(10001L);
int age = (user.getAge() + 7) % 30 + 20;
user.setAge(age);
userDao.updateUser(user);
UserVO user2 = userDao.findUserById(10001L);
assertTrue(user2.getAge() == age);
}
@Test
public void testDeleteUser() {
UserVO user = userDao.findUserById(10000L);
user.setUserName("testDelete");
Long id = userDao.createUser(user);
UserVO u_have = userDao.findUserById(id);
assertTrue(u_have != null);
UserVO udel = new UserVO();
udel.setUserId(id);
userDao.deleteUser(udel);// userName=test id=10003
UserVO u_no = userDao.findUserById(id);
assertTrue(u_no == null);
}
@After
public void after() throws Exception {
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
Query query = session.createQuery("delete from UserVO u where u.userId > 10122");
query.executeUpdate();
tx.commit();
session.close();
}
}