我如何使用 Java 中的泛型来更轻松地处理 JPA 存储库?
How can I use generics in Java to work with JPA repositories much easier?
我有一个名为 Select 的 Web 组件。它是Vaadin 框架中的一个下拉框。
我想在启动时构建 Select 下拉框,它们将包含来自 Spring Boot.
中来自 JPA 的存储库的数据
这是我的示例代码:
private <T extends UserLoggRepository> void addSelect(Select<Long> select, String placeHolder, T repository) {
List<UserLogg> userLoggers = repository.findAll();
List<Long> items = new ArrayList<Long>();
for(int i = 0; i < userLoggers.size(); i++) {
long value = userLoggers.get(i).getLoggerId();
if(items.contains(value) == false)
items.add(value);
}
if(items.contains((long) 0) == false)
items.add((long) 0);
select.setItems(items);
select.setPlaceholder(placeHolder);
}
此代码有效!但是我有不同的实体和不同的存储库。
我有实体:
- 用户日志
- 数据日志
- 校准日志
- 报警日志
我有存储库:
- UserLoggRepository
- DataLoggRepository
- CalibrationLoggRepository
- AlarmLoggRepository
问题:
如何更改方法 addSelect
以便它们可以与连接到实体的任何存储库一起使用?所有存储库都有标准函数 findAll()
,所有实体都有字段 loggerId
.
关注点:
我的问题是此代码仅适用于实体 UserLogg
和存储库 UserLoggRepository
。
List<UserLogg> userLoggers = repository.findAll();
需要做的事情:
这需要更改,但我不知道在这里写什么,所以对他们来说变得更通用。
private <T extends UserLoggRepository> void addSelect
更新 1:
JPA 中的存储库 header 看起来像这样:
public interface AlarmLoggRepository extends JpaRepository<AlarmLogg, Long>
我可以使用它,但仍然得到 UserLogg
class 已修复。
private <T extends JpaRepository<UserLogg, Long>> void addSelect(Select<Long> select, String placeHolder, T repository)
如果我对你的问题的理解正确,你可以继承并为所有现有实体创建父级 class,并将 addSelect 方法的定义更改为 return 父级 class ] 最终可能 return 它的任何子类型 classes.
例如,看起来您现有的实体都是日志,因此您可以拥有一个名为 LoggRepository 的抽象 class,并通过所有现有实体对其进行扩展,例如:
public class UserLoggRepository extends LoggRepository
然后,像下面那样更新 addSelect 方法,这样它就可以 return 和你父抽象的子classes class LoggRepository
private <? extends LoggRepository> void addSelect(Select<Long> select, String placeHolder, T repository)
希望这对您有所帮助:)
您的所有实体都需要一个通用接口或超类,以确保它们具有 getLoggedId()
方法。
之后,像这样的东西应该可以工作:
private void addSelect(Select<Long> select, String placeHolder, JpaRepository<? extends AbstractLogg, Long> repository) {
List<AbstractLogg> loggers = repository.findAll();
...
}
我有一个名为 Select 的 Web 组件。它是Vaadin 框架中的一个下拉框。 我想在启动时构建 Select 下拉框,它们将包含来自 Spring Boot.
中来自 JPA 的存储库的数据这是我的示例代码:
private <T extends UserLoggRepository> void addSelect(Select<Long> select, String placeHolder, T repository) {
List<UserLogg> userLoggers = repository.findAll();
List<Long> items = new ArrayList<Long>();
for(int i = 0; i < userLoggers.size(); i++) {
long value = userLoggers.get(i).getLoggerId();
if(items.contains(value) == false)
items.add(value);
}
if(items.contains((long) 0) == false)
items.add((long) 0);
select.setItems(items);
select.setPlaceholder(placeHolder);
}
此代码有效!但是我有不同的实体和不同的存储库。 我有实体:
- 用户日志
- 数据日志
- 校准日志
- 报警日志
我有存储库:
- UserLoggRepository
- DataLoggRepository
- CalibrationLoggRepository
- AlarmLoggRepository
问题:
如何更改方法 addSelect
以便它们可以与连接到实体的任何存储库一起使用?所有存储库都有标准函数 findAll()
,所有实体都有字段 loggerId
.
关注点:
我的问题是此代码仅适用于实体 UserLogg
和存储库 UserLoggRepository
。
List<UserLogg> userLoggers = repository.findAll();
需要做的事情:
这需要更改,但我不知道在这里写什么,所以对他们来说变得更通用。
private <T extends UserLoggRepository> void addSelect
更新 1:
JPA 中的存储库 header 看起来像这样:
public interface AlarmLoggRepository extends JpaRepository<AlarmLogg, Long>
我可以使用它,但仍然得到 UserLogg
class 已修复。
private <T extends JpaRepository<UserLogg, Long>> void addSelect(Select<Long> select, String placeHolder, T repository)
如果我对你的问题的理解正确,你可以继承并为所有现有实体创建父级 class,并将 addSelect 方法的定义更改为 return 父级 class ] 最终可能 return 它的任何子类型 classes.
例如,看起来您现有的实体都是日志,因此您可以拥有一个名为 LoggRepository 的抽象 class,并通过所有现有实体对其进行扩展,例如:
public class UserLoggRepository extends LoggRepository
然后,像下面那样更新 addSelect 方法,这样它就可以 return 和你父抽象的子classes class LoggRepository
private <? extends LoggRepository> void addSelect(Select<Long> select, String placeHolder, T repository)
希望这对您有所帮助:)
您的所有实体都需要一个通用接口或超类,以确保它们具有 getLoggedId()
方法。
之后,像这样的东西应该可以工作:
private void addSelect(Select<Long> select, String placeHolder, JpaRepository<? extends AbstractLogg, Long> repository) {
List<AbstractLogg> loggers = repository.findAll();
...
}