web-dev-qa-db-fra.com

H2 ne crée pas / ne met pas à jour la table dans mon application Spring Boot. Quelque chose ne va pas avec mon entité?

Je souhaite conserver certaines données dans la base de données H2 en créant un référentiel CRUD, en utilisant Hibernate.

Je n'arrive pas à obtenir la base de données pour stocker mes entrées que ce soit. Actuellement, j'essaie d'y parvenir lors de la mise à jour de la base de données en créant un exemple d'entrée. L'entrée semble bonne dans les journaux, mais la table n'est pas créée/mise à jour/générée.

Pourquoi Hibernate n'est pas en mesure de créer une table dans ce cas? (si le problème réside dans la structure de mes données)

Voici mon entité, classe Game.Java (j'ai essayé sans annotations @Column, aucune différence. L'ID n'est pas généré automatiquement, je dois être en mesure d'entrer mon propre ID à chaque fois):

@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;
    }


}

Et voici la classe 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;
    }

}

J'ai configuré la base de données H2 ici, dans le fichier 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

Le référentiel est configuré comme ceci:

import org.springframework.data.repository.CrudRepository;

import Java.util.List;

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

Je teste mon référentiel en allant sous localhost: 8080/test, où un exemple d'entrée doit être inséré dans le tableau:

@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";
}

J'obtiens le journal suivant:

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]

Il semble que les données soient liées aux paramètres, mais dans la console H2 SELECT * FROM GAME me renvoie: SELECT * FROM GAME; Table "GAME" introuvable; Instruction SQL: SELECT * FROM GAME [42102-193] 42S02/42102 (Aide)

J'ai essayé d'autres modes H2 tels que create-drop ou create, mais sans succès. Ce qui m'inquiète, c'est que je ne peux même pas obtenir la base de données pour créer une table vide avec les lignes correctes, prête pour les entrées.

Je pense que quelque chose ne va pas avec mon entité ou manque dans ma configuration GameRepository, mais je n'ai plus d'idées pour corriger cette erreur.

Je veux réaliser ce qui est ici: http://javasampleapproach.com/spring-framework/spring-boot/integrate-h2-database-springboot-spring-jpa-embedded-mode Et ici: - http://www.simplecodestuffs.com/value-object-entity-object-in-hibernate-mapping/

En outre, j'ai essayé cet ensemble de didacticiels pour un changement: 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/

Mais pas de chance pour l'instant.

8
VapeKop

Il semble que les données soient liées aux paramètres, mais dans la console H2, SELECT * FROM GAME ne me renvoie rien. La table n'existe pas.

Vous utilisez un in-memory instance de H2:

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

Dans ce mode, vous ne pouvez pas voir le contenu des modifications d'un autre client que celui qui a démarré le in-memory base de données.
Pour voir les changements des autres clients, vous devez utiliser le mode TCP.

Vous avez deux solutions:

  • en utilisant un fichier pour conserver l'instance de H2.

Où sont stockés les fichiers de base de données?

Lorsque vous utilisez des URL de base de données comme jdbc: h2: ~/test, la base de données est stockée dans le répertoire utilisateur. Pour Windows, il s'agit généralement de C:\Documents and Settings\ou C:\Users \. Si le répertoire de base n'est pas défini (comme dans jdbc: h2: ./ test), les fichiers de base de données sont stockés dans le répertoire où l'application est lancée (le répertoire de travail en cours). Lorsque vous utilisez l'application H2 Console dans le menu Démarrer, il s'agit de/bin. Le répertoire de base peut être défini dans l'URL de la base de données. Un chemin fixe ou relatif peut être utilisé. Lorsque vous utilisez l'URL jdbc: h2: fichier: ./données/échantillon, la base de données est stockée dans les données du répertoire (par rapport au répertoire de travail actuel). Le répertoire est créé automatiquement s'il n'existe pas encore. Il est également possible d'utiliser le nom de répertoire complet (et pour Windows, le nom du lecteur). Exemple: jdbc: h2: fichier: C:/data/test

  • en gardant d'utiliser une instance en mémoire mais en utilisant le mode TCP.

Remplacez:

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

par :

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

Généralement, je passe à ce mode pendant les tests unitaires d'entité JPA lorsque je veux vraiment savoir ce qui a été inséré dans la base de données.

De la documentation officielle :

Bases de données en mémoire

Pour certains cas d'utilisation (par exemple: prototypage rapide, tests, opérations hautes performances, bases de données en lecture seule), il peut ne pas être nécessaire de conserver les données ou de conserver les modifications apportées aux données. Cette base de données prend en charge le mode en mémoire, où les données ne sont pas conservées. ...

Dans certains cas, une seule connexion à une base de données en mémoire est requise. Cela signifie que la base de données à ouvrir est privée. Dans ce cas, l'URL de la base de données est jdbc: h2: mem: l'ouverture de deux connexions au sein de la même machine virtuelle signifie l'ouverture de deux bases de données (privées) différentes.

Parfois, plusieurs connexions à la même base de données en mémoire sont requises. Dans ce cas, l'URL de la base de données doit inclure un nom. Exemple: jdbc: h2: mem: db1. L'accès à la même base de données à l'aide de cette URL ne fonctionne que dans le même environnement de machine virtuelle et de chargeur de classe.

Pour accéder à une base de données en mémoire à partir d'un autre processus ou d'un autre ordinateur, vous devez démarrer un serveur TCP dans le même processus que la base de données en mémoire Les autres processus doivent ensuite accéder à la base de données via TCP/IP ou TLS, à l'aide d'une URL de base de données telle que: jdbc: h2: tcp: // localhost/mem: db1.


Alternative à la console H2 autonome: en utilisant la console H2 accessible depuis l'application Spring Boot

En effet, la base de données H2 fournit une console basée sur un navigateur qui Spring Boot peut se configurer automatiquement pour vous . La console est configurée automatiquement lorsque ces conditions sont remplies:

  • Vous développez une application Web basée sur servlet.
  • com.h2database: h2 est sur le chemin de classe.
  • Vous utilisez les outils de développement de Spring Boot.

Cela signifie donc que sera accessible uniquement en dev. Ce que vous voulez en général.

Par défaut, la console est disponible sur /h2-console.
Met le spring.h2.console.path propriété pour changer cela.

12
davidxxx

Accédez simplement à la console H2 par exemple à: http: // localhost: 9090/h2-console / et dans le champ URL JDBC, saisissez jdbc: h2: mem: testdb pour configurer la connexion à la base de données testdb en RAM.

17
Dev M

Vérifiez si votre classe principale (classe d'application Spring Boot) est capable d'analyser les entités définies. Cela se produit généralement lorsque les entités sont dans un package différent de celui de la classe principale.

3
Ashlin Karkada