Одностороннее сопоставление «многие ко многим» и использование только двух таблиц - PullRequest
1 голос
/ 28 августа 2010

У меня есть две сущности: проект, сотрудник

  • Сотрудник имеет первичный ключ {employeeId} + некоторые другие атрибуты
  • Проект имеет первичный ключ {projectId}

Код:

public class Employee {
  Long employeeId;
  String name;     
}
public class Project {
  Long projectId;
  Collection<Employee> employees;
}

Сотрудник и Проект - это односторонние отношения «многие ко многим». Общий подход состоит в том, чтобы иметь три таблицы: Employee, Project, EmployeesAssignedToProjects.

Employee
----------
employeeId (PK)
name

Project
----------
projectId (PK)

EmployeesAssignedToProjects
----------------------------
projectId (FK)
employeeId (FK)
{projectId,employeeId} (PK)

Поскольку у Project нет других атрибутов, кроме его идентификатора, таблица Project на самом деле не нужна. Это приводит к вопросу о том, как должно отображаться это отношение «многие ко многим», когда Project по существу сопоставляется с EmployeesAssignedToProjects.

Обратите внимание, что у Employee нет указателя на Project. Типичная конструкция mappedBy не может быть использована здесь.

[- Обновление -]

Проблема немного сложнее: у Project и Employee есть составные ключи.

  • Ключ проекта - {companyId, projectId}
  • Ключ сотрудника: {companyId, employeeId}

Я принял 3 таблицы. Таблица PROJECT_EMPLOYEE имеет 3 столбца: companyId, employeeId, projectId. И я сопоставил в xml:

<many-to-many name="PROJECT" >
 <join-table name="PROJECT_EMPLOYEE">
  <join-column name="companyId" referenced-column-name="companyId"/>
  <join-column name="employeeId" referenced-column-name="employeeId" />
  <inverse-join-column name="companyId" referenced-column-name="companyId" />
  <inverse-join-column name="projectId" referenced-column-name="projectId" />
 </join-table>
</many-to-many>     

Я получил сообщение об ошибке, вызвавшее появление компании несколько раз: Повторный столбец в сопоставлении для коллекции: столбец Project.employees: companyId

Ответы [ 2 ]

3 голосов
/ 28 августа 2010

Обратите внимание, что у Employee нет указателя на Project.Типичная конструкция mappedBy не может быть использована здесь.

В любом случае это не имеет значения.

И дело в том, что для всех ManyToMany отношений требуется JoinTable.JoinTable определяется с использованием @JoinTable неявно или явно.

@Entity
public class Project {
    @Id
    @Column(name="PROJECTID")
    private Long projectId;

    @ManyToMany
    @JoinTable(
        name="PROJECT_EMPLOYEE",
        joinColumns={@JoinColumn(name="PROJECT_PROJECTID", referencedColumnName="PROJECTID")},
        inverseJoinColumns={@JoinColumn(name="EMPLOYEE_EMPLOYEEID", referencedColumnName="EMPLOYEEID")})
    private Collection<Employee> employees;
    ...
}

Вы можете попытаться определить саму таблицу PROJECT как JoinTable, если вам нужна только поддержка reads (а я даже неконечно, это будет работать правильно) но это не сработает для пишет .

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

0 голосов
/ 28 августа 2010

Учитывая предоставленные вами файлы классов, вы, вероятно, пытаетесь изменить отношение n - m на отношение n - 0..1.

Это можно сделать, удалив EmployeesAssignedToProjects и денормализуя таблицу Employee, добавив к ней projectId (FK):

Employee
----------
employeeId (PK)
projectId (FK)
name

Project
----------
projectId (PK)

Это то, что вы действительно хотите?Я не рекомендую это.

...