【问题标题】:How should I create H2 using SpringBoot?我应该如何使用 Spring Boot 创建 H2?
【发布时间】:2016-11-13 09:53:27
【问题描述】:

我开始使用 Spring Boot,作为其中的一部分,我想创建一个内存数据库以使用和引导应用程序。

鉴于下面的配置/代码,我在启动日志中没有错误,并且可以正常访问应用程序,所以它确实启动了(我收到关于对象不存在的模板错误),但我没有从调用 findAll() 时的 DAO(或者如果我尝试调用 findById(int) )。

因此,虽然看起来一切正常(日志中没有错误,日志显示它找到了创建模式广告尝试运行 data.sql 语句的 sql),但当我尝试通过 DAO 访问数据时,我没有收到异常,但是没有数据返回。

对可能有问题的代码有任何想法或意见吗?

我已将 Spring Data / H2 内容添加到我的 pom 中:

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
    <dependency>
        <groupId>com.h2database</groupId>
        <artifactId>h2</artifactId>
    </dependency>

Spring DAO:

public interface PersonDao extends CrudRepository<Person, Integer> {
}

application.properties 中的 DB 属性:

server.contextPath=/
server.port=8080
spring.mvc.view.suffix=.ftl

datasource.mine.jdbcUrl=jdbc:h2:tcp://localhost/mem:clubmanagement
datasource.mine.user=sa
datasource.mine.password=
datasource.mine.poolSize=30

logging.level.org.springframework.web=DEBUG
logging.level.org.hibernate=DEBUG

spring.jpa.hibernate.ddl-auto=create

我的服务:

@Service
public class MemberServiceImpl implements MemberService {

@Autowired
PersonDao dao;

@Override
public Optional<ClubMember> getClubMember(int id) {
    Person dbPerson = dao.findOne(id);
    if(dbPerson == null) {
        return Optional.empty();
    }
    return Optional.of(fromEntity(dbPerson));
}

@Override
public List<ClubMember> allMembers() {
    Iterable<Person> people = dao.findAll();
    List<ClubMember> members = new ArrayList<>();
    people.forEach(person -> {
        members.add(fromEntity(person));
    });
    return members;
}

private ClubMember fromEntity(Person p) {
    ClubMember member = new ClubMember();
    member.setCurrentGrade(p.getCurrentGrade());
    member.setFirstName(p.getFirstName());
    member.setLastName(p.getLastName());
    member.setAssociationMemberId(p.getAssociationMemberId());
    member.setLastGradingDate(p.getLastGradingDate());
    return member;
}
}

资源/中的Schema.sql:

create table CLUB
  (id int not null, name varchar(60), association_member_id int);

create table PERSON
(
id int not null, grade_id int, first_name varchar(35), last_name varchar(35),
association_membership varchar(12), last_grading_date date
);

create table GRADE
  (id int not null, name varchar(20));

在 data.sql 中(同样在资源目录中):

insert into club (id, name, association_member_id) values (1, 'some club', '123');

insert into person (id, grade_id, first_name, last_name, association_membership, last_grading_date)
values (1, 1, 'name', 'lastname', 'a1234', '2016-03-23');

我正在尝试检索的实体类(尝试使用对我来说也是新的 Lombock 来生成 getter/setter):

@Entity
@Table(name = "person")
public @Data class Person {

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "id")
private int id;

@JoinColumn(name = "grade_id")
private GRADE currentGrade;

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

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

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

@Column(name = "last_grading_date")
@Temporal(value = TemporalType.DATE)
private Date lastGradingDate;
}

【问题讨论】:

  • 您是否在您的application.properties 中设置了spring.datasource.initialize
  • 开启sql日志查看是否有日志:在application.properties中添加spring.jpa.show-sql=true。也许看看你是否设置了所有必要的注释。也许@Transactional 不见了?

标签: spring hibernate spring-boot spring-data h2


【解决方案1】:

你想添加H2数据库,但是你添加了HSQLDB,请替换

<dependency>
        <groupId>org.hsqldb</groupId>
        <artifactId>hsqldb</artifactId>
        <scope>runtime</scope>
    </dependency>

<dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
        </dependency>

编辑

我注意到您的代码中有多个问题:

  1. 默认架构文件名是 schema.sql 而不是 Schema.sql
  2. schema.sql 中的表名称与 data.sql 中的名称不同(PERSON vs person)
  3. 您在 application.properties 中使用了这个spring.jpa.hibernate.ddl-auto=create(默认选项),在这种情况下,JPA 数据库模式只会自动创建(不创建数据),因此不会执行 data.sql , 要解决此问题,您可以使用 validateupdate 选项

我会写一个简单的例子,如何使用 H2 数据库和 Spring Boot 和 JPA

这是项目结构:

等级实体

package com.shijazi;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name="GRADE")
public class Grade {

    @Id
    @GeneratedValue
    private int id;

    private String name;

    public int getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

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

    public Grade(int id, String name) {
        super();
        this.id = id;
        this.name = name;
    }
    public Grade() {
    }



}

GradeRepository.java

package com.shijazi;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;


@Repository
public interface GradeRepository extends JpaRepository<Grade, Integer> {

}

Application.java

@SpringBootApplication
@RestController
public class Application {

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

    @Autowired
    private GradeRepository gradeRepo;

    @RequestMapping(value="api/test")
    public List<Grade> getall()
    {
        return  gradeRepo.findAll();
    }
}

application.properties

spring.jpa.hibernate.ddl-auto=validate

schema.sql

create table GRADE (id int not null, name varchar(20));

数据.sql

insert into GRADE (id, name) values (2,  'name');

pom.xml 中的依赖项

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <scope>runtime</scope>
        </dependency>

现在只需运行应用程序并调用此 URL:http://localhost:8080/api/test

尝试更改spring.jpa.hibernate.ddl-auto 并查看结果

如果你激活了 ddl-auto 并且有一个 schema.sql,它们都会被执行。但通常首先执行 schema.sql。所以ddl-auto把schema.sql和data.sql创建的所有东西都扔掉了

【讨论】:

  • 很好,但没有解决我的问题
  • 尝试删除 application.properties 中的所有 h2 属性,并告诉我发生了什么
  • 和以前一样,没有从数据库中检索到。
  • 能否添加整个服务类,以及如何调用服务方法
  • 从 Controller 调用服务方法,很高兴一切正常。只是 DB/DAO 层没有返回数据/没有正确初始化。
【解决方案2】:

在与@Safwan Hijazi 在聊天中花了一些时间研究一些想法后,得出的结论是正在运行 schema.sql 和 data.sql 但随后根据值重新创建了架构 (或缺少) spring.jpa.hibernate.ddl-auto 属性。

如果没有指定,它们之间的 spring/hibernate 最终会重新创建一个空模式(默认似乎是内存 DB 中的 create-drop)。

如果设置为“无”,则不会发生这种情况,并且由架构和数据 sql 脚本创建的数据库将保留,并且应用程序正常运行。

另请参阅:CrudRepository not reading data from schema.sql

【讨论】:

    【解决方案3】:
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
    

    只是给你一个 Spring Boot 自以为是的包含到 spring-boot-starter-data-jpa maven 文件中,用于所有依赖项的物料清单。要使用在 spring-boot-starter-data-jpa pom 的依赖管理中定义的任何依赖项,您必须在 pom 文件的依赖项部分显式声明依赖项。

    <dependency>
      <groupId>com.h2database</groupId>
      <artifactId>h2</artifactId>
    </dependency>
    

    要让 h2 数据库启动并与您的应用程序一起运行,您可以在 src/main/resources/application.properties 使用的 application.properties 文件中指定属性:

    spring.h2.console.enabled=true
    spring.h2.console.path=/h2DB
    

    所以当您使用 spring application starter 运行您的应用程序时,您将能够通过 http://localhost:8080/h2DB 登录到数据库来访问该应用程序,并且您可以验证数据库中是否有插入?

    如果在那里找不到数据,那么您就知道在哪里进行更改以将数据保留在那里。

    【讨论】:

    • 我之前尝试过控制台的事情,但再次尝试使用您建议的更新配置会给我同样的问题。每当我提交表单时,无论是测试还是尝试连接,都会显示控制台,但会收到“不支持 POST”。
    • 您必须在目标方法上添加 method=RequestType.POST 来处理请求。默认情况下,所有请求都被视为 GET 请求,您提交的表单将是 POST 请求
    • 如果我指的是我的控制器映射之一而不是 h2 控制台,那将是正确的
    猜你喜欢
    • 2021-08-12
    • 2019-01-12
    • 2021-06-12
    • 2020-08-23
    • 2020-05-21
    • 2019-06-12
    • 1970-01-01
    • 2020-12-25
    • 2021-02-26
    相关资源
    最近更新 更多