【问题标题】:Could not autowire field: private org.hibernate.SessionFactory Hibernate and Spring无法自动装配字段:私有 org.hibernate.SessionFactory Hibernate 和 Spring
【发布时间】:2016-05-03 22:30:13
【问题描述】:

在我的服务器 Tomcat 上部署项目后出现此错误。我发现了许多类似的问题,但我没有找到我的问题的答案。

org.springframework.beans.factory.BeanCreationException:创建名为“categoryDaoDbImpl”的bean时出错:注入自动装配的依赖项失败;嵌套异常是 org.springframework.beans.factory.BeanCreationException:无法自动装配字段:私有 org.hibernate.SessionFactory ua.com.goit.gojava7.kikstarter.dao.database.CategoryDaoDbImpl.sessionFactory;嵌套异常是 org.springframework.beans.factory.BeanCreationException:在类路径资源 [applicationContext.xml] 中定义名称为“sessionFactory”的 bean 创建错误:调用 init 方法失败;嵌套异常是 org.hibernate.AnnotationException: @OneToOne 或 @ManyToOne on ua.com.goit.gojava7.kikstarter.domain.Payment.projectId 引用未知实体:int 在 org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:334) 在 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1214) 在 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:543) 在 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482) 在 org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:305) 在 org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) 在 org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:301) 在 org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:196) 在 org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:772) 在 org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:835) 在 org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:537) 在 org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:446) 在 org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:328) 在 org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:107)

applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
    http://www.springframework.org/schema/beans 
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/aop 
    http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
    http://www.springframework.org/schema/tx    
    http://www.springframework.org/schema/tx/spring-tx.xsd
    http://www.springframework.org/schema/context 
    http://www.springframework.org/schema/context/spring-context-4.2.xsd
    http://www.springframework.org/schema/util
    http://www.springframework.org/schema/util/spring-util.xsd">

    <context:property-placeholder location="classpath:config.properties" />
    <context:component-scan base-package="ua.com.goit.gojava7.kikstarter.dao.database" />

    <bean id="basicDataSource" class="org.apache.commons.dbcp2.BasicDataSource" destroy-method="close">
        <property name="driverClassName" value="${jdbc.driverClassName}" />
        <property name="url" value="${jdbc.dataBaseUrl}" />
        <property name="username" value="${jdbc.username}" />
        <property name="password" value="${jdbc.password}" />
    </bean>

    <tx:annotation-driven transaction-manager="transactionManager" />
    <bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory" />
    </bean>

    <bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">

        <property name="dataSource">
            <ref bean="basicDataSource" />
        </property>

        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</prop>
                <prop key="hibernate.show_sql">false</prop>
            </props>
        </property>

        <property name="annotatedClasses">
            <list>
                <value>ua.com.goit.gojava7.kikstarter.domain.Quote</value>
                <value>ua.com.goit.gojava7.kikstarter.domain.Category</value>
                <value>ua.com.goit.gojava7.kikstarter.domain.Project</value>
                <value>ua.com.goit.gojava7.kikstarter.domain.Payment</value>
                <value>ua.com.goit.gojava7.kikstarter.domain.Reward</value>
            </list>
        </property>
    </bean>

CategoryDaoDbImpl 类

package ua.com.goit.gojava7.kikstarter.dao.database;

import java.util.List;

import org.hibernate.SessionFactory;
import org.hibernate.Session;
import org.hibernate.criterion.Restrictions;
import org.hibernate.Criteria;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import ua.com.goit.gojava7.kikstarter.dao.CategoryDao;
import ua.com.goit.gojava7.kikstarter.domain.Category;

@Repository
public class CategoryDaoDbImpl implements CategoryDao {

    @Autowired
    private SessionFactory sessionFactory;

    @SuppressWarnings("unchecked")
    @Transactional
    @Override
    public List<Category> getAll() {
        Session session=sessionFactory.openSession();

        Criteria criteria=session.createCriteria(Category.class);
        List<Category> categories=criteria.list();

        session.close();
        return categories;
    }

    @Transactional
    @Override
    public Category getCategory(int id) {
        Session session=sessionFactory.openSession();

        Criteria criteria=session.createCriteria(Category.class);
        criteria.add(Restrictions.eq("id", id));
        Category category=(Category) criteria.uniqueResult();

        session.close();
        return category;
    }
}

类别类

package ua.com.goit.gojava7.kikstarter.domain;

import java.util.Set;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;

@Entity
@Table(name = "categories")
public class Category {

    @Id
    @SequenceGenerator(name = "SEQ_GEN", sequenceName = "seq_id", allocationSize = 10)
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SEQ_GEN")
    private int id;

    @Column(name = "name")
    private String name;

    @OneToMany
    private Set<Project> projects;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public Set<Project> getProjects() {
        return projects;
    }

    public void setProjects(Set<Project> projects) {
        this.projects = projects;
    }

    @Override
    public String toString() {
        return "ID: " + id + "; Name: " + name;
    }
}

项目类

package ua.com.goit.gojava7.kikstarter.domain;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;

@Entity
@Table(name = "projects")
public class Project {

    @Id
    @SequenceGenerator(name = "SEQ_GEN", sequenceName = "seq_id", allocationSize = 10)
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SEQ_GEN")
    private int id;

    @ManyToOne
    @JoinColumn(name = "category_id")
    private Category category;

    @Column(name = "name")
    private String name;

    @Column(name = "general_description")
    private String generalDescription;

    @Column(name = "full_description")
    private String fullDescription;

    @Column(name = "video_link")
    private String videoLink;

    @Column(name = "required_sum")
    private int requiredSum;

    @Column(name = "collected_sum")
    private int collectedSum;

    @Column(name = "days_left")
    private int endOfDays;

    public int getId() {
        return id;
    }

    public Category getCategory() {
        return category;
    }

    public String getName() {
        return name;
    }

    public String getGenerelDescription() {
        return generalDescription;
    }

    public String getFullDescription() {
        return fullDescription;
    }

    public String getVideoLink() {
        return videoLink;
    }

    public int getRequiredSum() {
        return requiredSum;
    }

    public int getCollectedSum() {
        return collectedSum;
    }

    public int getEndOfDays() {
        return endOfDays;
    }

    public void setId(int id) {
        this.id = id;
    }

    public void setCategory(Category category) {
        this.category = category;
    }

    public void setName(String projectName) {
        this.name = projectName;
    }

    public void setGeneralDescription(String generalDescription) {
        this.generalDescription = generalDescription;
    }

    public void setFullDescription(String fullDescription) {
        this.fullDescription = fullDescription;
    }

    public void setVideoLink(String videoLink) {
        this.videoLink = videoLink;
    }

    public void setRequiredSum(int requiredSum) {
        this.requiredSum = requiredSum;
    }

    public void setCollectedSum(int collectedAmount) {
        this.collectedSum = collectedAmount;
    }

    public void setSumFromUser(int enteredAmount) {
        collectedSum += enteredAmount;
    }

    public void setEndOfDays(int endOfDays) {
        this.endOfDays = endOfDays;
    }

    @Override
    public String toString() {
        return "Project: name: " + name + "; general description: " + generalDescription + "; full description: "
            + fullDescription + "; video link: " + videoLink + "; required sum: " + requiredSum
            + "; collected sum: " + collectedSum + "; days left: " + endOfDays;
    }
}

【问题讨论】:

  • 请显示完整的堆栈跟踪并指定您使用的 Hibernate 版本。
  • 你的 dao 也有缺陷,不要使用openSession(),而是使用getCurrentSession()。现在,经过几次查询后,您的应用程序将被锁定,因为您正在打开 Spring 无法控制的新会话。
  • @M.Deinum 我认为如果他不混合弹簧相关的(@Transactional)代码和自定义代码是可以的。他只是打开和关闭一个会话。更大的问题是他不使用事务处理查询数据:)
  • 关键是他在混合这些东西,他不应该。
  • @M.Deinum 你是对的。我没有注意到他的@Transactional。无论如何,此代码将无法正常工作,因为他需要使用新会话打开一个新事务:) 或者只是按照您的建议获取当前会话。

标签: java spring hibernate autowired


【解决方案1】:

这对于评论来说太长了,根据您的评论,我认为给您一个更长的解释可能会有所帮助。

在阅读 Java 异常时,有几件事需要牢记。

  1. The Stack。通过向堆栈添加“帧”来跟踪代码执行。每次调用方法时,都会将一个新帧“推送”到堆栈上。这就是当抛出异常时,您能够获取导致异常的调用方法(称为Stack Trace)的方式。
  2. Chained Exceptions。在 Java 中,当抛出异常时,可以指定异常的“原因”。这是一种跟踪“导致”正在引发的新异常的异常的堆栈跟踪的方法。

Spring 框架因大量使用链式异常而臭名昭著(我个人认为这是一个很好的品质),这使得读取从框架返回的错误有点棘手。棘手的是堆栈跟踪的顺序和链式异常的顺序本质上是颠倒的。

也就是说,使用堆栈跟踪,最近执行的代码位于顶部。但是,对于链式异常,引发的“第一个”异常位于底部。

因此,您需要做的是查找引发的“第一个”异常,以找到异常的真正根本原因并修复该异常。已经有一个很好的问题/答案further explains我在说什么。

因此,查看您的具体示例(并对其进行简化以标出您需要注意的结构)我们会看到:

BeanCreationException: Error creating bean with name 'categoryDaoDbImpl': Injection of autowired dependencies failed; **nested exception is**
|
|-> BeanCreationException: Could not autowire field: private SessionFactory CategoryDaoDbImpl.sessionFactory; **nested exception is**
    |
    |-> BeanCreationException: Error creating bean with name 'sessionFactory' defined in class path resource [applicationContext.xml]: Invocation of init method failed; **nested exception is**
        |
        |-> AnnotationException: @OneToOne or @ManyToOne on Payment.projectId references an unknown entity: int at
                org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:334) at 
                org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1214) at
                org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:543) at 
                org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482) at 
                org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:305) at 
                org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) at 
                org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:301) at 
                org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:196) at 
                org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:772) at 
                org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:835) at 
                org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:537) at 
                org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:446) at 
                org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:328) at 
                org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:107)

当您看到 nested exception is 时,您正在处理链式异常。因此,您实际上拥有的是导致您的问题的 一个 异常,这是您的 Payment 对象上的映射问题;特别是 projectId 字段。

所以当你问

Could not autowire field: private org.hibernate.SessionFactory and Error Creating bean with name 'categoryDaoDbImpl' 我必须在文件 applicationContext.xml 中创建名称为 'categoryDaoDbImpl' 的 bean?

希望现在很清楚,您不必对“前”三个BeanCreationException 做任何事情,因为这些都是AnnotationException 引起的

【讨论】:

  • 我并没有居高临下的意思;所以我很抱歉,如果我这样离开。事实上,我已经使用 Spring 框架很长时间了,这是我看到新开发人员一遍又一遍地感到困惑的一件事。
  • 感谢您的精彩回复和解释!实际上我不明白如何从多行堆栈跟踪中找到所需的异常。但是经过您的详细解释,我对这个问题变得更加清楚了。我作为新手很难找到正确的答案。你对我来说一个困难的话题给了我一个非常清楚的解释。非常感谢!
  • @Vladimir 很高兴我能帮上忙。如果您觉得我已经充分回答了您的问题,习惯上使用答案左侧的箭头或复选标记vote and/or accept 答案。
猜你喜欢
  • 2014-09-07
  • 2023-03-13
  • 2016-03-23
  • 1970-01-01
  • 2014-02-26
  • 1970-01-01
  • 1970-01-01
  • 2011-11-20
  • 2016-01-06
相关资源
最近更新 更多