Java H2 不在我的 Spring Boot 应用程序中创建/更新表。我的实体有问题吗?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/45302132/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
H2 not creating/updating table in my Spring Boot app. Something's wrong with my Entity?
提问by VapeKop
I want to keep some data in H2 database by making a CRUD repository, using Hibernate.
我想通过使用 Hibernate 创建一个 CRUD 存储库来在 H2 数据库中保留一些数据。
I can't get the database to store my entries whatsoever. Currently, I'm trying to achieve that during updating the db by making a sample entry. Entry is looking good in the logs, but table is not created/updated/generated.
我无法让数据库存储我的条目。目前,我正在尝试通过创建示例条目在更新数据库期间实现这一目标。日志中的条目看起来不错,但未创建/更新/生成表。
Why Hibernate is not unable to create a table in this case?(if the problem lies in structure of my data)
为什么 Hibernate 在这种情况下不能创建表?(如果问题出在我的数据结构上)
Here's my Entity, Game.javaclass (I've tried without @Column annotations, no difference. Id is not auto-generated, I need to be able to enter my own ID everytime):
这是我的 Entity, 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;
}
}
And here's Cover.javaclass:
这是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;
}
}
I configured H2 database here, in application.propertiesfile:
我在这里配置了 H2 数据库,在application.properties文件中:
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
Repositoryis configured like this:
存储库配置如下:
import org.springframework.data.repository.CrudRepository;
import java.util.List;
public interface GameRepository extends CrudRepository<Game, Long> {
List<Game> findAllByName(String name);
}
I test my repository by going under localhost:8080/test, where a sample entry should be inserted into table:
我通过在 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";
}
I get the following log:
我得到以下日志:
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]
It looks like data is binded to parameters, but in H2 console SELECT * FROM GAMEreturns me: SELECT * FROM GAME; Table "GAME" not found; SQL statement: SELECT * FROM GAME [42102-193] 42S02/42102 (Help)
看起来数据绑定到参数,但在 H2 控制台SELECT * FROM GAME返回我:SELECT * FROM GAME; 未找到表“GAME”;SQL 语句:SELECT * FROM GAME [42102-193] 42S02/42102(帮助)
I've tried other H2 modes such as create-drop or create, but no success. What worries me is that, I can't even get the database to create an empty table with the correct rows, ready for entries.
我尝试过其他 H2 模式,例如 create-drop 或 create,但没有成功。让我担心的是,我什至无法让数据库创建一个包含正确行的空表,准备好输入。
I think that something's wrong either with my Entity or missing from my GameRepository configuration, but I have no more ideas to fix this error.
我认为我的实体有问题或我的 GameRepository 配置有问题,但我没有更多的想法来解决这个错误。
I want to achieve what's here: http://javasampleapproach.com/spring-framework/spring-boot/integrate-h2-database-springboot-spring-jpa-embedded-modeAnd here: http://www.simplecodestuffs.com/value-object-entity-object-in-hibernate-mapping/
我想实现这里的内容: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/
Also, I've tried this set of tutorials for a change: 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/
另外,我已经试过这一套教程一变: https://springframework.guru/using-the-h2-database-console-in-spring-boot-with-spring-security/ https://开头springframework的。大师/spring-boot-web-application-part-3-spring-data-jpa/
But no luck so far.
但到目前为止没有运气。
采纳答案by davidxxx
It looks like data is binded to parameters, but in H2 console SELECT * FROM GAME returns me nothing. The table doesn't exist.
看起来数据绑定到参数,但在 H2 控制台中 SELECT * FROM GAME 没有返回任何内容。该表不存在。
You are using an in-memory
instance of H2 :
您正在使用in-memory
H2 的一个实例:
spring.datasource.url=jdbc:h2:mem:test;DB_CLOSE_DELAY=-1
In this mode, you cannot see the content of the changes from another client that which one that started the in-memory
database.
To see the changes from other clients, you have to use the TCP mode.
在这种模式下,您无法看到来自另一个客户端的更改内容,而不是启动in-memory
数据库的那个客户端 。
要查看其他客户端的更改,您必须使用 TCP 模式。
You have two solutions :
您有两种解决方案:
- using a file to persist the instance of H2.
- 使用文件来持久化 H2 的实例。
Where are the Database Files Stored?
When using database URLs like jdbc:h2:~/test, the database is stored in the user directory. For Windows, this is usually C:\Documents and Settings\ or C:\Users\. If the base directory is not set (as in jdbc:h2:./test), the database files are stored in the directory where the application is started (the current working directory). When using the H2 Console application from the start menu, this is /bin. The base directory can be set in the database URL. A fixed or relative path can be used. When using the URL jdbc:h2:file:./data/sample, the database is stored in the directory data (relative to the current working directory). The directory is created automatically if it does not yet exist. It is also possible to use the fully qualified directory name (and for Windows, drive name). Example: jdbc:h2:file:C:/data/test
数据库文件存储在哪里?
使用 jdbc:h2:~/test 等数据库 URL 时,数据库存储在用户目录中。对于 Windows,这通常是 C:\Documents and Settings\ 或 C:\Users\。如果未设置基本目录(如 jdbc:h2:./test),则数据库文件存储在应用程序启动的目录(当前工作目录)中。从开始菜单使用 H2 控制台应用程序时,这是 /bin。可以在数据库 URL 中设置基本目录。可以使用固定或相对路径。当使用 URL jdbc:h2:file:./data/sample 时,数据库存储在目录 data 中(相对于当前工作目录)。如果目录尚不存在,则会自动创建该目录。也可以使用完全限定的目录名称(对于 Windows,驱动器名称)。示例:jdbc:h2:file:C:/data/test
- keeping to use an in-memory instance but using the TCP mode.
- 继续使用内存实例,但使用 TCP 模式。
Replace :
代替 :
spring.datasource.url=jdbc:h2:mem:test;DB_CLOSE_DELAY=-1
by :
经过 :
spring.datasource.url=jdbc:h2:tcp://localhost/~/test
Generally, I switch to this mode during JPA entity unit testing when I really want to know which was inserted in the database.
一般在JPA实体单元测试期间,当我真的想知道哪个插入到数据库中时,我会切换到这种模式。
From the official documentation:
从官方文档:
In-Memory Databases
For certain use cases (for example: rapid prototyping, testing, high performance operations, read-only databases), it may not be required to persist data, or persist changes to the data. This database supports the in-memory mode, where the data is not persisted. ...
In some cases, only one connection to a in-memory database is required. This means the database to be opened is private. In this case, the database URL is jdbc:h2:mem: Opening two connections within the same virtual machine means opening two different (private) databases.
Sometimes multiple connections to the same in-memory database are required. In this case, the database URL must include a name. Example: jdbc:h2:mem:db1. Accessing the same database using this URL only works within the same virtual machine and class loader environment.
To access an in-memory database from another process or from another computer, you need to start a TCP server in the same process as the in-memory database was created. The other processes then need to access the database over TCP/IP or TLS, using a database URL such as: jdbc:h2:tcp://localhost/mem:db1.
内存数据库
对于某些用例(例如:快速原型设计、测试、高性能操作、只读数据库),可能不需要持久化数据或持久化对数据的更改。该数据库支持内存模式,其中数据不持久化。...
在某些情况下,只需要一个到内存数据库的连接。这意味着要打开的数据库是私有的。在这种情况下,数据库 URL 是 jdbc:h2:mem:在同一虚拟机内打开两个连接意味着打开两个不同的(私有)数据库。
有时需要多个连接到同一个内存数据库。在这种情况下,数据库 URL 必须包含名称。示例:jdbc:h2:mem:db1。使用此 URL 访问相同的数据库仅适用于相同的虚拟机和类加载器环境。
要从另一个进程或另一台计算机访问内存数据库,您需要在创建内存数据库的同一进程中启动 TCP 服务器。然后其他进程需要通过 TCP/IP 或 TLS 访问数据库,使用数据库 URL,例如:jdbc:h2:tcp://localhost/mem:db1。
Alternative to standalone H2 Console : using the H2 console accessible from the Spring Boot application
独立 H2 控制台的替代方案:使用可从 Spring Boot 应用程序访问的 H2 控制台
Indeed the H2 database provides a browser-based console that Spring Boot can auto-configure for you. The console is auto-configured when these conditions are met :
事实上,H2 数据库提供了一个基于浏览器的控制台,Spring Boot 可以为你自动配置。当满足这些条件时,控制台会自动配置:
- You are developing a servlet-based web application.
- com.h2database:h2 is on the classpath.
- You are using Spring Boot's developer tools.
- 您正在开发基于 servlet 的 Web 应用程序。
- com.h2database:h2 在类路径上。
- 您正在使用 Spring Boot 的开发人员工具。
So it means that will be accessible only in dev. What generally you want.
所以这意味着只能在开发中访问。一般你想要什么。
By default, the console is available at /h2-console
.
Set the spring.h2.console.path
property to change that.
默认情况下,控制台位于/h2-console
。
设置spring.h2.console.path
属性来改变它。
回答by Ashlin Karkada
Check if you main class(Spring boot application class) is able to scan the entities defined. This usually happens when the entities are in a different package than that of the main class.
检查您的主类(Spring Boot 应用程序类)是否能够扫描定义的实体。当实体位于与主类不同的包中时,通常会发生这种情况。
回答by Dev M
Just go to the H2 console for example at: http://localhost:9090/h2-console/and In the JDBC URL field, type jdbc:h2:mem:testdbto configure the connection to the testdb database in RAM.
只需转到 H2 控制台,例如:http://localhost:9090/h2-console/并在 JDBC URL 字段中,键入jdbc:h2:mem:testdb以配置到 RAM 中 testdb 数据库的连接。
回答by Avinash Pratap Singh
Putting this line: spring.jpa.hibernate.ddl-auto = update
in your application.properties file start population data in in-memory database and in file based database for H2 data-base.Hope this helps anyone.
放置这一行:spring.jpa.hibernate.ddl-auto = update
在您的 application.properties 文件中,在内存数据库和基于文件的数据库中为 H2 数据库启动人口数据。希望这对任何人都有帮助。
回答by Ganesh Gope
use @EntityScan("com.db.jpasample.entity")
用 @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