【问题标题】:Spring Boot CRUD + Hibernate + JSP/JSON - Can´t put it all togetherSpring Boot CRUD + Hibernate + JSP/JSON - 不能把它们放在一起
【发布时间】:2017-11-24 19:14:35
【问题描述】:

在过去的三周里,我一直在尝试学习 Spring,同时做一些简单的练习,但即使在阅读了至少 15 个不同的教程并阅读了大量 StackOverflow 答案之后,我也无法完成这项工作:

我想做一个具有以下特点的“简单”应用程序:

  • 当浏览到/carsweb 时,能够使用带有一些 css 和 js(在外部文件中)的 JSP 页面给出响应;
  • 浏览到/carsjson 时能够返回JSON。此响应必须是实体“汽车”的列表;
  • 当我们调用 /newcar 时,在 DB 上保存一辆新车(Car 在请求正文中以 JSON 形式出现);
  • 能够使用 Hibernate 从 MySQL 数据库中检索和保存 Cars(application.properties 文件上的用户/密码);
  • 所有这些都只使用 Spring 注释,如果可能的话,不使用 XML 进行配置。

我几乎可以做任何事情,但我不能把它们放在一起。这是我目前的状态:

SpringBootWebApplication

@SpringBootApplication
public class SpringBootWebApplication extends SpringBootServletInitializer {

    public static void main(String[] args) throws Exception {
        SpringApplication.run(SpringBootWebApplication.class, args);
    }    
}

AppConfig

@Configuration
@ComponentScan(basePackages = "com.facundo")
public class AppConfig {

}

休眠配置

package com.facundo.configuration;

import java.util.Properties;

import javax.sql.DataSource;

import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.hibernate4.HibernateTransactionManager;
import org.springframework.orm.hibernate4.LocalSessionFactoryBean;
import org.springframework.transaction.annotation.EnableTransactionManagement;

@Configuration
@EnableTransactionManagement
@ComponentScan({ "com.facundo.configuration" })
@PropertySource(value = { "classpath:application.properties" })
public class HibernateConfiguration {
    @Autowired
    private Environment environment;

    private Properties hibernateProperties() {
        Properties properties = new Properties();
        properties.put("hibernate.dialect", environment.getRequiredProperty("hibernate.dialect"));
        properties.put("hibernate.show_sql", environment.getRequiredProperty("hibernate.show_sql"));
        properties.put("hibernate.format_sql", environment.getRequiredProperty("hibernate.format_sql"));
        return properties;
    }

    @Bean
    public LocalSessionFactoryBean sessionFactory() {
        LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
        sessionFactory.setDataSource(dataSource());
        sessionFactory.setPackagesToScan(new String[] { "com.mkyong.model" });
        sessionFactory.setHibernateProperties(hibernateProperties());
        return sessionFactory;
    }

    @Bean
    public DataSource dataSource() {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName(environment.getRequiredProperty("jdbc.driverClassName"));
        dataSource.setUrl(environment.getRequiredProperty("jdbc.url"));
        dataSource.setUsername(environment.getRequiredProperty("jdbc.username"));
        dataSource.setPassword(environment.getRequiredProperty("jdbc.password"));
        return dataSource;
    }

    @Bean
    @Autowired
    public HibernateTransactionManager transactionManager(SessionFactory s) {
        HibernateTransactionManager txManager = new HibernateTransactionManager();
        txManager.setSessionFactory(s);
        return txManager;
    }       
}

WelcomeController

@Controller
public class WelcomeController {
    @Autowired
    private CarService carService;
    @RequestMapping(value = "/carsweb", method = RequestMethod.GET)
    public String helloHtml(Model model) {
        return "welcome2";
    }

    @RequestMapping(path = "/newcar", method = RequestMethod.POST)
    public void postCustomer(@RequestBody Car modelo) {
        carService.save(modelo);
    }
}

CarDaoImpl

@Repository
public class CarDaoImpl implements CarDao{

    @Autowired
    private SessionFactory sessionFactory;

    @Override
    public void save(Car modelo) {
        sessionFactory.getCurrentSession().persist(modelo);
    }        
}

CarPruebaImpl

@Service("prubaService")
@Transactional
public class CarPruebaImpl implements CarService{
    @Autowired
    private CarDao modeloDao;

    @Override
    public void save(Car modelo) {
        modeloDao.save(modelo);
    }
}

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <artifactId>spring-boot-web-jsp</artifactId>
    <packaging>war</packaging>
    <name>Spring Boot Web JSP Example</name>
    <description>Spring Boot Web JSP Example</description>
    <version>1.0</version>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.4.RELEASE</version>
    </parent>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>

        <!-- Web -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!-- Web with Tomcat + Embed -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
            <scope>provided</scope>
        </dependency>

        <!-- JSTL -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
        </dependency>

        <!-- Need this to compile JSP -->
        <dependency>
            <groupId>org.apache.tomcat.embed</groupId>
            <artifactId>tomcat-embed-jasper</artifactId>
            <scope>provided</scope>
        </dependency>

        <!-- Need this to compile JSP -->
        <dependency>
            <groupId>org.eclipse.jdt.core.compiler</groupId>
            <artifactId>ecj</artifactId>
            <version>4.6.1</version>
            <scope>provided</scope>
        </dependency>

        <!-- Optional, for bootstrap -->
        <dependency>
            <groupId>org.webjars</groupId>
            <artifactId>bootstrap</artifactId>
            <version>3.3.7</version>
        </dependency>

        <!-- Persistencia -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-tx</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-orm</artifactId>
        </dependency>

        <!-- Hibernate -->
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-core</artifactId>
        </dependency>

        <!-- MySQL -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>

        <!-- Joda-Time -->
        <dependency>
            <groupId>joda-time</groupId>
            <artifactId>joda-time</artifactId>
        </dependency>

        <!-- To map JodaTime with database type -->
        <dependency>
            <groupId>org.jadira.usertype</groupId>
            <artifactId>usertype.core</artifactId>
            <version>3.0.0.CR1</version>
        </dependency>

    </dependencies>
    <build>
        <plugins>
            <!-- Package as an executable jar/war -->
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

application.properties:

spring.mvc.view.prefix: /WEB-INF/jsp/
spring.mvc.view.suffix: .jsp

jdbc.driverClassName = com.mysql.jdbc.Driver
jdbc.url = jdbc:mysql://localhost:3306/websystique
jdbc.username = root
jdbc.password = MWtqKDeS4I
hibernate.dialect = org.hibernate.dialect.MySQLDialect
hibernate.show_sql = false
hibernate.format_sql = false

所以,这是我执行时显示的错误

mvn spring-boot:run

在项目文件夹上:

BeanCreationException:org.springframework.beans.factory.UnsatisfiedDependencyException:创建名为“welcomeController”的bean时出错:Uns 通过字段“servicioPrueba”表达的满足依赖关系;嵌套异常是 org.springframework.beans.factory.Unsa tisfiedDependencyException:创建名称为“carPruebaImpl”的 bean 时出错:通过字段表示的不满足依赖项 d'modeloDao';嵌套异常是 org.springframework.beans.factory.UnsatisfiedDependencyException:创建 bean 时出错 名称为“carDaoImpl”:通过字段“sessionFactory”表示不满足的依赖关系;嵌套异常是 org.spring framework.beans.factory.BeanCreationException:在类路径资源库中定义名称为“sessionFactory”的 bean 创建错误 urce [com/facundo/configuration/HibernateConfiguration.class]:init 方法调用失败;嵌套异常是 jav a.lang.AbstractMethodError

我认为可以简化为:

创建名为“sessionFactory”的 bean 时出错

最后,我想说我认为问题出在某些配置中,@ComponentScan 找不到我的文件或类似的东西。
当然还有很多需要改进的地方,所以如果你告诉我哪些部分真的错了,请这样做。
不管怎样,先谢谢了。

【问题讨论】:

  • 尝试以下操作:将 SpringBootWebApplication 类移到包外,以便位于应用程序的根包上。不需要AppConfigHibernateConfiguration,将它们组合成一个配置类并将其与SpringBootWebApplication 类一起移出包以驻留在根包中。在您的新 Configuartion 类中,无需添加 @ComponentScan,因为 @SpringBootApplication 已经包含它。

标签: json spring hibernate spring-boot annotations


【解决方案1】:

所以,这就是我所做的。

删除了整个配置包(不再有 HibernateConfig.java 和 AppConfig.java)

pom.xml 更改为只有:

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.4.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>

        <!-- JSTL -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
        </dependency>
        <!-- Need this to compile JSP -->
        <dependency>
            <groupId>org.apache.tomcat.embed</groupId>
            <artifactId>tomcat-embed-jasper</artifactId>
            <scope>provided</scope>
        </dependency>
        <!-- Need this to compile JSP -->
        <dependency>
            <groupId>org.eclipse.jdt.core.compiler</groupId>
            <artifactId>ecj</artifactId>
            <version>4.6.1</version>
            <scope>provided</scope>
        </dependency>

    </dependencies>

并将 application.properties 更改为:

spring.datasource.url=jdbc:mysql://localhost:3306/arquitectura
spring.datasource.username=root
spring.datasource.password=MWtqKDeS4I
spring.datasource.tomcat.max-wait=20000
spring.datasource.tomcat.max-active=50
spring.datasource.tomcat.max-idle=20
spring.datasource.tomcat.min-idle=15

spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQLDialect
spring.jpa.properties.hibernate.id.new_generator_mappings = false
spring.jpa.properties.hibernate.format_sql = true

logging.level.org.hibernate.SQL=DEBUG
logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE 

spring.mvc.view.prefix: /WEB-INF/jsp/
spring.mvc.view.suffix: .jsp

这现在可以工作了,因为 Springs starter-web 已经配置为默认返回 jsp 和 JSON(基于方法返回类型:JSP 的 String 和 JSON 的 ResponseEntity),并且 starter-jps 也可以与 MySQL 一起使用,如果你仅更改(在 DAO 类中)

@Autowired
private SessionFactory sessionFactory;

...

sessionFactory.getCurrentSession().persist(object);

@PersistenceContext
private EntityManager entityManager;

...

entityManager.persist(object);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-06-02
    • 2020-04-12
    • 2017-09-17
    • 1970-01-01
    • 2021-02-13
    • 1970-01-01
    • 2022-01-16
    • 2017-06-16
    相关资源
    最近更新 更多