最近自己搭建了一个ssh的框架,在spring 整合 hibernate这块不是很理解,希望大家帮助我解决问题。 <?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:p="http://www.springframework.org/schema/p" 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 classpath:/org/springframework/beans/factory/xml/spring-beans-3.2.xsd http://www.springframework.org/schema/context classpath:/org/springframework/context/config/spring-context-3.2.xsd http://www.springframework.org/schema/tx classpath:/org/springframework/transaction/config/spring-tx-3.2.xsd http://www.springframework.org/schema/aop classpath:/org/springframework/aop/config/spring-aop-3.2.xsd"> <!-- 配置自动扫描的包 --> <context:component-scan base-package="com.*"/> <!-- 引用jdbc配置文件 --> <context:property-placeholder location="WEB-INF/jdbc.properties"/> <!-- 配置数据源 --> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="driverClass" value="${jdbc.driverClassName}"></property> <property name="jdbcUrl" value="${jdbc.url}"></property> <property name="user" value="${jdbc.username}"></property> <property name="password" value="${jdbc.password}"></property> <property name="acquireIncrement" value="1"></property> <property name="initialPoolSize" value="5"></property> <property name="maxIdleTime" value="60"></property> <property name="maxPoolSize" value="5"></property> <property name="minPoolSize" value="1"></property> <property name="acquireRetryDelay" value="1000"></property> <property name="acquireRetryAttempts" value="60"></property> <property name="breakAfterAcquireFailure" value="false"></property> </bean> <!-- 配置hibernate sessionFactory --> <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean" p:mappingLocations="classpath:/com/model/**/*.hbm.xml"> <property name="dataSource" ref="dataSource" /> <property name="hibernateProperties"> <props> <prop key="hibernate.dialect"> org.hibernate.dialect.OracleDialect </prop> <prop key="hibernate.show_sql"> true </prop> <!-- 如果没有此配置getCurrentSession()时就会报错:No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here --> <prop key="hibernate.current_session_context_class"> org.springframework.orm.hibernate3.SpringSessionContext </prop> </props> </property> </bean> <!-- Transaction Manager 事务管理器 --> <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory" /> </bean> <!-- 配置事务的传播特性 --> <tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes> <tx:method name="save*" propagation="REQUIRED" read-only="false" /> <tx:method name="delete*" propagation="REQUIRED" read-only="false" /> <tx:method name="update*" propagation="REQUIRED" read-only="false" /> <tx:method name="*" read-only="true" /> </tx:attributes> </tx:advice> <!-- 把切面注入到事务中 --> <aop:config> <aop:pointcut id="productServiceMethods" expression="execution(* com.ssh.*.*(..))" /> <aop:advisor advice-ref="txAdvice" pointcut-ref="productServiceMethods" /> </aop:config> </beans> 这是我的dao层基类 public class BaseDao { @Resource(name="sessionFactory") private SessionFactory sessionFactory; protected Session getSession() { return sessionFactory.getCurrentSession(); //return sessionFactory.openSession(); } protected void delete(Object object) { this.getSession().delete(object); } @SuppressWarnings("unchecked") protected <T> T get(Class<T> entityClass, long id) { return (T) this.getSession().get(entityClass, id); } @SuppressWarnings("unchecked") protected <T> List<T> query(Class<T> entityClass) { return this.getSession().createQuery( " from " + entityClass.getSimpleName()).list(); } public void save(Object object) { Session session = this.getSession(); session.save(object); } protected void update(Object object) { this.getSession().update(object); } @SuppressWarnings("unchecked") protected <T> T load(Class<T> entityClass, int id) { return (T) this.getSession().load(entityClass, id); } protected void saveOrUpdate(Object object) { this.getSession().saveOrUpdate(object); } } 以下,是我的几点疑问: |
|
在线等,大家帮忙看看
|
|
spring AOP自动完成事务的提交和异常回滚
|
|
那么我写的baseDao,getCurrentSession的异常是怎么回事,我的事务已经交给spring管理了 |
|
既然用spring管理事务,为啥不用spring提供的hibernateTemplate或者jdbcTemplate实现数据的操作呢? |
|
1:propagation=”REQUIRED”, 定义了事务的传播途径(调用其它业务时是否开启新的事务等等)。
2:spring AOP自动完成事务的提交和异常回滚 3:你的配置可以啊<prop key=”hibernate.current_session_context_class”> org.springframework.orm.hibernate3.SpringSessionContext </prop> 就是告诉hibernate 事务交由spring管理, 也就是通过aop实现hibernate Session的创建和关闭。 |
|
第3个问题,我和你配置的一样,但sessionFactory.getCurrentSession()的时候,抛出了org.hibernate.HibernateException: No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here异常,理论上来说,事务已经由spring管理了,为何还会抛出这个异常 |
|
我想用hibernate API来操作session,这样有更大的灵活性,现在的问题是,我调用getCurrentSession会抛出异常,而我不知道如何解决,希望朋友指点迷津 |
|
那你aop配置是否对呢? 是否已经切在对应方法上? |
|
<!– 配置事务的传播特性 –> <!– 把切面注入到事务中 –> |
|
40分 |
expression=”execution(* com.ssh.*.*(..))” 指定的切点是否正确? 就是说是否切到了你的业务方法上? 只有执行了这里aop切入的方法,spring才会开起事务,也就是会创建Hibernate Session, 保证你后面调用getCurrentSession能够获取到Session。
你可以断点到TransactionInterceptor的invoke方法里面,验证你的方法是否被aop切入事务。 Multiple markers at this line - implements com.xxxx.xxx.xxxService.xxxx - advised by org.springframework.transaction.interceptor.TransactionInterceptor.invoke(org.aopalliance.intercept.MethodInvocation) 鼠标放到符号上还有上面的提示哦 |
非常感谢你,我这就去试试~嘿嘿 |
|
拦截器没走,而且好像tomcat启动的时候,也没有实例化拦截器,我缺少TransactionInterceptor的配置吗? |