我们正在尝试在我们从其他人的应用程序导入的一些只读表上创建 JPA 映射。这些是多个 100 亿行的表,因此更改它们的模式不是一种选择。我们有一个表 Message 表,它有一个 OBJECT_ID 值和另一个表 DistributionGroup 表,它有许多与任何给定 OBJECT_ID 相关联的 ENTITY_ID 行。相关表定义如下:
CREATE TABLE Message (
OBJ_ID varchar(255) NOT NULL,
FileName varchar(255) NOT NULL,
KEY FileName (FileName)) ENGINE=InnoDB;
CREATE TABLE DistributionGroup (
OBJ_ID varchar(255) NOT NULL,
ENTITY_ID varchar(255) NOT NULL,
KEY OBJ_ID (OBJ_ID)) ENGINE=InnoDB;
以及将这两者联系起来的 JPA 映射:
public class MessageRecord {
private String obj_id;
private String file;
private List<DGRecord> list = new ArrayList<DGRecord>();
@Id
@Column(name = "OBJ_ID", nullable = false)
public String getObjID () { return obj_id; }
public void setObjID (String obj_id) { this.obj_id = obj_id; }
//... (Similar for FileName)
@OneToMany
@JoinColumn(name="OBJ_ID", referencedColumnName="OBJ_ID")
public List<DGRecord> getDGRecordList() { return list; }
public void setDGRecordList(List<DGRecord> list) { this.list = list; }
}
public class DGRecord {
private String obj_id;
private String entity_id;
@Id
@Column(name = "OBJ_ID", nullable = false)
public String getObjID () { return obj_id; }
public void setObjID (String obj_id) { this.obj_id = obj_id; }
@Column(name = "ENTITY_ID", nullable = false)
public String getEntityId () { return entity_id; }
public void setEntityId (String entity_id) { this.entity_id = entity_id; }
}
现在,当我们运行一些代码来迭代给定 MessageRecord 的所有 DGRecords 时,就会发生奇怪的事情:
MessageRecord record = [obtained earlier];
for (DGRecord dg : record.getDGRecordList()) {
System.out.println(dg.getEntityId());
//Do some work with the ENTITY_ID
}
当我对数据库手动运行此操作时,我得到了我期望看到的内容:
SELECT * FROM DistributionGroup WHERE OBJ_ID = 'ArbitraryObjID';
OBJ_ID, ENTITY_ID
ArbitraryObjID, EntityID1
ArbitraryObjID, EntityID2
ArbitraryObjID, EntityID3
但是实际代码的输出,当record
具有相同的时ArbitraryObjID
,是:
EntityID1
EntityID1
EntityID1
对于任何给定的组合,它不会返回 n 个不同的 DGRecord,而是返回 n 次相同的 DGRecord 值,其中 n 是手动运行查询返回的不同行数。我不确定这是否相关,但它实际上是在同一个对象上循环 n 次(由 System.out.println(dg) 返回相同的 package.DistributionGroup@MemoryAddress n 次证明)。
我们做错了什么,我们该如何解决?请记住,表模式更改或添加连接表的成本非常高,实际上是不可能的。但在当前的设置下,这似乎仍然可以工作,因为它作为人类工作得足够好。