Question

J'utilise Hibernate + JPA comme solution ORM.

J'utilise HSQL pour les tests unitaires et PostgreSQL comme base de données réelle.

Je souhaite pouvoir utiliser le UUID tapez avec Hibernate et utilisez l’UUID dans sa représentation String avec HSQL pour les tests unitaires (HSQL n’ayant pas de type UUID).

J'utilise un XML de persistance avec différentes configurations pour les tests d'unité Postgres et HSQL.

Voici comment j'ai mis Hibernate " voir " mon type d'utilisateur personnalisé:

@Id
@Column(name="UUID", length=36)
@org.hibernate.annotations.Type(type="com.xxx.UUIDStringType")
public UUID getUUID() {
    return uuid;
}


public void setUUID(UUID uuid) {
    this.uuid = uuid;
}

et cela fonctionne très bien. Mais ce qu’il me faut, c’est la possibilité d’échanger le "& com; x.xxx.UUIDStringType". une partie de l'annotation en XML ou à partir d'un fichier de propriétés pouvant être modifié sans recompilation.

Des idées?

Était-ce utile?

La solution

Cette question est vraiment ancienne et on y répond depuis longtemps, mais je me suis récemment retrouvée dans la même situation et j'ai trouvé une bonne solution. Pour commencer, j'ai découvert qu'Hibernate avait trois implémentations de type UUID intégrées différentes:

  1. binary-uuid : stocke l'UUID sous forme binaire
  2. uuid-char : stocke l'UUID en tant que séquence de caractères
  3. pg-uuid : utilise le type UUID Postgres natif

Ces types sont enregistrés par défaut et peuvent être spécifiés pour un champ donné avec une annotation @Type , par exemple.

@Column
@Type(type = "pg-uuid")
private UUID myUuidField;

Il existe également un mécanisme permettant de remplacer les types par défaut dans le Dialect . Donc, si le déploiement final doit communiquer avec une base de données Postgres, mais que les tests unitaires utilisent HSQL, vous pouvez remplacer le type pg-uuid pour lire / écrire des données de caractères en écrivant un dialecte personnalisé, comme suit:

public class CustomHSQLDialect extends HSQLDialect {

    public CustomHSQLDialect() {
        super();

        // overrides the default implementation of "pg-uuid" to replace it
        // with varchar-based storage.
        addTypeOverride(new UUIDCharType() {
            @Override
            public String getName() {
                return "pg-uuid";
            }
        });
    }
}

Il suffit maintenant de brancher le dialecte personnalisé et le type pg-uuid est disponible dans les deux environnements.

Autres conseils

Hy, pour ceux qui recherchent une solution dans Hibernate 4 (car la méthode Dialect # addTypeOverride n’est plus disponible), j’en ai trouvé un, sous-jacent à ce commentaire de Steve Ebersole

Vous devez créer un type d'utilisateur personnalisé comme celui-ci:

public class UUIDStringCustomType extends AbstractSingleColumnStandardBasicType {

    public UUIDStringCustomType() {
        super(VarcharTypeDescriptor.INSTANCE, UUIDTypeDescriptor.INSTANCE);
    }

    @Override
    public String getName() {
        return "pg-uuid";
    }

}

Et pour le lier au dialecte HSQLDB, vous devez créer un dialecte personnalisé qui substitue la méthode Dialect # ContribTypes comme ceci:

public class CustomHsqlDialect extends HSQLDialect {


    @Override
    public void contributeTypes(TypeContributions typeContributions, ServiceRegistry serviceRegistry) {
        super.contributeTypes(typeContributions,serviceRegistry);
        typeContributions.contributeType(new UUIDStringCustomType());
    }

}

Ensuite, vous pouvez utiliser le @Type (type = "pg-uuid") avec les deux bases de données.

J'espère que ça va aider quelqu'un ...

Pour éviter les problèmes entre les types d'UUID sans spécifier l'annotation @Type (ce qui signifie que vous devez ajuster toutes les annotations lorsque vous souhaitez passer de postgres à mysql ou inversement ... ) J'utilise un package-info.java avec l'annotation hibernates @TypeDef sur ce package.

Voici un exemple de configuration de votre application:
En supposant que module / src / main / java / app.package.domain contient vos entités. Et vos tests sont stockés dans module / src / test / java / app.package .

Créez simplement deux package-info.java dans vos packages domain .

  

Assurez-vous que les fichiers de paquet-info sont toujours dans le même paquet (pour le test et la production). Voir l'exemple ci-dessous:

src/main/java
  app
    package
      domain
        package-info.java 

src/test/java
  app
    package
      domain
        package-info.java 

Le contenu de votre production package-info.java devrait ressembler à ceci (Postgres):

@TypeDef(
  name = "pg-uuid",
  defaultForType = UUID.class,
  typeClass = PostgresUUIDType.class
)
package app.package.domain;

import org.hibernate.annotations.TypeDef;
import org.hibernate.type.PostgresUUIDType;

import java.util.UUID;

Et voici comment vous testez la "configuration". devrait ressembler à (H2):

@TypeDef(
  name = "uuid-char",
  defaultForType = UUID.class,
  typeClass = UUIDCharType.class
)
package app.package.domain;

import org.hibernate.annotations.TypeDef;
import org.hibernate.type.UUIDCharType;

import java.util.UUID;

J'espère que ça aide

Peut-être pouvez-vous créer des connaissances intelligentes dans votre type d'utilisateur pour faire les choses correctement en fonction des capacités de la base de données. Hibernate lui-même adopte une approche similaire avec son "natif" Générateur d'ID, qui se comporte différemment selon le type de base de données utilisé. Une telle approche élimine le besoin de changer de mappage au moment de l’exécution.

Par exemple, vous pouvez créer une classe stratégie pour chaque base de données. Ensuite, dans votre classe de types d'utilisateurs, détectez la base de données à laquelle vous êtes connecté lorsque vous êtes appelé pour la première fois, instanciez la stratégie appropriée pour cette base de données, puis déléguez tous les appels à l'objet de stratégie.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top