Fluent API β ΡΡΠΎ ΡΡΠΈΠ»Ρ ΠΏΡΠΎΠ΅ΠΊΡΠΈΡΠΎΠ²Π°Π½ΠΈΡ API, Π² ΠΊΠΎΡΠΎΡΠΎΠΌ ΠΌΠ΅ΡΠΎΠ΄Ρ Π²ΠΎΠ·Π²ΡΠ°ΡΠ°ΡΡ ΠΎΠ±ΡΠ΅ΠΊΡ, ΠΊ ΠΊΠΎΡΠΎΡΠΎΠΌΡ ΠΎΠ½ΠΈ ΠΏΡΠΈΠ½Π°Π΄Π»Π΅ΠΆΠ°Ρ, ΠΏΠΎΠ·Π²ΠΎΠ»ΡΡ Π²ΡΠ·ΡΠ²Π°ΡΡ ΠΌΠ΅ΡΠΎΠ΄Ρ ΡΠ΅ΠΏΠΎΡΠΊΠΎΠΉ (chaining).
ΠΡΠ½ΠΎΠ²Π½ΡΠ΅ ΠΊΠΎΠ½ΡΠ΅ΠΏΡΠΈΠΈ
- Method Chaining. Fluent API ΠΏΠΎΠ·Π²ΠΎΠ»ΡΠ΅Ρ Π²ΡΠ·ΡΠ²Π°ΡΡ ΠΌΠ΅ΡΠΎΠ΄Ρ ΠΎΠ΄ΠΈΠ½ Π·Π° Π΄ΡΡΠ³ΠΈΠΌ, ΡΡΠΎ ΡΠΌΠ΅Π½ΡΡΠ°Π΅Ρ ΠΊΠΎΠ»ΠΈΡΠ΅ΡΡΠ²ΠΎ ΠΏΡΠΎΠΌΠ΅ΠΆΡΡΠΎΡΠ½ΡΡ ΠΏΠ΅ΡΠ΅ΠΌΠ΅Π½Π½ΡΡ ΠΈ ΡΠ»ΡΡΡΠ°Π΅Ρ ΡΠΈΡΠ°Π΅ΠΌΠΎΡΡΡ.
- Π‘Π°ΠΌΠΎΠΎΠΏΠΈΡΡΠ²Π°ΡΡΠΈΠΉΡΡ ΠΊΠΎΠ΄. ΠΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΠ΅ ΡΠ΅ΠΏΠΎΡΠΊΠΈ ΠΌΠ΅ΡΠΎΠ΄ΠΎΠ² Π΄Π΅Π»Π°Π΅Ρ ΠΊΠΎΠ΄ Π±ΠΎΠ»Π΅Π΅ ΠΏΠΎΠ½ΡΡΠ½ΡΠΌ ΠΈ Π»ΠΎΠ³ΠΈΡΠ½ΡΠΌ, ΠΏΡΠΈΠ±Π»ΠΈΠΆΠ°Ρ Π΅Π³ΠΎ ΠΊ Π΅ΡΡΠ΅ΡΡΠ²Π΅Π½Π½ΠΎΠΌΡ ΡΠ·ΡΠΊΡ.
ΠΠ΄Π΅ Π²ΡΡΡΠ΅ΡΠ°Π΅ΡΡΡ?
- Π€ΡΠ΅ΠΉΠΌΠ²ΠΎΡΠΊΠΈ Ρ ΡΠ΅Π°ΠΊΡΠΈΠ²Π½ΡΠΌ ΠΏΠΎΠ΄Ρ ΠΎΠ΄ΠΎΠΌ.
- Java Stream
- ΠΠΈΠ±Π»ΠΈΠΎΡΠ΅ΠΊΠΈ Π΄Π»Ρ ΡΠ°Π±ΠΎΡΡ Ρ Π±Π°Π·Π°ΠΌΠΈ Π΄Π°Π½Π½ΡΡ . Π’Π°ΠΊΠΈΠ΅ ΡΡΠ΅ΠΉΠΌΠ²ΠΎΡΠΊΠΈ, ΠΊΠ°ΠΊ JPA ΠΈΠ»ΠΈ Hibernate, ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΡΡ Fluent API Π΄Π»Ρ ΡΠΎΠ·Π΄Π°Π½ΠΈΡ Π·Π°ΠΏΡΠΎΡΠΎΠ². ΠΠ°ΠΏΡΠΈΠΌΠ΅Ρ, Π·Π°ΠΏΡΠΎΡΡ ΠΌΠΎΠ³ΡΡ Π²ΡΠ³Π»ΡΠ΄Π΅ΡΡ ΡΠ°ΠΊ
CriteriaBuilder builder = entityManager.getCriteriaBuilder();
CriteriaQuery<Car> query = builder.createQuery(Car.class);
query.select(query.from(Car.class))
.where(builder.equal(root.get("color"), "Red"));
- ΠΠ°ΡΡΡΠΎΠΉΠΊΠ° ΠΎΠ±ΡΠ΅ΠΊΡΠΎΠ². Fluent API ΡΠ°ΡΡΠΎ ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΠ΅ΡΡΡ Π² Builder Pattern, Π³Π΄Π΅ ΠΎΠ±ΡΠ΅ΠΊΡ ΡΡΡΠΎΠΈΡΡΡ ΠΏΠΎΡΡΠ°ΠΏΠ½ΠΎ ΡΠ΅ΡΠ΅Π· ΡΠ΅ΠΏΠΎΡΠΊΡ ΠΌΠ΅ΡΠΎΠ΄ΠΎΠ².
- ΠΠΎΠ½ΡΠΈΠ³ΡΡΠ°ΡΠΈΡ. ΠΠ°ΠΏΡΠΈΠΌΠ΅Ρ Spring Security, Kafka Streams
- Π€ΡΠ΅ΠΉΠΌΠ²ΠΎΡΠΊΠΈ Π΄Π»Ρ ΡΠ΅ΡΡΠΈΡΠΎΠ²Π°Π½ΠΈΡ. ΠΠ°ΠΏΡΠΈΠΌΠ΅Ρ, Π² JUnit ΠΈΠ»ΠΈ AssertJ ΠΌΠΎΠΆΠ½ΠΎ ΡΡΡΠΎΠΈΡΡ ΡΠ΅ΠΏΠΎΡΠΊΠΈ ΡΡΠ²Π΅ΡΠΆΠ΄Π΅Π½ΠΈΠΉ:
Fluent API ΡΠ°ΡΡΠΎ ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΠ΅ΡΡΡ Π΄Π»Ρ ΠΏΠΎΡΡΡΠΎΠ΅Π½ΠΈΡ ΡΠΏΠ΅ΡΠΈΡΠΈΡΠ΅ΡΠΊΠΈΡ ΡΠ·ΡΠΊΠΎΠ² (DSL), ΠΊΠΎΡΠΎΡΡΠ΅ ΠΈΠΌΠΈΡΠΈΡΡΡΡ ΡΠ΅Π»ΠΎΠ²Π΅ΡΠ΅ΡΠΊΠΈΠΉ ΡΠ·ΡΠΊ ΠΈ Π΄Π΅Π»Π°ΡΡ ΠΊΠΎΠ΄ ΠΌΠ°ΠΊΡΠΈΠΌΠ°Π»ΡΠ½ΠΎ ΡΠ°ΠΌΠΎΠΎΠΏΠΈΡΠ°ΡΠ΅Π»ΡΠ½ΡΠΌ.
ΠΡΠΈΠΌΠ΅Ρ ΠΈΠΌΠΏΠ΅ΡΠ°ΡΠΈΠ²Π½ΠΎΠ³ΠΎ ΠΊΠΎΠ΄Π°
Instant start = Instant.now();
Duration timeout = Duration.ofSeconds(10);
do {
Thread.sleep(200);
var entity = repo.get("id");
if ("EXPECTED".equals(entity.status)) {
return;
ο½
} while (Instant.now().isBefore(start.plus(timeout)));
throw new AssertionError("Status was not updated to EXPECTED");
Π Π°Π½Π°Π»ΠΎΠ³ΠΈΡΠ½ΡΠΉ Π² ΡΡΠΈΠ»Π΅ Fluent API
Awaitility.await("Entity status should be updated to EXPECTED")
.atMost(Duration.ofSeconds(10))
.pollDelay(Duration.ofMillis(200))
.until(() -> "EXPECTED".equals(repo.get("id").status));
ΠΡΠΈΠ΅ΠΌΡ ΠΈ ΠΏΠΎΠ΄Ρ ΠΎΠ΄Ρ
Method chaining
Method chaining β ΡΡΠΎ ΡΠ΅Ρ
Π½ΠΈΠΊΠ°, ΠΏΡΠΈ ΠΊΠΎΡΠΎΡΠΎΠΉ ΠΌΠ΅ΡΠΎΠ΄Ρ Π²ΠΎΠ·Π²ΡΠ°ΡΠ°ΡΡ ΡΠ΅ΠΊΡΡΠΈΠΉ ΠΎΠ±ΡΠ΅ΠΊΡ (ΠΎΠ±ΡΡΠ½ΠΎ ΡΠ΅ΡΠ΅Π· this
), ΠΏΠΎΠ·Π²ΠΎΠ»ΡΡ Π²ΡΠ·ΡΠ²Π°ΡΡ Π½Π΅ΡΠΊΠΎΠ»ΡΠΊΠΎ ΠΌΠ΅ΡΠΎΠ΄ΠΎΠ² ΠΏΠΎΡΠ»Π΅Π΄ΠΎΠ²Π°ΡΠ΅Π»ΡΠ½ΠΎ Π² ΠΎΠ΄Π½ΠΎΠΉ ΡΡΡΠΎΠΊΠ΅.
public class Car {
private String engine;
private int doors;
public Car setEngine(String engine) {
this.engine = engine;
return this; // ΠΠΎΠ·Π²ΡΠ°ΡΠ°Π΅ΠΌ ΡΠ΅ΠΊΡΡΠΈΠΉ ΠΎΠ±ΡΠ΅ΠΊΡ
}
public Car setDoors(int doors) {
this.doors = doors;
return this;
}
}
Π‘ΠΌΠ΅Π½Π° ΠΊΠΎΠ½ΡΠ΅ΠΊΡΡΠ°
Π‘ ΠΏΠΎΠΌΠΎΡΡΡ method chaining
ΠΡΠ΅Π΄ΡΡΠ°Π²ΠΈΠΌ, ΡΡΠΎ ΠΌΡ Π½Π°ΡΡΡΠ°ΠΈΠ²Π°Π΅ΠΌ ΡΠ΅ΡΠ²Π΅ΡΠ½ΠΎΠ΅ ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ Ρ Π½Π΅ΡΠΊΠΎΠ»ΡΠΊΠΈΠΌΠΈ Π°ΡΠΏΠ΅ΠΊΡΠ°ΠΌΠΈ: Π±Π°Π·ΠΎΠ²Π°Ρ Π½Π°ΡΡΡΠΎΠΉΠΊΠ°, Π½Π°ΡΡΡΠΎΠΉΠΊΠ° Π±Π΅Π·ΠΎΠΏΠ°ΡΠ½ΠΎΡΡΠΈ, Π»ΠΎΠ³ΠΈΡΠΎΠ²Π°Π½ΠΈΡ ΠΈ Ρ.Π΄. ΠΠ΄Π΅ΡΡ ΠΊΠ°ΠΆΠ΄ΡΠΉ Π²ΡΠ·ΠΎΠ² ΠΌΠ΅ΡΠΎΠ΄Π° ΠΏΠ΅ΡΠ΅ΠΊΠ»ΡΡΠ°Π΅Ρ Π½Π°Ρ Π½Π° Π½ΠΎΠ²ΡΠΉ βΠΊΠΎΠ½ΡΠ΅ΠΊΡΡβ, Π³Π΄Π΅ ΠΌΡ ΠΏΡΠΎΠ΄ΠΎΠ»ΠΆΠ°Π΅ΠΌ Π½Π°ΡΡΡΠ°ΠΈΠ²Π°ΡΡ ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅, Π½ΠΎ Π² ΡΠ°ΠΌΠΊΠ°Ρ Π΄ΡΡΠ³ΠΎΠΉ ΠΎΠ±Π»Π°ΡΡΠΈ (Π½Π°ΠΏΡΠΈΠΌΠ΅Ρ, Ρ Π±Π΅Π·ΠΎΠΏΠ°ΡΠ½ΠΎΡΡΠΈ ΠΏΠ΅ΡΠ΅ΠΊΠ»ΡΡΠ°Π΅ΠΌΡΡ Π½Π° Π»ΠΎΠ³ΠΈΡΠΎΠ²Π°Π½ΠΈΠ΅).
public class ServerConfig {
public ServerConfig http() {
System.out.println("HTTP basic configuration");
return this; // ΠΠΎΠ·Π²ΡΠ°ΡΠ°Π΅ΠΌ ΡΠΎΡ ΠΆΠ΅ ΠΎΠ±ΡΠ΅ΠΊΡ Π΄Π»Ρ ΠΏΡΠΎΠ΄ΠΎΠ»ΠΆΠ΅Π½ΠΈΡ ΡΠ΅ΠΏΠΎΡΠΊΠΈ
}
public ServerConfig security() {
System.out.println("Security configuration");
return this; // ΠΠ΅ΡΠ΅ΠΊΠ»ΡΡΠ΅Π½ΠΈΠ΅ Π½Π° ΠΊΠΎΠ½ΡΠ΅ΠΊΡΡ Π±Π΅Π·ΠΎΠΏΠ°ΡΠ½ΠΎΡΡΠΈ
}
public ServerConfig authorizeRequests() {
System.out.println("Authorization configuration");
return this; // ΠΠ΅ΡΠ΅ΠΊΠ»ΡΡΠ΅Π½ΠΈΠ΅ Π½Π° Π½Π°ΡΡΡΠΎΠΉΠΊΡ Π°Π²ΡΠΎΡΠΈΠ·Π°ΡΠΈΠΈ Π·Π°ΠΏΡΠΎΡΠΎΠ²
}
public ServerConfig requestMatchers(String pattern) {
System.out.println("Configuring request matchers for: " + pattern);
return this; // ΠΡΠΎΠ΄ΠΎΠ»ΠΆΠ΅Π½ΠΈΠ΅ ΡΠ°Π±ΠΎΡΡ Π² ΠΊΠΎΠ½ΡΠ΅ΠΊΡΡΠ΅ Π°Π²ΡΠΎΡΠΈΠ·Π°ΡΠΈΠΈ
}
public ServerConfig csrf() {
System.out.println("CSRF protection disabled");
return this; // ΠΠ΅ΡΠ΅ΠΊΠ»ΡΡΠ΅Π½ΠΈΠ΅ Π½Π° Π½Π°ΡΡΡΠΎΠΉΠΊΡ Π·Π°ΡΠΈΡΡ CSRF
}
public ServerConfig exceptionHandling() {
System.out.println("Exception handling configuration");
return this; // ΠΠ΅ΡΠ΅ΠΊΠ»ΡΡΠ΅Π½ΠΈΠ΅ Π½Π° ΠΎΠ±ΡΠ°Π±ΠΎΡΠΊΡ ΠΈΡΠΊΠ»ΡΡΠ΅Π½ΠΈΠΉ
}
public Server build() {
System.out.println("Server is configured and built");
return new Server();
}
}
class Server {
// ΠΠΌΠΈΡΠ°ΡΠΈΡ Π·Π°ΠΏΡΡΠ΅Π½Π½ΠΎΠ³ΠΎ ΡΠ΅ΡΠ²Π΅ΡΠ°
}
Server server = new ServerConfig()
.http() // ΠΠΎΠ½ΡΠ΅ΠΊΡΡ Π±Π°Π·ΠΎΠ²ΠΎΠΉ Π½Π°ΡΡΡΠΎΠΉΠΊΠΈ HTTP
.security() // ΠΠ΅ΡΠ΅ΠΊΠ»ΡΡΠ΅Π½ΠΈΠ΅ Π½Π° ΠΊΠΎΠ½ΡΠ΅ΠΊΡΡ Π±Π΅Π·ΠΎΠΏΠ°ΡΠ½ΠΎΡΡΠΈ
.authorizeRequests() // ΠΠ°ΡΡΡΠΎΠΉΠΊΠ° Π°Π²ΡΠΎΡΠΈΠ·Π°ΡΠΈΠΈ Π·Π°ΠΏΡΠΎΡΠΎΠ²
.requestMatchers("/") // ΠΠ°ΡΡΡΠΎΠΉΠΊΠ° Π΄ΠΎΡΡΡΠΏΠ° Π΄Π»Ρ Π³Π»Π°Π²Π½ΠΎΠΉ ΡΡΡΠ°Π½ΠΈΡΡ
.requestMatchers("/api") // ΠΠ°ΡΡΡΠΎΠΉΠΊΠ° Π΄ΠΎΡΡΡΠΏΠ° ΠΊ API
.csrf() // ΠΡΠΊΠ»ΡΡΠ΅Π½ΠΈΠ΅ CSRF
.exceptionHandling() // ΠΠ°ΡΡΡΠΎΠΉΠΊΠ° ΠΎΠ±ΡΠ°Π±ΠΎΡΠΊΠΈ ΠΈΡΠΊΠ»ΡΡΠ΅Π½ΠΈΠΉ
.build(); // ΠΠ°Π²Π΅ΡΡΠ°Π΅ΠΌ ΠΊΠΎΠ½ΡΠΈΠ³ΡΡΠ°ΡΠΈΡ ΠΈ Π·Π°ΠΏΡΡΠΊΠ°Π΅ΠΌ ΡΠ΅ΡΠ²Π΅Ρ
Π‘ ΠΏΠΎΠΌΠΎΡΡΡ Π»ΡΠΌΠ±Π΄Π°-Π²ΡΡΠ°ΠΆΠ΅Π½ΠΈΠΉ
public class ServerConfig {
public ServerConfig http(Consumer<HttpConfig> httpConfig) {
System.out.println("Entering HTTP configuration context");
httpConfig.accept(new HttpConfig());
return this; // ΠΠΎΠ·Π²ΡΠ°ΡΠ°Π΅ΠΌ ΡΠΎΡ ΠΆΠ΅ ΠΎΠ±ΡΠ΅ΠΊΡ Π΄Π»Ρ Π΄Π°Π»ΡΠ½Π΅ΠΉΡΠ΅ΠΉ ΠΊΠΎΠ½ΡΠΈΠ³ΡΡΠ°ΡΠΈΠΈ
}
public ServerConfig security(Consumer<SecurityConfig> securityConfig) {
System.out.println("Entering Security configuration context");
securityConfig.accept(new SecurityConfig());
return this; // ΠΠ΅ΡΠ΅ΠΊΠ»ΡΡΠ΅Π½ΠΈΠ΅ Π½Π° ΠΊΠΎΠ½ΡΠ΅ΠΊΡΡ Π±Π΅Π·ΠΎΠΏΠ°ΡΠ½ΠΎΡΡΠΈ
}
public ServerConfig logging(Consumer<LoggingConfig> loggingConfig) {
System.out.println("Entering Logging configuration context");
loggingConfig.accept(new LoggingConfig());
return this; // ΠΠ΅ΡΠ΅ΠΊΠ»ΡΡΠ΅Π½ΠΈΠ΅ Π½Π° ΠΊΠΎΠ½ΡΠ΅ΠΊΡΡ Π»ΠΎΠ³ΠΈΡΠΎΠ²Π°Π½ΠΈΡ
}
public Server build() {
System.out.println("Server is configured and built");
return new Server(); // Π€ΠΈΠ½Π°Π»ΡΠ½ΡΠΉ ΡΡΠ°ΠΏ β Π·Π°ΠΏΡΡΠΊ ΡΠ΅ΡΠ²Π΅ΡΠ°
}
// ΠΠ»ΠΎΠΆΠ΅Π½Π½ΡΠ΅ ΠΊΠ»Π°ΡΡΡ ΠΊΠΎΠ½ΡΠΈΠ³ΡΡΠ°ΡΠΈΠΉ Π΄Π»Ρ ΡΠ°Π·Π½ΡΡ
ΠΊΠΎΠ½ΡΠ΅ΠΊΡΡΠΎΠ²
public static class HttpConfig {
public HttpConfig enableHttp2() {
System.out.println("HTTP/2 enabled");
return this;
}
public HttpConfig port(int port) {
System.out.println("Server will listen on port: " + port);
return this;
}
}
public static class SecurityConfig {
public SecurityConfig enableTLS() {
System.out.println("TLS enabled");
return this;
}
public SecurityConfig authorizeRequests(Consumer<RequestAuthorization> authorizationConfig) {
System.out.println("Authorizing requests...");
authorizationConfig.accept(new RequestAuthorization());
return this;
}
}
public static class LoggingConfig {
public LoggingConfig level(String level) {
System.out.println("Logging level set to: " + level);
return this;
}
}
public static class RequestAuthorization {
public RequestAuthorization permitAll() {
System.out.println("All requests are permitted");
return this;
}
public RequestAuthorization authenticated() {
System.out.println("Authenticated requests only");
return this;
}
}
}
Server server = new ServerConfig()
.http(http -> http.enableHttp2().port(8080)) // ΠΠ°ΡΡΡΠΎΠΉΠΊΠ° HTTP Ρ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΠ΅ΠΌ Π»ΡΠΌΠ±Π΄Π°-Π²ΡΡΠ°ΠΆΠ΅Π½ΠΈΡ
.security(security -> security
.enableTLS() // ΠΠ°ΡΡΡΠΎΠΉΠΊΠ° Π±Π΅Π·ΠΎΠΏΠ°ΡΠ½ΠΎΡΡΠΈ
.authorizeRequests(auth -> auth.authenticated())) // Π‘ΠΌΠ΅Π½Π° ΠΊΠΎΠ½ΡΠ΅ΠΊΡΡΠ° Π²Π½ΡΡΡΠΈ Π»ΡΠΌΠ±Π΄Ρ
.logging(log -> log.level("INFO")) // ΠΠ°ΡΡΡΠΎΠΉΠΊΠ° Π»ΠΎΠ³ΠΈΡΠΎΠ²Π°Π½ΠΈΡ Ρ ΠΏΠΎΠΌΠΎΡΡΡ Π»ΡΠΌΠ±Π΄Π°
.build(); // Π€ΠΈΠ½Π°Π»ΡΠ½Π°Ρ ΡΠ±ΠΎΡΠΊΠ° ΡΠ΅ΡΠ²Π΅ΡΠ°
Step building
ΠΠΎΠ·Π²ΠΎΠ»ΡΠ΅Ρ ΠΎΡΠ³Π°Π½ΠΈΠ·ΠΎΠ²Π°ΡΡ ΠΏΡΠΎΡΠ΅ΡΡ ΡΠΎΠ·Π΄Π°Π½ΠΈΡ ΠΎΠ±ΡΠ΅ΠΊΡΠΎΠ² ΠΈΠ»ΠΈ Π²ΡΠΏΠΎΠ»Π½Π΅Π½ΠΈΡ ΠΎΠΏΠ΅ΡΠ°ΡΠΈΠΉ ΡΠ΅ΡΠ΅Π· ΡΡΡΠΎΠ³ΠΎ ΡΠΏΠΎΡΡΠ΄ΠΎΡΠ΅Π½Π½ΡΠ΅ ΡΠ°Π³ΠΈ. Π₯ΠΎΡΡ ΡΡΠΎΡ ΠΏΠΎΠ΄Ρ ΠΎΠ΄ ΡΠ°ΡΡΠΎ ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΠ΅ΡΡΡ Π² Builder Pattern, ΠΎΠ½ ΠΏΡΠΈΠΌΠ΅Π½ΠΈΠΌ ΠΈ Π² Π΄ΡΡΠ³ΠΈΡ ΠΊΠΎΠ½ΡΠ΅ΠΊΡΡΠ°Ρ , Π½Π°ΠΏΡΠΈΠΌΠ΅Ρ, ΠΏΡΠΈ Π²ΡΠ·ΠΎΠ²Π΅ API, ΠΊΠΎΠ½ΡΠΈΠ³ΡΡΠ°ΡΠΈΠΈ ΡΠ»ΠΎΠΆΠ½ΡΡ ΠΏΡΠΎΡΠ΅ΡΡΠΎΠ², ΠΏΠΎΡΡΡΠΎΠ΅Π½ΠΈΠΈ Π·Π°ΠΏΡΠΎΡΠΎΠ² ΠΈ Π΄Π°ΠΆΠ΅ Π² ΡΠ°Π±ΠΎΡΠΈΡ ΠΏΡΠΎΡΠ΅ΡΡΠ°Ρ (workflow).
ΠΡΠ½ΠΎΠ²Π½ΡΠ΅ ΠΊΠΎΠ½ΡΠ΅ΠΏΡΠΈΠΈ
- Π£ΠΏΠΎΡΡΠ΄ΠΎΡΠ΅Π½Π½ΡΠ΅ ΡΠ°Π³ΠΈ. ΠΡΠΎΡΠ΅ΡΡ Π²ΡΠΏΠΎΠ»Π½Π΅Π½ΠΈΡ ΠΎΠΏΠ΅ΡΠ°ΡΠΈΠΈ ΠΈΠ»ΠΈ ΡΠΎΠ·Π΄Π°Π½ΠΈΡ ΠΎΠ±ΡΠ΅ΠΊΡΠ° ΡΠ°Π·Π΄Π΅Π»Π΅Π½ Π½Π° Π½Π΅ΡΠΊΠΎΠ»ΡΠΊΠΎ ΡΡΠ°ΠΏΠΎΠ² (ΡΠ°Π³ΠΎΠ²), ΠΊΠΎΡΠΎΡΡΠ΅ Π΄ΠΎΠ»ΠΆΠ½Ρ Π²ΡΠΏΠΎΠ»Π½ΡΡΡΡΡ Π² ΠΎΠΏΡΠ΅Π΄Π΅Π»ΡΠ½Π½ΠΎΠΉ ΠΏΠΎΡΠ»Π΅Π΄ΠΎΠ²Π°ΡΠ΅Π»ΡΠ½ΠΎΡΡΠΈ. ΠΠ°ΠΆΠ΄ΡΠΉ ΡΠ°Π³ ΠΌΠΎΠΆΠ΅Ρ ΠΏΡΠ΅Π΄ΡΡΠ°Π²Π»ΡΡΡ ΡΠΎΠ±ΠΎΠΉ Π½Π°ΡΡΡΠΎΠΉΠΊΡ, ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠ΅ ΡΠΎΡΡΠΎΡΠ½ΠΈΡ ΠΈΠ»ΠΈ Π²ΡΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅ ΠΎΡΠ΄Π΅Π»ΡΠ½ΠΎΠΉ ΠΎΠΏΠ΅ΡΠ°ΡΠΈΠΈ.
- ΠΠΎΠ½ΡΡΠΎΠ»Ρ ΠΎΠ±ΡΠ·Π°ΡΠ΅Π»ΡΠ½ΡΡ ΡΠ°Π³ΠΎΠ². ΠΠΎΡΠ°Π³ΠΎΠ²Π°Ρ ΡΠ±ΠΎΡΠΊΠ° Π³Π°ΡΠ°Π½ΡΠΈΡΡΠ΅Ρ, ΡΡΠΎ ΠΎΠΏΡΠ΅Π΄Π΅Π»Π΅Π½Π½ΡΠ΅ Π²Π°ΠΆΠ½ΡΠ΅ ΡΠ°Π³ΠΈ Π½Π΅ Π±ΡΠ΄ΡΡ ΠΏΡΠΎΠΏΡΡΠ΅Π½Ρ. ΠΡΠΎ ΠΎΡΠΎΠ±Π΅Π½Π½ΠΎ ΠΏΠΎΠ»Π΅Π·Π½ΠΎ Π΄Π»Ρ ΠΏΡΠΎΡΠ΅ΡΡΠΎΠ², Π³Π΄Π΅ Π²Π°ΠΆΠ½ΠΎ ΡΠΎΠ±Π»ΡΠ΄Π΅Π½ΠΈΠ΅ ΠΏΠΎΡΠ»Π΅Π΄ΠΎΠ²Π°ΡΠ΅Π»ΡΠ½ΠΎΡΡΠΈ Π΄Π΅ΠΉΡΡΠ²ΠΈΠΉ ΠΈΠ»ΠΈ ΠΊΠΎΠ½ΡΠΈΠ³ΡΡΠ°ΡΠΈΠΈ ΠΎΠ±ΡΠ·Π°ΡΠ΅Π»ΡΠ½ΡΡ ΠΏΠ°ΡΠ°ΠΌΠ΅ΡΡΠΎΠ².
ΠΡΠΈΠΌΠ΅ΡΡ ΠΏΡΠΈΠΌΠ΅Π½Π΅Π½ΠΈΡ ΠΏΠΎΡΠ°Π³ΠΎΠ²ΠΎΠΉ ΡΠ±ΠΎΡΠΊΠΈ
ΠΠΎΡΡΡΠΎΠ΅Π½ΠΈΠ΅ SQL-Π·Π°ΠΏΡΠΎΡΠΎΠ²
public interface SelectStep {
FromStep select(String... columns);
}
public interface FromStep {
WhereStep from(String table);
}
public interface WhereStep {
OrderByStep where(String condition);
}
public interface OrderByStep {
BuildStep orderBy(String column);
}
public interface BuildStep {
String build();
}
public class SqlQueryBuilder implements SelectStep, FromStep, WhereStep, OrderByStep, BuildStep {
private String query;
@Override
public FromStep select(String... columns) {
query = "SELECT " + String.join(", ", columns);
return this;
}
@Override
public WhereStep from(String table) {
query += " FROM " + table;
return this;
}
@Override
public OrderByStep where(String condition) {
query += " WHERE " + condition;
return this;
}
@Override
public BuildStep orderBy(String column) {
query += " ORDER BY " + column;
return this;
}
@Override
public String build() {
return query;
}
public static SelectStep start() {
return new SqlQueryBuilder();
}
}
Π‘Π°ΠΌΠΎΠΎΠ±ΠΎΠ±ΡΠ΅Π½ΠΈΠ΅
ΠΠΎΠ³Π΄Π° ΠΌΡ ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΠ΅ΠΌ Π½Π°ΡΠ»Π΅Π΄ΠΎΠ²Π°Π½ΠΈΠ΅ Π΄Π»Ρ ΡΠΎΠ·Π΄Π°Π½ΠΈΡ ΠΏΠΎΠ΄ΠΊΠ»Π°ΡΡΠΎΠ², Π²ΠΎΠ·Π½ΠΈΠΊΠ°Π΅Ρ ΠΏΡΠΎΠ±Π»Π΅ΠΌΠ°, ΡΡΠΎ ΠΌΠ΅ΡΠΎΠ΄Ρ Fluent API ΠΌΠΎΠ³ΡΡ Π²ΠΎΠ·Π²ΡΠ°ΡΠ°ΡΡ Π½Π΅ ΠΏΠΎΠ΄ΠΊΠ»Π°ΡΡ, Π° Π±Π°Π·ΠΎΠ²ΡΠΉ ΠΊΠ»Π°ΡΡ, ΡΠ°Π·ΡΡΠ²Π°Ρ ΡΠ΅ΠΏΠΎΡΠΊΡ Π²ΡΠ·ΠΎΠ²ΠΎΠ². Π‘Π°ΠΌΠΎΠΎΠ±ΠΎΠ±ΡΠ΅Π½ΠΈΠ΅ ΡΠ΅ΡΠ°Π΅Ρ ΡΡΡ ΠΏΡΠΎΠ±Π»Π΅ΠΌΡ, ΠΏΠΎΠ·Π²ΠΎΠ»ΡΡ ΠΌΠ΅ΡΠΎΠ΄Π°ΠΌ Π²ΠΎΠ·Π²ΡΠ°ΡΠ°ΡΡ ΠΏΡΠ°Π²ΠΈΠ»ΡΠ½ΡΠΉ ΡΠΈΠΏ ΠΏΠΎΠ΄ΠΊΠ»Π°ΡΡΠ°.
ΠΡΠΈΠΌΠ΅Ρ ΠΏΡΠΎΠ±Π»Π΅ΠΌΡ Π±Π΅Π· ΡΠ°ΠΌΠΎΠΎΠ±ΠΎΠ±ΡΠ΅Π½ΠΈΡ. ΠΠΎΠΏΡΡΡΠΈΠΌ, Ρ Π½Π°Ρ Π΅ΡΡΡ Π±Π°Π·ΠΎΠ²ΡΠΉ ΠΊΠ»Π°ΡΡ Ρ ΡΠ΅ΠΏΠΎΡΠΊΠΎΠΉ ΠΌΠ΅ΡΠΎΠ΄ΠΎΠ², ΠΈ ΠΌΡ Ρ ΠΎΡΠΈΠΌ ΡΠ½Π°ΡΠ»Π΅Π΄ΠΎΠ²Π°ΡΡ ΡΡΠΎΡ ΠΊΠ»Π°ΡΡ.
class BaseBuilder {
public BaseBuilder setName(String name) {
System.out.println("Name set to: " + name);
return this;
}
}
class AdvancedBuilder extends BaseBuilder {
public AdvancedBuilder setFeature(String feature) {
System.out.println("Feature set to: " + feature);
return this;
}
}
public class Main {
public static void main(String[] args) {
AdvancedBuilder builder = new AdvancedBuilder();
builder.setName("MyObject")
.setFeature("AdvancedFeature"); // ΠΡΠΈΠ±ΠΊΠ°: Π²ΠΎΠ·Π²ΡΠ°ΡΠ°Π΅ΡΡΡ BaseBuilder
}
}
Π ΡΡΠΎΠΌ ΠΏΡΠΈΠΌΠ΅ΡΠ΅ setName()
Π²ΠΎΠ·Π²ΡΠ°ΡΠ°Π΅Ρ ΡΠΈΠΏ BaseBuilder
, ΠΏΠΎΡΡΠΎΠΌΡ ΠΏΠΎΠΏΡΡΠΊΠ° Π²ΡΠ·Π²Π°ΡΡ setFeature()
Π½Π° ΡΠ΅Π·ΡΠ»ΡΡΠ°Ρ ΡΡΠΎΠ³ΠΎ Π²ΡΠ·ΠΎΠ²Π° ΠΏΡΠΈΠ²Π΅Π΄Π΅Ρ ΠΊ ΠΎΡΠΈΠ±ΠΊΠ΅. ΠΠ΅ΡΠΎΠ΄ setFeature()
Π±ΡΠ΄Π΅Ρ Π½Π΅Π΄ΠΎΡΡΡΠΏΠ΅Π½.
Π Π΅ΡΠ΅Π½ΠΈΠ΅ Ρ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΠ΅ΠΌ ΡΠ°ΠΌΠΎΠΎΠ±ΠΎΠ±ΡΠ΅Π½ΠΈΡ (Self-type Generics). ΠΡ ΠΌΠΎΠΆΠ΅ΠΌ ΡΠ΅ΡΠΈΡΡ ΡΡΡ ΠΏΡΠΎΠ±Π»Π΅ΠΌΡ, ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΡ ΡΠ°ΠΌΠΎΠΎΠ±ΠΎΠ±ΡΠ΅Π½ΠΈΠ΅ Ρ ΠΏΠΎΠΌΠΎΡΡΡ ΠΎΠ±ΠΎΠ±ΡΠ΅Π½ΠΈΠΉ (generics). ΠΡΠΎ ΠΏΠΎΠ·Π²ΠΎΠ»ΠΈΡ ΠΌΠ΅ΡΠΎΠ΄Π°ΠΌ Π²ΠΎΠ·Π²ΡΠ°ΡΠ°ΡΡ ΡΠ°ΠΌΡΠΉ ΡΠΏΠ΅ΡΠΈΡΠΈΡΠ½ΡΠΉ ΡΠΈΠΏ.
class BaseBuilder<T extends BaseBuilder<T>> {
public T setName(String name) {
System.out.println("Name set to: " + name);
return (T) this; // ΠΠΎΠ·Π²ΡΠ°ΡΠ°Π΅ΠΌ ΡΠ΅ΠΊΡΡΠΈΠΉ ΠΎΠ±ΡΠ΅ΠΊΡ Ρ ΡΠΈΠΏΠΎΠΌ T
}
}
class AdvancedBuilder extends BaseBuilder<AdvancedBuilder> {
public AdvancedBuilder setFeature(String feature) {
System.out.println("Feature set to: " + feature);
return this; // ΠΠΎΠ·Π²ΡΠ°ΡΠ°Π΅ΠΌ ΡΠ΅ΠΊΡΡΠΈΠΉ ΠΎΠ±ΡΠ΅ΠΊΡ Ρ ΡΠΈΠΏΠΎΠΌ AdvancedBuilder
}
}
public class Main {
public static void main(String[] args) {
AdvancedBuilder builder = new AdvancedBuilder();
builder.setName("MyObject")
.setFeature("AdvancedFeature"); // Π’Π΅ΠΏΠ΅ΡΡ ΡΠ°Π±ΠΎΡΠ°Π΅Ρ ΠΏΡΠ°Π²ΠΈΠ»ΡΠ½ΠΎ
}
}
ΠΠ΅ΡΠ° ΠΈΠ½ΡΠΎΡΠΌΠ°ΡΠΈΡ
ΠΠ±Π»Π°ΡΡΡ:: 00 Java ΡΠ°Π·ΡΠ°Π±ΠΎΡΠΊΠ°
Π ΠΎΠ΄ΠΈΡΠ΅Π»Ρ::
ΠΡΡΠΎΡΠ½ΠΈΠΊ::
Π‘ΠΎΠ·Π΄Π°Π½Π°:: 2024-10-04
ΠΠ²ΡΠΎΡ::