在组件扫描中添加属性

时间:2018-02-16 16:06:48

标签: java spring hibernate

我们在项目和他们自己的实现中有很多DAO。例如,我有一个名为CorDAO和CorDAOHibernate的类(CorDAO是一个接口,CorDAOHibernate实现了CorDAO)。对于我需要的每个接口:

    <bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
            <property name="dataSource" ref="dataSource"/>
            <property name="packagesToScan" value="com.myproject.*.to"/>
            <property name="hibernateProperties">
                <props>
                    <prop key="hibernate.dialect">${hibernate.dialect}</prop>
                    <prop key="hibernate.hbm2ddl.auto">update</prop>
                    <prop key="hibernate.show_sql">false</prop>
                    <prop key="hibernate.cache.use_query_cache">true</prop>
                    <prop key="hibernate.cache.use_second_level_cache">true</prop>
                    <prop key="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</prop>
                </props>
            </property>
        </bean>

<bean id="genericDAO" class="com.myproject.dao.hibernate.GenericDAOHibernate">
        <property name="sessionFactory" ref="sessionFactory"/>
    </bean>

        <bean id="CorDAO" class="com.myproject.dao.hibernate.CorDAOHibernate">
                <property name="sessionFactory" ref="sessionFactory"/>
        </bean>
        <bean id="ExampleDAO" class="com.myproject.dao.hibernate.ExampleDAOHibernate">
                <property name="sessionFactory" ref="sessionFactory"/>
        </bean>

这就是我想在com.myproject.dao.hibernate。*包中使用ComponentScan的原因。请注意,CorDAO是 @Repository ,而CorDAOHibernate没有任何注释。 每个DAO课程都是GenericDAO的孩子。

如何使用ComponentScan?我使用的是Spring 3,所以我尝试了这个:

 <bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
        <property name="dataSource" ref="dataSource"/>
        <property name="packagesToScan" value="com.myproject.*.to"/>
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.dialect">${hibernate.dialect}</prop>
                <prop key="hibernate.hbm2ddl.auto">update</prop>
                <prop key="hibernate.show_sql">false</prop>
                <prop key="hibernate.cache.use_query_cache">true</prop>
                <prop key="hibernate.cache.use_second_level_cache">true</prop>
                <prop key="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</prop>
            </props>
        </property>
    </bean>

    <context:component-scan base-package="com.myproject.dao.hibernate" />

我在CorDAOHibernate和GenericDAOHibernate中添加了一个 @Component 注释但是我得到了一个IllegalArgumentException:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'corDAOHibernate' defined in URL [jar:file:/home/danielamorais/Documents/apache-tomcat-8.0.47/webapps/myproject/WEB-INF/lib/myproject-3.1.0.jar!/com/myproject/dao/hibernate/corDAOHibernate.class]: Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: 'sessionFactory' or 'hibernateTemplate' is required

我认为这是因为sessionFactory在GenericDAOHibernate中自动装配但在CorDAOHibernate中为null。如何使用组件扫描解决此问题?

类 CorDAO

@Repository
public interface CorDAO extends GenericDAO {
    //Methods
}

CorDAOHibernate

@Component
public class CorDAOHibernate extends GenericDAOHibernate implements CorDAO {
    //Methods
}

GenericDAO

public interface GenericDAO extends DAO {
    //Methods. This class doesn't contains @Repository annotation
}

GenericDAOHibernate

    @Component
    public class GenericDAOHibernate extends HibernateDaoSupport implements GenericDAO, PropertySelector {

        @Autowired
        private SessionFactory sessionFactory;

    protected Session getCurrentSession() {
        return sessionFactory.getCurrentSession();
    }
        //Methods
    }

DAO

public interface DAO {
//There's no method here.
}

另外,添加 @Component(&#34; genericDAO&#34;)我得到了(可能是因为继承问题):

NoUniqueBeanDefinitionException: No qualifying bean of type [com.myproject.dao.GenericDAO] is defined: expected single matching bean but found 88

3 个答案:

答案 0 :(得分:1)

嗯,您的主要问题是因为:

  

调用init方法失败;嵌套异常是java.lang.IllegalArgumentException:必需'sessionFactory'或'hibernateTemplate'

我也回答了类似的问题before

长话短说,GenericDAOHibernate的实现方式错误:

  1. 不需要像SessionFactory那样在内部实现HibernateDaoSupport,而只需致电getSessionFactory()即可
  2. 您必须通过构造函数将SessionFactory传递给HibernateDaoSupport,以便在HibernateTemplate中初始化HibernateDaoSupport。否则,它将为null,因此会发生此异常消息。

此外,您的@Repository@Component似乎也被注释了。基本上,我只会对DAO使用@Repository。它与@Component相同,并带有spring“ exception translation”功能。

无论如何,请尝试更改为以下内容:

@Repository  
public class GenericDAOHibernate extends HibernateDaoSupport implements GenericDAO, PropertySelector {

         @Autowired
         public GenericDAOHibernate(SessionFactory sessionFactory){
             super.setSessionFactory(sessionFactory);
         }

        protected Session getCurrentSession() {
            return getSessionFactory().getCurrentSession();
        }

}     

每个DAO实现:

@Repository
public class CorDAOHibernate extends GenericDAOHibernate implements CorDAO {
     public CorDAOHibernate(SessionFactory sessionFactory) {
          super(sessionFactory);
     }
}   

还要从@Repository界面中删除CorDAO@Component("genericDAO")的内容.....

答案 1 :(得分:0)

您必须将声明为sessionFactory的类注释为@Bean(或@Component,请参阅this question并确保它将通过ComponentScan进行扫描。

另外,请考虑使用Spring Data中的Repository方法,以便您不必编写样板代码。

答案 2 :(得分:0)

我认为您应该删除

  

@自动连线   私有SessionFactory sessionFactory;

字段。

因为sessionFactory字段已经在父类中定义。并将setSessionFactory方法清除为final。因此,您无需为sessionFactory清除新的私有字段。

这是setSessionFactory方法的实现。

/**
 * Set the Hibernate SessionFactory to be used by this DAO.
 * Will automatically create a HibernateTemplate for the given SessionFactory.
 * @see #createHibernateTemplate
 * @see #setHibernateTemplate
 */
public final void setSessionFactory(SessionFactory sessionFactory) {
    if (this.hibernateTemplate == null || sessionFactory != this.hibernateTemplate.getSessionFactory()) {
        this.hibernateTemplate = createHibernateTemplate(sessionFactory);
    }
}

同时删除sessionFactory和getCurrentSession(HibernateDaoSupport已经具有currentSession()方法)

或如下更改getCurrentSession

public class GenericDAOHibernate extends HibernateDaoSupport implements GenericDAO, PropertySelector {



protected Session getCurrentSession()  throws DataAccessResourceFailureException  {
    return currentSession()
}
    //Methods
}