前者更复杂,但它允许您进行双向导航(因为它是一个实体,因此可以共享引用),后者在构建和使用它时都更简单,但你不能使用它在实体之间导航(但是,您可以编写查询来检索您需要的对象)
- 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”一书中的第 7.2.3 章中找到对 JPA 内容的更好解释。
注意:如果你使用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();
}
}