H2不在我的Spring Boot应用程序中创建/更新表。我的实体出了什么问题?

时间:2017-07-25 11:37:25

标签: java hibernate jpa spring-boot h2

我希望通过使用Hibernate制作CRUD存储库来保留H2数据库中的一些数据。

我无法通过数据库存储我的条目。目前,我试图通过制作样本条目来更新数据库期间实现这一目标。条目在日志中看起来很好,但不会创建/更新/生成表。

为什么Hibernate在这种情况下无法创建表?(如果问题出在我的数据结构中)

这是我的实体, Game.java 类(我已经尝试过没有@Column注释,没有区别.Id不是自动生成的,我需要能够每次都输入我自己的ID:

@Entity
@Table(name = "GAME")
public class Game {

    @Id
    @Column (name = "ID")
    private long id;

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

    @Column(name = "STORYLINE", length = 4000)
    private String storyline;

    @Column(name = "AGGREGATED_RATING")
    @JsonProperty("aggregated_rating")
    private double aggregatedRating;

    @Column(name = "FIRST_RELEASE_DATE")
    @JsonProperty("first_release_date")
    private long firstReleaseDate;

    @Embedded
    private Cover cover;

    public Game(){

    }

    public Game(long id, String name, String storyline, double aggregatedRating, long firstReleaseDate, Cover cover) {
        this.id = id;
        this.name = name;
        this.storyline = storyline;
        this.aggregatedRating = aggregatedRating;
        this.firstReleaseDate = firstReleaseDate;
        this.cover = cover;
    }

    public long getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public String getStoryline() {
        return storyline;
    }

    public double getAggregatedRating() {
        return aggregatedRating;
    }

    public long getFirstReleaseDate() {
        return firstReleaseDate;
    }

    public Cover getCover() {
        return cover;
    }


}

以及 Cover.java 类:

@Embeddable
public class Cover {

    @Column (name = "URL")
    private String url;
    @JsonProperty("cloudinary_id")
    @Column (name = "CLOUDINARY_ID")
    private String cloudinaryId;
    @Column (name = "WIDTH")
    private Integer width;
    @Column (name = "HEIGHT")
    private Integer height;

    public Cover(){
    }

    public Cover(String url, String cloudinaryId, Integer width, Integer height) {
        this.url = url;
        this.cloudinaryId = cloudinaryId;
        this.width = width;
        this.height = height;
}

    public String getUrl() {
        return url;
    }

    public String getCloudinaryId() {
        return cloudinaryId;
    }

    public Integer getWidth() {
        return width;
    }

    public Integer getHeight() {
        return height;
    }

}

我在 application.properties 文件中配置了H2数据库:

spring.h2.console.enabled=true
spring.h2.console.path=/h2_console
spring.datasource.url=jdbc:h2:mem:test;DB_CLOSE_DELAY=-1
spring.datasource.username=sa
spring.datasource.password=
spring.datasource.driverClassName=org.h2.Driver
spring.jpa.hibernate.ddl-auto = update
spring.jpa.show-sql=true
logging.level.org.hibernate.SQL=DEBUG
logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE

存储库的配置如下:

import org.springframework.data.repository.CrudRepository;

import java.util.List;

public interface GameRepository extends CrudRepository<Game, Long> {
    List<Game> findAllByName(String name);
}

我通过在localhost:8080 / test下测试我的存储库,其中应该将一个示例条目插入到表中:

@RequestMapping("/test")
public String saveSth(){
    gameRepository.save(new Game(127, "Assassin's Creed II", "The lineage continues as this new chapter introduces Ezio, inheritor of the talents and creed of the Assassins. His family murdered by rival families, Ezio resolves to learn the ancient art of the Assassin in order to seek revenge. He will not do so alone though, allying with historical figures such as philosopher and writer Niccolò Machiavelli. You will also be able to master the art of the assassin with all new weapons and instruments created by the renowned inventor and genius of the Renaissance, Leonardo Da Vinci himself.", 90.25, 1258416000000L, new Cover("//images.igdb.com/igdb/image/upload/t_thumb/doczeiofd1ckpapdhqs7.jpg", "doczeiofd1ckpapdhqs7", 1000, 1426)));
    return "success";
}

我得到以下日志:

2017-07-25 13:09:58.873 DEBUG 9442 --- [nio-8080-exec-1] org.hibernate.SQL                        : select game0_.id as id1_0_0_, game0_.aggregated_rating as aggregat2_0_0_, game0_.cloudinary_id as cloudina3_0_0_, game0_.height as height4_0_0_, game0_.url as url5_0_0_, game0_.width as width6_0_0_, game0_.first_release_date as first_re7_0_0_, game0_.name as name8_0_0_, game0_.storyline as storylin9_0_0_ from game game0_ where game0_.id=?
Hibernate: select game0_.id as id1_0_0_, game0_.aggregated_rating as aggregat2_0_0_, game0_.cloudinary_id as cloudina3_0_0_, game0_.height as height4_0_0_, game0_.url as url5_0_0_, game0_.width as width6_0_0_, game0_.first_release_date as first_re7_0_0_, game0_.name as name8_0_0_, game0_.storyline as storylin9_0_0_ from game game0_ where game0_.id=?
2017-07-25 13:09:58.875 TRACE 9442 --- [nio-8080-exec-1] o.h.type.descriptor.sql.BasicBinder      : binding parameter [1] as [BIGINT] - [127]
2017-07-25 13:09:58.894 DEBUG 9442 --- [nio-8080-exec-1] org.hibernate.SQL                        : insert into game (aggregated_rating, cloudinary_id, height, url, width, first_release_date, name, storyline, id) values (?, ?, ?, ?, ?, ?, ?, ?, ?)
Hibernate: insert into game (aggregated_rating, cloudinary_id, height, url, width, first_release_date, name, storyline, id) values (?, ?, ?, ?, ?, ?, ?, ?, ?)
2017-07-25 13:09:58.895 TRACE 9442 --- [nio-8080-exec-1] o.h.type.descriptor.sql.BasicBinder      : binding parameter [1] as [DOUBLE] - [90.25]
2017-07-25 13:09:58.896 TRACE 9442 --- [nio-8080-exec-1] o.h.type.descriptor.sql.BasicBinder      : binding parameter [2] as [VARCHAR] - [doczeiofd1ckpapdhqs7]
2017-07-25 13:09:58.896 TRACE 9442 --- [nio-8080-exec-1] o.h.type.descriptor.sql.BasicBinder      : binding parameter [3] as [INTEGER] - [1426]
2017-07-25 13:09:58.897 TRACE 9442 --- [nio-8080-exec-1] o.h.type.descriptor.sql.BasicBinder      : binding parameter [4] as [VARCHAR] - [//images.igdb.com/igdb/image/upload/t_thumb/doczeiofd1ckpapdhqs7.jpg]
2017-07-25 13:09:58.897 TRACE 9442 --- [nio-8080-exec-1] o.h.type.descriptor.sql.BasicBinder      : binding parameter [5] as [INTEGER] - [1000]
2017-07-25 13:09:58.897 TRACE 9442 --- [nio-8080-exec-1] o.h.type.descriptor.sql.BasicBinder      : binding parameter [6] as [BIGINT] - [1258416000000]
2017-07-25 13:09:58.897 TRACE 9442 --- [nio-8080-exec-1] o.h.type.descriptor.sql.BasicBinder      : binding parameter [7] as [VARCHAR] - [Assassin's Creed II]
2017-07-25 13:09:58.897 TRACE 9442 --- [nio-8080-exec-1] o.h.type.descriptor.sql.BasicBinder      : binding parameter [8] as [VARCHAR] - [The lineage continues as this new chapter introduces Ezio, inheritor of the talents and creed of the Assassins. His family murdered by rival families, Ezio resolves to learn the ancient art of the Assassin in order to seek revenge. He will not do so alone though, allying with historical figures such as philosopher and writer Niccolò Machiavelli. You will also be able to master the art of the assassin with all new weapons and instruments created by the renowned inventor and genius of the Renaissance, Leonardo Da Vinci himself.]
2017-07-25 13:09:58.897 TRACE 9442 --- [nio-8080-exec-1] o.h.type.descriptor.sql.BasicBinder      : binding parameter [9] as [BIGINT] - [127]

看起来数据绑定到参数,但在H2控制台 SELECT * FROM GAME 返回给我:      SELECT * FROM GAME;     表&#34;游戏&#34;未找到; SQL语句:     SELECT * FROM GAME [42102-193] 42S02 / 42102(帮助)

我尝试过其他H2模式,例如create-drop或create,但没有成功。令我担心的是,我甚至无法让数据库创建一个包含正确行的空表,准备好输入。

我认为我的实体或我的GameRepository配置中遗漏了一些错误,但我没有更多想法来修复此错误。

我想在这里实现目标: http://javasampleapproach.com/spring-framework/spring-boot/integrate-h2-database-springboot-spring-jpa-embedded-mode 和这里: http://www.simplecodestuffs.com/value-object-entity-object-in-hibernate-mapping/

另外,我已经尝试了这组教程进行更改: https://springframework.guru/using-the-h2-database-console-in-spring-boot-with-spring-security/ https://springframework.guru/spring-boot-web-application-part-3-spring-data-jpa/

但到目前为止没有运气。

6 个答案:

答案 0 :(得分:11)

只需转到H2控制台,例如:http://localhost:9090/h2-console/ 在JDBC URL字段中,输入 jdbc:h2:mem:testdb 以配置与RAM中的testdb数据库的连接。

答案 1 :(得分:9)

  

看起来数据绑定到参数,但在H2控制台中SELECT *   FROM GAME没有回复我。该表不存在。

您正在使用H2的in-memory实例:

spring.datasource.url=jdbc:h2:mem:test;DB_CLOSE_DELAY=-1

在此模式下,您无法从另一个客户端看到启动in-memory数据库的更改内容。
要查看其他客户端的更改,您必须使用TCP模式。

您有两种解决方案:

  • 使用文件来保存H2的实例。
  

存储的数据库文件在哪里?

     

使用jdbc:h2:〜/ test等数据库URL时,会存储数据库   在用户目录中。对于Windows,这通常是C:\ Documents and   设置\或C:\ Users \。如果是基目录   未设置(如在jdbc:h2:./ test中),数据库文件存储在   应用程序启动的目录(当前工作   目录)。从开始菜单使用H2控制台应用程序时,   这是/ bin。可以在中设置基目录   数据库URL。可以使用固定或相对路径。使用时   URL jdbc:h2:file:./ data / sample,数据库存储在   目录数据(相对于当前工作目录)。该   如果目录尚不存在,则会自动创建。它是   也可以使用完全限定的目录名称(和for   Windows,驱动器名称)。示例:jdbc:h2:file:C:/ data / test

  • 继续使用内存中的实例但使用TCP模式。

替换:

spring.datasource.url=jdbc:h2:mem:test;DB_CLOSE_DELAY=-1

by:

spring.datasource.url=jdbc:h2:tcp://localhost/~/test

一般情况下,我在JPA实体单元测试期间切换到此模式,我真的想知道哪些插入数据库。

来自the official documentation

  

内存数据库

     

对于某些用例(例如:快速原型设计,测试,高   性能操作,只读数据库),可能不需要   持久化数据,或持续更改数据。这个数据库   支持内存模式,数据不会持久存在。   ...

     

在某些情况下,只有一个与内存数据库的连接   需要。这意味着要打开的数据库是私有的。在这   case,数据库URL是jdbc:h2:mem:打开两个连接   同一个虚拟机意味着打开两个不同的(私有)   数据库。

     

有时与同一内存数据库有多个连接   需要。在这种情况下,数据库URL必须包含名称。例:   JDBC:H2:MEM:DB1。使用此URL访问同一数据库仅起作用   在同一个虚拟机和类加载器环境中。

     

从另一个进程或另一个进程访问内存数据库   在计算机上,你需要在与之相同的进程中启动TCP服务器   内存数据库已创建。然后需要其他过程   使用数据库URL通过TCP / IP或TLS访问数据库,例如:   JDBC:H 2:TCP://本地主机/ MEM:DB1

替代独立H2控制台:使用可从Spring Boot应用程序访问的H2控制台

确实H2数据库提供了基于浏览器的控制台Spring Boot can auto-configure for you。控制台在这些时间自动配置 条件得到满足:

  
      
  • 您正在开发基于servlet的Web应用程序。
  •   
  • com.h2database:h2在类路径上。
  •   
  • 您正在使用Spring Boot的开发人员工具。
  •   

所以这意味着只能在dev中访问。一般你想要什么。

默认情况下,控制台位于/h2-console 设置spring.h2.console.path属性以更改它。

答案 2 :(得分:2)

检查您的主类(Spring启动应用程序类)是否能够扫描定义的实体。当实体与主类的包不同时,通常会发生这种情况。

答案 3 :(得分:0)

将以下行放入:spring.jpa.hibernate.ddl-auto = update在application.properties文件中开始在内存数据库和H2数据库的基于文件的数据库中填充数据。希望这对任何人都有帮助。

答案 4 :(得分:0)

使用@EntityScan("com.db.jpasample.entity")

@SpringBootApplication
@EntityScan("com.db.jpasample.entity")
public class GsoftApplication {

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

}

application.properties

server.port = 9090
spring.h2.console.enabled=true
spring.datasource.platform=h2
spring.datasource.url=jdbc:h2:mem:socialdb;DB_CLOSE_DELAY=-1
spring.datasource.driverClassName=org.h2.Driver
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
spring.jpa.hibernate.ddl-auto = create

答案 5 :(得分:0)

application.properties 文件中,尝试使用 spring.jpa.defer-datasource-initialization=true