论坛首页 Java企业应用论坛

spring的事务不起作用?无法和当前sessin绑定?

浏览 25199 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2007-06-05  
ahuaxuan 写道
原来你是在liferay里啊,但是我有一点不明白,你是如何做到把HibernateConfiguration的实例赋给SessionFactoryImplementor 的引用的呢,这两个类型完全不一样啊,而且hibenate包中的ssionFactoryImplementor类根本没有getCurrentSession()方法,于是我就迷惑了,难道这是liferay对hibernate的封装

请看 liferay中操作数据库的 HibernateUtil.java 这个类,类里面注射了SessionFactoryImplementor,  而不是 SessionFactory 这个类:
public class HibernateUtil {

	public static final String SPRING_HIBERNATE_DATA_SOURCE =
		PropsUtil.get(PropsUtil.SPRING_HIBERNATE_DATA_SOURCE);

	public static final String SPRING_HIBERNATE_SESSION_FACTORY =
		PropsUtil.get(PropsUtil.SPRING_HIBERNATE_SESSION_FACTORY);

	public static final String COUNT_COLUMN_NAME = "COUNT_VALUE";

	public static Connection getConnection() throws SQLException {
		return getDataSource().getConnection();
	}

	public static DataSource getDataSource() {
		if (_dataSource == null) {
			_dataSource = (DataSource)BeanLocatorUtil.locate(
				SPRING_HIBERNATE_DATA_SOURCE);
		}

		return _dataSource;
	}

	public static SessionFactoryImplementor getSessionFactory() {
		return getSessionFactory(SPRING_HIBERNATE_SESSION_FACTORY);
	}

	public static SessionFactoryImplementor getSessionFactory(
		String sessionFactoryName) {

		if (sessionFactoryName.equals(SPRING_HIBERNATE_SESSION_FACTORY)) {
			if (_sessionFactory == null) {
				LocalSessionFactoryBean lsfb =
					(LocalSessionFactoryBean)BeanLocatorUtil.locate(
						sessionFactoryName);

				_sessionFactory = (SessionFactoryImplementor)lsfb.getObject();
			}

			return _sessionFactory;
		}
		else {
			SessionFactoryImplementor sessionFactory =
				(SessionFactoryImplementor)_sessionFactories.get(
					sessionFactoryName);

			if (sessionFactory == null) {
				LocalSessionFactoryBean lsfb =
					(LocalSessionFactoryBean)BeanLocatorUtil.locate(
						sessionFactoryName);

				sessionFactory = (SessionFactoryImplementor)lsfb.getObject();

				_sessionFactories.put(sessionFactoryName, sessionFactory);
			}

			return sessionFactory;
		}
	}

	public static Dialect getDialect() {
		return getDialect(SPRING_HIBERNATE_SESSION_FACTORY);
	}

	public static Dialect getDialect(String sessionFactoryName) {
		return getSessionFactory(sessionFactoryName).getDialect();
	}

	public static void closeSession(Session session) {
		try {
			if (session != null) {

				// Let Spring manage sessions

				//session.close();
			}
		}
		catch (HibernateException he) {
			_log.error(he.getMessage());
		}
	}

	public static Session openSession() throws HibernateException {
		return openSession(SPRING_HIBERNATE_SESSION_FACTORY);
	}

	public static Session openSession(String sessionFactoryName)
		throws HibernateException {

		SessionFactoryImplementor sessionFactory =
			getSessionFactory(sessionFactoryName);

		return openSession(sessionFactory);
	}

	public static Session openSession(SessionFactory sessionFactory)
		throws HibernateException {

		// Let Spring manage sessions

		return sessionFactory.getCurrentSession();
	}

	public static String getCountColumnName() {
		return COUNT_COLUMN_NAME;
	}

	private static Log _log = LogFactory.getLog(HibernateUtil.class);

	private static DataSource _dataSource;
	private static SessionFactoryImplementor _sessionFactory;
	private static Map _sessionFactories = CollectionFactory.getHashMap();

}


liferay完全用 这个 HibernateUtil类操作的数据库.奥妙也全都在这里类里面.不明白 liferay为什么注入的是SessionFactoryImplementor? 但是所有他都是这样操作的数据库,得到的session,尔我只要使用就报刚才的错误,好像被他完全隔绝在在外边? 无论如何也不能在 liferay中使用 声明的事务创建session? 你看这个类 hibernateUtil有什么特别的地方么?
0 请登录后投票
   发表时间:2007-06-05  
你仔细看一下LocaleSessionFactoryBean第1064行,SessionFactoryUtils.doGetSession((SessionFactory) proxy, false),就是这个false,导致在SessionFactoryUtil的第363行抛出了异常,异常得信息就是这个“throw new IllegalStateException("No Hibernate Session bound to thread, " +
    "and configuration does not allow creation of non-transactional one here");”
由此可以看出,这个应该还是配置得问题,导致事务没有正确的起作用
0 请登录后投票
   发表时间:2007-06-05  
ahuaxuan 写道
你仔细看一下LocaleSessionFactoryBean第1064行,SessionFactoryUtils.doGetSession((SessionFactory) proxy, false),就是这个false,导致在SessionFactoryUtil的第363行抛出了异常,异常得信息就是这个“throw new IllegalStateException("No Hibernate Session bound to thread, " +
    "and configuration does not allow creation of non-transactional one here");”
由此可以看出,这个应该还是配置得问题,导致事务没有正确的起作用

你好,我最开始的发表中说道:
引用
很明显是因为那个 allowCreate的问题,当没有事务启动的时候,getCurrentSession是无法创建Session的! 说明配置事务没有成功!但是我的配置已经和例子一摸一样了啊~

应该是配置的问题,关键是: 哪里配置错了呢,我的配置已经和例子一摸一样了啊?  
不知道你注意过 liferay的spring配置没有,非常诡异,他居然把 transaction的拦截器注入到其他类中使用,没见过有这样用:
	<bean id="com.liferay.portal.service.AccountLocalService.professional" class="com.liferay.portal.service.impl.AccountLocalServiceImpl" lazy-init="true" />
	<bean id="com.liferay.portal.service.AccountLocalService.transaction" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean" lazy-init="true">
		<property name="transactionManager">
			<ref bean="liferayTransactionManager" />
		</property>
		<property name="target">
			<ref bean="com.liferay.portal.service.AccountLocalService.professional" />
		</property>
		<property name="transactionAttributes">
			<props>
				<prop key="*">PROPAGATION_REQUIRED</prop>
			</props>
		</property>
	</bean>
	<bean id="com.liferay.portal.service.AccountLocalServiceFactory" class="com.liferay.portal.service.AccountLocalServiceFactory" lazy-init="true">
		<property name="service">
			<ref bean="com.liferay.portal.service.AccountLocalService.transaction" />
		</property>
	</bean>

居然把这个"com.liferay.portal.service.AccountLocalService.transaction" 拦截事务管理器注入到了另一个bean中,不知道是何用意? 难道不按照他这个奇怪的做法就行不通? 但是我还是想知道到底是因为什么?
是不是用了 spring什么高级的特性?
0 请登录后投票
   发表时间:2007-06-05  
它这里的“com.liferay.portal.service.AccountLocalService.transaction”这个bean是由org.springframework.transaction.interceptor.TransactionProxyFactoryBean生成的一个代理对象,这个bean实质上是一个com.liferay.portal.service.impl.AccountLocalServiceImpl,只不过外面加了一个spring的事务代理,使得“com.liferay.portal.service.AccountLocalService.professional”这个bean的方法可以进行spring的事务管理,要由spring进行事务管理都要是要生成代理的。
0 请登录后投票
   发表时间:2007-06-06  
lujh99 写道
它这里的“com.liferay.portal.service.AccountLocalService.transaction”这个bean是由org.springframework.transaction.interceptor.TransactionProxyFactoryBean生成的一个代理对象,这个bean实质上是一个com.liferay.portal.service.impl.AccountLocalServiceImpl,只不过外面加了一个spring的事务代理,使得“com.liferay.portal.service.AccountLocalService.professional”这个bean的方法可以进行spring的事务管理,要由spring进行事务管理都要是要生成代理的。

我在 com.liferay.portal.service.AccountLocalServiceFactory 这个类中应该怎样得到这个service呢? 这样注入后, getService返回什么呢? 如果我返回com.liferay.portal.service.AccountLocalService.professional,会报错说类型不一致,应该返回代理 XXXProxy,而不是com.liferay.portal.service.AccountLocalService.professional?
0 请登录后投票
   发表时间:2007-06-06  
我记得org.springframework.transaction.interceptor.TransactionProxyFactoryBean中有个属性,名字忘记了,意思是代理目标类,要设为true的,否则生成的代理对象不会instanceof目标类的。
0 请登录后投票
   发表时间:2007-06-06  
之前没有搞过liferay,所以看到奇怪的配置时使我想到其他地方,于是昨天我把hibernate中sessionfactory相关的代码,spring中事务相关的代码又看了一下,也搞明白了很多东西,觉得配置上好像确实没有什么问题(我是指此类配置如果用在一般的spring+hibernate中是没问题的)

于是我有一个疑问,你在测试那个testquery方法的时候是写在什么地方的,你不会在testutil里调用这个testquery方法的吧

lyo 写道
lujh99 写道
它这里的“com.liferay.portal.service.AccountLocalService.transaction”这个bean是由org.springframework.transaction.interceptor.TransactionProxyFactoryBean生成的一个代理对象,这个bean实质上是一个com.liferay.portal.service.impl.AccountLocalServiceImpl,只不过外面加了一个spring的事务代理,使得“com.liferay.portal.service.AccountLocalService.professional”这个bean的方法可以进行spring的事务管理,要由spring进行事务管理都要是要生成代理的。

我在 com.liferay.portal.service.AccountLocalServiceFactory 这个类中应该怎样得到这个service呢? 这样注入后, getService返回什么呢? 如果我返回com.liferay.portal.service.AccountLocalService.professional,会报错说类型不一致,应该返回代理 XXXProxy,而不是com.liferay.portal.service.AccountLocalService.professional?

在代理的时候可以设置接口,这样注入的时候,用接口注入就不会有这种问题了


ps:楼上凌晨3点还在网上啊
0 请登录后投票
   发表时间:2007-06-06  
我的 TestUtil类:
public class TestUtil {
	
	private static SessionFactoryImplementor sessionFactory;
	
	
	public  SessionFactoryImplementor getSessionFactory() {
		return sessionFactory;
	}

	public  void setSessionFactory(SessionFactoryImplementor factory) {
		sessionFactory = factory;
	}	
	public   List testquery(){
		List list=new ArrayList();
		
		Session hsession=this.getSessionFactory().getCurrentSession();
		list=hsession.createQuery("from UserImpl as u").list();
		hsession.close();
		return list;
		
	}
}


我在jsp中的测试代码:
org.springframework.context.ApplicationContext ctx
        = new org.springframework.context.support.ClassPathXmlApplicationContext(new String []{"META-INF/ext-spring-professional.xml","classpath*:META-INF/portal-spring-professional.xml","classpath*:META-INF/counter-spring-professional.xml"});
		Object objBean=ctx.getBean("com.liferay.portlet.lyo.service.persistence.TestUtil");
		out.println("get bean: "+objBean);
com.liferay.portlet.lyo.service.persistence.TestUtil th=(com.liferay.portlet.lyo.service.persistence.TestUtil)objBean;
java.util.List list=th.testquery();


其中加载了我得 ext-spring-professional.xml和 liferay系统的那些xml,包括他创建数据源的xml.写的应该没问题吧?

最近有点失眠,我电脑也总忘关,有时候起来就看看论坛,呵呵~
0 请登录后投票
   发表时间:2007-06-06  
改成Object objBean=ctx.getBean("myProductService");呢?
0 请登录后投票
   发表时间:2007-06-06  
引用
Object objBean=ctx.getBean("com.liferay.portlet.lyo.service.persistence.TestUtil");  

你取了一个没有被事务代理过的对象的引用,所以不能正常启动事务,确实应该取myProductService,也就是说应该取代理才对。

0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics