这个问题涉及使用JPA来管理一些数据,其中一些场景受益于完整的对象模型,而其他场景似乎更好地通过更平坦的模型实现。因此,我倾向于创建两个模型。我觉得这不是一个好主意,但我很难确切地知道为什么,或者替代方案可能是什么。
基础场景是有一个实体,让我们称之为A与实体B的关系的多方面。所以在数据库A中有一个外键字段,如果我们看到完整的对象模型(简化,getters) / setters已删除)
public Class A {
public int aKey;
public B;
// more attributes
}
public Class B {
public int bKey;
public List<A> collectionOfA;
// and more
}
一个特殊情况是处理新As的系统到达。它们来自某些外部,例如文本文件。插入代码需要
for each CVS record
get the bKey from the record
find the B, or manage any error
create the A, setting the B
persist
现在实际上我的场景更复杂,有几个这样的关系,所以查找/设置配对会重复多次。
或者我可以(事实上)为A表创建第二个映射
public Class Ainserter {
public int aKey;
public int bKey;
// more attributes
}
现在我只设置两个值并保持不变。这确实假设DB将具有参照完整性约束,但是使用我正在使用的工具就是这种情况。在此,并且在许多遗留系统中,DB预先存在,并且可以从新的JPA代码和其他甚至非Java代码访问。因此,我没有理由在这样简单的情况下将参照完整性检查放在JPA代码中。
我可以看到,对于我的插入,整个模型的某些方面可能会变得陈旧,但在遗留环境中,DB本身可能随时会发生插入。所以我在这里看不到新问题。
如果两个模型使用相同的实体上下文,我也会发现混淆的可能性,但可以通过适当的封装来避免这种情况。
还有其他想法吗?
编辑:
axtavt建议使用EntityManager.getReference(B.class,bkey)来获取B实例。我的理解是,如果我这样做,那么为了正确地符合JPA编程模型,我应该设置关系的两个方面,因此我需要访问“引用的”B对象并将我的A添加到他的集合中。
再次编辑:
我担心访问B会导致数据库查找,所以在性能方面我不会得到胜利。我有非常好的权威,至少OpenJPA,如果我们只访问B的密钥和As的集合,事实上不需要“膨胀”B - 所以getReference()是一个很好的建议。我认为设计良好的JPA实现会有这样的优化,这似乎是合理的。
答案 0 :(得分:3)
JPA有EntityManager.getReference()
方法,它基本上结合了您描述的方法。
它获取主键并返回具有该主键的代理对象,而不会访问数据库。因此,您可以使用该对象初始化关系字段,就像您在第二种方法中所做的那样。