Использование разных типов пользователей Hibernate в разных ситуациях

Я использую Hibernate + JPA в качестве своего решения ORM.

Я использую HSQL для модульного тестирования и PostgreSQL в качестве реальной базы данных.

Я хочу иметь возможность использовать собственный тип UUID Postgres с Hibernate и использовать UUID в представлении String с HSQL для модульного тестирования (поскольку HSQL не имеет типа UUID).

Я использую XML с постоянством с различными конфигурациями для Postgres и HSQL Unit Testing.

Вот как у меня Hibernate «см.» Мой пользовательский тип пользователя:

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

и это отлично работает. Но мне нужна возможность поменять часть «com.xxx.UUIDStringType» аннотации в XML или из файла свойств, который можно изменить без повторной компиляции.

Есть идеи?

java,hibernate,jpa,annotations,hsqldb,

5

Ответов: 4


4 принят

Этот вопрос действительно старенький, и на него ответили в течение длительного времени, но я недавно оказался в той же ситуации и нашел хорошее решение. Для начала я обнаружил, что Hibernate имеет три различные встроенные реализации типа UUID:

  1. binary-uuid : сохраняет UUID как двоичный
  2. uuid-char : сохраняет UUID как последовательность символов
  3. pg-uuid : использует собственный тип UUID Postgres

Эти типы регистрируются по умолчанию и могут быть указаны для заданного поля с @Typeаннотацией, например

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

Существует также механизм переопределения типов по умолчанию Dialect. Поэтому, если окончательное развертывание заключается в том, чтобы поговорить с базой данных Postgres, но в модульных тестах используется HSQL, вы можете переопределить pg-uuidтип для чтения / записи символьных данных, написав собственный диалект:

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

Теперь просто подключите настраиваемый диалект, и этот pg-uuidтип доступен в обеих средах.


6

Hy, для тех, кто ищет решение в Hibernate 4 (потому что метод Dialect # addTypeOverride больше недоступен), я нашел один, лежащий в основе этого комментария Steve Ebersole

Вы должны создать пользовательский тип пользователя, подобный этому:

public class UUIDStringCustomType extends AbstractSingleColumnStandardBasicType {

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

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

}

И чтобы связать его с диалектом HSQLDB, вы должны создать настраиваемый диалект, который переопределяет метод Dialect # contribTypes следующим образом:

public class CustomHsqlDialect extends HSQLDialect {


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

}

Затем вы можете использовать @Type (type = "pg-uuid") с двумя базами данных.

Надеюсь, это поможет кому-то ...


3

Чтобы избежать проблем между типами UUID без указания @Typeаннотации (в основном это означает, что вам нужно отрегулировать все аннотации, когда вы хотите изменить их из postgres в mysql или наоборот). Я использую аннотацию package-info.javahibernates @TypeDefна этом пакет.

Вот пример настройки вашего приложения:
Предположения module/src/main/java/app.package.domainсодержат ваши сущности. И ваши тесты хранятся module/src/test/java/app.package.

Просто создайте два package-info.javaв своих domainпакетах.

Убедитесь, что файлы с информацией о пакете всегда находятся в одном пакете (для тестирования и производства). См. Следующий пример ниже:

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

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

Содержимое вашего производства package-info.javaдолжно выглядеть так: (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;

И вот как вы тестируете «конфигурацию», должно выглядеть как (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;

Надеюсь, поможет


2

Возможно, вы можете создать несколько smarts в своем типе пользователя, чтобы делать правильные вещи в зависимости от возможностей базы данных. Сам спящий режим использует аналогичный подход с его «родным» генератором идентификаторов, который ведет себя по-разному в зависимости от типа используемой базы данных. Такой подход исключает необходимость переключения отображения во время выполнения.

Например, вы можете создать один класс стратегии для каждой базы данных. Затем в своем классе пользовательского типа определите, к какой базе данных вы подключились, когда вы вызываетесь в первый раз, создайте правильную стратегию для этой базы данных и затем делегируйте все вызовы объекту стратегии.

Java, спящий режим, JPA, аннотации, HSQLDB,
Похожие вопросы
Яндекс.Метрика