Tutorial 11~25 MinutenMittel

Datenbanken & ORM

Das db-Modul (basierend auf SeaORM) ermöglicht typisierten Datenbankzugriff mit PostgreSQL, MySQL und SQLite.

Was du lernen wirst

  • Modelle mit @Entity definieren
  • CRUD-Operationen mit SeaORM
  • Komplexe Queries, Joins und Filter
  • Transaktionen für Datenkonsistenz
1

Modelle definieren

Modelle sind normale Structs mit @Entity-Annotationen:

@Entity(table: "users")
struct User {
    @Id
    @Generated  // Auto-Increment oder UUID
    id: string,

    @Column(unique: true)
    email: string,
    
    name: string,
    
    @Column(name: "created_at")
    createdAt: string,
    
    @Column(default: true)
    isActive: boolean,
}

@Entity(table: "orders")
struct Order {
    @Id
    @Generated
    id: string,
    
    @Column(name: "user_id")
    @ForeignKey(User, "id")
    userId: string,
    
    total: number,
    status: string,
    createdAt: string,
}
2

CRUD Operationen

@POST("/api/users")
fn createUser(name: string, email: string): User {
    let user = User {
        id: utils.uuid(),
        email: email,
        name: name,
        createdAt: datetime.now(),
        isActive: true,
    };
    
    // SeaORM: ActiveModel::insert()
    return db.save(user);
}
3

Komplexe Queries (Fluent API)

// Filter und Sortierung
fn findActiveUsers(): List<User> {
    return db.query(User)
        .where("isActive", "=", true)
        .where("role", "!=", "banned")
        .orderBy("createdAt", "DESC")
        .limit(10)
        .findAll();
}

// Mehrere Bedingungen
fn searchUsers(term: string, minAge: number): List<User> {
    return db.query(User)
        .where("name", "LIKE", "%" + term + "%")
        .where("age", ">=", minAge)
        .where("isActive", "=", true)
        .orderBy("name", "ASC")
        .findAll();
}

// Pagination
@GET("/api/users")
fn getUsersPaginated(page: number = 1, limit: number = 20): List<User> {
    let offset = (page - 1) * limit;
    
    return db.query(User)
        .orderBy("createdAt", "DESC")
        .limit(limit)
        .offset(offset)
        .findAll();
}
4

Joins und Beziehungen

// Einfacher Join
fn getUsersWithOrders(): List<UserWithOrders> {
    return db.query(User)
        .join(Order, "userId")
        .select(["User.*", "COUNT(Order.id) as orderCount"])
        .groupBy("User.id")
        .findAll();
}

// Eager Loading (N+1 Problem vermeiden)
@GET("/api/orders")
fn getOrdersWithDetails(): List<Order> {
    return db.query(Order)
        .include("user")           // User mitladen
        .include("items.product")  // Items und deren Products
        .findAll();
}

// Left Join
fn getUsersWithOptionalOrders(): List<UserWithOrders> {
    return db.query(User)
        .leftJoin(Order, "userId")
        .findAll();
}
5

Transaktionen

Transaktionen sind essentiell für Datenkonsistenz bei mehreren zusammenhängenden Operationen:

fn transferMoney(fromId: string, toId: string, amount: number): Result<void, Error> {
    try {
        db.transaction(|tx| {
            // Alle Operationen auf 'tx' statt 'db' ausführen
            let sender = tx.find(Account, fromId);
            let receiver = tx.find(Account, toId);
            
            if (sender.balance < amount) {
                throw Error("Nicht genug Guthaben");
            }
            
            sender.balance -= amount;
            receiver.balance += amount;
            
            tx.save(sender);
            tx.save(receiver);
            
            // Audit Log
            tx.save(Transaction {
                id: utils.uuid(),
                fromAccount: fromId,
                toAccount: toId,
                amount: amount,
                createdAt: datetime.now(),
            });
        });
        
        return Ok(());
    } catch (e) {
        log.error("Transaktion fehlgeschlagen, Rollback: " + e.message);
        return Err(e);
    }
}

Zusammenfassung

Was du gelernt hast:

  • @Entity Modelle definieren
  • CRUD mit db.save(), db.find(), db.delete()
  • Fluent API für komplexe Queries
  • Joins, Eager Loading, Transaktionen

Nächste Schritte:

  • Paketmanagement lernen
  • Vector Datenbanken für KI