0

我正在尝试为我的 Discord Bot 创建一个 Web 界面,它允许用户更改其服务器上 Bot 的某些设置。

我使用 Spring JPA 存储这些设置。问题是存储的信息永远不会出现在 Crud 组件中,但我能够通过它创建新信息。

存储类:

@Table(name = "guild_temp_channel_settings")
@Entity
public class GuildTempChannelSettings {
    @GeneratedValue
    @Id
    @Getter
    @Setter
    private Long id;
    @Getter
    @Setter
    private long guildId;
    @Getter
    @Setter
    private long channelId;
    @Getter
    @Setter
    private String channelName;
}

存储库:

public interface GuildTempChannelSettingsRepository extends JpaRepository<GuildTempChannelSettings, Long> {
    List<GuildTempChannelSettings> findByGuildId(long guildId);

}

数据提供者:

@Slf4j
public class GuildTempChannelSettingsDataProvider extends AbstractBackEndDataProvider<GuildTempChannelSettings, CrudFilter> {
    private final GuildTempChannelSettingsRepository tempChannelSettingsRepository;
    private final long guildId;

    public GuildTempChannelSettingsDataProvider(GuildTempChannelSettingsRepository tempChannelSettingsRepository, long guildId) {
        this.tempChannelSettingsRepository = tempChannelSettingsRepository;
        this.guildId = guildId;
    }


    @Override
    protected Stream<GuildTempChannelSettings> fetchFromBackEnd(Query<GuildTempChannelSettings, CrudFilter> query) {
        int offset = query.getOffset();
        int limit = query.getLimit();

        Stream<GuildTempChannelSettings> stream = tempChannelSettingsRepository.findByGuildId(this.guildId).stream();
        log.info("Found {} entries", stream.count());

        if (query.getFilter().isPresent()) {
            stream = stream
                .filter(predicate(query.getFilter().get()))
                .sorted(comparator(query.getFilter().get()));
        }

        return stream.skip(offset).limit(limit);
    }

    @Override
    protected int sizeInBackEnd(Query<GuildTempChannelSettings, CrudFilter> query) {
        return tempChannelSettingsRepository.findByGuildId(this.guildId).size();
    }

    private static Predicate<GuildTempChannelSettings> predicate(CrudFilter filter) {
        // For RDBMS just generate a WHERE clause
        return filter.getConstraints().entrySet().stream()
            .map(constraint -> (Predicate<GuildTempChannelSettings>) person -> {
                try {
                    Object value = valueOf(constraint.getKey(), person);
                    return value != null && value.toString().toLowerCase()
                        .contains(constraint.getValue().toLowerCase());
                } catch (Exception e) {
                    e.printStackTrace();
                    return false;
                }
            })
            .reduce(Predicate::and)
            .orElse(e -> true);
    }

    private static Comparator<GuildTempChannelSettings> comparator(CrudFilter filter) {
        return filter.getSortOrders().entrySet().stream()
            .map(sortClause -> {
                try {
                    Comparator<GuildTempChannelSettings> comparator = Comparator.comparing(settings ->
                        (Comparable) valueOf(sortClause.getKey(), settings)
                    );

                    if (sortClause.getValue() == SortDirection.DESCENDING) {
                        comparator = comparator.reversed();
                    }

                    return comparator;

                } catch (Exception ex) {
                    return (Comparator<GuildTempChannelSettings>) (o1, o2) -> 0;
                }
            })
            .reduce(Comparator::thenComparing)
            .orElse((o1, o2) -> 0);
    }

    private static Object valueOf(String fieldName, GuildTempChannelSettings person) {
        try {
            Field field = GuildTempChannelSettings.class.getDeclaredField(fieldName);
            field.setAccessible(true);
            return field.get(person);
        } catch (Exception ex) {
            throw new RuntimeException(ex);
        }
    }
}

布局 Crud 用于:

private VerticalLayout createTemporaryChannelSettings() {
        VerticalLayout layout = new VerticalLayout();
        layout.addClassNames("box l radius", "contrast-5pct");

        Span title = new Span("Coming Soon");
        title.addClassNames("header-text", "font-size-xxl");
        layout.add(title);

        Hr titleLine = new Hr();
        layout.add(titleLine);

        Crud<GuildTempChannelSettings> crud = new Crud<>(GuildTempChannelSettings.class, createGrid(), createCrudEditor());

        GuildTempChannelSettingsDataProvider dataProvider = new GuildTempChannelSettingsDataProvider(this.guildTempChannelSettingsRepository, this.guild.getIdLong());
        crud.setDataProvider(dataProvider);
        crud.addDeleteListener(deleteEvent -> {
            //TODO delete channel
            this.guildTempChannelSettingsRepository.delete(deleteEvent.getItem());
        });
        crud.addSaveListener(saveEvent -> {
            //TODO create channel
            this.guildTempChannelSettingsRepository.save(saveEvent.getItem());
        });


        layout.add(crud);

        Html total = new Html("<span>Total: <b>" + this.guildTempChannelSettingsRepository.findByGuildId(this.guild.getIdLong()).size() + "</b> employees</span>");

        Button button = new Button("New", VaadinIcon.PLUS.create());
        button.addClickListener(event -> crud.edit(new GuildTempChannelSettings(), Crud.EditMode.NEW_ITEM));
        button.addThemeVariants(ButtonVariant.LUMO_TERTIARY);

        HorizontalLayout toolbar = new HorizontalLayout(total, button);
        toolbar.setAlignItems(FlexComponent.Alignment.CENTER);
        toolbar.setFlexGrow(1, toolbar);
        toolbar.setJustifyContentMode(FlexComponent.JustifyContentMode.BETWEEN);
        toolbar.setSpacing(false);

        crud.setToolbar(toolbar);

        return layout;
    }

我已经尝试使用Vaadin Crud 组件文档来实现这一点,但它永远不会在组件内部显示一些数据。DataProvider 中的fetchFromBackEnd永远不会被调用(不确定这是否重要)。

我错过了加载信息的东西吗?

编辑:

我可以通过添加crud.addNewListener(newEvent -> newEvent.getItem().setGuildId(this.guild.getIdLong()));到 Crud 组件来解决这个问题。感谢给了我提示的 Simon Martinelli。

可悲的是,当我被调用时,我现在遇到了一个stream has already been operated upon or closed 异常。fetchFromBackEnd

我不知道那里发生了什么:S

4

1 回答 1

0

第一个问题可以通过添加crud.addNewListener(newEvent -> newEvent.getItem().setGuildId(this.guild.getIdLong()));到布局来解决。感谢西蒙·马蒂内利 :)

另一个问题可以通过在 DataProviderfetchFromBackEnd方法中使用 List 而不是 Stream 来解决

于 2021-11-27T10:51:35.950 回答