1

我在创建扩展 AnnotationSessionFactoryBean 的 bean 的 Spring 配置中遇到问题。

这是类的定义:

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")

当我运行一个测试时,我遇到了一个堆栈跟踪崩溃,它指出相同的实体名称被使用了两次(尽管它们位于不同的包中)。在堆栈跟踪的末尾,它建议将“自动导入”设置为 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 无关,是由于您的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 回答