Working with Data
In diesem Schritt lernen Sie, wie man ein Datenmodell mit Spring erstellt und diese Daten visuell darstellt. Am Ende dieses Schrittes wird die im vorherigen Schritt erstellte App, Erstellen einer grundlegenden App, eine Tabelle haben, die Daten über Kunden anzeigt. Das Nachvollziehen des Vorgehens wird Ihnen Folgendes vermitteln:
- Spring-Anmerkungen
- Datenverwaltung
- Die webforJ
Table-Komponente
Das Abschließen dieses Schrittes erstellt eine Version von 2-working-with-data.
App ausführen
Während Sie Ihre App entwickeln, können Sie 2-working-with-data als Vergleich verwenden. Um die App in Aktion zu sehen:
-
Navigieren Sie zum obersten Verzeichnis, das die
pom.xml-Datei enthält. Dies ist2-working-with-data, wenn Sie dem auf GitHub verfügbaren Version folgen. -
Verwenden Sie den folgenden Maven-Befehl, um die Spring Boot-App lokal auszuführen:
mvn
Das Ausführen der App öffnet automatisch einen neuen Browser unter http://localhost:8080.
Abhängigkeiten und Konfigurationen
Dieses Tutorial verwendet die H2-Datenbank und in einem zukünftigen Schritt die Jakarta Persistence API (JPA) über Spring Data JPA. Dazu müssen Sie Abhängigkeiten zu pom.xml hinzufügen und application.properties aktualisieren. Dies wird das letzte Mal sein, dass Sie diese beiden Dateien für den Rest des Tutorials ändern müssen.
Fügen Sie in Ihrem POM die folgenden Abhängigkeiten hinzu:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
</dependency>
Fügen Sie in application.properties, in src/main/resources, Folgendes hinzu:
# H2 Datenbankkonfiguration
spring.datasource.url=jdbc:h2:mem:testdb
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=
# JPA-Konfiguration
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
spring.jpa.hibernate.ddl-auto=update
Dieses Tutorial verwendet eine In-Memory-Datenbank und die Standardanmeldeinformationen für den Datenzugriff. Gehen Sie zu Springs Datenzugriffs Dokumentation, um mehr über spezifische Spring Boot-Konfigurationsoptionen zu erfahren.
Spring-Besitzobjekte
Ein wichtiger Teil der Verwendung des Spring-Frameworks ist das Verständnis, was Beans sind. Beans sind Objekte mit definierten Spring-Anmerkungen, die es Spring erleichtern, sie zu konfigurieren, da der beabsichtigte Zweck der Klasse bekannt ist. Gehen Sie zur Bean-Übersicht in der Spring-Dokumentation, um mehr zu erfahren.
Erstellen eines Datenmodells
Bevor die Daten visuell dargestellt oder erstellt werden können, benötigt dieses Tutorial eine Möglichkeit, die Daten jedes Kunden darzustellen, einschließlich deren Name, Land und Unternehmen. Mit Spring geschieht dies durch eine Klasse, die die Anmerkung @Entity hat.
Erstellen Sie eine Klasse in src/main/java/com/webforj/tutorial/entity mit dem Namen Customer.java. Sie sollte die Anmerkung @Entity besitzen und Getter- und Setter-Methoden für die Kundenwerte beinhalten, mit Ausnahme der id. Anstelle einer Erstellungsmetode für id-Werte sollten die Anmerkungen @Id und @GeneratedValue verwendet werden, um sicherzustellen, dass jeder Kunde eine eindeutige id erhält.
Mit dem Customer-Datenmodell können Sie nun beginnen, Geschäftslogik in Ihre App einzufügen.
Datenverwaltung
Nachdem Sie ein Datenmodell erstellt haben, erstellen Sie ein Repository und einen Service zur Verwaltung der Kundendaten. Diese Arten von Klassen in Ihrer App zu erstellen, ermöglicht es Ihnen, Operationen wie das Hinzufügen, Löschen und Aktualisieren von Kundenaufzeichnungen zu enthalten.
Ein Repository erstellen
Ein Repository zu erstellen, macht die Daten der Entitäten zugänglich, sodass Ihre App mehrere Kunden enthalten kann. Das Ziel dieses Tutorials ist es, die Daten bearbeitbar, sortierbar und validierbar zu machen. Sie bestimmen die Fähigkeiten eines Repositories durch das Spring Data Repository, das Sie verwenden.
In einem zukünftigen Schritt, Daten validieren und binden, benötigen Sie Zugriff auf Spring Data JPA, um die Eigenschaften von Kunden zu validieren. Daher ist das passende Repository das JpaRepository.
Erstellen Sie in src/main/java/com/webforj/tutorial/repository ein Repository-Interface, das die Spring-Anmerkung @Repository hat und JpaRepository erweitert. Sie müssen angeben, welche Art von Entitäten in diesem Repository enthalten sind und welchen Typ das id ist. Zu Ihrer Sicherheit sollten Sie auch JpaSpecificationExecutor erweitern. Diese Ergänzung ermöglicht es Ihnen, später, falls erforderlich, erweiterte Filteroptionen zu implementieren.
@Repository
public interface CustomerRepository
extends JpaRepository<Customer, Long>,
JpaSpecificationExecutor<Customer> {
}
Das CustomerRepository, das Sie gerade erstellt haben, wird keine deklarierten Methoden haben. Die Methoden zur Verwaltung der Daten (die Geschäftslogik der App) werden in einer Service-Klasse untergebracht.
Hier sind vier Links zur Dokumentation von Spring, die Ihnen helfen werden, Spring-Repositories besser zu verstehen:
Einen Service erstellen
Erstellen Sie in src/main/java/com/webforj/tutorial/service eine Klasse CustomerService. Dieser Service enthält Methoden, um Kunden zu erstellen, zu aktualisieren, zu löschen und nach Kunden mit CustomerRepository zu suchen.
Darüber hinaus benötigt dieser Service einen Mechanismus, um Spring Data Repositories mit den UI-Komponenten von webforJ zu verbinden. Die Verwendung der Klasse SpringDataRepository von webforJ ermöglicht es Ihnen, diese Brücke zu erstellen. Sie vereinfacht die Datenbindung und CRUD-Operationen, indem sie es Ihren webforJ-Tabellen und -Formularen ermöglicht, frei mit Ihrer von Spring verwalteten Datenschicht zu arbeiten. Weitere Informationen zur Spring-Integration von webforJ finden Sie im Artikel Spring Data JPA.
Für diese Service-Klasse verwenden Sie zwei Spring-Anmerkungen:
-
@Service- Diese kennzeichnet eine Klasse als Service-Komponente in Spring, sodass sie automatisch erkannt und als Bean für Geschäftslogik oder wiederverwendbare Operationen verwaltet wird. -
@Transactional- Diese Annotation sagt Spring, dass die Methode oder Klasse innerhalb einer Datenbanktransaktion ausgeführt werden soll, sodass alle Operationen zusammen festgeschrieben oder zurückgerollt werden. Weitere Details finden Sie in der Spring-Dokumentation, Verwendung von @Transactional.
@Service
@Transactional
public class CustomerService {
private final CustomerRepository repository;
public CustomerService(CustomerRepository repository) {
this.repository = repository;
}
public Customer createCustomer(Customer customer) {
return repository.save(customer);
}
public Customer updateCustomer(Customer customer) {
if (!repository.existsById(customer.getId())) {
throw new IllegalArgumentException("Kunde mit ID nicht gefunden: " + customer.getId());
}
return repository.save(customer);
}
public void deleteCustomer(Long id) {
if (!repository.existsById(id)) {
throw new IllegalArgumentException("Kunde mit ID nicht gefunden: " + id);
}
repository.deleteById(id);
}
public long getTotalCustomersCount() {
return repository.count();
}
public SpringDataRepository<Customer, Long> getRepositoryAdapter() {
return new SpringDataRepository<>(repository);
}
public Customer getCustomerByKey(Long id) {
return repository.findById(id)
.orElseThrow(() -> new IllegalArgumentException("Kunde mit ID nicht gefunden: " + id));
}
public boolean doesCustomerExist(Long id) {
return repository.existsById(id);
}
}
Initiale Daten laden
Für dieses Tutorial stammt der initiale Kundendatensatz aus einer JSON-Datei. Um den direkten Zugriff über den Browser zu verhindern, sollte die Datei außerhalb von src/main/resources/static erstellt werden. Zu Ihrem Vorteil können Sie die JSON-Datei in src/main/resources/data mit den folgenden Daten erstellen:
Anschließend benötigt die App eine Möglichkeit, diese Daten beim Start abzurufen. Erstellen Sie in src/main/java/com/webforj/tutorial/config eine DataInitializer-Klasse. Wenn die App ausgeführt wird und keine Kunden festgestellt werden, lädt sie die Kunden aus der JSON-Datei und fügt sie in die H2-Datenbank ein:
@Component
public class DataInitializer implements CommandLineRunner {
private final CustomerService customerService;
public DataInitializer(CustomerService customerService) {
this.customerService = customerService;
}
@Override
public void run(String... args) {
if (customerService.getTotalCustomersCount() == 0) {
loadCustomersFromJson();
}
}
private void loadCustomersFromJson() {
ObjectMapper mapper = new ObjectMapper();
try (InputStream is = getClass().getResourceAsStream("/data/customers.json")) {
List<Customer> customers = mapper.readValue(is, new TypeReference<List<Customer>>() {
});
for (Customer customer : customers) {
customerService.createCustomer(customer);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
Daten visuell anzeigen
Der letzte Teil dieses Schrittes besteht darin, die Table-Komponente zu verwenden und sie mit den Spring-Daten zu verbinden.
Eine Instanz einer webforJ Table benötigt einen Datentyp, um zu funktionieren, das ist die vorher in diesem Schritt erstellte Entitätsklasse:
Table<Customer> table = new Table<>();
Sobald Sie ein Table haben, erhält jede Kundeneigenschaft ihre eigene Spalte. Für jede Spalte, die Sie hinzufügen, verwenden Sie den Eigenschaftsnamen, die Getter-Methode in der Customer-Entität und die Methode setLabel(), um die Informationen in der von Ihnen gewünschten Reihenfolge anzuzeigen:
table.addColumn("firstName", Customer::getFirstName).setLabel("Vorname");
table.addColumn("lastName", Customer::getLastName).setLabel("Nachname");
table.addColumn("company", Customer::getCompany).setLabel("Unternehmen");
table.addColumn("country", Customer::getCountry).setLabel("Land");
Nachdem die Spalten hinzugefügt wurden, müssen Sie angeben, welches Repository die Table verwenden soll, um ihre Daten zu füllen. Diese App erhält das Repository von der getRepositoryAdapter()-Methode im erstellten CustomerService:
table.setRepository(customerService.getRepositoryAdapter());
Tabellenformatierung
Für die Tabelle können Sie setSize() verwenden, um ihre Größe in Pixel oder anderen CSS-Einheiten festzulegen. Indem Sie eine maximale Breite relativ zur Bildschirmbreite festlegen, helfen Sie Ihrer App, besser auf kleinere Bildschirme zu reagieren.
Für die Spalten können Sie die Breiten einzeln festlegen oder eine der Table-Methoden wie setColumnsToAutoFit() verwenden, um webforJ die Breiten für Sie anpassen zu lassen:
table.setSize("1000px", "294px");
table.setMaxWidth("90vw");
table.setColumnsToAutoFit();
Nutzerinteraktionen
Die Table-Komponente hat auch Methoden, um zu steuern, wie Benutzer mit den Spalten interagieren:
table.setColumnsToResizable(false);
table.getColumns().forEach(column -> column.setSortable(true));
Die hervorgehobenen Teile der Klasse Application fügen die Table-Komponente hinzu, definieren ihre Spalten und verwenden den CustomerService, um das Repository abzurufen:
@SpringBootApplication
@StyleSheet("ws://css/card.css")
@AppTheme("system")
@AppProfile(name = "Kundenanwendung", shortName = "KundenApp")
public class Application extends App {
//Fügen Sie eine Konstruktorinjektion für CustomerService hinzu
private final CustomerService customerService;
public Application(CustomerService customerService) {
this.customerService = customerService;
}
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@Override
public void run() throws WebforjException {
Frame mainFrame = new Frame();
Paragraph tutorial = new Paragraph("Tutorial-App!");
Button btn = new Button("Info");
//Fügen Sie die Table-Komponente hinzu
Table<Customer> table = new Table<>();
mainFrame.setWidth("fit-content");
mainFrame.addClassName("card");
//Formatieren Sie die Table-Komponente, legen Sie die Spalten fest und setzen Sie das Repository
table.setSize("1000px", "294px");
table.setMaxWidth("90vw");
table.addColumn("firstName", Customer::getFirstName).setLabel("Vorname");
table.addColumn("lastName", Customer::getLastName).setLabel("Nachname");
table.addColumn("company", Customer::getCompany).setLabel("Unternehmen");
table.addColumn("country", Customer::getCountry).setLabel("Land");
table.setColumnsToAutoFit();
table.setColumnsToResizable(false);
table.getColumns().forEach(column -> column.setSortable(true));
table.setRepository(customerService.getRepositoryAdapter());
btn.setTheme(ButtonTheme.PRIMARY)
.setMaxWidth(200)
.addClickListener(e -> OptionDialog.showMessageDialog("Dies ist ein Tutorial!", "Info"));
//Fügen Sie die Tabelle zum Frame hinzu
mainFrame.add(tutorial, btn, table);
}
}
Nächster Schritt
Mit diesen Änderungen lädt die App Kundendaten in die Datenbank und zeigt sie dann in einer Table-Komponente an. Der nächste Schritt, Routing und Komposite, führt in das Routing und mehrere Ansichten zum Hinzufügen neuer Kunden ein.