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".
・ JDK1.8 ・ Hibernation (5.2.10.FINAL) · SQL Server 2016
sequence_mng
CREATE TABLE sequence_mng (
colname VARCHAR(40) NOT NULL,
nextvalue BIGINT NOT NULL,
PRIMARY KEY colname
);
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.
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.
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();
}
}
Puisque StringType arrive au premier argument, remplacez-le par BigDecimalType () avant de le passer à la classe parente (^^)
La valeur renvoyée par la classe parente est BigDecimal, remplacez-la par une chaîne avant de la renvoyer. c'est tout.
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.
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
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.