核心技术靠化缘是要不来的——自己动手写ORM框架

SpringBoot和Vue法律咨询案件进度与智能文书管理系统源码 包含前后端源码、SQL初始化脚本和启动说明。JDK 17、Spring Boot、Vue;默认H2演示数据库。 立即下载

开源市场上的Java的ORM框架一个都不好用,所以花了几天时间自己撸了一个 OrmKids,欢迎大家下载学习。遇到问题请关注公众号进群大家一起讨论。

640?wx_fmt=jpeg

OrmKids

支持分库分表的MySQL单表ORM框架,暂用于学习,后续会在生产环境进行检验

功能特性

  1. 代码简洁,没有任何依赖项,除了使用时需要用到MySQL driver

  2. 易于使用,无须复杂的配置

  3. 提供自动创建表功能

  4. 支持分库又分表,可以只分库,也可以只分表

  5. 支持groupby/having

  6. 支持原生SQL

  7. 支持事件回调,可用于服务跟踪调试和动态sql改写

不支持多表关联

  1. 多表比较复杂,实现成本高,学习成本也高,容易出错

  2. 常用的多表的操作一般都可以使用多条单表操作组合实现

  3. 在分库分表的场合,很少使用多表操作

  4. 不使用外键,专注于sql逻辑

db.withinTx

对于复杂的多表查询和批量数据处理,可以使用该方法。

Q

用户可以使用Q对象构建复杂的SQL查询

其它数据库支持

暂时没有

实体接口

/**
 * 所有的实体类必须实现该接口
 */
public interface IEntity {

    /**
     * 表名
     * @return
     */
    String table();

    /**
     * 分表必须覆盖此方法
     * @return
     */
    default String suffix() {
        return null;
    }

    default String tableWithSuffix() {
        return tableWith(suffix());
    }

    default String tableWith(String suffix) {
        return Utils.tableWithSuffix(table(), suffix);
    }

    /**
     * 定义表的物理结构属性如engine=innodb,用于动态创建表
     * @return
     */
    TableOptions options();

    /**
     * 定义表的主键和索引信息,用于动态创建表
     * @return
     */
    TableIndices indices();

}

单表单主键

@Table
public class User implements IEntity {

    @Column(name = "id", type = "int", autoincrement = true, nullable = false)
    private Integer id;
    @Column(name = "name", type = "varchar(255)", nullable = false)
    private String name;
    @Column(name = "nick", type = "varchar(255)", nullable = false)
    private String nick;
    @Column(name = "passwd", type = "varchar(255)")
    private String passwd;
    @Column(name = "created_at", type = "datetime", nullable = false, defaultValue = "now()")
    private Date createdAt;

    public User() {
    }

    public User(String name, String nick, String passwd) {
        this.name = name;
        this.nick = nick;
        this.passwd = passwd;
    }

    public Integer getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public String getNick() {
        return nick;
    }

    public String getPasswd() {
        return passwd;
    }

    public Date getCreatedAt() {
        return createdAt;
    }

    @Override
    public TableOptions options() {
        return new TableOptions().option("engine", "innodb");
    }

    @Override
    public TableIndices indices() {
        return new TableIndices().primary("id").unique("name");
    }

    @Override
    public String table() {
        return "user";
    }

}

单表复合主键

@Table
public class Member implements IEntity {

    @Column(name = "user_id", type = "int", nullable = false)
    private Integer userId;
    @Column(name = "group_id", type = "int", nullable = false)
    private Integer groupId;
    @Column(name = "title", type = "varchar(255)")
    private String title;
    @Column(name = "created_at", type = "datetime", nullable = false, defaultValue = "now()")
    private Date createdAt;

    public Member() {
    }

    public Member(Integer userId, Integer groupId, String title, Date createdAt) {
        this.userId = userId;
        this.groupId = groupId;
        this.title = title;
        this.createdAt = createdAt;
    }

    public Integer getUserId() {
        return userId;
    }

    public Integer getGroupId() {
        return groupId;
    }

    public String getTitle() {
        return title;
    }

    public Date getCreatedAt() {
        return createdAt;
    }

    @Override
    public TableOptions options() {
        return new TableOptions().option("engine", "innodb");
    }

    @Override
    public TableIndices indices() {
        return new TableIndices().primary("user_id", "group_id");
    }

    @Override
    public String table() {
        return "member";
    }

}

分库接口

public interface IGridable<T extends IEntity> {

    /**
     * 根据实体对象选择分库索引
     */
    int select(int dbs, T t);

    /**
     * 根据特定参数选择分库索引
     */
    int select(int dbs, Object... params);

}

分库分表

@Table
public class BookShelf implements IEntity {

    public final static int PARTITIONS = 4;

    @Column(name = "user_id", type = "varchar(255)", nullable = false)
    private String userId;
    @Column(name = "book_id", type = "varchar(255)", nullable = false)
    private String bookId;
    @Column(name = "comment", type = "varchar(255)")
    private String comment;
    @Column(name = "created_at", type = "datetime", nullable = false, defaultValue = "now()")
    private Date createdAt;

    public BookShelf() {
    }

    public BookShelf(String userId, String bookId, String comment, Date createdAt) {
        this.userId = userId;
        this.bookId = bookId;
        this.comment = comment;
        this.createdAt = createdAt;
    }

    public String getUserId() {
        return userId;
    }

    public String getBookId() {
        return bookId;
    }

    public void setComment(String comment) {
        this.comment = comment;
    }

    public String getComment() {
        return comment;
    }

    public Date getCreatedAt() {
        return createdAt;
    }

    @Override
    public String table() {
        return "book_shelf";
    }

    @Override
    public TableOptions options() {
        return new TableOptions().option("engine", "innodb");
    }

    @Override
    public TableIndices indices() {
        return new TableIndices().primary("user_id", "book_id");
    }

    /* 
     * 分表策略
     */
    @Override
    public String suffix() {
        var crc32 = new CRC32();
        crc32.update(userId.getBytes(Utils.UTF8));
        return String.valueOf(Math.abs(crc32.getValue()) % PARTITIONS);
    }

    /**
     * 分库策略
     */
    public static class GridStrategy<D extends DB> implements IGridable<BookShelf> {

        @Override
        public int select(int dbs, BookShelf t) {
            return Math.abs(t.getUserId().hashCode()) % dbs;
        }

        @Override
        public int select(int dbs, Object... params) {
            String userId = (String) params[0];
            return Math.abs(userId.hashCode()) % dbs;
        }

    }

}

定义单个数据库

public class DemoDB extends DB {

    private DataSource ds;

    public DemoDB(String name, String uri) {
        this(name, new HashMap<>(), uri);
    }

    public DemoDB(String name, Map<Class<? extends IEntity>, Meta> metas, String uri) {
        super(name, metas);
        var ds = new MysqlConnectionPoolDataSource(); // 连接池
        ds.setUrl(uri);
        this.ds = ds;
    }

    @Override
    protected Connection conn() {  // 获取链接
        try {
            return ds.getConnection();
        } catch (SQLException e) {
            throw new KidsException(e);
        }
    }

}

定义网格数据库——分库

public class GridDemoDB extends GridDB<DemoDB> {

    /**
     * 传进来多个DB对象
     */
    public GridDemoDB(DemoDB[] dbs) {
        super(dbs);
        this.registerGridables();
    }

    /* 
     * 注册实体类的分库策略
     */
    @Override
    public void registerGridables() {
        this.gridWith(BookShelf.class, new BookShelf.GridStrategy<DemoDB>());
    }

}

单表单主键增删改查

public class DemoSimplePk {

    private final static String URI = "jdbc:mysql://localhost:3306/mydrc?user=mydrc&password=mydrc&useUnicode=true&characterEncoding=UTF8";

    public static void main(String[] args) {
        var db = new DemoDB("demo", URI);
        try {
            db.create(User.class); // 创建表
            var user = new User("test1", "nick1", "passwd1");
            db.insert(user); // 插入
            System.out.println(user.getId());
            user = db.get(User.class, user.getId());  // 主键查询
            System.out.printf("%s %s %s %s %s\n", user.getId(), user.getName(), user.getNick(), user.getPasswd(),
                    user.getCreatedAt());
            user = new User("test2", "nick2", "passwd2");
            db.insert(user); // 再插入
            var count = db.count(User.class); // 查询总行数
            System.out.println(count);
            var users = db.find(User.class);  // 列出所有行
            System.out.println(users.size());
            for (var u : users) {
                System.out.printf("%s %s %s %s %s\n", u.getId(), u.getName(), u.getNick(), u.getPasswd(),
                        u.getCreatedAt());
            }
            users = db.find(User.class, Q.eq_("nick"), "nick2"); // 条件查询
            System.out.println(users.size());
            var setters = new HashMap<String, Object>();
            setters.put("passwd", "whatever");
            db.update(User.class, setters, 2); // 修改
            users = db.find(User.class); // 再列出所有行
            System.out.println(users.size());
            for (var u : users) {
                System.out.printf("%s %s %s %s %s\n", u.getId(), u.getName(), u.getNick(), u.getPasswd(),
                        u.getCreatedAt());
            }
            db.delete(User.class, 1); // 删除
            db.delete(User.class, 2); // 再删除
            count = db.count(User.class); // 统计所有行
            System.out.println(count);
        } finally {
            db.drop(User.class); // 删除表
        }
    }

}

单表复合主键增删改查

public class DemoCompoundPk {
    private final static String URI = "jdbc:mysql://localhost:3306/mydrc?user=mydrc&password=mydrc&useUnicode=true&characterEncoding=UTF8";

    public static void main(String[] args) {
        var db = new DemoDB("demo", URI);
        try {
            db.create(Member.class);  // 建表
            var member = new Member(1, 2, "boss", null);
            db.insert(member); // 插入
            member = db.get(Member.class, 1, 2); // 主键查询
            System.out.println(member.getTitle());
            member = new Member(2, 2, "manager", new Date());
            db.insert(member); // 再插入
            var count = db.count(Member.class);  // 获取总行数 
            System.out.println(count);
            var members = db.find(Member.class); // 获取全部行
            for (var m : members) {
                System.out.printf("%d %d %s %s\n", m.getUserId(), m.getGroupId(), m.getTitle(), m.getCreatedAt());
            }
            member = new Member(2, 3, "manager", new Date());
            db.insert(member); // 再插入
            members = db.find(Member.class, Q.eq_("group_id"), 2);  // 条件查询
            for (var m : members) {
                System.out.printf("%d %d %s %s\n", m.getUserId(), m.getGroupId(), m.getTitle(), m.getCreatedAt());
            }
            var setters = new HashMap<String, Object>();
            setters.put("title", "employee");
            db.update(Member.class, setters, 2, 3); // 修改
            member = db.get(Member.class, 2, 3); // 主键查询
            System.out.println(member.getTitle());
            db.delete(Member.class, 1, 2); // 删除
            db.delete(Member.class, 2, 2); // 删除
            db.delete(Member.class, 2, 3); // 删除
            count = db.count(Member.class); // 再获取总行数
            System.out.println(count);
        } finally {
            db.drop(Member.class); // 删表
        }
    }

}

复杂查询

public class DemoComplexQuery {
    private final static String URI = "jdbc:mysql://localhost:3306/mydrc?user=mydrc&password=mydrc&useUnicode=true&characterEncoding=UTF8";

    public static void main(String[] args) {
        var db = new DemoDB("demo", URI);
        try {
            db.create(Exam.class); // 建表
            var random = new Random();
            for (var i = 0; i < 100; i++) {
                var userId = Math.abs(random.nextLong());
                var exam = new Exam(userId, random.nextInt(100), random.nextInt(100), random.nextInt(100),
                        random.nextInt(100), random.nextInt(100), random.nextInt(100));
                db.insert(exam); // 插入
            }
            System.out.println(db.count(Exam.class)); // 查询总行数
            // math >= 50
            var exams = db.find(Exam.class, Q.ge_("math"), 50); // 条件查询
            System.out.println(exams.size());
            var count = db.count(Exam.class, Q.ge_("math"), 50); // 条件总行数
            System.out.println(count);
            // math > 50 & english >= 50
            exams = db.find(Exam.class, Q.and(Q.gt_("math"), Q.ge_("english")), 50, 50); // 条件查询
            System.out.println(exams.size());
            count = db.count(Exam.class, Q.and(Q.gt_("math"), Q.ge_("english")), 50, 50); // 条件总行数
            System.out.println(count);
            // math > 50 || english >= 50
            exams = db.find(Exam.class, Q.or(Q.gt_("math"), Q.ge_("english")), 50, 50); // 条件查询
            System.out.println(exams.size());
            count = db.count(Exam.class, Q.or(Q.gt_("math"), Q.ge_("english")), 50, 50); // 条件总行数
            System.out.println(count);
            // math > 50 && (english >= 50 || chinese > 60)
            exams = db.find(Exam.class, Q.and(Q.gt_("math"), Q.or(Q.ge_("english"), Q.gt_("chinese"))), 50, 50, 60); // 条件查询
            System.out.println(exams.size());
            count = db.count(Exam.class, Q.and(Q.gt_("math"), Q.or(Q.ge_("english"), Q.gt_("chinese"))), 50, 50, 60); // 条件总行数
            System.out.println(count);
            // math > 50 || physics between 60 and 80 || chemistry < 60
            exams = db.find(Exam.class, Q.or(Q.gt_("math"), Q.between_("physics"), Q.lt_("chemistry")), 50, 60, 80, 60); // 条件查询
            System.out.println(exams.size());
            count = db.count(Exam.class, Q.or(Q.gt_("math"), Q.between_("physics"), Q.lt_("chemistry")), 50, 60, 80,
                    60); // 条件总行数
            System.out.println(count);
            // group by math / 10
            var q = Q.select().field("(math div 10) * 10 as mathx", "count(1)").table("exam").groupBy("mathx")
                    .having(Q.gt_("count(1)")).orderBy("count(1)", "desc"); // 复杂sql构造
            var rank = new LinkedHashMap<Integer, Integer>();
            db.any(Exam.class, q, stmt -> { // 原生sql查询
                stmt.setInt(1, 0);
                ResultSet rs = stmt.executeQuery();
                while (rs.next()) {
                    rank.put(rs.getInt(1), rs.getInt(2));
                }
                return rs;
            });
            rank.forEach((mathx, c) -> {
                System.out.printf("[%d-%d) = %d\n", mathx, mathx + 10, c);
            });
        } finally {
            db.drop(Exam.class);
        }
    }

}

分表

public class DemoPartitioning {
    private final static String URI = "jdbc:mysql://localhost:3306/mydrc?user=mydrc&password=mydrc&useUnicode=true&characterEncoding=UTF8";

    public static void main(String[] args) {
        var db = new DemoDB("demo", URI);
        try {
            for (int i = 0; i < BookShelf.PARTITIONS; i++) {
                db.create(BookShelf.class, String.valueOf(i)); // 创建所有分表
            }
            var bss = new ArrayList<BookShelf>();
            for (int i = 0; i < 100; i++) {
                var bs = new BookShelf("user" + i, "book" + i, "comment" + i, new Date());
                bss.add(bs);
                db.insert(bs); // 插入,自动插入相应分表
            }
            for (int i = 0; i < BookShelf.PARTITIONS; i++) {
                System.out.printf("partition %d count %d\n", i, db.count(BookShelf.class, String.valueOf(i)));
            }
            Random random = new Random();
            for (var bs : bss) {
                bs.setComment("comment_update_" + random.nextInt(100));
                db.update(bs); // 更新,自动更新相应分表数据
            }
            bss = new ArrayList<BookShelf>();
            for (int i = 0; i < BookShelf.PARTITIONS; i++) {
                bss.addAll(db.find(BookShelf.class, String.valueOf(i))); // 指定分表列出所有行
            }
            for (var bs : bss) {
                System.out.println(bs.getComment());
            }
            for (var bs : bss) {
                db.delete(bs); // 挨个删除,自动删除相应分表数据
            }
        } finally {
            for (int i = 0; i < BookShelf.PARTITIONS; i++) {
                db.drop(BookShelf.class, String.valueOf(i)); // 删除所有分表
            }
        }
    }

}

分库

public class DemoSharding {

    private static DemoDB[] dbs = new DemoDB[3];
    static {
        Map<Class<? extends IEntity>, Meta> metas = new HashMap<>();
        dbs[0] = new DemoDB("demo-0", metas,
                "jdbc:mysql://localhost:3306/mydrc?user=mydrc&password=mydrc&useUnicode=true&characterEncoding=UTF8");
        dbs[1] = new DemoDB("demo-1", metas,
                "jdbc:mysql://localhost:3307/mydrc?user=mydrc&password=mydrc&useUnicode=true&characterEncoding=UTF8");
        dbs[2] = new DemoDB("demo-2", metas,
                "jdbc:mysql://localhost:3308/mydrc?user=mydrc&password=mydrc&useUnicode=true&characterEncoding=UTF8");
    }

    public static void main(String[] args) {
        var grid = new GridDemoDB(dbs); // 构造Grid实例
        try {
            for (int k = 0; k < BookShelf.PARTITIONS; k++) {
                grid.create(BookShelf.class, String.valueOf(k)); // 创建所有分库中的分表
            }
            var bss = new ArrayList<BookShelf>();
            for (int i = 0; i < 100; i++) {
                var bs = new BookShelf("user" + i, "book" + i, "comment" + i, new Date());
                bss.add(bs);
                grid.insert(bs); // 插入,自动分发到相应的分库中的分表
            }
            for (int k = 0; k < grid.size(); k++) {
                for (int i = 0; i < BookShelf.PARTITIONS; i++) {
                    System.out.printf("db %d partition %d count %d\n", k, i,
                            grid.count(BookShelf.class, k, String.valueOf(i))); // 依次查询出所有分库的分表的行数
                }
            }
            Random random = new Random();
            for (var bs : bss) {
                bs.setComment("comment_update_" + random.nextInt(100));
                grid.update(bs); // 更新,自动分发到相应的分库中的分表
            }
            for (var bs : bss) {
                bs = grid.get(BookShelf.class, bs.getUserId(), bs.getBookId()); // 主键查询,自动分发到相应的分库中的分表
                System.out.println(bs.getComment());
            }
            for (var bs : bss) {
                grid.delete(bs); // 删除,自动分发到相应的分库中的分表
            }
            for (int k = 0; k < grid.size(); k++) {
                for (int i = 0; i < BookShelf.PARTITIONS; i++) {
                    System.out.printf("db %d partition %d count %d\n", k, i,
                            grid.count(BookShelf.class, k, String.valueOf(i))); // 依次查询出所有分库的分表的行数
                }
            }
        } finally {
            for (int k = 0; k < BookShelf.PARTITIONS; k++) {
                grid.drop(BookShelf.class, String.valueOf(k)); // 删除所有分库中的分表
            }
        }
    }

}

事件上下文对象

public class Context {

    private DB db; // 数据库实例
    private Connection conn;  // 当前的链接
    private Class<? extends IEntity> clazz; // 当前的实体类
    private Q q; // 查询sql
    private Object[] values; // 查询的绑定参数
    private boolean before; // before or after
    private Exception error; // 异常
    private long duration; // 耗时microsecond

}

事件回调

public class DemoEvent {

    private final static String URI = "jdbc:mysql://localhost:3306/mydrc?user=mydrc&password=mydrc&useUnicode=true&characterEncoding=UTF8";

    public static void main(String[] args) {
        var db = new DemoDB("demo", URI);
        db.on(ctx -> { // 全局事件回调
            System.out.printf("db=%s sql=%s cost=%dus\n", ctx.db().name(), ctx.q().sql(), ctx.duration());
            return true; // 返回false会导致事件链终止,后续的ORM操作也不会执行
        });
        try {
            db.create(User.class);
            db.scope(ctx -> { // 范围回调,execute方法内部的所有ORM操作都会回调
                System.out.printf("db=%s sql=%s cost=%dus\n", ctx.db().name(), ctx.q().sql(), ctx.duration());
                return true;
            }).execute(() -> {
                db.count(User.class);
                db.find(User.class);
            });
        } finally {
            db.drop(User.class); // 删除表
        }
    }

}

640?wx_fmt=jpeg

关注公众号【码洞】,欢迎大家一起进群讨论

汽车电子基于OTA的Bootloader更新机制:量产车软件升级断点版本限制与跨代更新规避策略 内容概要:本文深入剖析了量产汽车ECU中Bootloader在OTA升级过程中为何无法跨“断点版本”升级的核心原理。文章从Bootloader作为可信根的不可变性出发,解释了其在SOP后禁止常规OTA更新的原因,并揭示了Flash分区机制下OTA仅能擦写Application区的限制。通过介绍“两段式搬运”自更新机制,阐明了新版Bootloader需依赖旧版Bootloader执行迁移的“鸡生蛋”困境,进而引出断点版本的概念——即首次引入新Bootloader特性的关键过渡版本。文中详细列举了导致断点的典型变更(如签名算法、分区表等),并指出跨版本升级失败的根本原因在于旧Bootloader无法解析新镜像格式或执行更新流程。最后提出系统性解决方案,包括构建有向升级路径图、终端前置校验、A/B冗余、Golden恢复区等工程防护措施,强调需从架构、发布、OTA后台到售后体系全流程协同管理断点风险。; 适合人群:汽车电子工程师、车载软件开发人员、OTA系统设计师及从事ECU固件升级相关的技术管理人员,尤其适合具备嵌入式系统和UDS诊断基础的研发人员。; 使用场景及目标:①理解Bootloader在OTA中的核心作用及其不可随意更新的设计逻辑;②掌握断点版本的成因与应对策略,避免实际升级中出现“变砖”事故;③指导OTA系统设计与升级路径规划,提升整车软件迭代的安全性与可靠性。; 阅读建议:此资源结合真实工程场景深入浅出地讲解复杂机制,建议结合Bootloader自更新流程图与实际UDS刷写案例对照学习,重点关注版本兼容性判断、安全校验设计及故障恢复机制,在开发和测试中充分模拟跨断点升级场景以验证系统鲁棒性。 立即下载

相关推荐

Delphi 13.2控件之TdsProxy.rar

Delphi 13.2控件之TdsProxy.rar

tableIndex

.caret辅助类显示下拉功能 .dropdown-menu显示下拉框 class=”dropdown-header” 下拉菜单表头 divider 分离的下划线H5 role role 是增强语义性,当现有的 HTML标签 不能充分表达语义性的时候,就可以借助role来说明。 Tabindex = -1 用处就是,当你填写完第一个文本框时会自动走到下一个,不会乱串。tabIn

枫的博客 1740

电力电子基于CCM Boost拓扑的3.3kW PFC电路参数设计:功率因数校正系统电感与器件选型优化

摘要:工程计算最难的不是算出来,而是「算完讲得清、改得动」。本文以一份 《3.3kW CCM BOOST PFC circuit parameters calculation》计算书为例,梳理 Maple Flow 的核心功能,并看它如何把规格、公式、器件选型、损耗校验和环路设计收进同一份可交付文档。

码洞原创深度技术文章大全 —— 高端面试必备

《快学 Go 语言》第 11 课 —— 协程《快学 Go 语言》第 10 课 —— 错误与异常《快学 Go 语言》第 9 课 —— 接口《快学 Go 语言》第 8 课 —...

codehole_的博客 293

政府科技管理者在推动科技成果转化过程中,如何精准识别具有高转化潜力的科技成果?.docx

政府科技管理者在推动科技成果转化过程中,如何精准识别具有高转化潜力的科技成果?

政府科技管理者如何精准识别本区域高校科研成果的技术转化潜力?.docx

科易网基于AI模型+行业大数据,在技术转移、成果转化、技术经纪、知识产权、产业创新、科技招商等垂直领域的多样化应用场景,推出科技创新领域的AI+工具与数智化解决方案,推动科技创新与产业创新智能化发展。

双向全桥CLLC谐振变换器仿真模型(Simulink仿真实现)

内容概要:本文系统介绍了双向全桥CLLC谐振变换器的Simulink仿真模型,重点阐述了变频控制、闭环仿真及其与多种电力电子拓扑(如维也纳整流器、DAB变换器、图腾柱PFC等)的联合仿真设计。资源包涵盖2.5kW双向全桥LLC、V2G电动汽车充放电系统、三相PFC、多相交错LLC等多种变换器的仿真案例,并深入展示了三电平VIENNA整流器在双闭环PI控制与SVPWM调制策略下,结合上下电容电压差值补偿实现中点电位平衡的先进控制方法。通过仿真验证,该策略不仅有效维持了800V直流母线电压的稳定,还在动态工况下显著提升了电容电压的均衡度,同时保持了较低的输入电流THD,充分体现了SVPWM与中点平衡控制协同优化的技术优势。; 适合人群:具备电力电子与自动控制理论基础,从事新能源发电、电动汽车、工业电源、微电网等领域的研究生、工程师及科研人员。; 使用场景及目标:① 学习并构建高频谐振变换器(如LLC、CLLC)的Simulink仿真模型,掌握其变频与混合控制策略;② 深入理解并应用中点电位平衡、双闭环PI控制、SVPWM调制等核心技术于VIENNA等三电平变换器中;③ 复现高水平期刊论文中的控制算法,服务于科研项目申报、学术论文撰写或工程产品开发。; 阅读建议:该资源为综合性仿真资料库,建议使用者结合自身研究方向(如电动汽车充电、新能源并网)选择对应案例进行精学,重点关注控制策略的设计逻辑、仿真参数的整定方法以及SVPWM与中点平衡的协同机制,并充分利用附带的计算书和参考文献深化理解,以实现从仿真模型到实际工程应用的顺利转化。

国央企创新负责人如何利用数智工具提升技术引进与消化吸收能力?.docx

国央企创新负责人如何利用数智工具提升技术引进与消化吸收能力?

全桥LLC谐振软开关Simulink仿真设计

内容概要:本文系统介绍了全桥LLC谐振软开关在Simulink环境下的仿真设计,涵盖单相、三相、双向全桥、半桥及多相交错并联等多种LLC谐振变换器拓扑结构,重点研究软开关技术、变频控制、移相混合控制、闭环仿真建模与关键参数设计。详细展示了全桥LLC谐振变换器的闭环仿真模型构建流程,包括开环与闭环控制策略、软启动机制、恒压恒流双闭环控制体系,并结合Mathcad进行精确的参数计算。此外,文档还整合了丰富的电力电子系统仿真案例,如PFC变换器、PWM整流器、CLLC变换器等,充分体现了该资源在电力电子变换器仿真设计中的全面性与实用价值; 适合人群:具备电力电子、自动化或电气工程等相关专业背景,熟悉Simulink/Matlab仿真工具,从事电源变换器设计、新能源系统开发或电力系统仿真的研究生、科研人员及工程技术人员; 使用场景及目标:①用于深入学习和掌握LLC谐振变换器的工作原理与系统级仿真建模方法;②支撑软开关技术、闭环控制策略、谐振参数优化等方面的科研攻关与工程项目开发;③作为高校电力电子课程教学、实验设计或毕业设计的重要参考资料,全面提升仿真实践能力与工程设计素养; 其他说明:该资源不仅提供完整的Simulink/Plecs仿真模型,还配套提供详细的设计报告、参数计算书、说明PPT及参考文献,有助于用户深入理解设计逻辑与实现细节,建议结合公众号“荔枝科研社”获取全套资料与持续的技术支持。

产业园区运营负责人如何精准对接企业技术需求与科研成果?.docx

科易网基于AI模型+行业大数据,在技术转移、成果转化、技术经纪、知识产权、产业创新、科技招商等垂直领域的多样化应用场景,推出科技创新领域的AI+工具与数智化解决方案,推动科技创新与产业创新智能化发展。

邻传 NearShare v1.3.0|Windows局域网扫码文件互传、Word/Excel预览与直接打印(含MIT源码)

邻传是一款运行在 Windows 10/11 x64 电脑上的局域网文件共享工具。手机与电脑连接同一 Wi-Fi,扫码后使用浏览器双向上传、下载文件,无需蓝牙、手机 App 或配对码。 功能:同名文件以最后成功上传版本为准并保留历史;Word DOC/DOCX、Excel XLS/XLSX/XLSB/XLSM、ODS/CSV 在线预览;电脑端点击直接调出打印界面;类型筛选、搜索、列表/网格、批量删除和清空;自动识别电脑名称及可获取的手机型号,自动更新 IP 与二维码。 包内包含安装版、免安装版、MIT 协议源码、使用说明和 SHA-256 校验值,内置 Node.js,无需安装开发环境,不含个人共享数据。 使用:电脑启动 → 手机同一 Wi-Fi 扫码 → 上传/预览/下载。适合家庭、可信办公网络分享照片与文档。 限制:无登录、HTTP,能访问服务地址的设备可读写删除,请勿映射公网。Office 复杂排版可能简化;预览上限20MB,表格预览1000行50列;打印上限20MB/10万格/100页PDF,仅电脑支持。为手动分享工具,非自动文件夹同步。安装包暂未数字签名。

超全Mathcad全桥LLC谐振变换器开关电源设计mathcad计算书

内容概要:本文档为《超全Mathcad全桥LLC谐振变换器开关电源设计mathcad计算书》,系统性地围绕全桥LLC谐振变换器的开关电源设计展开,重点基于Mathcad平台进行详细的理论计算与参数设计,适用于2.5kW功率等级的电源系统。内容涵盖LLC谐振变换器的核心建模、闭环仿真、关键参数(如谐振电感Lr、励磁电感Lm、谐振电容Cr)优化设计,以及变频控制、移相控制等先进控制策略的实现方法。资源配套齐全,提供Simulink/Plecs仿真模型、设计报告与计算书,支持从理论推导到仿真验证的全流程开发。此外,还包含多相交错、双向全桥CLLC、软启动控制、恒压恒流双闭环等多种高级设计案例,突出其在工程实践与科研复现中的高实用价值。; 适合人群:具备电力电子与电源系统基础知识的高校研究生、科研人员及从事开关电源研发的工程师,尤其适用于需要完成LLC谐振变换器建模、参数设计与控制算法开发的技术人员。; 使用场景及目标:①用于全桥LLC谐振变换器的关键参数设计与Mathcad计算验证;②结合Simulink/Plecs仿真开展闭环控制策略研究,如变频与移相结合控制;③支撑科研项目中的拓扑创新与控制算法复现,提升设计效率与仿真精度; 阅读建议:建议结合配套的仿真模型与计算书同步操作,重点关注谐振参数的计算逻辑与闭环稳定性分析,推荐按照文档目录顺序系统学习,以全面掌握从理论设计到仿真验证的完整开发流程。

产业园区如何高效匹配企业技术需求与高校科研成果?.docx

科易网基于AI模型+行业大数据,在技术转移、成果转化、技术经纪、知识产权、产业创新、科技招商等垂直领域的多样化应用场景,推出科技创新领域的AI+工具与数智化解决方案,推动科技创新与产业创新智能化发展。

上一篇: 码洞技术文章大全
下一篇: 程序员的心理疾病
codehole_
博客等级 码龄7年 34粉丝 132原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值