所以,我有实体,有几件。
InputField
CheckBoxField
SelectField
它们都继承自同一个抽象实体AbstractEntity
。对于每个实体,都有一个继承自 CommonRepository 的存储库:
@NoRepositoryBean
public interface CommonRepository<E extends AbstractEntity> extends JpaRepository<E, Long>
我将存储库自动连接到服务中:
@Service
public class ShiftServiceImpl implements ShiftService
并将其放入地图<дискриминатор, бин репозитория>
中,如下所示:
private Map<String, CommonRepository> fieldRepositories;
fieldRepositories = new HashMap<>();
fieldRepositories.put("input", inputFieldRepository);
fieldRepositories.put("checkbox", checkBoxFieldRepository);
fieldRepositories.put("select", selectFieldRepository);
接下来,我得到一个形式为 的实体鉴别器String
。而且,在鉴别器确定了什么样的实体之后,我想通过相应的存储库 bean 拉出我需要的实体。也就是说,像这样:
fieldRepositories.get(e.get("type"))
.findById(id)
.ifPresent(i -> entities.add(i));
同时,IDEA 不允许我这样做,强调后者i
写道:
add (ru.field.AbstractField) in List cannot be applied to
(java.lang.Object)
告诉我如何正确键入类/映射以使一切正常?
升级版:
多亏了一位同事的回答,它起作用了,但是现在它没有完全检查类型(未经检查的演员表):
UPD2:
该评论有所帮助,但现在它在另一个地方掉了下来,同时保存了实体:
entities
.forEach(e -> {
fieldRepositories.get(e.getFieldType().getName()).save(e);
});
据我了解,所有存储库
fieldRepositories
都与后代实体一起使用AbstractField
,并且entities
- 的集合AbstractField
。错误是
fieldRepositories
从这里不清楚,因为您可以向其中添加另一个存储库,这findById
将返回一个与AbstractField
.你可以像这样修复它:
现在
fieldRepositories
添加“错误”对象将不起作用 - 将发生编译错误。更新:是的,打字问题在这里更深入。此代码中的错误:
表示编译器不确定每个实体的字典中是否映射了正确的存储库。
例如,错误地,字典中的键可能与
e.getFieldType().getName()
. 或者在收集和保存实体之间的某个地方,您可以执行类似的操作fieldRepositories.put("input", checkBoxFieldRepository);
编译器无法知道实体-存储库映射是否正确。此信息不在代码中。正确性仅取决于填写
Map
. 包括。恐怕如果没有类型转换,它就不会在这里工作。您可以强制编译器像这样吞下错误:
但是演员表,尤其是未经测试的演员表,看起来很丑。如果你不能没有演员表,那么他们通常会尝试将其隔离到一个单独的方法中,例如:
我现在没有想到强类型的解决方案。也许有人会提供一些复杂的选择。