1

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
4

1 に答える 1

8

問題はBeanとは関係がなく、に同じ論理名を持つ2つのエンティティがあることが原因ですSessionFactory。これは、Hibernateが。などのクエリでどのエンティティを使用する必要があるかを理解できないことを意味しますfrom MyTableName1

これらのエンティティをSessionFactory同時に同じにする必要がある場合は、次のように、それらに異なる論理名を指定する必要があります。

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

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

これらの名前をHQLクエリで使用します。

それらを同時に必要としない場合は、SessionFactoriesスキーマごとに異なるものに配置できます。

また、私が理解している限り、独自のサブクラスを作成する必要はありません。AnnotationSessionFactoryBeanデフォルトのサブクラスは、達成しようとしているのと同じ機能をサポートしているためですpackagesToScan。プロパティを参照してください。

于 2012-10-02T16:53:06.120 に答える