如何在春天的Roo中建立多对多的关系,在de relationship中有属性?

时间:2011-09-02 16:58:53

标签: many-to-many relationship spring-roo

我一直在研究这个主题,还没有找到任何答案。我使用spring roo,我想知道是否有一种方式可以在这种关系中建立与属性的多对多关系。例如,我有两个表Employee和MedicalEquipment,员工可以预订许多设备,设备可以由许多员工预订,但我想存储此储备发生的日期。

如果有人可以帮助我会很感激。提前谢谢!

2 个答案:

答案 0 :(得分:9)

  • 为了实现与属性的多对多关系,您需要一个包含其他列的连接表。也就是说,除了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配置的例子。

你可以在Manning“Java Persistence with Hibernate”一书中找到对JPA内容的更好解释,第7.2.3章。

注意:如果使用roo 1.2.1,count查询将生成带有“count(id1,id2)”的SQL,所有数据库都不支持,包括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();
        }
    }

答案 1 :(得分:0)

为什么你不能有一个单独的实体来表示你的关系?

只需引入一个名为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一起欢呼!