[英]How to pass generics to an Spring CRUD Repository's save method
Let's say we have three JPA objects with name and id. 假设我们有三个具有名称和ID的JPA对象。 I made an interface with getters+setters for name and id. 我用getters + setters建立了一个接口来输入名称和ID。
class Car implements MetadataObject
class Bus implements MetadataObject
class Train implements MetadataObject
We also have three repositories for these JPA objects: 我们还为这些JPA对象提供了三个存储库:
interface CarRepository extends CrudRepository<Car, Long>
interface BusRepository extends CrudRepository<Bus, Long>
interface TrainRepository extends CrudRepository<Train, Long>
For each of these objects we want to run the same method in an spring service. 对于这些对象中的每一个,我们希望在spring服务中运行相同的方法。 (highly simplified) (高度简化)
private void importMetadata(CrudRepository<? extends MetadataObject, String> mRepository) {
Optional<? extends MetadataObject> currentOptional = mRepository.findById(1);
if (currentOptional.isPresent()) {
MetadataObject current = (MetadataObject) currentOptional.get();
current.setName("a1");
mRepository.save(current);
}
}
Which is callable by the same spring service by 可以通过同一spring服务调用
@Autowired
private CarRepository carRepository;
...
importMetadata(carRepository);
This results in the error: 这导致错误:
The method save(S) in the type CrudRepository<capture#4-of ? extends MetadataObject, Long> is not applicable for the arguments (MetadataObject)
Which is odd if I look at Springs CRUD Repository: CrudRepository<T, ID>
and its save method: <S extends T> S save(S entity);
如果我查看Springs CRUD存储库,这是很奇怪的: CrudRepository<T, ID>
及其保存方法: <S extends T> S save(S entity);
. 。
In our example we have T = ? extends MetadataObject
在我们的示例中,我们有T = ? extends MetadataObject
T = ? extends MetadataObject
and S = ? extends ? extends MetadataObjects
T = ? extends MetadataObject
并且S = ? extends ? extends MetadataObjects
S = ? extends ? extends MetadataObjects
S = ? extends ? extends MetadataObjects
. S = ? extends ? extends MetadataObjects
。
If we change my function to private void importMetadata(CrudRepository<MetadataObject, String> bdbRepository)
the save method is correct but I can't call the method with my carRepository anymore 如果我们将函数更改为private void importMetadata(CrudRepository<MetadataObject, String> bdbRepository)
则save方法正确,但是我无法再通过carRepository调用该方法
The method importMetadata(CrudRepository<MetadataObject,String>) in the type <...> is not applicable for the arguments (CarRepository)
Be aware: I highly simplified the example. 请注意:我高度简化了示例。 I know that in this example Interfaces for these JPA classes makes no sense. 我知道在此示例中,这些JPA类的接口没有任何意义。 I also know that my method makes no sense but it highlights the problem perfectly. 我也知道我的方法没有意义,但是可以完美地突出问题。
My question would be: What to pass to save or how to rewrite this function that it works? 我的问题是:保存什么内容或如何重写此功能? What exactly is the issue here? 这到底是什么问题?
You can use this method definition: 您可以使用以下方法定义:
private void <T extends MetadataObject>importMetadata(CrudRepository<T, String> mRepository) {
Optional<T> currentOptional = mRepository.findById(1);
if (currentOptional.isPresent()) {
T current = currentOptional.get();
current.setName("a1");
mRepository.save(current);
}
}
I will try the explain the reason the method save
of CrudRepository<? extends MetadataObject, String> mRepository
我将尝试解释CrudRepository<? extends MetadataObject, String> mRepository
方法save
的CrudRepository<? extends MetadataObject, String> mRepository
CrudRepository<? extends MetadataObject, String> mRepository
fails. CrudRepository<? extends MetadataObject, String> mRepository
失败。
Suppose we have a generic class: 假设我们有一个通用类:
class C<T> {
public void save (T t) {
// .. whatever
}
}
When we write something like: 当我们写类似的东西时:
void f (C<? extends Object> c) {
c.save(new Object());
}
the compiler complains about the c.save
line. 编译器抱怨c.save
行。
That's because, when applying the type restriction, the compile doesn't know whether the c
reference points, in fact, to C<Object>
or C<Number>
or whatever, since both C<Object>
and C<Number>
are accepted as arguments for f
. 这是因为,在应用类型限制时,编译器不知道c
引用实际上指向C<Object>
还是C<Number>
或其他任何东西,因为C<Object>
和C<Number>
都被接受作为f
参数。
Because of that, the compiler doesn't know whether the save
method's argument is allowed or not, hence the error. 因此,编译器不知道是否允许使用save
方法的参数,因此会出错。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.