Hibernate отношение OneToMany с не уникальным ключом - PullRequest
1 голос
/ 29 сентября 2011

Я не могу описать свою проблему, я пытаюсь повторить ее на примере:

У меня есть две сущности (таблицы): Отдел и Человек .Обе таблицы имеют поле CODE , которое не уникально .

Как мне определить manyToMany двунаправленные отношения между этими таблицами?

  1. У отправителя есть коллекция Persons, которая возвращает все сущности с Person.CODE eq Department.CODE
  2. Партнер имеет коллекцию Department, которая возвращает все сущности с Department.CODE eq Partner.CODE

Мне нужно определение отношения - без запроса sql или hpql.

--------- Оригинальный вопрос -------

Мне нужносоздать гибернацию отношения один ко многим между отделом и человеком (в одном отделе много людей).Отдел и лица имеют срок действия (validFrom, validTill)

class Department {
  Long id;
  String code; 
  String name;
  Date validFrom;
  Date validTill;
  @OneToMany(fetch = FetchType.LAZY, mappedBy = "departmentId")
  @OnDelete(action = OnDeleteAction.CASCADE)
  private Set<Person> persons = new HashSet<Person>();
}


 class Person {
      Long id;
      String name;
      String surname;
      Date validFrom;
      Date validTill;
    }


Без ORM (гибернация) легко выбрать лиц конкретного отдела науказанная дата:

select P.* from Person P, Deparment d 
where d.code = ? and 
p.department_id = d.department_id and 
? between d.validFrom and d.validTill and 
? between p.validFrom and p.validTill

В отношении должен использоваться неуникальный ключ (КОД) вместо идентификатора отдела.

Возможно ли сделать что-то подобное с Hibernate?

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

Я хочу использовать все функции, которые предлагает ORM (отложенная загрузка, сохранение в каскаде ...)

Ответы [ 2 ]

2 голосов
/ 30 сентября 2011

ОБНОВЛЕНО

Прежде всего, вы упоминаете, что хотите использовать все функции, которые предлагает ORM. Если это так, то вам нужно использовать схему, к которой Hibernate подходит. Есть аннотации, доступные как в API сохраняемости JPA, так и в API, специфичном для Hibernate, что позволяет вам более легко работать с «устаревшими» базами данных. Но если вам нужно полное и правильное использование Hibernate, то вы должны разработать свою схему в соответствии с ожиданиями Hibernate.

Вы можете сделать то, что вы просите в этом случае, используя формулу соединения вместо столбца соединения для ваших отношений. Формула соединения является допустимым фрагментом SQL (который может уменьшить переносимость). Я оставил фактический SQL в приведенном ниже примере.

public class Person {
    ...
    @OneToMany
    @JoinFormula("sql fragment")
    private List<Department> departments;
    ...
}

public class Department {
    ...
    @OneToMany
    @JoinFormula("sql fragment")
    private List<Person> people;
    ...
}

Вам также следует рассмотреть возможность обработки кода как объекта Hibernate:

@Embeddable
public class Code {
    ...
    @Column(nullable = false, length = 20)
    private String code;
    ...
}

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

Наконец, рассмотрите возможность отображения отношений между Person и Department как объединяющую таблицу в вашей схеме. После этого вы сможете использовать аннотации @ManyToMany и @JoinTable для создания реальных отношений на основе схемы в ваших сущностях.

2 голосов
/ 29 сентября 2011

Вы можете определить Фильтр . Это позволяет вам добавить эту проверку к каждому вашему запросу или отключить его, если хотите.

Пример:

<class name="Department" ...>
    ...
    <many-to-one name="person" column="person_id" class="Person"/>
    <property name="validFrom" type="date" column="validFrom"/>
    <property name="validTill" type="date" column="validTill"/>
    <property name="code" type="string" column="code"/>
    ...
    <!--
        Note that this assumes non-terminal records have an eff_end_dt set to
        a max db date for simplicity-sake
    -->
    <filter name="effectiveDate"
            condition="code = :code and :asOfDate BETWEEN validFrom and validTill"/>
</class>

С уважением.

...