基础 CRUD 操作

本文档详细介绍 Unabo 框架的基础 CRUD(增删改查)操作。

目录


创建(Create)

方式一:使用实体类插入

import online.sanen.unabo.template.jpa.Table;
import online.sanen.unabo.template.jpa.Id;
import lombok.Data;

@Data
@Table(name = "user")
public class User {
    @Id
    private Integer id;
    private String name;
    private String email;
    private Integer age;
}

// 插入单条记录
User user = new User();
user.setName("张三");
user.setEmail("zhangsan@example.com");
user.setAge(25);

int rows = bootstrap.query(user).insert();
System.out.println("插入行数: " + rows); // 输出: 1

方式二:使用 Map 插入

import java.util.HashMap;
import java.util.Map;

Map<String, Object> user = new HashMap<>();
user.put("name", "李四");
user.put("email", "lisi@example.com");
user.put("age", 30);

bootstrap.queryMap("user", user).insert();

方式三:批量插入

// 批量插入实体类
List<User> users = new ArrayList<>();
for (int i = 0; i < 100; i++) {
    User user = new User();
    user.setName("用户" + i);
    user.setEmail("user" + i + "@example.com");
    user.setAge(20 + i % 40);
    users.add(user);
}

bootstrap.query(users).insert();

// 批量插入 Map
List<Map<String, Object>> userList = new ArrayList<>();
for (int i = 0; i < 100; i++) {
    Map<String, Object> user = new HashMap<>();
    user.put("name", "用户" + i);
    user.put("email", "user" + i + "@example.com");
    user.put("age", 20 + i % 40);
    userList.add(user);
}

bootstrap.queryMap("user", userList).insert();

WARNING

批量操作时,控制台不会打印完整的 SQL 语句,只会打印参数化的 SQL。

方式四:只插入指定字段

User user = new User();
user.setName("王五");
user.setEmail("wangwu@example.com");
user.setAge(28);

// 只插入 name 和 email,不插入 age
bootstrap.query(user)
    .setFields("name", "email")
    .insert();

读取(Read)

查询所有记录

// 查询所有记录,返回 Map 列表
List<Map<String, Object>> users = bootstrap.queryTable("user").maps();

// 查询所有记录,返回实体列表
List<User> users = bootstrap.queryTable("user").list(User.class);

根据主键查询

// 方式一:使用 QueryPK
Optional<User> user = bootstrap.queryPk(User.class, 1);
if (user.isPresent()) {
    System.out.println(user.get().getName());
}

// 方式二:使用条件查询
Optional<Map<String, Object>> user = bootstrap.queryTable("user")
    .addCondition(C.eq("id", 1))
    .unique();

条件查询

import online.sanen.unabo.api.condition.C;
import online.sanen.unabo.api.structure.enums.Sorts;

// 等于
List<User> users = bootstrap.queryTable("user")
    .addCondition(C.eq("age", 25))
    .list(User.class);

// 不等于
List<User> users = bootstrap.queryTable("user")
    .addCondition(C.notEq("age", 25))
    .list(User.class);

// 大于
List<User> users = bootstrap.queryTable("user")
    .addCondition(C.gt("age", 25))
    .list(User.class);

// 大于等于
List<User> users = bootstrap.queryTable("user")
    .addCondition(C.gte("age", 25))
    .list(User.class);

// 小于
List<User> users = bootstrap.queryTable("user")
    .addCondition(C.lt("age", 30))
    .list(User.class);

// 小于等于
List<User> users = bootstrap.queryTable("user")
    .addCondition(C.lte("age", 30))
    .list(User.class);

// 模糊查询
List<User> users = bootstrap.queryTable("user")
    .addCondition(C.like("name", "张%"))
    .list(User.class);

// IN 查询
List<User> users = bootstrap.queryTable("user")
    .addCondition(C.in("id", 1, 2, 3, 4, 5))
    .list(User.class);

// BETWEEN 查询
List<User> users = bootstrap.queryTable("user")
    .addCondition(C.between("age", 20, 30))
    .list(User.class);

// IS NULL 查询
List<User> users = bootstrap.queryTable("user")
    .addCondition(C.isNull("email"))
    .list(User.class);

// IS NOT NULL 查询
List<User> users = bootstrap.queryTable("user")
    .addCondition(C.isNotNull("email"))
    .list(User.class);

多条件查询

// AND 条件(默认)
List<User> users = bootstrap.queryTable("user")
    .addCondition(C.eq("age", 25))
    .addCondition(C.like("name", "张%"))
    .list(User.class);

// OR 条件
List<User> users = bootstrap.queryTable("user")
    .addCondition(C.or(
        C.eq("age", 25),
        C.eq("age", 30)
    ))
    .list(User.class);

// 复合条件 (age=25 AND (name LIKE '张%' OR name LIKE '李%'))
List<User> users = bootstrap.queryTable("user")
    .addCondition(C.eq("age", 25))
    .addCondition(C.or(
        C.like("name", "张%"),
        C.like("name", "李%")
    ))
    .list(User.class);

排序

// 单字段排序(降序)
List<User> users = bootstrap.queryTable("user")
    .sort(Sorts.DESC, "id")
    .list(User.class);

// 单字段排序(升序)
List<User> users = bootstrap.queryTable("user")
    .sort(Sorts.ASC, "age")
    .list(User.class);

// 多字段排序
List<User> users = bootstrap.queryTable("user")
    .sort(Sorts.DESC, "age")
    .sort(Sorts.ASC, "id")
    .list(User.class);

分页查询

import com.mhdt.structure.Page;

int currentPage = 1;
int pageSize = 10;

// 查询总数
int total = bootstrap.queryTable("user").count();

// 创建分页对象
Page page = new Page(currentPage, pageSize);
page.setCount(total);

// 分页查询
List<User> users = bootstrap.queryTable("user")
    .limit(page.skip(), pageSize)
    .sort(Sorts.DESC, "id")
    .list(User.class);

System.out.println("总记录数: " + total);
System.out.println("总页数: " + page.getTotalPage());
System.out.println("当前页: " + page.getCurrentPage());

指定查询字段

// 只查询指定字段
List<Map<String, Object>> users = bootstrap.queryTable("user")
    .setFields("id", "name", "age")
    .maps();

// 排除某些字段
List<Map<String, Object>> users = bootstrap.queryTable("user")
    .setExceptFields("email", "password")
    .maps();

TIP

指定查询字段可以减少数据传输量,提升查询性能,特别是在表字段很多的情况下。

统计查询

// 查询记录数
int count = bootstrap.queryTable("user").count();

// 条件统计
int count = bootstrap.queryTable("user")
    .addCondition(C.gt("age", 20))
    .count();

更新(Update)

根据主键更新

User user = new User();
user.setId(1);
user.setName("张三丰");
user.setEmail("zhangsanfeng@example.com");
user.setAge(50);

// 更新所有字段
bootstrap.query(user).update();

// 只更新指定字段
bootstrap.query(user)
    .setFields("name", "age")
    .update();

根据条件更新

// 方式一:使用 Map 更新
bootstrap.queryTable("user")
    .addCondition(C.eq("id", 1))
    .update(Collections.singletonMap("age", 26));

// 方式二:批量更新
Map<String, Object> updates = new HashMap<>();
updates.put("age", 30);
updates.put("email", "newemail@example.com");

bootstrap.queryTable("user")
    .addCondition(C.like("name", "张%"))
    .update(updates);

批量更新

List<User> users = bootstrap.queryTable("user")
    .addCondition(C.lt("age", 18))
    .list(User.class);

// 修改数据
users.forEach(user -> user.setAge(18));

// 批量更新
bootstrap.query(users).update();

删除(Delete)

根据主键删除

User user = new User();
user.setId(1);

bootstrap.query(user).delete();

根据条件删除

// 删除单条记录
bootstrap.queryTable("user")
    .addCondition(C.eq("id", 1))
    .delete();

// 批量删除
bootstrap.queryTable("user")
    .addCondition(C.lt("age", 18))
    .delete();

删除所有记录

DANGER

谨慎使用!此操作会删除表中所有数据,且无法撤销。

bootstrap.queryTable("user").delete();

删除表

DANGER

谨慎使用!此操作会删除整个表及其数据,且无法撤销。

bootstrap.queryTable("user").drop();

使用实体类

实体类注解

import online.sanen.unabo.template.jpa.*;

@Data
@Table(name = "user", schema = "public")  // 指定表名和 schema
public class User {

    @Id  // 主键
    private Integer id;

    @Column(name = "user_name")  // 指定列名
    private String name;

    @Column(jsonSerialization = true)  // JSON 序列化
    private Map<String, Object> metadata;

    @NoDB  // 不映射到数据库
    private transient String tempField;

    @NoInsert  // 插入时忽略
    private String createTime;

    @NoUpdate  // 更新时忽略
    private String updateTime;
}

使用 Behavior 接口

import online.sanen.unabo.sql.Behavior;

@Data
@Table(name = "user")
public class User implements Behavior<User> {
    @Id
    private Integer id;
    private String name;
    private Integer age;
}

// 使用 Behavior 接口
User user = new User();
user.setName("赵六");
user.setAge(35);

// 插入
user.insert();

// 查询
Optional<User> found = user.findByPk();

// 更新
user.setName("赵七");
user.update();

// 删除
user.delete();

TIP

Behavior 接口提供了更简洁的 API,适合简单的 CRUD 操作。


使用 Map

基本操作

// 创建
Map<String, Object> user = new HashMap<>();
user.put("name", "钱八");
user.put("age", 40);
bootstrap.queryMap("user", user).insert();

// 查询
List<Map<String, Object>> users = bootstrap.queryTable("user")
    .addCondition(C.gt("age", 30))
    .maps();

// 更新
Map<String, Object> updates = new HashMap<>();
updates.put("age", 41);
bootstrap.queryTable("user")
    .addCondition(C.eq("name", "钱八"))
    .update(updates);

// 删除
bootstrap.queryTable("user")
    .addCondition(C.eq("name", "钱八"))
    .delete();

批量操作

// 批量创建
List<Map<String, Object>> users = new ArrayList<>();
for (int i = 0; i < 10; i++) {
    Map<String, Object> user = new HashMap<>();
    user.put("name", "用户" + i);
    user.put("age", 20 + i);
    users.add(user);
}
bootstrap.queryMap("user", users).insert();

// 批量更新
List<Map<String, Object>> updates = new ArrayList<>();
for (int i = 0; i < 10; i++) {
    Map<String, Object> update = new HashMap<>();
    update.put("id", i + 1);
    update.put("age", 25 + i);
    updates.add(update);
}
bootstrap.queryMap("user", updates).update();

完整示例

import online.sanen.unabo.api.Bootstrap;
import online.sanen.unabo.api.condition.C;
import online.sanen.unabo.api.structure.enums.DriverOption;
import online.sanen.unabo.api.structure.enums.Sorts;
import online.sanen.unabo.sql.factory.Unabo;
import online.sanen.unabo.template.jpa.*;
import lombok.Data;
import java.util.*;

public class CRUDExample {
    public static void main(String[] args) {
        try (Bootstrap bootstrap = Unabo.load(configuration -> {
            configuration.setUrl("jdbc:sqlite:crud.db");
            configuration.setDriverOption(DriverOption.SQLITE);
            configuration.setIsShowSql(true);
        })) {

            // 1. 创建表
            Map<String, Object> schema = new HashMap<>();
            schema.put("id", 1);
            schema.put("name", "");
            schema.put("email", "");
            schema.put("age", 0);
            bootstrap.queryMap("user", schema).setPrimary("id").create();

            // 2. 插入数据
            User user1 = new User();
            user1.setName("张三");
            user1.setEmail("zhangsan@example.com");
            user1.setAge(25);
            bootstrap.query(user1).insert();

            User user2 = new User();
            user2.setName("李四");
            user2.setEmail("lisi@example.com");
            user2.setAge(30);
            bootstrap.query(user2).insert();

            // 3. 查询数据
            List<User> users = bootstrap.queryTable("user")
                .addCondition(C.gte("age", 25))
                .sort(Sorts.DESC, "age")
                .list(User.class);
            System.out.println("查询结果: " + users);

            // 4. 更新数据
            user1.setAge(26);
            bootstrap.query(user1).setFields("age").update();

            // 5. 删除数据
            bootstrap.query(user2).delete();

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Data
    @Table(name = "user")
    public static class User {
        @Id
        private Integer id;
        private String name;
        private String email;
        private Integer age;
    }
}

下一步