我有一个基于grails 2.0的独立GORM应用程序,可以处理单个数据源的NO问题。在我引入另一个gorm:sessionFactory引用第二个数据源的那一刻,应用程序失败了。详情如下。
spring应用程序上下文代码供参考:
`
<bean id="dataSource_aaa" class="org.apache.commons.dbcp.BasicDataSource">
<property name="url" value="jdbc:mysql://localhost/aaa" />
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
</bean>
<bean id="aaaMessageSource"
class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basename" value="messages" />
</bean>
<!-- Single gorm session factory works, either one, but both together fail -->
<gorm:sessionFactory base-package="com.aaa.entity"
data-source-ref="dataSource_aaa"
message-source-ref="aaaMessageSource">
<property name="hibernateProperties">
<util:map>
<entry key="hibernate.hbm2ddl.auto" value="update" />
<entry key="hibernate.connection.autocommit" value="false" />
<entry key="hibernate.show_sql" value="false" />
</util:map>
</property>
</gorm:sessionFactory>
<bean id="dataSource_bbb" class="org.apache.commons.dbcp.BasicDataSource">
<property name="url" value="jdbc:mysql://localhost/bbb" />
...
</bean>
<bean id="bbbMessageSource"
class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basename" value="messages" />
</bean>
<!-- Single gorm session factory works, either one, but both together fail -->
<gorm:sessionFactory base-package="com.bbb.entity"
data-source-ref="dataSource_bbb"
message-source-ref="bbbMessageSource">
<property name="hibernateProperties">
<util:map>
<entry key="hibernate.hbm2ddl.auto" value="create-drop" />
<entry key="hibernate.connection.autocommit" value="false" />
<entry key="hibernate.show_sql" value="false" />
</util:map>
</property>
</gorm:sessionFactory>
`
应用程序尝试初始化spring bean容器,但请注意bean被覆盖为:
2013-12-04 16:21:20,091 INFO XmlBeanDefinitionReader - Loading XML bean definitions from class path resource [spring/application-context.xml]
2013-12-04 16:21:20,323 INFO XmlBeanDefinitionReader - Loading XML bean definitions from class path resource [spring/application-beans.xml]
2013-12-04 16:21:20,345 INFO XmlBeanDefinitionReader - Loading XML bean definitions from class path resource [spring/application-config.xml]
2013-12-04 16:21:20,778 INFO DefaultListableBeanFactory - Overriding bean definition for bean 'grailsApplication': replacing [Generic bean: class [org.codehaus.groovy.grails.commons.DefaultGrailsApplication]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=initialise; destroyMethodName=null] with [Generic bean: class [org.codehaus.groovy.grails.commons.DefaultGrailsApplication]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=initialise; destroyMethodName=null]
2013-12-04 16:21:20,779 INFO DefaultListableBeanFactory - Overriding bean definition for bean 'gormEnhancingPostProcessor': replacing [Generic bean: class [org.codehaus.groovy.grails.orm.hibernate.cfg.GORMEnhancingBeanPostProcessor]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null] with [Generic bean: class [org.codehaus.groovy.grails.orm.hibernate.cfg.GORMEnhancingBeanPostProcessor]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null]
2013-12-04 16:21:20,779 INFO DefaultListableBeanFactory - Overriding bean definition for bean 'transactionManager': replacing [Generic bean: class [org.codehaus.groovy.grails.orm.hibernate.GrailsHibernateTransactionManager]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null] with [Generic bean: class [org.codehaus.groovy.grails.orm.hibernate.GrailsHibernateTransactionManager]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null]
2013-12-04 16:21:21,033 INFO ClassPathXmlApplicationContext - Bean 'org.springframework.transaction.annotation.AnnotationTransactionAttributeSource#0' of type [class org.springframework.transaction.annotation.AnnotationTransactionAttributeSource] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2013-12-04 16:21:21,035 INFO ClassPathXmlApplicationContext - Bean 'org.springframework.transaction.config.internalTransactionAdvisor' of type [class org.springframework.transaction.interceptor.BeanFactoryTransactionAttributeSourceAdvisor] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2013-12-04 16:21:21,047 INFO DefaultListableBeanFactory - Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@69f674: defining beans
然后因例外而失败:
Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'com.aaa.entity.CategoryValidator': Error setting property values; nested exception is org.springframework.beans.PropertyBatchUpdateException; nested PropertyAccessExceptions (1) are:
PropertyAccessException 1: org.springframework.beans.MethodInvocationException: Property 'domainClass' threw exception; nested exception is java.lang.NullPointerException
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1423)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1128)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:519)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:458)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:295)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:223)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:292)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:626)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:932)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:479)
at org.springframework.context.support.ClassPathXmlApplicationContext.(ClassPathXmlApplicationContext.java:139)
at org.springframework.context.support.ClassPathXmlApplicationContext.(ClassPathXmlApplicationContext.java:83)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)
at java.lang.reflect.Constructor.newInstance(Unknown Source)
at org.codehaus.groovy.reflection.CachedConstructor.invoke(CachedConstructor.java:77)
at org.codehaus.groovy.runtime.callsite.ConstructorSite$ConstructorSiteNoUnwrapNoCoerce.callConstructor(ConstructorSite.java:102)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallConstructor(CallSiteArray.java:57)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callConstructor(AbstractCallSite.java:182)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callConstructor(AbstractCallSite.java:190)
at App.main(App.groovy:15)
Caused by: org.springframework.beans.PropertyBatchUpdateException; nested PropertyAccessExceptions (1) are:
PropertyAccessException 1: org.springframework.beans.MethodInvocationException: Property 'domainClass' threw exception; nested exception is java.lang.NullPointerException
at org.springframework.beans.AbstractPropertyAccessor.setPropertyValues(AbstractPropertyAccessor.java:101)
at org.springframework.beans.AbstractPropertyAccessor.setPropertyValues(AbstractPropertyAccessor.java:57)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1420)
... 22 more
我怀疑问题在于没有命名空间通过Gorm通过两个sessionFactories创建的bean:http://grepcode.com/file/repo1.maven.org/maven2/org.grails/grails-hibernate/2.1.1/org/codehaus/groovy/grails/orm/hibernate/cfg/GORMSessionFactoryDefinitionParser.java?av=f
这似乎也在Grails错误列表中引用,但不相信有一个有效的解决方案:http://jira.grails.org/browse/GRAILS-4507
有没有人在使用多个数据源的独立GORM应用程序方面取得了成功? 任何和所有的帮助都能让我前进。
更新的 在绝望中,我终于创建了3个不同的spring应用程序上下文。一个用于两个gorm sessionFactories,一个用于处理这些数据源的应用程序业务逻辑进行编组。这项工作具有明显的局限性,即无法跨越数据源跨越事务操作。还会添加一些代码噪音,我会尝试清理。
如果有人有更好的建议,那么,我更喜欢比这更清洁的解决方案。