简短的回答是你不能这样做。
但是这里的解决方案可能适合您的问题:
在实体 A 中,仍然将与实体 B 的关系定义为 List(甚至更好地定义为 Set,因此不能多次包含相同的 B)。
@OneToMany(mappedBy="a")
private Set<B> bs;
由于您不想公开普通列表,请省略 getter 和 setter for as
。
然后你可以为你的地图定义一个 getter 来动态构建地图:
// a transient field to cache the map
private transient Map<String, B> bsMappedByCName;
public Map<String, B> getBsMappedByCName() {
if(bsMappedByCName == null) {
bsMappedByCName = new HashMap<String, B>();
for(B b : bs) {
mapB(b);
}
}
// return as unmodifiable map so that it is immutable for clients
return Collections.unmodifiableMap(bsMappedByCName);
}
private void mapB(B b) {
// we assume here that field c in class B and likely also field name in class C are not nullable. Further more both of this fields sould be immutable (i.e. have no setter).
if(bsMappedByCName.put(b.getC().getName(), b) != null) {
// multiple bs with same CName, this is an inconsistency you may handle
}
}
最后一个要解决的问题是我们如何将新的 B 添加到 A 或删除一个。使用将地图返回为不可修改的策略,我们必须在类 A 中提供一些添加和删除方法:
public void addB(B b) {
bs.add(b);
mapB(b);
}
public void removeB(B b) {
bs.remove(b);
bsMappedByCName.remove(b.getC().getName());
}
另一种选择是替换return Collections.unmodifiableMap(...)
为(灵感来自apache 的 ObservaleCollection):
return new Map<String, B>() {
// implement all methods that add or remove elements in map with something like this
public B put(String name, B b) {
// check consistency
if(!b.getC().getName().equals(name)) {
// this sould be handled as an error
}
B oldB = get(name);
mapB(b);
return oldB;
}
// implement all accessor methods like this
public B get(String name) {
return bsMappedByCName.get(name);
}
// and so on...
};