Гибернация: принудительное применение уникальных элементов данных

#java #hibernate #unique

#java #гибернация #уникальный

Вопрос:

У меня возникла проблема с гибернацией и принудительным применением уникальных элементов данных при вставке.

Вот мои сокращенные объекты сущностей:

Рабочий процесс:

 @Entity
public class Workflow {

    private long wfId;

    private Set<Service> services;

    /** Getter/Setter for wfId */
    ...

    @OneToMany(cascade = CascadeType.ALL)
    @JoinTable(name = "workflow_services", 
        joinColumns = @JoinColumn(name = "workflow_id"), 
        inverseJoinColumns = @JoinColumn(name = "service_id"))
    public Set<Service> getServices() {
        return services;
    }
  

Обслуживание:

 @Entity
public class Service {

    private long serviceId;
    private String serviceName;

    /** Getter/Setter for serviceId */
    ...

    @Column(unique=true,nullable=false)
    public String getServiceName() {
     return serviceName;
    }

    @OneToMany(cascade = CascadeType.ALL)
    @JoinTable(name = "service_operations", 
        joinColumns = { @JoinColumn(name = "serviceId") },
        inverseJoinColumns = { @JoinColumn(name = "operationId") })
    public Set<Operation> getOperations() {
        return operations;
    }
  

Операция:

 @Entity
public class Operation {

  private long operationId;
  private String operationName;

  /** Getter/Setter for operationId */

  @Column(unique=true,nullable=false)
  public String getOperationName() {
      return operationName;
  }
  

Моя проблема:

Хотя я указал в каждом объекте, что должно быть уникальным, оно не применяется.

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

В настоящее время я получаю повторения в своих таблицах служб и операций.

Я попытался использовать аннотацию: @Table(UniqueConstraints)

но с этим не повезло.

Любая помощь будет с благодарностью

Комментарии:

1. Какую базу данных и диалект вы используете? Как вы создавали таблицы в своей базе данных? hbm2ddl? Можете ли вы показать запросы, используемые для создания вашей таблицы? Я не думаю, что hibernate когда-либо проверяет уникальность сам по себе, но он должен генерировать таблицы с соответствующими уникальными ограничениями в вашей базе данных.

Ответ №1:

Атрибуты unique или UniqueConstraints не используются для обеспечения уникальности в БД, но создают правильный DDL, если вы создаете его из hibernate (и для документации тоже, но это спорно).

Если вы объявляете что-то уникальным в hibernate, вы также должны объявить это в БД, добавив ограничение.

Доведя это до крайности, вы можете создать сопоставление, в котором PK не является уникальным в БД, и hibernate выдаст исключение, когда попытается загрузить один элемент, вызвав Session.load и неожиданно обнаружив, что существует 2 элемента.

Ответ №2:

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

Я думаю, вы просите Hibernate обнаруживать повторяющиеся объекты при добавлении их в набор, да? Другими словами, когда вы помещаете объект в набор, вы хотите, чтобы Hibernate искал постоянную версию этого объекта и использовал ее. Однако это не так, как работает гибернация. Если вы хотите, чтобы он «повторно использовал» объект, вы должны сами его найти, а затем использовать. Гибернация этого не делает.

Я бы предложил использовать вспомогательный метод для объекта, подобного DAO, который принимает родительский и дочерний объекты, а затем выполняет поиск и настройку для вас.

Комментарии:

1. Это то, над чем я сейчас работаю. Сейчас моя проблема заключается в том, что Hibernate выдает ошибку при попытке повторного добавления объекта, и я получаю ошибку «дубликат ключа». Я использую ‘session.saveOrUpdate (workflow)’, что приятно, однако я считаю, что это только для самого рабочего процесса, а не для его вспомогательных элементов. т.е. Сервис и операция. Есть мысли?

2. Похоже, вы можете устанавливать отдельные объекты в объект Workflow. Вам нужно извлечь подобъекты (по запросу, идентификатору и т. Д.), А Затем в том же сеансе добавить их в соответствующий набор и сохранить родительский объект. Пока ваше каскадирование настроено правильно, Hibernate должен просто «делать правильные вещи» с подобъектами. Имеет ли это смысл?