Я нашел следующее решение. Это решение без сложного ключа в Bridge. Я добавил нормальное поле @Id в классе Bridge, и отношения с учеником и курсом - это нормальные отношения. Это решение содержит дополнительное поле «id» в таблице «bridge» в базе данных.
Вот код:
Student.java:
@Entity
public class Student extends Model {
@Id
public Integer id;
@OneToMany(mappedBy="student")
public List<Bridge> bridges;
public static Finder<Integer,Student> find = new Finder<Integer,Student>(
Integer.class, Student.class
);
}
Course.java:
@Entity
public class Course extends Model {
@Id
public Integer id;
@OneToMany(mappedBy="course")
public List<Bridge> bridges;
public static Finder<Integer,Course> find = new Finder<Integer,Course>(
Integer.class, Course.class
);
}
Bridge.java:
@Entity
public class Bridge extends Model {
@Id
public Integer id;
@ManyToOne public Student student;
@ManyToOne public Course course;
public String additional_field;
public static Finder<Integer,Bridge> find = new Finder<Integer,Bridge>(
Integer.class, Bridge.class
);
}
EDIT
После многих попыток я нашел решение с составным ключом в классе Bridge. Классы Студенты и курс те же, что и в предыдущем решении.
Bridge.java изменено на следующее:
@Entity
public class Bridge extends Model {
Bridge() {
bridgeId = new BridgeId();
}
@EmbeddedId
protected BridgeId bridgeId;
@ManyToOne
@JoinColumn(name = "student_id", insertable = false, updatable = false)
private Student student;
@ManyToOne
@JoinColumn(name="course_id", insertable = false, updatable = false)
private Course course;
public String additional_field;
public Student getStudent() {
return student;
}
public void setStudent(Student aStudent) {
student=aStudent;
bridgeId.student_id = aStudent.id;
}
public Course getCourse() {
return course;
}
public void setCourse(Course aCourse){
course=aCourse;
bridgeId.course_id = aCourse.id;
}
}
И есть дополнительный BridgeId.java:
@Embeddable
public class BridgeId implements Serializable
{
public Integer student_id;
public Integer course_id;
public int hashCode() {
return student_id + course_id;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
BridgeId b = (BridgeId)obj;
if(b==null)
return false;
if (b.student_id == student_id && b.course_id == course_id) {
return true;
}
return false;
}
}
Что более важно в этом коде:
- Поля встроенные идентификаторы отображаются в те же столбцы, что и отношения ManyToOne.
- Значения столбцов 'student_id' и 'course_id' вставляются из встроенного id, а не из отношений. Это связано с тем, что отношения имеют атрибуты «insertable» и «updatable», равные false.
- Мне пришлось добавлять геттеры и сеттеры в поля «ученик» и «курс». В сеттерах я обновляю поля встроенного ключа.
Выше решения есть несколько обходных решений. Но я не был ableto найти проще и чище.
Почему список мостов является первичным ключом? Должен ли первичный ключ быть длинным или int? – rtruszk
@rtruszk Вот как я прочитал это в ebean userguide, что отношение OneToMany сделано. Логически да, я хочу, чтобы pk был int, но тогда я не знаю, как связать его с таблицей моста. – Wlad
Просто обратите внимание, что таблица «Bridge» часто упоминается как таблица «Пересечение», поэтому просто добавляйте этот комментарий здесь, чтобы помочь будущему поиску google. –