[JAVA] Générez un numéro de série avec TableGenerator of Hibernate (JPA) et stockez-le dans l'ID de String.

introduction

Lors de la persistance d'une entité Hibernate, je souhaite utiliser l'annotation @GeneratedValue pour le champ annoté @Id et la définir dans une colonne CHAR.

Cependant, en raison des spécifications du micrologiciel d'entreprise adopté, il existe une table d'acquisition du numéro de série de séquence distincte (sequence_mng) au lieu de SEQUENCE of DBMS (SQL Server), et sequence_mng n'est pas utilisé pour maintenir la cohérence lors de la création d'un nouvel enregistrement. Cela ne doit pas être.

La colonne doit aussi être BIGINT! Je pense, mais cela ne peut pas être aidé parce qu'il y a quelque chose comme la croyance "zéro remplissage et chiffre fixe".

Conditions préalables

Environnement d'exécution

・ JDK1.8 ・ Hibernation (5.2.10.FINAL) · SQL Server 2016

Tableau de gestion des séquences

sequence_mng


CREATE TABLE sequence_mng (
	colname VARCHAR(40) NOT NULL,
	nextvalue BIGINT NOT NULL,
	PRIMARY KEY colname
);

Tableau des cibles d'octroi de séquence

partner


CREATE TABLE m_partner (
	partner_cd CHAR(6) NOT NULL,
	partner_nm NVARCHAR(60) NOT NULL,
        -- OMITTED
        PRIMARY KEY partner_cd
);

Comme ça, quand vous essayez de le rendre permanent en appelant save () etc. -Obtenir un enregistrement où le colname de sequence_mng est "partner_cd" -Magasiner la valeur suivante dans partnerCd de Partner.class ・ Valeur suivante ++ Je veux le faire fonctionner basé sur l'annotation.

Essai du générateur de table

Et avec ce modèle, j'ai l'impression de pouvoir utiliser GenerationType.TABLE. juste comme ça

Partner.java(Failure)


@Entity
@Table(name = "partner")
public class Partner {

    @Id
    @GeneratedValue(strategy = GenerationType.TABLE, generator = "SEQ_TBL_PARTNER")
    @TableGenerator(name = "SEQ_TBL_PARTNER", 
      table = "sequence_mng",
      pkColumnName = "colname",
      valueColumnName = "nextvalue",
      pkColumnValue = "partner_cd")
    @Column(name = "partner_cd", unique = true, nullable = false, length = 6)
    private Integer partnerCd;

    @Column(name = "partner_nm", nullable = false)
    private String partnerNm;
//Ce qui suit est omis
}

Cependant, la substance de @TableGenerator org.hibernate.id.enhanced.TableGenerator En fait avec 'org.hibernate.id.IdentifierGeneratorHelper # getIntegralDataTypeHolder' Le champ @Id ne permet pas sauf long (Long), BigDecimal IdentifierGenerationException("Unknown integral data type for ids : StringType()) Il ne bouge pas à côté. Comme mentionné ci-dessus, les attributs de colonne ne peuvent pas être modifiés.

Personnaliser

Par conséquent, je vais créer un StringTableGenerator qui hérite de TableGenerator et le faire fonctionner. StringTableGenerator.java Créez un StringTableGenerator qui hérite de TableGenerator.

StringTableGenerator.java


package sample.hibernate.id;

import org.hibernate.MappingException;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.id.IdentifierGeneratorHelper;
import org.hibernate.id.IntegralDataTypeHolder;
import org.hibernate.id.enhanced.TableGenerator;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.type.BigDecimalType;
import org.hibernate.type.Type;

import java.io.Serializable;
import java.util.Properties;

/**
 * TableGenerator (Prise en charge des colonnes de chaînes de caractères)
 */
public class StringTableGenerator extends TableGenerator {

  @Override
  public void configure(Type type, Properties params, ServiceRegistry serviceRegistry)
    throws MappingException {
    super.configure(new BigDecimalType() , params, serviceRegistry);
  }

  @Override
  public Serializable generate(SharedSessionContractImplementor session, Object obj) {
    return super.generate(session, obj).toString();
  }

}

configure () méthode

Puisque StringType arrive au premier argument, remplacez-le par BigDecimalType () avant de le passer à la classe parente (^^)

méthode generate ()

La valeur renvoyée par la classe parente est BigDecimal, remplacez-la par une chaîne avant de la renvoyer. c'est tout.

Paramètres d'annotation

Ensuite, réécrivez l'entité qui génère réellement la séquence comme suit.

Partner.java


@Entity
@Table(name = "partner")
public class Partner implements Serializable {
  @Id
  @GeneratedValue(strategy = GenerationType.TABLE, generator = "CUSTOM_SEQ")
  @GenericGenerator(strategy = "sample.hibernate.id.StringTableGenerator", 
    name = "CUSTOM_SEQ", parameters = {
    @Parameter(name = "segment_value", value = "partner_cd"),
    @Parameter(name = "table_name", value = "sequence_mng"),
    @Parameter(name = "segment_column_name", value = "colname"),
    @Parameter(name = "value_column_name", value = "nextvalue")
  })
  @Column(name = "partner_cd", unique = true, nullable = false, length = 6)
  private String partnerCd;

  @Column(name = "partner_nm", nullable = false)
  private String partnerNm;
 
(Ce qui suit est omis)

Remplacez @TableGenerator, qui a une classe fixe, @GenericGenerator, et spécifiez que le StringTableGenerator créé précédemment doit être utilisé. Notez que les paramètres changent également de nom.

Avec les modifications ci-dessus, les numéros de série seront également générés et définis dans le champ Chaîne.

finalement

Cliquez ici pour le générateur de séquence (matériel presque original) https://stackoverflow.com/questions/12517421/how-to-map-a-string-to-db-sequence-in-hibernate

Description facile à comprendre du générateur de tables http://d.hatena.ne.jp/taedium/20070627/p1

Ceci est également un générateur de table facile à comprendre http://qiita.com/KevinFQ/items/a6d92ec7b32911e50ffe

De côté

Hibernate modifie de temps à autre la structure du package et le nom de la classe, donc Les matériaux là-bas deviennent rapidement obsolètes.

Si vous pensez que c'est étrange - ça ne bouge pas, il est plus rapide de regarder la source. Cette fois, l'attribut de nom @Parameter l'a fait.

Je n'ai pas trouvé d'autre support de TableGenerator et StringType, donc je l'entrerai dans l'espoir qu'il sera utile à quelqu'un. puis.

Recommended Posts

Générez un numéro de série avec TableGenerator of Hibernate (JPA) et stockez-le dans l'ID de String.
Trouvez le nombre de jours dans un mois avec Kotlin
clé composite de mise en veille prolongée
Jusqu'à l'utilisation de Spring Data et JPA Part 2
Jusqu'à l'utilisation de Spring Data et JPA Part 1
Générez un numéro de série avec TableGenerator of Hibernate (JPA) et stockez-le dans l'ID de String.
Résumer les principaux points de démarrage avec JPA appris avec Hibernate
Élimine les tracas liés au traitement des tableaux C comme des tuples par Swift
Comment obtenir l'identifiant de la clé PRIMAY incrémentée automatiquement dans MyBatis
Représentez graphiquement les informations du capteur de Raspberry Pi en Java et vérifiez-les avec un navigateur Web
Comment obtenir l'ID d'un utilisateur qui s'est authentifié avec Firebase dans Swift
Le nième et le n + 1er caractères d'une chaîne Ruby
[Swift] Lorsque vous voulez savoir si le nombre de caractères dans String correspond à un certain nombre ...
[Rails] Obtenez access_token au moment de l'authentification Twitter avec Sorcery et enregistrez-le dans la base de données
[Spring Data JPA] L'ID personnalisé est attribué dans une séquence unique au moment de l'enregistrement.
Résumer les principaux points de démarrage avec JPA appris avec Hibernate
[Java] Affiche le résultat de ffprobe -show_streams dans JSON et mappe-le à un objet dans Jackson
[Swift] Au contraire, il est significatif d'éviter var et de le déclarer avec let uniquement lorsqu'il y a une branche dans l'affectation de la valeur initiale.
Augmenter dynamiquement le nombre d'éléments dans un tableau bidimensionnel Java (tableau multidimensionnel)
Définissez le nombre de secondes d'avance et de retour rapides dans ExoPlayer
Utilisez docker-compose pour spécifier votre adresse IP préférée sur le réseau hôte et lancez-la.
J'ai écrit une fonction Lambda en Java et l'ai déployée avec SAM
L'identité des paramètres de rails [: id]
Extraire une partie d'une chaîne en Ruby
Diviser une chaîne avec ". (Dot)" en Java
J'ai reçu les données du voyage (application agenda) en Java et j'ai essayé de les visualiser # 001
Obtenez des informations vidéo YouTube avec Retrofit et conservez-les dans l'application Android.
Créez un formateur personnalisé pour Yellowfin et affichez le moins de la valeur numérique avec △ (triangle)
Valider le jeton d'ID d'un utilisateur authentifié par AWS Cognito en Java
[Java] Lors de la mise d'une chaîne de caractères dans le cas de l'instruction switch, il est nécessaire d'en faire une expression constante
Je veux trouver la somme de contrôle MD5 d'un fichier en Java et obtenir le résultat sous forme de chaîne de caractères en notation hexadécimale.