2012-10-02 67 views
1

我在創建一個擴展AnnotationSessionFactoryBean的bean的Spring配置中遇到問題。Hibernate/Spring - AnnotationSessionFactoryBean - 如何解決重複導入?

這裏的類的定義:

public class ExtendedAnnotationSessionFactoryBean extends AnnotationSessionFactoryBean { 

    private String[] basePackages; 
    private ClassLoader beanClassLoader; 

    @Override 
    public void afterPropertiesSet() throws Exception { 
     System.out.println("ExtendedAnnotationSessionFactoryBean, in afterPropertiesSet"); 
     Collection<Class<?>> entities = new ArrayList<Class<?>>(); 
     ClassPathScanningCandidateComponentProvider scanner = this.createScanner(); 
     for (String basePackage : this.basePackages) { 
      this.findEntities(scanner, entities, basePackage); 
     } 
     this.setAnnotatedClasses(entities.toArray(new Class<?>[entities.size()])); 

     super.afterPropertiesSet(); 
    } 

    private ClassPathScanningCandidateComponentProvider createScanner() { 
     System.out.println("ExtendedAnnotationSessionFactoryBean, in createScanner"); 
     ClassPathScanningCandidateComponentProvider scanner = new ClassPathScanningCandidateComponentProvider(false); 
     scanner.addIncludeFilter(new AnnotationTypeFilter(Entity.class)); 
     return scanner; 
    } 

    private void findEntities(ClassPathScanningCandidateComponentProvider scanner, 
      Collection<Class<?>> entities, String basePackage) { 
     System.out.println("ExtendedAnnotationSessionFactoryBean, in findEntities"); 
     Set<BeanDefinition> annotatedClasses = scanner.findCandidateComponents(basePackage); 
     for (BeanDefinition bd : annotatedClasses) { 
      String className = bd.getBeanClassName(); 
      System.out.println("ExtendedAnnotationSessionFactoryBean, className: " + className); 
      Class<?> type = ClassUtils.resolveClassName(className, this.beanClassLoader); 
      entities.add(type); 
     } 

    } 

    public void setBasePackage(String basePackage) { 
     this.basePackages = new String[]{basePackage}; 
    } 

    public void setBasePackages(String[] basePackages) { 
     this.basePackages = basePackages; 
    } 

    @Override 
    public void setBeanClassLoader(ClassLoader beanClassLoader) { 
     this.beanClassLoader = beanClassLoader; 
    } 
} 

下面是它的配置:

<b:bean id="sessionFactory" class="com.mycompany.spring.ExtendedAnnotationSessionFactoryBean"> 
     <b:property name="dataSource" ref="dataSource" /> 
     <b:property name="configurationClass" value="org.hibernate.cfg.AnnotationConfiguration" /> 
     <b:property name="hibernateProperties" ref="hibernateProperties" /> 
     <b:property name="entityInterceptor" ref="baseEntityInterceptor" /> 
     <b:property name="basePackages"> 
      <b:list> 
       <b:value>com.mycompany.entities</b:value> 
       <b:value>com.mycompany.entities1_1</b:value> 
      </b:list> 
     </b:property> 
    </b:bean> 

在每個包中的源代碼(com.mycompany.entities,com.mycompany.entities1_1)是除了目錄是在第二個中定義的:

@Table(catalog="myDatabase1_1", name = "mytablename1") 

當我運行測試I使用堆棧跟蹤崩潰,該堆棧跟蹤聲明同一實體名稱正在使用兩次(儘管它們位於不同的包中)。在堆棧跟蹤的結尾,它暗示了「自動導入」設置爲false:

Caused by: org.hibernate.DuplicateMappingException: duplicate import: MyTableName1 refers to both com.mycompany.entities1_1.MyTableName1 and com.mycompany.entities.MyTableName1 (try using auto-import="false") 

問題:什麼自動導入的意思是,爲什麼會工作,在那裏我會指定它?

這裏就是整個堆棧跟蹤:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionFactory' defined in URL [file:WEB-INF/myconfiguration.xml]: Invocation of init method failed; nested exception is org.hibernate.AnnotationException: Use of the same entity name twice: MyTableName1 
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionFactory' defined in URL [file:WEB-INF/myconfiguration.xml]: Invocation of init method failed; nested exception is org.hibernate.AnnotationException: Use of the same entity name twice: MyTablenNme1 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1337) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:473) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory$1.run(AbstractAutowireCapableBeanFactory.java:409) 
    at java.security.AccessController.doPrivileged(Native Method) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:380) 
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:264) 
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:221) 
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:261) 
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:185) 
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:164) 
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:423) 
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:729) 
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:381) 
    at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:139) 
    at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:93) 
    at com.nuval.infrastructure.test.BaseTest.init(BaseTest.java:44) 
    at com.nuval.infrastructure.test.BaseTest.setUp(BaseTest.java:62) 
    at com.nuval.test.CloneTest.setUp(CloneTest.java:104) 
    at junit.framework.TestCase.runBare(TestCase.java:125) 
    at junit.framework.TestResult$1.protect(TestResult.java:106) 
    at junit.framework.TestResult.runProtected(TestResult.java:124) 
    at junit.framework.TestResult.run(TestResult.java:109) 
    at junit.framework.TestCase.run(TestCase.java:118) 
    at junit.framework.TestSuite.runTest(TestSuite.java:208) 
    at junit.framework.TestSuite.run(TestSuite.java:203) 
    at org.eclipse.jdt.internal.junit.runner.junit3.JUnit3TestReference.run(JUnit3TestReference.java:130) 
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) 
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467) 
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683) 
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390) 
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197) 
Caused by: org.hibernate.AnnotationException: Use of the same entity name twice: MyTableName1 
    at org.hibernate.cfg.annotations.EntityBinder.bindEntity(EntityBinder.java:347) 
    at org.hibernate.cfg.AnnotationBinder.bindClass(AnnotationBinder.java:613) 
    at org.hibernate.cfg.AnnotationConfiguration.processArtifactsOfType(AnnotationConfiguration.java:636) 
    at org.hibernate.cfg.AnnotationConfiguration.secondPassCompile(AnnotationConfiguration.java:359) 
    at org.hibernate.cfg.Configuration.buildMappings(Configuration.java:1206) 
    at org.springframework.orm.hibernate3.LocalSessionFactoryBean.buildSessionFactory(LocalSessionFactoryBean.java:673) 
    at org.springframework.orm.hibernate3.AbstractSessionFactoryBean.afterPropertiesSet(AbstractSessionFactoryBean.java:211) 
    at com.zeer.onqi.spring.ExtendedAnnotationSessionFactoryBean.afterPropertiesSet(ExtendedAnnotationSessionFactoryBean.java:36) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1368) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1334) 
    ... 30 more 
Caused by: org.hibernate.DuplicateMappingException: duplicate import: MyTableName1 refers to both com.mycompany.entities1_1.MyTableName1 and com.mycompany.entities.MyTableName1 (try using auto-import="false") 
    at org.hibernate.cfg.Configuration$MappingsImpl.addImport(Configuration.java:2418) 
    at org.hibernate.cfg.annotations.EntityBinder.bindEntity(EntityBinder.java:340) 
    ... 39 more 

回答

8

您的問題是不相關的bean並通過的事實,你有兩個實體具有相同的邏輯名稱與SessionFactory引起的。這意味着Hibernate將無法理解在查詢中使用哪個實體,如from MyTableName1

如果你真的需要在同一SessionFactory同時具有這些實體,你應該爲它們指定不同的邏輯名稱,具體如下:

@Entity(name = "MyTableName1") 
@Table(...) 
public class MyTableName1 { ... } 

@Entity(name = "MyTableName1_1") 
@Table(...) 
public class MyTableName1 { ... } 

並使用HQL查詢這些名字。

如果你不需要他們同時,也許你可以把它們放到不同的模式SessionFactories不同的模式。

另請注意,據我所知,您不需要創建AnnotationSessionFactoryBean的自己的子類,因爲默認的支持您嘗試實現的相同功能,請參閱packagesToScan屬性。