org.springframework.beans.factory.UnsatisfiedDependencyException:创建名称为“ userController”的bean时出错

时间:2018-09-11 05:03:42

标签: hibernate spring-boot javabeans crud

相关问题似乎对我没有帮助。这是我第一次使用Spring Boot开发Webapp,遇到了这个错误。这是我的代码。

UserController

package com.rtc_insurance.controller;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

import com.rtc_insurance.dao.UserDAO;
import com.rtc_insurance.entity.Users;

@Controller
@RequestMapping("/user")
public class UserController {

    //inject DAO
    //scan for a component that implements UserDAO interface
    @Autowired
    private UserDAO userDAO;


    @RequestMapping("/list")
    public String listUsers(Model theModel) {

        //get user from the dao
        List<Users> theUsers = userDAO.getUsers();

        //add the customer to the model
        //users = table name
        theModel.addAttribute("users",theUsers);

        return "list-users";
    }
}

UserDAO

package com.rtc_insurance.dao;

import java.util.List;
import com.rtc_insurance.entity.Users;

public interface UserDAO {

    public List<Users> getUsers();
}

UserDAOImpl

package com.rtc_insurance.dao;

import java.util.List;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.query.Query;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;


import com.rtc_insurance.entity.Users;

@Repository
public class UserDAOImpl implements UserDAO {

    //need to inject the session factory
    @Autowired
    private SessionFactory sessionFactory;

    @Override
    @Transactional
    public List<Users> getUsers() {

        //get current hibernate session
        Session currentSession = sessionFactory.getCurrentSession();

        //query
        Query<Users> theQuery = 
                currentSession.createQuery("from users", Users.class);

        //execute result
        List<Users> users = theQuery.getResultList();

        //return list of users
        return users;

    }

}

Servlet

<?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:context="http://www.springframework.org/schema/context"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc.xsd
        http://www.springframework.org/schema/tx 
        http://www.springframework.org/schema/tx/spring-tx.xsd">

    <!-- Add support for component scanning -->
    <context:component-scan base-package="com.rtc_insurance" />

    <!-- Add support for conversion, formatting and validation support -->
    <mvc:annotation-driven/>

    <!-- Define Spring MVC view resolver -->
    <bean
        class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/view/" />
        <property name="suffix" value=".jsp" />
    </bean>

    <!-- Step 1: Define Database DataSource / connection pool -->
    <bean id="myDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
        destroy-method="close">
        <property name="driverClass" value="com.mysql.cj.jdbc.Driver" />
        <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/rtc_insurance?useSSL=false&amp;characterEncoding=latin1&amp;serverTimezone=UTC" />
        <property name="user" value="root" />
        <property name="password" value="root" /> 

        <!-- these are connection pool properties for C3P0 -->
        <property name="initialPoolSize" value="5"/>
        <property name="minPoolSize" value="5" />
        <property name="maxPoolSize" value="20" />
        <property name="maxIdleTime" value="30000" />
    </bean>  

    <!-- Step 2: Setup Hibernate session factory -->
    <bean id="sessionFactory"
        class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
        <property name="dataSource" ref="myDataSource" />
        <property name="packagesToScan" value="com.rtc_insurance.entity" />
        <property name="hibernateProperties">
        <props>
            <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
            <prop key="hibernate.show_sql">true</prop>
        </props>
        </property>
</bean>   

    <!-- Step 3: Setup Hibernate transaction manager -->
    <bean id="myTransactionManager"
            class="org.springframework.orm.hibernate5.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory"/>
    </bean>

    <!-- Step 4: Enable configuration of transactional behavior based on annotations -->
    <tx:annotation-driven transaction-manager="myTransactionManager" />

    <!-- Add support for reading web resources: css, images, js, etc ... -->
    <mvc:resources location="/resources/" mapping="/resources/**"></mvc:resources>



</beans>

我一直收到这个错误。

1 个答案:

答案 0 :(得分:1)

Spring Boot为您提供了许多开箱即用的功能。

配置DataSource

首先,有数据源。遗憾的是,C3P0不是受支持的连接池提供程序(仅DBCP,Hikari和Tomcat是)。这意味着您必须手动创建一个DataSource bean,例如:

@Bean
@ConfigurationProperties("custom.datasource")
public ComboPooledDataSource dataSource() {
    return new ComboPooledDataSource();
}

如果将此方法添加到您的主类或任何其他用@Configuration注释的类中,Spring将自动选择数据源bean,并为其中创建一个TransactionManagerSessionFactory您。它还启用注释驱动的事务。

由于我们使用的是@ConfigurationProperties,因此所有以custom.datasource.*开头的属性都会自动注入到数据源中。这使您可以从application.properties内部配置数据源。如果还没有这样的文件,请在类路径上创建一个文件并添加以下属性:

custom.datasource.jdbc-url=jdbc:mysql://localhost:3306/rtc_insurance?useSSL=false&amp;characterEncoding=latin1&amp;serverTimezone=UTC
custom.datasource.user=root
custom.datasource.password=root
custom.datasource.initial-pool-size=5
custom.datasource.min-pool-size=5
custom.datasource.max-pool-size=20
custom.datasource.max-idle-time=30000

通过Spring Data替换DAO

下一部分是DAO。 Spring Data项目试图使这些事情变得容易得多。首先,您需要向项目添加spring-boot-starter-data-jpa依赖项。如果您使用的是Maven,则可以执行以下操作:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
    <exclusions>
        <exclusion>
            <groupId>com.zaxxer</groupId>
            <artifactId>HikariCP</artifactId>
        </exclusion>
    </exclusions>
</dependency>

排除是可选的,但是由于您不使用默认连接池,因此可以排除默认连接池(Hikari)。之后,您可以将整个UserDAOUserDAOImpl替换为以下内容:

public interface UserRepository extends JpaRepository<User, Long> {
}

通过创建接口并从JpaRepository(或CrudRepository,...)扩展,Spring知道它应该为您创建一个类型为User且类型为Long的存储库bean。标识符的类型为User(您没有共享Long实体,因此,如果它不是findAll(),则可以更改泛型)。

它还将包括一些不再需要编写的默认方法,例如findById()save()delete()getUsers()等。由于您是findAll()方法,因此与UserRepository操作基本相同。这意味着您不需要该代码,只需将findAll()自动连接到控制器中,然后使用<context:component-scan base-package="com.rtc_insurance" /> 操作即可。

组件扫描

在XML配置中,您还可以进行组件扫描:

@ComponentScan("com.xyz")

这不再是必需的,因为Spring Boot会自动扫描同一包或主类的任何子包中的组件。如果要添加其他组件罐,可以通过在主类或任何其他用@Configuration注释的类的顶部添加application.properties批注来实现。

Spring MVC配置

您还具有与Spring MVC相关的一些配置,例如:

  1. MVC注释驱动
  2. 视图解析器的前缀和后缀
  3. 静态资源的位置

由于Spring Boot自动启用了MVC注释,因此您已经可以对其进行抓取了。另一方面,也可以通过配置以下属性,通过spring.mvc.view.prefix=/WEB-INF/view/ spring.mvc.view.suffix=.jsp 来配置视图解析器的前缀和后缀:

classpath:/static/

最后,还有静态资源。默认情况下,Spring Boot将自动将来自多个位置(例如classpath:/public/export const generateEventThumbnail = functions.storage.object().onFinalize(async (object) => { const fileBucket = object.bucket; // The Storage bucket that contains the file. const filePath = object.name; // File path in the bucket. const contentType = object.contentType; // File content type. const fileName = path.basename(filePath); // Get the file name. console.log(filePath) console.log(fileName) if (!contentType.startsWith('image/')) { console.log('This is not an image.'); return null; } try { // [START thumbnailGeneration] // Download file from bucket. const bucket = gcs.bucket(fileBucket); const tempFilePath = path.join(os.tmpdir(), fileName); const metadata = {contentType: contentType}; await bucket.file(filePath).download({destination: tempFilePath}) console.log('Image downloaded locally to', tempFilePath) // Generate a thumbnail using ImageMagick. await spawn('convert', [tempFilePath, '-thumbnail', '100x100>', tempFilePath]) console.log('Thumbnail created at', tempFilePath) // We add a 'thumb_' prefix to thumbnails file name. That's where we'll upload the thumbnail. const thumbFileName = `${fileName}`; const thumbFilePath = `eventThumbnail/${thumbFileName}` // Uploading the thumbnail. await bucket.upload(tempFilePath, {destination: thumbFilePath,metadata: metadata}) // Once the thumbnail has been uploaded delete the local file to free up disk space. fs.unlinkSync(tempFilePath) // [END thumbnailGeneration] // then save the thumbnail path to the event data in firestore database return Promise.resolve(null) } catch (error) { console.log(error) } }); )的资源作为静态资源位置。

这意味着,如果您将任何文件放在这些文件夹中,则会自动提供该文件。

之后,整个bean XML配置文件已过时,可以删除。