Spring構成でAnnotationSessionFactoryBeanを拡張するBeanを作成する際に問題が発生しました。
クラスの定義は次のとおりです。
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)のソースコードは、カタログが2番目のパッケージで定義されていることを除いて同じです。
@Table(catalog="myDatabase1_1", name = "mytablename1")
テストを実行すると、同じエンティティ名が2回使用されていることを示すスタックトレースでクラッシュが発生します(ただし、それらは異なるパッケージに含まれています)。スタックトレースの最後に、「自動インポート」を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