programing

H2가 내 Spring Boot 앱에서 테이블을 생성/업데이트하지 않습니다.내 엔티티에 문제가 있나요?

yellowcard 2023. 6. 24. 08:57
반응형

H2가 내 Spring Boot 앱에서 테이블을 생성/업데이트하지 않습니다.내 엔티티에 문제가 있나요?

H2 데이터베이스에서 Hibernate를 사용하여 CRUD 저장소를 만들어 데이터를 보관하고 싶습니다.

항목을 저장할 데이터베이스를 가져올 수 없습니다.현재 db 업데이트 중에 샘플 항목을 만들어 그것을 달성하려고 노력하고 있습니다.로그에서 항목이 올바르게 표시되지만 테이블이 생성/업데이트/생성되지 않습니다.

이 경우 최대 절전 모드에서 테이블을 만들 수 없는 이유는 무엇입니까?(내 데이터의 구조에 문제가 있는 경우)

여기 제 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;
    }


}

다음은 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, 테이블 "GAME"을 찾을 수 없습니다. SQL 문: SELECT * FROM GAME [42102-193] 42S02/42102 (도움말)

저는 create-drop이나 create 같은 다른 H2 모드를 시도해봤지만 성공하지 못했습니다.제가 걱정하는 것은 데이터베이스가 입력할 준비가 된 올바른 행으로 빈 테이블을 만들 수 없다는 것입니다.

엔티티에 문제가 있거나 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/s/spring-boot-web-application-part-data-jpa/

하지만 아직까지는 운이 없습니다.

H2 콘솔(예: http://localhost:9090/h2-console/)로 이동하고 JDBC URL 필드에 jdbc:h2:mem:testdb를 입력하여 RAM의 testdb 데이터베이스에 대한 연결을 구성합니다.

데이터가 매개 변수에 바인딩된 것처럼 보이지만 H2 콘솔에서 SELECT * FROM GAME은 아무것도 반환하지 않습니다.테이블이 존재하지 않습니다.

다음을 사용하고 있습니다.in-memoryH2 :

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

이 모드에서는 다른 클라이언트에서 변경된 내용을 볼 수 없습니다. 이 변경 내용은 다음 클라이언트에서 시작된 변경 내용입니다.in-memory데이터베이스
다른 클라이언트의 변경 내용을 보려면 TCP 모드를 사용해야 합니다.

두 가지 솔루션이 있습니다.

  • 파일을 사용하여 H2 인스턴스를 유지합니다.

데이터베이스 파일은 어디에 저장됩니까?

jdbc:h2:~/test와 같은 데이터베이스 URL을 사용하는 경우 데이터베이스는 사용자 디렉토리에 저장됩니다.Windows의 경우 일반적으로 C:\Documents and Settings\ 또는 C:\사용자\.기본 디렉토리가 설정되지 않은 경우(jdbc:h2:/.test에서처럼), 데이터베이스 파일은 응용프로그램이 시작되는 디렉토리(현재 작업 디렉토리)에 저장됩니다.시작 메뉴에서 H2 Console 응용 프로그램을 사용하는 경우 /bin입니다.데이터베이스 URL에서 기본 디렉토리를 설정할 수 있습니다.고정 경로 또는 상대 경로를 사용할 수 있습니다.URL jdbc:h2:file:/.data/sample을 사용하는 경우 데이터베이스는 디렉토리 데이터(현재 작업 디렉토리를 기준으로 함)에 저장됩니다.디렉토리가 아직 존재하지 않는 경우 자동으로 작성됩니다.정규화된 디렉터리 이름(및 윈도우즈의 경우 드라이브 이름)을 사용할 수도 있습니다.예: jdbc:h2:file:C:/data/test

  • 메모리 내 인스턴스를 사용하도록 유지하지만 TCP 모드를 사용합니다.

바꾸기:

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

기준:

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

일반적으로 데이터베이스에 삽입된 것이 무엇인지 정말 알고 싶을 때 JPA 엔티티 유닛 테스트 중에 이 모드로 전환합니다.

공식 문서에서:

인메모리 데이터베이스

특정 사용 사례(예: 신속한 프로토타이핑, 테스트, 고성능 운영, 읽기 전용 데이터베이스)의 경우 데이터를 유지하거나 데이터를 지속적으로 변경할 필요가 없을 수 있습니다.이 데이터베이스는 데이터가 지속되지 않는 메모리 내 모드를 지원합니다. ...

경우에 따라 메모리 내 데이터베이스에 대한 연결이 하나만 필요합니다.이것은 열려 있는 데이터베이스가 비공개라는 것을 의미합니다.이 경우 데이터베이스 URL은 jdbc:h2:mem입니다.동일한 가상 시스템 내에서 두 개의 연결을 여는 것은 두 개의 서로 다른(개인) 데이터베이스를 여는 것을 의미합니다.

때때로 동일한 메모리 내 데이터베이스에 대한 여러 연결이 필요합니다.이 경우 데이터베이스 URL에 이름이 포함되어야 합니다.예: jdbc:h2:mem:db1.이 URL을 사용하여 동일한 데이터베이스에 액세스하는 것은 동일한 가상 시스템 및 클래스 로더 환경 내에서만 작동합니다.

다른 프로세스 또는 다른 시스템에서 메모리 내 데이터베이스에 액세스하려면 메모리 내 데이터베이스가 생성된 것과 동일한 프로세스에서 TCP 서버를 시작해야 합니다.그런 다음 다른 프로세스는 다음과 같은 데이터베이스 URL(예: jdbc:h2:tcp://localhost/mem:db1)을 사용하여 TCP/IP 또는 TLS를 통해 데이터베이스에 액세스해야 합니다.


독립 실행형 H2 콘솔의 대안: Spring Boot 응용 프로그램에서 액세스할 수 있는 H2 콘솔 사용

실제로 H2 데이터베이스는 Spring Boot이 자동으로 구성할 수 있는 브라우저 기반 콘솔을 제공합니다.다음 조건이 충족되면 콘솔이 자동으로 구성됩니다.

  • 서블릿 기반 웹 응용프로그램을 개발하고 있습니다.
  • com.h2px:h2가 클래스 경로에 있습니다.
  • Spring Boot의 개발자 도구를 사용하고 있습니다.

그래서 그것은 오직 dev에서만 접근할 수 있다는 것을 의미합니다.당신이 일반적으로 원하는 것.

기본적으로 콘솔은 다음 위치에서 사용할 수 있습니다./h2-console.
을 합니다.spring.h2.console.path그것을 바꿀 재산.

행을 합니다: 다음행입력:spring.jpa.hibernate.ddl-auto = update및 H2 application.properties 파일 를 시작합니다.이것이 누구에게 도움이 되기를 바랍니다.

메인 클래스(Spring boot application class)가 정의된 엔티티를 검색할 수 있는지 확인합니다.일반적으로 엔티티가 기본 클래스의 엔티티와 다른 패키지에 있을 때 이 문제가 발생합니다.

사용하다@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

SQL Script용 데이터 원본 초기화 기능은 Spring Boot 2.5에서 재설계되었습니다.


기본적으로 데이터입니다.이제 최대 절전 모드가 초기화되기 전에 sql 스크립트가 실행됩니다.이것은 기본 스크립트 기반 초기화 동작을 Flyway 및 Liquibase 동작과 일치시킵니다.데이터를 사용하고자 하는 경우.sql을 사용하여 Hibernate에서 만든 스키마를 채우려면 spring.jpa.defer-data source-initialization을 true로 설정합니다.데이터베이스 초기화 기술을 혼합하는 것은 권장되지 않지만 스키마를 사용할 수도 있습니다.sql 스크립트는 data.sql을 통해 채워지기 전에 Hibernate에서 생성된 스키마를 기반으로 합니다.

참조:

Spring Boot 2.5 릴리스 정보

에서application.properties파일, 사용해 보십시오.spring.jpa.defer-datasource-initialization=true.

제가 직면한 동일한 문제를 해결하기 위해 아래에 변경 사항을 추가했습니다.

저는 pom.xml의 H2 종속성에 대한 아래 버전을 추가했습니다.

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

그리고 application.properties 파일에 아래 구성을 추가했습니다.

spring.h2.console.enabled=true
spring.datasource.platform=h2
spring.datasource.driverClassName = org.h2.Driver
spring.datasource.url=jdbc:h2:file:~/test;
spring.datasource.username=sa
spring.datasource.password=

ddl 스크립트 누락

나도 마찬가지였지만 ddl 부분을 추가하지 않은 것 같았습니다.

spring.h2.console.enabled=true
spring.datasource.url=jdbc:h2:~/test
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=   //empty as i didnt has password in h2
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
spring.jpa.hibernate.ddl-auto = create //add this to create table first time then use 'update'

데이터를 로드하고 동일한 JVM 세션 내의 모든 작업을 호출하는 경우 메모리 내 H2 인스턴스와 함께 작동합니다.

이것은 연결 장치의 설계와 많은 관련이 있습니다.

다음 두 가지를 모두 확인하십시오.

  • 연결을 설정하기 위한 URL
  • hibernate.hbm2dl 매개 변수를 잘 선택하여 스키마 DDL을 데이터베이스로 내보냅니다.자동의

이 두 가지 매개 변수에 대해 작업을 수행해야 합니다. 시간이 좀 걸릴 수 있습니다.

in memory db에 대한 추가 옵션.

언급URL : https://stackoverflow.com/questions/45302132/h2-not-creating-updating-table-in-my-spring-boot-app-somethings-wrong-with-my

반응형