Guide de la bibliothèque de types Hibernate

1. Vue d'ensemble

Dans ce didacticiel, nous examinerons les types de mise en veille prolongée. Cette bibliothèque nous fournit quelques types qui ne sont pas natifs dans le noyau Hibernate ORM.

2. Dépendances

Pour activer les types d'hibernation, nous allons simplement ajouter la dépendance appropriée des types d'hibernate :

 com.vladmihalcea hibernate-types-52 2.9.7  

Cela fonctionnera avec les versions 5.4, ​​5.3 et 5.2 d'Hibernate .

Si la version d'Hibernate est plus ancienne, la valeur artifactId ci-dessus sera différente. Pour les versions 5.1 et 5.0, nous pouvons utiliser hibernate-types-51. De même, la version 4.3 nécessite hibernate-types-43, et les versions 4.2 et 4.1 nécessitent hibernate-types-4.

Les exemples de ce didacticiel nécessitent une base de données. En utilisant Docker, nous avons fourni un conteneur de base de données. Par conséquent, nous aurons besoin d'une copie de travail de Docker.

Donc, pour exécuter et créer notre base de données, il suffit d'exécuter:

$ ./create-database.sh

3. Bases de données prises en charge

Nous pouvons utiliser nos types avec les bases de données Oracle, SQL Server, PostgreSQL et MySQL. Par conséquent, le mappage des types en Java aux types de colonnes de base de données varie en fonction de la base de données que nous utilisons. Dans notre cas, nous utiliserons MySQL et mapperons le JsonBinaryType à un type de colonne JSON.

La documentation sur les mappages pris en charge peut être trouvée sur le référentiel Hibernate Types.

4. Modèle de données

Le modèle de données de ce didacticiel nous permettra de stocker des informations sur les albums et les chansons. Un album a une pochette et une ou plusieurs chansons. Une chanson a un artiste et une durée. La pochette comprend deux URL d'image et un code UPC. Enfin, un artiste a un nom, un pays et un genre musical.

Dans le passé, nous aurions créé des tableaux pour représenter toutes les données de notre modèle. Mais, maintenant que nous avons des types à notre disposition, nous pouvons très facilement stocker certaines des données au format JSON.

Pour ce tutoriel, nous créerons uniquement des tableaux pour les albums et les chansons:

public class Album extends BaseEntity { @Type(type = "json") @Column(columnDefinition = "json") private CoverArt coverArt; @OneToMany(fetch = FetchType.EAGER) private List songs; // other class members }
public class Song extends BaseEntity { private Long length = 0L; @Type(type = "json") @Column(columnDefinition = "json") private Artist artist; // other class members }

En utilisant le JsonStringType, nous représenterons la pochette et les artistes sous forme de colonnes JSON dans ces tableaux:

public class Artist implements Serializable { private String name; private String country; private String genre; // other class members }
public class CoverArt implements Serializable { private String frontCoverArtUrl; private String backCoverArtUrl; private String upcCode; // other class members }

Il est important de noter que les classes Artist et CoverArt sont des POJO et non des entités. De plus, ils sont membres de nos classes d'entités de base de données, définies avec l' annotation @Type (type = «json») .

4.1. Stockage des types JSON

Nous avons défini nos modèles d'albums et de chansons pour contenir des membres que la base de données stockera au format JSON. Cela est dû à l'utilisation du type json fourni . Afin d'avoir ce type à notre disposition, nous devons le définir à l'aide d'une définition de type:

@TypeDefs({ @TypeDef(name = "json", typeClass = JsonStringType.class), @TypeDef(name = "jsonb", typeClass = JsonBinaryType.class) }) public class BaseEntity { // class members }

Le @Type pour JsonStringType et JsonBinaryType rend les types json et jsonb disponibles.

Les dernières versions de MySQL prennent en charge JSON en tant que type de colonne. Par conséquent, JDBC traite toute lecture JSON depuis ou tout objet enregistré dans une colonne avec l'un de ces types en tant que chaîne . Cela signifie que pour mapper correctement à la colonne, nous devons utiliser JsonStringType dans notre définition de type.

4.2. Hiberner

En fin de compte, nos types se traduiront automatiquement en SQL en utilisant JDBC et Hibernate. Ainsi, nous pouvons maintenant créer quelques objets de chanson, un objet d'album et les conserver dans la base de données. Par la suite, Hibernate génère les instructions SQL suivantes:

insert into song (name, artist, length, id) values ('A Happy Song', '{"name":"Superstar","country":"England","genre":"Pop"}', 240, 3); insert into song (name, artist, length, id) values ('A Sad Song', '{"name":"Superstar","country":"England","genre":"Pop"}', 120, 4); insert into song (name, artist, length, id) values ('A New Song', '{"name":"Newcomer","country":"Jamaica","genre":"Reggae"}', 300, 6) insert into album (name, cover_art, id) values ('Album 0', '{"frontCoverArtUrl":"//fakeurl-0","backCoverArtUrl":"//fakeurl-1","upcCode":"b2b9b193-ee04-4cdc-be8f-3a276769ab5b"}', 7) 

Comme prévu, nos objets Java de type json sont tous traduits par Hibernate et stockés sous forme de JSON bien formé dans notre base de données.

5. Stockage des types génériques

Outre la prise en charge des colonnes basées sur JSON, la bibliothèque ajoute également quelques types génériques: YearMonth , Year et Month du package java.time .

Maintenant, nous pouvons mapper ces types qui ne sont pas pris en charge nativement par Hibernate ou JPA . De plus, nous avons maintenant la possibilité de les stocker sous forme de colonne Integer , String ou Date .

Par exemple, disons que nous voulons ajouter la date d'enregistrement d'une chanson à notre modèle de chanson et la stocker en tant qu'Integer dans notre base de données. Nous pouvons utiliser YearMonthIntegerType dans notre définition de classe d'entité Song :

@TypeDef( typeClass = YearMonthIntegerType.class, defaultForType = YearMonth.class ) public class Song extends BaseEntity { @Column( name = "recorded_on", columnDefinition = "mediumint" ) private YearMonth recordedOn = YearMonth.now(); // other class members } 

Notre recordedOn valeur de la propriété est traduit à la classe de types nous avons fourni. En conséquence, un convertisseur prédéfini conservera la valeur dans notre base de données sous la forme d'un entier .

6. Autres classes d'utilité

Hibernate Types a quelques classes d'assistance qui améliorent encore l'expérience des développeurs lors de l'utilisation d'Hibernate.

La CamelCaseToSnakeCaseNamingStrategy mappe les propriétés camel-cased dans nos classes Java aux colonnes snake-cased dans notre base de données.

Le ClassImportIntegrator permet des valeurs de nom de classe simple Java DTO dans les paramètres du constructeur JPA.

Il existe également les classes ListResultTransformer et MapResultTransformer qui fournissent des implémentations plus propres des objets de résultat utilisés par JPA. En outre, ils prennent en charge l'utilisation de lambdas et offrent une compatibilité descendante avec les anciennes versions de JPA.

7. Conclusion

Dans ce didacticiel, nous avons présenté la bibliothèque Java Hibernate Types et les nouveaux types qu'elle ajoute à Hibernate et JPA. Nous avons également examiné certains des utilitaires et types génériques fournis par la bibliothèque.

L'implémentation des exemples et des extraits de code est disponible à l'adresse over sur GitHub.