Я хотел бы сопоставить многие-ко-многим в Hibernate с помощью таблицы ссылок. У меня есть два класса, родительский и дочерний, например:
public class Parent{
private List<Child> _children;
//...getters and setters
}
Я использую таблицу ссылок (link_table) с тремя столбцами link_id, parent_id и child_id. База данных - это SQL-сервер, а типы идентификаторов - uniqueidentifier. Итак, я обычно использую guid для полей id.
Как вы можете реализовать это с помощью тега <list />, если это правильный тег для использования? Вы знаете какую-нибудь хорошую документацию для этого?
В настоящее время я получаю исключение ConstraintViolationException, но мне не удалось найти хорошую документацию или примеры этого.
Я думаю, что главная проблема заключается в следующем: как указать, что link_id будет автоматически сгенерирован в таблице ссылок.




Я не уверен, что вы легко справитесь с этим для существующей базы данных с существующими данными. Hibernate обычно лучше определять собственную схему данных при первом подключении ...
Я использовал только аннотации "многие ко многим", но я думаю, что документация по спящему режиму предлагает примеры на основе XML: текст ссылки
Я делаю это с помощью аннотаций, в частности @ManyToMany и @JoinTable:
@Entity
public class Employer implements Serializable {
@ManyToMany(
targetEntity=org.hibernate.test.metadata.manytomany.Employee.class,
cascade = {CascadeType.PERSIST, CascadeType.MERGE}
)
@JoinTable(
name = "EMPLOYER_EMPLOYEE",
joinColumns=@JoinColumn(name = "EMPER_ID"),
inverseJoinColumns=@JoinColumn(name = "EMPEE_ID")
)
public Collection getEmployees() {
return employees;
}
}
@Entity
public class Employee implements Serializable {
@ManyToMany(
cascade = {CascadeType.PERSIST, CascadeType.MERGE},
mappedBy = "employees",
targetEntity = Employer.class
)
public Collection getEmployers() {
return employers;
}
}
Я не думаю, что можно (или нужно) добавить первичный ключ link_id в таблицу соединений. Таблица соединения обычно состоит из первичных ключей двух участвующих таблиц.
При использовании XML вам понадобится такой синтаксис:
<class name = "Parent">
....
<list name = "children" table = "link_table">
<key column = "parent_id"/>
<many-to-many column = "child_id"
class = "Children"/>
</list>
...
</class>
<class name = "Child">
...
<list name = "parents" inverse = "true" table = "link_table">
<key column = "child_id"/>
<many-to-many column = "parent_id"
class = "Parent"/>
</list>
...
</class>
Хотя я считаю, что лучше использовать аннотации.
Я считаю, что для этого также требуется индексный столбец.
Требовать - сильное слово. Вы можете получить то, что некоторые назвали бы чрезмерно низкой производительностью без индекса, но я не могу представить, что индекс будет обязательный.
«столбец индекса» сильно отличается от индекса базы данных в этом контексте.
@Brandon, почему Hibernate требует дополнительного столбца индекса?
Я нашел в Интернете очень хороший блог, в котором есть два способа добавить дополнительные поля к столбцу «многие ко многим», отображаемому в спящем режиме. Традиционно мы ожидаем, что отображение многих ко многим даст новую таблицу, в которой будут отображены FK таблиц. Но есть способы настроить это и добавить больше полей / столбцов в эту объединенную таблицу.
Эта объединенная таблица может содержать PK или может содержать некоторые дополнительные поля без PK. См. Этот блог для точной реализации Глянь сюда
И в соответствии с вашим примером вам нужен дополнительный PK в таблице, поэтому вы объявляете новую таблицу ParentChildren и объявляете свой первичный ключ как linkId. Я показываю только аннотированный класс parentchildren, так как на аннотации для сопоставления многих ко многим в родительском и дочернем классе можно ссылаться в сообщении выше.
@Entity
@Table(name = "parent_children")
public class ParentChildren{
@Id @GeneratedValue
private long linkId;
@ManyToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "parent_id")
private Parent parent;
@ManyToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "children_id)
private Children children;
// additional fields if you want
private boolean activated;
//getters and setters
}
}
Таким образом, будет создана таблица сопоставления, в которой linkId является первичным ключом, а parent_id и children_id - внешним ключом. Просто поясните, почему вам нужен link_id отдельно в качестве первичного ключа и как вы собираетесь его использовать.
отличный ответ, очень помог