如何在内存数据库中使用H2调试Spring Boot存储库?

时间:2018-09-27 10:20:18

标签: hibernate spring-boot h2 spring-repositories

我正在使用Spring Boot并尝试在内存中使用H2数据库(在内存中)。我的Spring数据存储库实现无法正常工作,我需要对其进行调试。

我将我的项目(不使用原始项目)简化为以下示例,以隔离并演示该问题。该项目可以在GitHub中找到。

Eclipse项目结构:

project structure

pom.xml:

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

    <dependencies>
        <dependency>
        <groupId>org.glassfish.jaxb</groupId>
        <artifactId>jaxb-runtime</artifactId>
        <version>2.3.0.1</version>
    </dependency>
    <dependency>
        <groupId>javax.activation</groupId>
        <artifactId>activation</artifactId>
        <version>1.1.1</version>
    </dependency>
    <dependency>
        <groupId>javax.transaction</groupId>
        <artifactId>jta</artifactId>
        <version>1.1</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.apache.maven</groupId>
        <artifactId>maven-model</artifactId>
        <version>3.5.4</version>
    </dependency>
    <dependency>
        <groupId>org.modelmapper</groupId>
        <artifactId>modelmapper</artifactId>
        <version>2.2.0</version>
    </dependency>
    <dependency>
        <groupId>com.h2database</groupId>
        <artifactId>h2</artifactId>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>
</dependencies>

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <configuration>
                <executable>true</executable>
                <skipTests>true</skipTests>
            </configuration>
            <executions>
                <execution>
                    <goals>
                        <goal>repackage</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

<repositories>
    <repository>
        <id>spring-releases</id>
        <url>https://repo.spring.io/libs-release</url>
    </repository>
</repositories>
<pluginRepositories>
    <pluginRepository>
        <id>spring-releases</id>
        <url>https://repo.spring.io/libs-release</url>
    </pluginRepository>
</pluginRepositories>

application.properties:

debug=true

logging.level.root=WARN
logging.level.org.foo=WARN
logging.level.org.springframework=WARN

spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.url=jdbc:h2:mem:test_database;DB_CLOSE_DELAY=-1
spring.datasource.username=sa
spring.datasource.password=sa

spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
spring.h2.console.enabled=true
spring.h2.console.path=/h2-console

主要配置类:

@SpringBootApplication
@Configuration
@PropertySource("classpath:application.properties")
@EnableJpaRepositories(basePackages = "org.foo.repositories")
@EntityScan("org.foo.entities")
@EnableTransactionManagement
public class Application {

    Logger logger = LoggerFactory.getLogger(Application.class);

    public static void main(String[] args) {
        Logger logger = LoggerFactory.getLogger(Application.class);
        SpringApplication.run(Application.class, args);
        logger.info("Application started");
    }

    @Bean
    public CommandLineRunner commandLineRunner(ApplicationContext ctx) {
        return args -> {

            logger.trace("Let's inspect the beans provided by Spring Boot:");
            String[] beanNames = ctx.getBeanDefinitionNames();
            Arrays.sort(beanNames);
            for (String beanName : beanNames) {
                logger.trace(beanName);
            }
        };
    }
}

学生实体类:

package org.foo.entities;

import javax.persistence.Entity;
import javax.persistence.Id;
import lombok.Data;

@Entity
@Data
public class Student {

    @Id
    private long id;

    private String first_name;

    private String last_name;

}

StudentRepository类:

@Repository
public interface StudentRepository extends JpaRepository<Student, Long> {
    @Override
    List<Student> findAll();
}

StudentRepositoryTester类:

@RunWith(SpringRunner.class)
@SpringBootTest
@Transactional
@ContextConfiguration(classes = { org.foo.Application.class }, loader = AnnotationConfigContextLoader.class)
public class StudentRepositoryTester {

    Logger logger = LoggerFactory.getLogger(StudentRepositoryTester.class);

    @Autowired
    private StudentRepository studentRepository;

    @Test
    public void findAllTester() {
        Iterable<Student> students = studentRepository.findAll();
        for(Student student: students) {
            logger.info(student.toString());
        }
        long size = StreamSupport.stream(students.spliterator(), false).count();
        assertTrue(students != null && size == 3);
    }

}

data.sql:

USE `test_database`;

INSERT INTO `students` (`id`,`first_name`,`last_name`) VALUES (1,'First1','Last1');
INSERT INTO `students` (`id`,`first_name`,`last_name`) VALUES (2,'First2','Last2');
INSERT INTO `students` (`id`,`first_name`,`last_name`) VALUES (3,'First3','Last3');

schema.sql:

DROP ALL OBJECTS; 

CREATE SCHEMA `test_database`;
USE `test_database`;

CREATE TABLE `students` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `first_name` varchar(45) NOT NULL,
  `last_name` varchar(45) NOT NULL,
  PRIMARY KEY (`id`)
);

我可以在控制台日志中看到已填充H2,因为我可以看到data.sql中的语句已执行。我在日志中没有发现其他可疑的东西。

具体问题:

  1. 运行StudentRepositoryTester测试类,我看到(在assert语句上带有断点)没有实体返回。我不明白为什么。也许我错过了Spring Boot配置注释中的某些内容?

  2. 我试图在断点处检查数据库内容,但是找不到找到H2数据库的方法。我遵循this tutorial打开H2的Web资源管理器应用程序,但是localhost:8080没有提供任何服务。难道我做错了什么?另外,还有另一种方法可以调试H2数据库(在内存中)发生的情况吗?

请注意,相应的Eclipse项目已上传到GitHub中,以方便讨论。

2 个答案:

答案 0 :(得分:0)

打开由Hibernate执行的SQL语句的日志记录(在application.properties中):

logging.level.org.hibernate.SQL=DEBUG

这会将所有SQL语句输出到控制台。但是没有注入变量。这应该可以帮助您进行故障排除。

答案 1 :(得分:0)

H2引导脚本由ScriptUtils

处理

因此,在application.properties中增加其日志记录级别:

logging.level.org.springframework.jdbc.datasource.init.ScriptUtils=DEBUG