工作总结:org.springframework.orm.hibernate3.LocalSessionFactoryBean的疑惑解决办法

使用xml 配置的hibernate配置信息后,事例如下:

<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
  <property name="dataSource" ref="dataSource"></property>
  <property name="hibernateProperties">
  <props>
  <prop key="hibernate.dialect" >org.hibernate.dialect.SQLServerDialect</prop>
  <prop key="hibernate.jdbc.batch_size">20</prop>
  <prop key="hibernate.show_sql">true</prop>
  </props>
  </property>
  <property name="mappingResources">
  <list>
  <value>com/jw/pojo/JwUser.hbm.xml</value>
  </list>
  </property>
  </bean>

在junit4中定义了一个测试

@Test
public void beanSessionFactoryTest(){
  LocalSessionFactoryBean sessionFactory=(LocalSessionFactoryBean)appContext.getBean("sessionFactory");
}

运行测试的时候报了一个异常

Testcase: beanSessionFactoryTest(com.test.spring.SpringBeanTest): Caused an ERROR
org.hibernate.impl.SessionFactoryImpl cannot be cast to org.springframework.orm.hibernate3.LocalSessionFactoryBean
java.lang.ClassCastException: org.hibernate.impl.SessionFactoryImpl cannot be cast to org.springframework.orm.hibernate3.LocalSessionFactoryBean

问题分析:

  LocalSessionFactoryBean实现了org.springframework.beans.factory.FactoryBean接口, spring在装配的时候, 如果发现实现了org.springframework.beans.factory.FactoryBean接口, 就会使用FactoryBean#getObject() 方法返回的对象装配,具体的可以看下文档.
  如果你想拿到LocalSessionFactoryBean实例, 在id前面加个'&'就可以了,在你的配置文件中BeanFactory.getBean('&sessionFactory')拿到的就是LocalSessionFactoryBean的实例.

解决方法:

1、取真实的LocalSessionFactoryBean 实例对象

ClassPathXmlApplicationContext cpx=new ClassPathXmlApplicationContext("beans.xml");
LocalSessionFactoryBean sessionFactory=(LocalSessionFactoryBean)cpx.getBean("&sessionFactory");
System.out.println("step3 sessionFactory=" + sessionFactory );

2、取SessionFactoryImpl 对象(即Hibernate的SessionFactory的具体实现类)

 SessionFactoryImpl sessionFactoryImpl = (SessionFactoryImpl) applicationContext.getBean("sessionFactory");

 

这个错误通常出现在使用 Spring 和 Hibernate 整合时,尤其是在涉及事务管理的情况下。具体来说,`HibernateSystemException` 包裹了底层的 `HibernateException` 异常,提示“无法获得当前线程同步的事务Session”,意味着尝试获取与当前线程绑定并且处于活动状态的 Hibernate 会话失败。 ### 可能的原因及解决办法 #### 1. 缺少 @Transactional 注解 最常见的原因是忘记在业务方法上添加适当的事务注释(如 `@Transactional`)。如果希望某个特定的操作在一个事务上下文中执行,则必须明确指出这一点。检查控制器层、服务层等地方是否遗漏了该注解。 **解决方案**: 确保相关的 service 方法上有正确的 `@Transactional` 注解: ```java @Service public class MyService { @Autowired private SomeRepository repository; @Transactional(readOnly = false) public void performAction() { // ... your code here ... } } ``` #### 2. 数据源配置不正确 另一个可能是数据源或 sessionFactory bean 的配置有问题,导致 spring 没有找到合适的 session 来进行操作。 **解决方案**: 验证应用程序上下文中的 DataSource 和 LocalSessionFactoryBean 是否已正确定义,并确保它们能够正常工作。 ```xml <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"> <!-- Data Source configuration --> </bean> <bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean"> <property name="dataSource" ref="dataSource"/> <property name="packagesToScan" value="com.example.model"/> <property name="hibernateProperties"> <props> <prop key="hibernate.dialect">...</prop> <!-- Other properties --> </props> </property> </bean> ``` 对于基于 Java Config 的应用,你可以这样做: ```java @Configuration @EnableTransactionManagement @ComponentScan(basePackages={"com.example"}) public class AppConfig { @Bean(name = "dataSource") public BasicDataSource dataSource(){ final BasicDataSource basicDataSource = new BasicDataSource(); // 设置连接池属性... return basicDataSource; } @Bean public LocalSessionFactoryBean sessionFactory(@Qualifier("dataSource") DataSource ds){ final LocalSessionFactoryBean sessionFactoryBean = new LocalSessionFactoryBean(); sessionFactoryBean.setDataSource(ds); sessionFactoryBean.setPackagesToScan(new String[]{"com.example"}); Properties hibernateProperties = new Properties(); hibernateProperties.put("hibernate.dialect", "..."); sessionFactoryBean.setHibernateProperties(hibernateProperties); return sessionFactoryBean; } } ``` #### 3. TransactionManager 配置缺失或无效 Spring 使用 PlatformTransactionManager 接口来协调事务边界。如果你的应用缺少它或者它的设置不当也可能会引发这个问题。 **解决方案**: 添加并验证 `PlatformTransactionManager` Bean 是否存在且已被正确注入到其他组件中: ```xml <!-- XML-based config --> <tx:annotation-driven/> <bean id="transactionManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory"/> </bean> ``` 如果是采用纯Java配置的方式,请确保已经启用了 `@EnableTransactionManagement` 并声明了相应的 Manager 实现: ```java // Java-based config @Bean @Autowired public PlatformTransactionManager txManager(SessionFactory sf) { return new HibernateTransactionManager(sf); } @EnableTransactionManagement ``` 此外,在某些场景下还需要考虑是否有多个数据库资源同时参与同一个事务的问题,此时需要更复杂的分布式事务支持方案。 --- 总结而言,“Could not obtain transaction-synchronized Session” 错误通常是由于缺乏必要的事务管理机制或是其配置上的失误造成的。通过对上述各项内容逐一排查可以帮助定位和解决问题的根本原因。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值