Как сделать отношения «многие ко многим» в Spring Roo с атрибутами внутри отношений? - PullRequest
3 голосов
/ 02 сентября 2011

Я изучал эту тему и пока не нашел ответов. Я использую Spring Roo, и я хотел бы знать, есть ли способ, которым я могу установить отношения многие-ко-многим с атрибутами в этих отношениях. Например, у меня есть две таблицы Employee и MedicalEquipment, сотрудники могут зарезервировать много оборудования, а оборудование может быть зарезервировано многими сотрудниками, однако я хочу сохранить дату, когда произошел этот резерв.

Если кто-то может помочь, я был бы признателен. Заранее спасибо!

Ответы [ 2 ]

9 голосов
/ 12 сентября 2011
  • Чтобы получить отношение многие-ко-многим с атрибутами, вам нужна таблица соединений, которая содержит дополнительные столбцы.То есть, кроме Employee и MedicalEquipment, вам понадобится третье EmployeeMedicalEquipment.

  • В отношении JPA у вас есть два варианта:

    1. Отображение таблицы соединения на промежуточное звеноСущность
    2. Отображение таблицы соединения на набор компонентов

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

  • Roo является генератором кода, но в нем отсутствуют все опции, которые предлагает JPA, поэтому вам нужно отредактировать классы Java и тестовые классы.Построение представления также имеет некоторые ограничения, поэтому вам нужно будет также отредактировать его.

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

Я сделал что-то вроде этого:

entity --class ~.domain.Employee --table T_Employee [etc...]
field [etc...]

entity --class ~.domain.MedicalEquipment --table T_MedicalEquipment [etc...]
field [etc...]

entity --class ~.domain.EmployeeMedicalEquipment --table T_Employee_MedicalEquipment --identifierType ~.domain.EmployeeMedicalEquipmentId
//to store the date this reserve took place.
field date --fieldName reserveDate --column C_reserveDate [etc...]

//Bidirectional: you´ll need @JoinColumn insertable = false and updatable = false
field reference --fieldName employee --type ~.domain.Employee --cardinality MANY_TO_ONE 

//Bidirectional: you'll need @JoinColumn insertable = false and updatable = false
field reference --fieldName medicalEquipment --type ~.MedicalEquipment --cardinality MANY_TO_ONE 

//Join table's composite primary key
field string --fieldName employeeId --column employee_ID --class ~.domain.EmployeeMedicalEquipmentId [etc...]
field string --fieldName medicalEquipmentId --column medicalEquipment_ID  --class ~.domain.EmployeeMedicalEquipmentId [etc...]

//Now, it's time to complete the relationship:
focus --class ~.domain.Employee
field set --type ~.domain.EmployeeMedicalEquipment --fieldName medicalEquipments --cardinality ONE_TO_MANY --mappedBy employee
focus --class ~.domain.MedicalEquipment
field set --type ~.domain.EmployeeMedicalEquipment --fieldName employees --cardinality ONE_TO_MANY --mappedBy medicalEquipment

Более того, вам нужно гарантировать ссылочную целостность, управляя коллекциями по обе стороны от ассоциации с помощью конструктора.Поэтому вам нужно отредактировать класс следующим образом:

@RooEntity(...
public class EmployeeMedicalEquipment {

@ManyToOne
@JoinColumn(name = "employeeId", referencedColumnName = "employeeId", insertable = false, updatable = false)
private Employee employee;

@ManyToOne
@JoinColumn(name="medicalEquipmentId", referencedColumnName="medicalEquipmentId", insertable=false, updatable=false)
private MedicalEquipment medicalEquipment;

/**
 * No-arg constructor for JavaBean tools
 */
public EmployeeMedicalEquipment() {
}


/**
 * Full constructor, the Employee and MedicalEquipment instances have to have an identifier value, they have to be in detached or persistent state.
 * This constructor takes care of the bidirectional relationship by adding the new instance to the collections on either side of the
 * many-to-many association (added to the collections)
 */
public EmployeeMedicalEquipment(Employee employee, MedicalEquipment medicalEquipment, Date reserveDate) {
    this.setReserveDate (reserveDate);

    this.employee = employee;
    this.medicalEquipment = medicalEquipment;

    this.setId(new EmployeeMedicalEquipmentId(employee.getId(),  medicalEquipment.getId());

    // If Employee or MedicalEquipment  Guarantee referential integrity
    employee.getMedicalEquipments().add(this);
    medicalEquipment.getEmployees().add(this);
}
...

}

Я попытался привести пример конфигурации Roo.

Более подробное объяснение материала JPA можно найти в книге Мэннинга «Сохранение Java с Hibernate», глава 7.2.3.

Примечание: если вы используете roo 1.2.1,запрос count будет генерировать SQL с «count (id1, id2)», который поддерживается не всеми базами данных, включая HSQLDB.Вы можете настроить его так:

...

-@RooJpaActiveRecord(identifierType = EmployeeMedicalEquipmentId.class, table = "T_Employee_MedicalEquipment")
+@RooJpaActiveRecord(identifierType = EmployeeMedicalEquipmentId.class, table = "T_Employee_MedicalEquipment", countMethod="")
...
public class EmployeeMedicalEquipment {
...
    // count method initially copied from ActiveRecord aspect
    public static long countEmployeeMedicalEquipments() {
-       return entityManager().createQuery("SELECT COUNT(o) FROM EmployeeMedicalEquipment o", Long.class).getSingleResult();
+       return entityManager().createQuery("SELECT COUNT(o.employee) FROM EmployeeMedicalEquipment o", Long.class).getSingleResult();
        }
    }
0 голосов
/ 05 сентября 2011

Почему у вас не может быть отдельной сущности для обозначения ваших отношений?

Просто введите новую сущность под названием MedicalEquipmentReservation, которая будет содержать все атрибуты резервирования вместе с отношениями между Сотрудником исубъекты медицинского оборудования.

См. следующий пример.

class MedicalEquipmentReservation{  
    //attributes  
    Date reservationStartDate;    
    Date reservationEndDate; 

    //relationships
    Employee employee; 
    Set<Equipment> equipments; //assuming more than one equipment can be borrowed at one reservation
}

Приветствия и всего наилучшего в Spring Roo!

...