标签 Maven 下的文章

在当今的数据驱动时代,不同系统间的数据交换与集成已成为常态。Excel作为常见的报表和数据存储格式,XML作为一种跨平台的数据交换标准,它们之间的相互转换是Java开发者经常面临的实际需求。无论是将Excel数据导出为XML进行API调用,还是将接收到的XML数据导入Excel进行可视化分析,都需要一套高效可靠的解决方案。本文将深入探讨如何利用强大的Spire.XLS for Java库,在Java环境中轻松实现Excel到XML以及XML到Excel的灵活转换,帮助你提升数据处理效率。

Spire.XLS for Java 库简介与安装

Spire.XLS for Java是一个功能丰富的Excel操作库,它允许开发者在Java应用程序中创建、读取、编辑、转换和打印Excel文件,无需依赖Microsoft Office。其特点是API直观、性能高效,并且支持多种Excel文件格式(如XLS、XLSX、CSV等)与XML、PDF、HTML等格式的转换。

要开始使用Spire.XLS for Java,你需要在项目构建文件中添加相应的依赖。

Maven 依赖:

将下列代码添加到 pom.xml 文件中,以导入 JAR 文件

<repositories>
    <repository>
        <id>com.e-iceblue</id>
        <name>e-iceblue</name>
        <url>https://repo.e-iceblue.cn/repository/maven-public/</url>
    </repository>
</repositories>
<dependencies>
    <dependency>
        <groupId>e-iceblue</groupId>
        <artifactId>spire.xls</artifactId>
        <version>16.1.3</version>
    </dependency>
</dependencies>

在 Java 中将 Excel 转换为 XML

将Excel数据转换为XML在数据集成、Web服务交互或自定义数据存储方面非常常见。Spire.XLS支持将整个工作簿或指定工作表的数据导出为XML格式。该库提供了灵活的选项来控制XML的输出结构。

以下示例展示了如何将一个Excel工作簿转换为XML文件:

import com.spire.xls.*;

public class ExcelToXML {
    public static void main(String[] args) {
        //创建Workbook类的对象
        Workbook wb = new Workbook();

        //加载Excel文档
        wb.loadFromFile("input.xlsx");

        //保存为XML文件
        wb.saveAsXml("ToXML.xml");
    }
}
  • 首先创建一个Workbook对象,然后使用loadFromFile()加载示例的Excel文件。
  • wb.saveAsXml()方法将刚在加载的Excel文件保存为XML格式。

在 Java 中将 XML 转换为 Excel

反向转换,即将XML数据导入到Excel中,同样是常见的需求,尤其是在处理来自Web服务或配置文件的数据时。Spire.XLS能够解析XML数据并将其填充到Excel工作表中。

以下代码展示了如何将一个XML文件转换为Excel文件:

import com.spire.xls.*;

public class XmlToExcel {
    public static void main(String[] args) {
        //创建Workbook类的对象
        Workbook wb = new Workbook();

        //加载XML文档
        wb.loadFromXml("sample.xml");

        //转为xlsx格式的Excel
        wb.saveToFile("toExcel.xlsx",FileFormat.Version2013);
    }
}
  • 首先创建一个Workbook对象,然后使用loadFromXml加载XML文件。
  • 调用saveToFile()将XML文件保存为Excel工作簿。

注意: 上述XML转Excel示例中的XML解析部分是基于一个简单、扁平化的XML结构。对于复杂的、嵌套的XML结构,你需要更复杂的解析逻辑来映射到Excel的行和列。

结语

通过本文的介绍和代码示例,我们详细探讨了如何在Java环境中,利用Spire.XLS for Java库实现Excel与XML文件的双向转换。无论是将Excel数据高效导出为XML,还是将XML数据灵活导入到Excel中进行处理,Spire.XLS都提供了直观且功能强大的API支持。掌握这些转换技巧,将极大地增强你在数据处理、系统集成和报表自动化方面的能力。希望本文能为你提供有价值的参考,助你在实际项目中更加游刃有余地处理各种文件转换需求。


MyBatis Dynamic SQL 是一种类型安全的 Java 领域特定语言(DSL),用于通过编程方式构建 SQL 查询,而非编写 SQL 字符串或基于 XML 的动态查询。它在运行时使用流畅的 Java 构建器生成 SQL,同时仍通过标准的 MyBatis 映射器执行。与手动拼接字符串或复杂的 XML 逻辑相比,这使得查询构建更安全、更易于重构,并且更不容易出错。

由于查询是用 Java 编写的,列名和表引用通过强类型的元数据类在编译时进行验证,这提供了更好的 IDE 支持并减少了运行时 SQL 错误。本文将解释 MyBatis Dynamic SQL,并展示如何在 Java 应用程序中使用它。

1. 使用 MyBatis Dynamic SQL 可以做什么?

MyBatis Dynamic SQL 支持大多数常见的 SQL 操作,包括 SELECTINSERTUPDATEDELETE,以及连接、子查询、分页、排序、条件过滤和批量操作。它允许我们逐步构建查询,仅在某些参数存在时添加条件,这使其成为搜索界面和过滤 API 的理想选择。

它直接与 MyBatis 映射器接口集成,意味着我们仍然可以受益于结果映射、事务处理和连接管理。由于它生成标准的 SQL,因此适用于 MyBatis 支持的任何数据库,没有供应商锁定的问题。

1.1 MyBatis Dynamic SQL 的工作原理

Dynamic SQL 基于两个组件:表元数据类和 DSL 构建器。元数据类用 Java 描述表和列。DSL 构建器使用这些类以流畅、类型安全的方式组装 SQL 语句。

DSL 不直接执行 SQL。相反,它生成语句提供者对象,例如 SelectStatementProviderInsertStatementProvider。这些对象被传递给使用 @SelectProvider@InsertProvider 及类似注解标注的映射器方法,然后 MyBatis 使用其正常的执行引擎来执行这些语句。

2. 项目设置与依赖

Maven 依赖

<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.5.15</version>
</dependency>

<dependency>
    <groupId>org.mybatis.dynamic-sql</groupId>
    <artifactId>mybatis-dynamic-sql</artifactId>
    <version>1.5.2</version>
</dependency>

<dependency>
    <groupId>com.h2database</groupId>
    <artifactId>h2</artifactId>
    <version>2.4.240</version>
    <scope>runtime</scope>
</dependency>

这些依赖项包括 MyBatis 本身、Dynamic SQL DSL 以及一个用于测试的嵌入式数据库。

注意
数据库驱动可以替换为 MySQL、PostgreSQL 或任何其他支持的数据库。MyBatis Dynamic SQL 不依赖于数据库类型,仅依赖于标准 SQL 生成。

数据库模式

schema.sql

CREATE TABLE users (
    id BIGINT AUTO_INCREMENT PRIMARY KEY,
    username VARCHAR(50) NOT NULL,
    email VARCHAR(100),
    age INT
);

INSERT INTO users(username, email, age) VALUES
('thomas', 'thomas@jcg.com', 30),
('benjamin', 'benjamin@jcg.com', 22),
('charles', 'charles@jcg.com', 17);

此脚本创建一个简单的表并插入测试数据。内存中的 H2 数据库将在启动时执行此脚本,因此无需外部依赖即可测试查询。

领域模型

public class User {

    private Long id;
    private String username;
    private String email;
    private Integer age;

    // Getter 和 Setter 方法...
}

这个 POJO 代表数据库中的一行。MyBatis 会自动使用匹配的字段名将列映射到字段,因此本例不需要额外的结果映射。

3. 用于 Dynamic SQL 的表元数据

下面的类以类型安全的方式定义数据库表及其列,允许在构建查询时被 Dynamic SQL DSL 引用。它充当 Java 代码与实际数据库结构之间的桥梁,实现了列名和类型的编译时验证。

public final class UserDynamicSqlSupport {

    public static final User user = new User();

    public static final SqlColumn<Long> id = user.id;
    public static final SqlColumn<String> username = user.username;
    public static final SqlColumn<String> email = user.email;
    public static final SqlColumn<Integer> age = user.age;

    public static final class User extends SqlTable {

        public final SqlColumn<Long> id = column("id", JDBCType.BIGINT);
        public final SqlColumn<String> username = column("username", JDBCType.VARCHAR);
        public final SqlColumn<String> email = column("email", JDBCType.VARCHAR);
        public final SqlColumn<Integer> age = column("age", JDBCType.INTEGER);

        public User() {
            super("users");
        }
    }
}

这个类为 users 表定义了类型安全的元数据,使 MyBatis Dynamic SQL 可以在不使用原始 SQL 字符串的情况下构建查询。DSL 使用这些 Java 对象而非按名称引用列,从而提高了安全性和 IDE 支持。

内部类 User 继承 SqlTable,这将其标记为可用于 from(user) 和连接等子句的数据表。构造函数调用 super("users") 来告知 MyBatis 要在 SQL 语句(如 FROM users)中呈现的确切表名。

每个列都使用 SqlTable 中的 column() 方法定义,该方法注册列名及其 JDBC 类型。这会产生强类型的 SqlColumn<T> 对象,确保比较和条件在编译时使用正确的 Java 类型。

外部类公开了对表及其列的静态引用,以便于静态导入,使得查询读起来很自然,例如:select(id, username).from(user),同时保持完全的类型安全和重构友好。

映射器接口

@Mapper
public interface UserMapper {

    @SelectProvider(type = SqlProviderAdapter.class, method = "select")
    List<User> selectMany(SelectStatementProvider selectStatement);
}

@Mapper 注解告诉 MyBatis 此接口应注册为映射器并在运行时进行代理。MyBatis 会自动生成实现,因此不需要具体的类。

selectMany 方法接受一个 SelectStatementProvider,它封装了完全呈现的 SQL 语句及其参数。MyBatis 执行该语句并将每个结果行映射到 User 对象,将它们作为 List<User> 返回。

@SelectProvider 注解指定 SQL 将由 MyBatis Dynamic SQL 的一部分 SqlProviderAdapter 动态提供。实际的 SQL 是在运行时从使用 DSL 构建的 SelectStatementProvider 生成的,而不是在注解或 XML 中编写 SQL。

4. 构建动态查询

在这里,我们使用流畅的 Dynamic SQL DSL 构建 SQL 语句,而不是编写原始 SQL 字符串。

public static void main(String[] args) throws Exception {

    MyBatisUtil.runSchema();

    try (SqlSession session = MyBatisUtil.getSession()) {

        UserMapper mapper = session.getMapper(UserMapper.class);

        SelectStatementProvider select
                = select(id, username, email, age)
                        .from(user)
                        .where(age, isGreaterThan(18))
                        .and(username, isLike("%tho%"))
                        .orderBy(username)
                        .build()
                        .render(RenderingStrategies.MYBATIS3);

        List<User> users = mapper.selectMany(select);

        users.forEach(u
                -> System.out.println(u.getUsername() + " - " + u.getAge()));
    }
}

此代码使用流畅的 Dynamic SQL DSL 动态构建一个 SELECT 查询,并将其渲染为与 MyBatis 兼容的语句提供者。通过以编程方式添加条件,它能够以类型安全且可维护的方式创建复杂的过滤器。在本例中,查询选择 age 大于 18 岁且 username 包含 "tho" 的用户,然后按用户名字母顺序对结果进行排序。

MyBatis 工具类

public class MyBatisUtil {

    private static SqlSessionFactory factory;

    static {
        try {
            Reader reader = Resources.getResourceAsReader("mybatis-config.xml");
            factory = new SqlSessionFactoryBuilder().build(reader);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public static SqlSession getSession() {
        return factory.openSession(true);
    }

    public static void runSchema() throws IOException, SQLException {
        try (SqlSession session = getSession()) {
            Connection conn = session.getConnection();
            Statement stmt = conn.createStatement();

            try (InputStream is = Resources.getResourceAsStream("schema.sql")) {
                String sql = new String(is.readAllBytes(), StandardCharsets.UTF_8);
                stmt.execute(sql);
            }
        }
    }
}

此工具类加载 MyBatis 配置,构建 SqlSessionFactory,并提供对数据库会话的访问。它还通过执行 SQL 脚本(schema.sql)手动初始化数据库模式。

5. 使用 Dynamic SQL 进行插入、更新和删除

MyBatis 中的 Dynamic SQL 允许我们使用流畅的 DSL 以编程方式构造 INSERT、UPDATE 和 DELETE 语句。在此,我们演示如何执行这些常见的数据操作。

// INSERT
User newUser = new User();
newUser.setUsername("andrew");
newUser.setEmail("andrew@jcg.com");
newUser.setAge(28);

InsertStatementProvider<User> insert
        = insert(newUser)
                .into(user)
                .map(username).toProperty("username")
                .map(email).toProperty("email")
                .map(age).toProperty("age")
                .build()
                .render(RenderingStrategies.MYBATIS3);

int inserted = mapper.insert(insert);
System.out.println("Rows inserted: " + inserted);

// UPDATE
UpdateStatementProvider update
        = update(user)
                .set(age).equalTo(35)
                .where(username, isEqualTo("thomas"))
                .build()
                .render(RenderingStrategies.MYBATIS3);

int updated = mapper.update(update);
System.out.println("Rows updated: " + updated);

// DELETE
DeleteStatementProvider delete
        = deleteFrom(user)
                .where(age, isLessThan(18))
                .build()
                .render(RenderingStrategies.MYBATIS3);

int deleted = mapper.delete(delete);
System.out.println("Rows deleted: " + deleted);

相同的 DSL 风格也用于写操作。语句以流畅的方式构建、渲染,然后由映射器提供者方法执行。

  • INSERT:创建一个新的 User 对象并填充值。使用 Dynamic SQL DSL,我们将其字段映射到表列并生成 InsertStatementProvider。映射器执行插入操作,返回受影响的行数。
  • UPDATE:DSL 构建一个更新语句,将用户名为 "thomas" 的用户的年龄设置为 35。这确保只修改目标行,映射器执行更新。
  • DELETE:删除语句移除所有年龄小于 18 岁的用户。在 DSL 中使用条件保证了类型安全并避免了字符串拼接。

更新后的映射器接口

为了支持这些操作,映射器接口必须包含用于 INSERT、UPDATE 和 DELETE 的方法,使用 MyBatis Dynamic SQL 提供者。

// INSERT
@InsertProvider(type = SqlProviderAdapter.class, method = "insert")
int insert(InsertStatementProvider<User> insertStatement);

// UPDATE
@UpdateProvider(type = SqlProviderAdapter.class, method = "update")
int update(UpdateStatementProvider updateStatement);

// DELETE
@DeleteProvider(type = SqlProviderAdapter.class, method = "delete")
int delete(DeleteStatementProvider deleteStatement);

映射器中的每个方法处理一个特定的 DML 操作(插入、更新或删除),并接受一个封装了生成的 SQL 及其参数的 InsertStatementProviderUpdateStatementProviderDeleteStatementProvider。这种方法允许所有写操作都在 Java 中以编程方式表达,而无需手动组合 SQL 字符串,同时仍能利用 MyBatis 高效地执行语句和映射结果。

6. 结论

在本文中,我们探讨了如何在 Java 应用程序中使用 MyBatis Dynamic SQL 来创建类型安全、可维护且可编程的 SQL 查询。通过将 SQL 构建与执行分离,MyBatis Dynamic SQL 简化了复杂查询逻辑的处理,降低了错误风险,并提高了代码可读性。这种方法非常适合查询需要动态变化或经常修改的应用程序。

7. 下载源代码

本文讨论了 MyBatis Dynamic SQL 及其在 Java 中的使用方法。

下载

您可以通过此处下载此示例的完整源代码:java mybatis dynamic sql


【注】本文译自:Getting Started with MyBatis Dynamic SQL

一、发布前必知:价值与前提

为什么要发布到 Maven 中央仓库?

  • 全局可访问:任何使用 Maven、Gradle 的开发者都能轻松引入,无需额外配置私有仓库
  • 标准化保障:遵循严格的发布规范,提升组件的可信度与安全性
  • 版本自动管理:中央仓库会妥善保存各版本,避免依赖冲突与版本混乱
  • 社区认可:开源共享是技术成长的重要途径,优质组件能获得更多反馈与迭代

发布前提

  • 组件非敏感信息:中央仓库所有内容公开,严禁发布企业私有代码或涉密逻辑
  • 遵守开源协议:推荐使用 Apache License 2.0 等主流开源协议,避免版权纠纷
  • 准备必要工具:已安装 Maven(配置好环境变量)、可访问 GitHub/Gitee 等代码仓库

二、核心步骤:从配置到发布全流程

第一步:Sonatype 平台配置(获取发布权限)

Maven 中央仓库由 Sonatype 维护,所有发布操作需通过其平台授权:

  1. 访问 Sonatype 官网注册或登录账号,建议绑定常用邮箱
    image.png
  2. 申请 Namespace:登录后进入 Publish 页面,点击 "Add Namespace",格式需遵循反向 DNS 规则
  • 有自有域名:如 www.example.com 对应 com.example
  • 无域名:使用代码仓库地址,GitHub 用户填 io.github. 用户名,Gitee 用户填 io.gitee. 用户名
    image.png
  1. 验证 Namespace:点击 "Verify Namespace",系统会生成验证密钥,需在对应代码仓库创建同名公开仓库,完成后点击 "Verify Namespace",显示 "Verified" 即通过
    image.png
    image.png
  2. 生成访问 Token:点击右上角用户名 →View Account→Generate User Token,复制生成的用户名和密码,后续用于 Maven 认证(仅显示一次,务必保存)
    image.png
    image.png
    image.png

第二步:GPG 密钥配置(保障代码安全)

为防止组件被篡改,中央仓库要求所有发布的文件必须经过 GPG 签名:

  1. 下载安装 GPG:前往 GnuPG 官网,根据系统选择对应版本(Windows 选 Gpg4win,Mac 选 Mac GPG)
    image.png
  2. 生成密钥对:打开终端 / 命令提示符,输入 gpg --gen-key,按提示填写真实姓名、邮箱(与 Sonatype 账号一致),设置密钥密码并牢记
    image.png
    image.png
  3. 记录密钥 ID:生成成功后,找到输出中 "pub" 行后的一串字符(如 519314C3477B2B3122A13EC8123FB84FB9BC06DE),这是你的公钥 ID
    image.png
  4. 上传公钥至公共服务器:执行 gpg --keyserver hkp://keyserver.ubuntu.com:11371 --send-keys 你的密钥ID,让中央仓库能验证签名合法性
  5. 验证 gpg 秘钥: 有两种方式可以验证秘钥,一种是通过 gpg 命令: gpg --keyserver keyserver.ubuntu.com --recv-keys xxxxxx;另外一种方式直接到 https://keyserver.ubuntu.com/秘钥平台查询:
    image.png
    image.png
    出现以上内容表明秘钥发布成功。

第三步:Maven 环境配置(关联认证信息)

打开 Maven 的 settings.xml 文件(通常在 conf 目录下),添加以下配置:

<!-- Sonatype访问权限配置 -->
<servers>
    <server>
        <id>central</id>
        <username>Sonatype生成的Token用户名</username>
        <password>Sonatype生成的Token密码</password>
    </server>
</servers>
<!-- GPG签名配置 -->
<profiles>
    <profile>
        <id>gpg</id>
        <properties>
            <gpg.executable>gpg</gpg.executable>
            <gpg.keyname>你的GPG绑定邮箱</gpg.keyname>
            <gpg.passphrase>你的GPG密钥密码</gpg.passphrase>
            <gpg.useagent>true</gpg.useagent>
        </properties>
    </profile>
</profiles>

第四步:项目 POM 文件配置(标准化组件信息)

修改待发布项目的 pom.xml,补充必要信息(直接复制替换占位符即可):

<project>
    <!-- 核心信息:GroupID需与验证通过的Namespace一致 -->
    <groupId>io.github.你的用户名</groupId>
    <artifactId>组件名称</artifactId>
    <version>1.0.0.RELEASE</version>
    <!-- 必须是正式版本,禁止SNAPSHOT -->
    <url>你的代码仓库地址(如https://github.com/用户名/仓库名)</url>
    <!-- 许可证信息(推荐Apache 2.0) -->
    <licenses>
        <license>
            <name>The Apache License, Version 2.0</name>
            <url>https://www.apache.org/licenses/LICENSE-2.0</url>
        </license>
    </licenses>
    <!-- 开发者信息 -->
    <developers>
        <developer>
            <name>你的姓名</name>
            <email>你的邮箱</email>
        </developer>
    </developers>
    <!-- 代码仓库信息 -->
    <scm>
        <connection>scm:git:你的仓库克隆地址(如https://github.com/用户名/仓库名.git)</connection>
        <developerConnection>scm:git:你的仓库SSH地址(如git@github.com:用户名/仓库名.git)</developerConnection>
        <url>你的仓库网页地址</url>
    </scm>
    <!-- 必要插件配置 -->
    <build>
        <plugins>
            <!-- 源码打包插件 -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-source-plugin</artifactId>
                <version>3.3.0</version>
                <executions>
                    <execution>
                        <id>attach-sources</id>
                        <goals>
                            <goal>jar-no-fork</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <!-- Javadoc打包插件 -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-javadoc-plugin</artifactId>
                <version>2.9.1</version>
                <configuration>
                    <charset>UTF-8</charset>
                    <encoding>UTF-8</encoding>
                    <docencoding>UTF-8</docencoding>
                    <additionalparam>-Xdoclint:none</additionalparam>
                </configuration>
                <executions>
                    <execution>
                        <id>attach-javadocs</id>
                        <goals>
                            <goal>jar</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <!-- GPG签名插件 -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-gpg-plugin</artifactId>
                <version>3.1.0</version>
                <executions>
                    <execution>
                        <id>sign-artifacts</id>
                        <phase>verify</phase>
                        <goals>
                            <goal>sign</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <!-- 中央仓库发布插件 -->
            <plugin>
                <groupId>org.sonatype.central</groupId>
                <artifactId>central-publishing-maven-plugin</artifactId>
                <version>0.4.0</version>
                <extensions>true</extensions>
                <configuration>
                    <publishingServerId>central</publishingServerId>
                    <tokenAuth>true</tokenAuth>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

第五步:打包上传与发布

  1. 推送项目代码:将配置好的项目推送到对应的 GitHub/Gitee 仓库(确保仓库公开)
  2. 执行部署命令:打开终端,进入项目根目录,执行 mvn clean deploy -Dmaven.test.skip=true,过程中会提示输入 GPG 密钥密码,输入后等待执行完成
  3. 等待 Sonatype 审核:登录 Sonatype 平台,在 Deployments 中可看到状态(PUBLISHING 为审核中),审核时间通常为几小时到 1 天,状态变为 PUBLISHED 即发布成功
    image.png

三、验证与使用:让别人轻松引入你的组件

发布成功后,可通过 Maven 中央仓库搜索页,输入 GroupID 或组件名称查询你的组件。其他开发者只需在 pom.xml 中添加以下依赖,即可直接使用:

<dependency>
    <groupId>io.github.你的用户名</groupId>
    <artifactId>组件名称</artifactId>
    <version>1.0.0.RELEASE</version>
</dependency>

四、注意事项与避坑指南

  1. 版本不可逆:发布后的版本无法删除或修改,务必做好测试再发布,建议遵循语义化版本规范
  2. 隐私保护:严禁发布包含密钥、敏感业务逻辑的组件,一旦发布无法撤回
  3. 常见错误处理:

    • 提示 "Namespace 不允许":检查 POM 文件的 GroupID 与 Sonatype 验证通过的 Namespace 完全一致
    • 提示 "SNAPSHOT 不被允许":将版本号改为正式版本(如 1.0.0.RELEASE),中央仓库不接受快照版本
    • 签名验证失败:确认 GPG 密钥已上传至公共服务器,且 settings.xml 中 GPG 配置信息正确

至此,你的组件就正式加入 Maven 中央仓库的生态了!从自己用的工具到全球开发者可复用的组件,只差这一套标准化的发布流程。如果遇到问题,可参考 Sonatype 官方文档或留言交流,祝你发布顺利 ~

Kite:Kotlin/Java 通用的全自动 ORM 框架

Kite 是一个高效的轻量级 ORM 框架,基于 Kotlin 编写,开箱即用,内置分页查询、增删改查等常用功能,支持多表操作。它支持 PostgreSQL、MySQL、Derby 等多种数据库,旨在通过简化数据库操作,减少代码量,提升开发效率。

框架特点

  • 全自动映射:无需手动编写 SQL,Kite 会自动根据实体类生成相应的数据库操作语句
  • 支持自定义 SQL:在需要时,可以编写自定义 SQL 语句,满足复杂查询需求,还可以像写代码一样写流程控制语句
  • 多数据库支持:支持 PostgreSQL、MySQL、Derby 等主流关系型数据库
  • Kotlin/Java 双语言支持:既可以在 Kotlin 项目中使用,也可以在 Java 项目中无缝集成
  • 轻量级设计:无过多依赖,性能优秀
  • 丰富的 API:提供简洁直观的 API,支持各种复杂查询和操作
  • Spring Boot 集成:提供 Spring Boot Starter,便于在 Spring Boot 项目中快速集成

使用方法(Spring Boot 集成示例)

Maven 中央仓库: kite-spring-boot-starter
  1. 向项目添加以下依赖:
  • Maven
<dependency>
   <groupId>io.github.tangllty</groupId>
   <artifactId>kite-spring-boot-starter</artifactId>
   <version>${kite.version}</version>
</dependency>
  • Gradle
implementation("io.github.tangllty:kite-spring-boot-starter:${kite.version}")
  1. 在数据库中创建表
使用 MySQL 演示
create table account (
  id          bigint not null auto_increment,
  username    varchar(32)     default '',
  password    varchar(32)     default '',
  balance     decimal(10,2)   default '0.00',
  create_time datetime        default null,
  update_time datetime        default null,
  primary key (`id`)
);

insert into account (username, password, create_time, balance) values
('admin', 'admin123', '2020-01-01 12:00:00', 1000.10),
('user', 'user123', '2024-05-02 8:30:00', 101.00),
('guest', 'guest123', '2022-03-03 15:00:00', 10.00),
('tang', 'tang123', '2019-06-01 21:30:30', 1.88),
('jeo', 'jeo123', '2024-07-01 5:59:59', 0.10);
  1. application.yml 文件中配置数据库连接信息
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://127.0.0.1:3306/kite-test
    username: root
    password: password
  1. account 表创建模型类
  • Java
import com.tang.kite.annotation.id.Id;
import com.tang.kite.annotation.id.IdType;
import java.math.BigDecimal;
import java.time.LocalDateTime;

public class Account {

    @Id(type = IdType.AUTO)
    private Long id;
    private String username;
    private String password;
    private BigDecimal balance;
    private LocalDateTime createTime;
    private LocalDateTime updateTime;

    // Getters and Setters
}
  • Kotlin
import com.tang.kite.annotation.id.Id
import com.tang.kite.annotation.id.IdType
import java.math.BigDecimal
import java.time.LocalDateTime

class Account (

    @Id(type = IdType.AUTO)
    var id: Long? = null,
    var username: String? = null,
    var password: String? = null,
    var balance: BigDecimal? = null,
    var createTime: LocalDateTime? = null,
    var updateTime: LocalDateTime? = null

)
  1. 继承 BaseMapper 接口创建 Mapper 接口
  • Java
import com.tang.kite.mapper.BaseMapper;
import com.tang.kite.spring.annotation.Mapper;

@Mapper
public interface AccountMapper extends BaseMapper<Account> {
}
  • Kotlin
import com.tang.kite.mapper.BaseMapper
import com.tang.kite.spring.annotation.Mapper

@Mapper
interface AccountMapper : BaseMapper<Account>
  1. 在 Spring Boot 应用类上添加 @MapperScan 注解
  • Java
import com.tang.kite.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@MapperScan("com.tang.application.mapper")
@SpringBootApplication
public class KiteApplication {

    public static void main(String[] args) {
        SpringApplication.run(KiteApplication.class, args);
    }

}
  • Kotlin
import com.tang.kite.spring.annotation.MapperScan
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication

@MapperScan(["com.tang.application.mapper"])
@SpringBootApplication
class KiteApplication

fun main(args: Array<String>) {
    runApplication<KiteApplication>(*args)
}
  1. 测试 Mapper 接口
  • Java
import com.tang.demo.mapper.AccountMapper;
import com.tang.kite.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@MapperScan("com.tang.application.mapper")
@SpringBootApplication
public class KiteApplication {

    public static void main(String[] args) {
        var context = SpringApplication.run(KiteApplication.class, args);
        var accountMapper = context.getBean(AccountMapper.class);
        var accounts = accountMapper.select();
        accounts.forEach(System.out::println);
    }

}
  • Kotlin
import com.tang.demo.mapper.AccountMapper
import com.tang.kite.spring.annotation.MapperScan
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication

@MapperScan(["com.tang.application.mapper"])
@SpringBootApplication
class KiteApplication

fun main(args: Array<String>) {
    val context = runApplication<KiteApplication>(*args)
    val accountMapper = context.getBean(AccountMapper::class.java)
    val accounts = accountMapper.select()
    accounts.forEach { println(it) }
}

文档与社区

官方文档

详细的使用文档请参考:

源码

Kite 的源码托管在 GitHub 和 Gitee 上,您可以在以下地址查看和贡献:

总结

Kite 是一个功能强大、易于使用的 ORM 框架,它通过全自动映射和简洁的 API,大大简化了数据库操作的开发工作。无论是在 Kotlin 项目还是 Java 项目中,都能提供高效、便捷的数据库访问体验。

如果您正在寻找一个轻量级、高性能的 ORM 框架,Kite 绝对值得一试!

在现代企业和个人开发中,文档处理是不可或缺的一环。尤其是在报告演示、内容整合等场景下,PowerPoint 文件(PPT/PPTX)的自动化处理需求日益增长。当我们需要将多个演示文稿或其中的特定幻灯片合并时,手动操作不仅效率低下,而且容易出错。本文将深入探讨如何利用 Java 编程语言,结合强大的 Spire.Presentation for Java 库,实现 PowerPoiont 文件的合并,为开发者提供一套高效、灵活的解决方案。

Spire.Presentation for Java 库简介与安装

Spire.Presentation for Java 是一个功能丰富的 Java API,专为创建、读取、编辑、转换和打印 PowerPoint 演示文稿而设计。它支持 PPT、PPTX、PPS、PPSX 等多种格式,无需安装 Microsoft Office,即可在 Java 应用程序中轻松处理幻灯片、文本、图片、表格、图表、多媒体等元素。其高性能和易用性使其成为 Java 处理 PowerPoint 的理想选择。

要使用 Spire.Presentation for Java,您可以通过 Maven 配置依赖。

Maven依赖配置:

<repositories>
    <repository>
        <id>com.e-iceblue</id>
        <name>e-iceblue</name>
        <url>https://repo.e-iceblue.cn/repository/maven-public/</url>
    </repository>
</repositories>
<dependencies>
    <dependency>
        <groupId>e-iceblue</groupId>
        <artifactId>spire.presentation</artifactId>
        <version>11.1.1</version>
    </dependency>
</dependencies>

您也可以直接从 Spire.Presentation for Java 官方网站下载 JAR 包,并手动添加到您的项目类路径中。

合并来自外部文件的指定幻灯片

有时我们不需要合并整个演示文稿,而仅仅需要从一个或多个文件中提取特定的幻灯片,并将其插入到目标演示文稿中。Spire.Presentation 提供了灵活的 API 来实现这一需求。

以下代码示例演示了如何从两个源 PPTX 文件中提取指定幻灯片,并将其插入到一个新的演示文稿中。

import com.spire.presentation.*;

public class MergeFiles1 {
    public static void main(String[] args) throws Exception{
        //加载文档1,获取第三张幻灯片
        Presentation ppt1 = new Presentation();
        ppt1.loadFromFile("test1.pptx");
        ISlide slide = ppt1.getSlides().get(2);

        //加载文档2,将文档1中获取的幻灯片作为第二张插入到文档2
        Presentation ppt2 = new Presentation();
        ppt2.loadFromFile("test2.pptx");
        int index = 1;
        ppt2.getSlides().insert(index,slide);

        //保存文档2
        ppt2.saveToFile("merge1.pptx",FileFormat.PPTX_2013);
        ppt2.dispose();
    }
}

代码解析:

  • new Presentation():创建一个演示文稿对象,作为我们合并操作的容器。
  • ppt1.loadFromFile():加载一个幻灯片文件作为源文档。
  • ISlide slide = ppt1.getSlides().get(2):获取源文档上的某一页幻灯片。
  • ppt2.loadFromFile():加载另一个 PowerPoint 文件作为目标文档。
  • ppt2.getSlides().insert(index,slide):将源文档获取到幻灯片插入到目标文档中,index 就是插入的位置。
  • ppt2.saveToFile():将合并后的演示文稿保存为新的 PPTX 文件。

将多个 PowerPoint 文件合并为一个新的文件

将多个完整的 PowerPoint 文件按顺序合并成一个全新的演示文稿也是一个常见的需求,尤其是在演示文稿都是关于同一主题时。Spire.Presentation 同样提供了简洁高效的方法来实现这一目标。

下面的代码示例展示了如何将两个独立的 PPTX 文件合并成一个统一的演示文稿。

import com.spire.presentation.*;

public class MergeFiles2 {
    public static void main(String[] args)throws  Exception {
        //加载文档1,文档2
        Presentation ppt1 = new Presentation();
        ppt1.loadFromFile("test1.pptx");
        Presentation ppt2 = new Presentation();
        ppt2.loadFromFile("test2.pptx");

        //遍历文档1的所有幻灯片,添加到文档2
        for(int i = 0;i<ppt1.getSlides().getCount();i++){
            ppt2.getSlides().append(ppt1.getSlides().get(i));
        }

        //保存文档2
        ppt2.saveToFile("merge2.pptx",FileFormat.PPTX_2013);
        ppt2.dispose();
    }
}

代码解析:

  • ppt2.getSlides().append(ppt1.getSlides().get():这是实现多个演示文稿合并的关键。append() 方法会将源文档中的所有幻灯片按原顺序复制到当前演示文稿的末尾。这个过程会自动处理幻灯片的主题、布局、内容等,确保合并后的演示文稿保持一致性和完整性。
  • 循环处理多个文件,确保所有源文件的幻灯片都被添加到目标演示文稿中。

结语

通过上述详细的 Java 代码示例,我们不难看出 Spire.Presentation for Java 在处理 PowerPoint 合并任务上的强大能力和便捷性。无论是精确到指定幻灯片的合并,还是将多个完整演示文稿整合,该库都能提供高效且稳定的解决方案。

这种基于 Java 的 PowerPoint 合并幻灯片编程开发技术教程极大地提升了 Java 在文档处理领域的实用性,为自动化报告生成、内容聚合等场景提供了坚实的技术支撑。掌握这些技能,开发者可以更灵活地应对各种文档处理挑战,优化工作流程,提高开发效率。未来,我们还可以进一步探索幻灯片内容的修改、格式调整乃至更复杂的自动化操作,让 Java 在 PowerPoint 技术教程 中发挥更大的作用。

在日常开发工作中,我们经常会遇到需要自动化处理文档的场景,尤其是PowerPoint演示文稿。无论是批量生成报告、根据数据动态创建演示文稿,还是对现有PPT进行内容调整,手动操作都显得效率低下且容易出错。如何利用Java的强大能力,实现对PowerPoint幻灯片的添加、隐藏和删除,从而极大地提高工作效率,成为了许多开发者关注的焦点。本文将深入探讨这一需求,并提供一套高效实用的解决方案。

库介绍与环境配置:Spire.Presentation for Java

要实现Java对PowerPoint幻灯片的自动化操作,我们需要借助一个功能强大的第三方库。Spire.Presentation for Java 正是这样一个专门为Java应用程序设计,用于创建、读取、编辑、转换和打印PowerPoint文件的API。它支持多种PPT格式,并提供了丰富的接口,让开发者能够轻松控制幻灯片的各个方面,包括文本、图片、表格、图表以及幻灯片本身的操作。

Maven依赖配置:

<repositories>
    <repository>
        <id>com.e-iceblue</id>
        <name>e-iceblue</name>
        <url>https://repo.e-iceblue.cn/repository/maven-public/</url>
    </repository>
</repositories>
<dependencies>
    <dependency>
        <groupId>e-iceblue</groupId>
        <artifactId>spire.presentation</artifactId>
        <version>11.1.1</version>
    </dependency>
</dependencies>

环境配置说明:

在开始编程之前,请确保您的开发环境已正确配置。这包括安装Java Development Kit (JDK) 1.8或更高版本,并配置好Maven或Gradle构建工具。此外,推荐使用IntelliJ IDEA或Eclipse等IDE,它们能提供更好的代码提示和调试体验。

Java 在 PowerPoint 中添加幻灯片

添加幻灯片是构建演示文稿的基础。Spire.Presentation for Java 允许我们创建全新的PPT文件,并在其中添加各种类型的幻灯片,甚至可以向幻灯片中添加内容。

代码示例:

Java

import com.spire.presentation.*;

public class Slides {
    public static void main(String[] args) throws Exception {

        //创建一个 PowerPoint 文档并加载示例文档

        Presentation presentation = new Presentation();
        presentation.loadFromFile("/Sample.pptx");

        //在文档末尾添加新幻灯
        presentation.getSlides().append();

        //在第二页插入空白幻灯片
        presentation.getSlides().insert(1);

       //保存文档
        presentation.saveToFile("output/AddSlide.pptx", FileFormat.PPTX_2010);
    }

}

代码解析:

  1. new Presentation():创建一个空的PowerPoint演示文稿对象。
  2. presentation.getSlides().append():在PowerPoint文件的末尾添加一个新的空白幻灯片。
  3. presentation.getSlides().insert(1):在指定位置添加一张新的幻灯片,这里是添加为第二张。
  4. presentation.saveToFile(...):将修改后的演示文稿保存到指定路径和格式。

Java 在 PowerPoint 中隐藏指定幻灯片

有时我们需要在不删除幻灯片的前提下,使其在演示模式下不可见。Spire.Presentation 提供了简便的方法来实现这一功能。

代码示例:

import com.spire.presentation.*;

public class Slides {
    public static void main(String[] args) throws Exception {

        //创建一个 PowerPoint 文档并加载示例文档
        Presentation presentation = new Presentation();
        presentation.loadFromFile("/Sample.pptx");

        //隐藏第二张幻灯片
        presentation.getSlides().get(1).setHidden(true);

        //保存文档
        presentation.saveToFile("output/Hideslide.pptx", FileFormat.PPTX_2010);
    }

}

代码解析:

  1. presentation.loadFromFile(...):加载一个已存在的PowerPoint文件。
  2. presentation.getSlides().get(1).setHidden(true):通过索引获取需要操作的幻灯片对象。然后将setHidden的参数设置为true使该幻灯片隐藏。
  3. presentation.saveToFile(...):保存修改后的演示文稿。

Java 删除 PowerPoint 中指定幻灯片

当某些幻灯片不再需要时,我们可以将其从演示文稿中彻底移除。Spire.Presentation for Java 同样提供了直接的方法来删除幻灯片。

代码示例:

import com.spire.presentation.*;

public class Slides {
    public static void main(String[] args) throws Exception {

        //创建一个 PowerPoint 文档并加载示例文档
        Presentation presentation = new Presentation();
        presentation.loadFromFile("/Sample.pptx");

        //删除第二张幻灯片
        presentation.getSlides().removeAt(1);

        //保存文档
        presentation.saveToFile("output/Removeslide.pptx", FileFormat.PPTX_2010);
    }

}

代码解析:

  1. presentation.loadFromFile(...):加载一个已存在的PowerPoint文件。
  2. presentation.getSlides().removeAt(1):这是删除幻灯片的关键API。它会从幻灯片集合中移除指定索引的幻灯片,此处删除了第二张幻灯片。
    注意事项: 删除幻灯片后,后续幻灯片的索引会自动更新。例如,如果删除了索引为1的幻灯片,原来索引为2的幻灯片将变为索引1。在进行批量删除操作时,应特别注意这一变化,通常建议从后往前删除,或者每次删除后重新获取幻灯片集合的大小和索引。
  3. presentation.saveToFile(...):保存修改后的演示文稿。

总结

本文详细介绍了如何使用 Spire.Presentation for Java 库在Java应用程序中实现PowerPoint幻灯片的添加、隐藏和删除操作。通过这些实用的代码示例,我们展示了如何创建新的演示文稿、向其中添加自定义内容的幻灯片,以及如何根据需求灵活地隐藏或移除现有幻灯片。掌握这些技能,将极大地提升您在自动化办公、数据报告生成和演示文稿管理方面的效率。Spire.Presentation 的强大功能远不止于此,它在自动化文档处理领域拥有广阔的应用前景,期待各位开发者能利用它创造更多有价值的解决方案。

这几天升级了下 idea 到最新版 (2025.3.1),打开大型 Maven 项目时经常卡死。每天给我来一次。每次把.idea 删除了才可以。今天去论坛上看了下,确实是个 bug。临时解决版本是降版本或手动删除 Maven 文件夹。

  • Linux: ~/.cache/JetBrains/IntelliJIdea2025.3/Maven
  • Windows: C:\Users\<YOUR_USERNAME>\AppData\Local\JetBrains\IntelliJIdea2025.3\Maven
  • macOS: ~/Library/Caches/JetBrains/IntelliJIdea2025.3/Maven

参考 https://youtrack.jetbrains.com/issue/IJPL-225151/Intellij-IDEA-is-not-responding

据说新版本会在这两天发布,我还是等新版本吧,降级是不可能降级的


📌 转载信息
原作者:
tanran
转载时间:
2026/1/8 12:25:26

可以缓存,Maven 构建速度提升数倍,强烈建议大家安装

一、安装插件 Develocity

二、安装 Maven 插件

自动安装

mvn com.gradle:develocity-maven-extension:2.3:init -Ddevelocity.url=https://develocity.example.com

手动安装

我这边自动安装没成功,手动安装步骤如下:

  1. 项目根目录下新建 .mvn 文件夹
  2. .mvn 下新建两个文件

extensions.xml

<extensions> <extension> <groupId>com.gradle</groupId> <artifactId>develocity-maven-extension</artifactId> <version>2.3</version> </extension> </extensions> 

develocity.xml

<develocity> <server> <url>https://develocity.example.com</url> </server> </develocity> 

📌 转载信息
原作者:
ageovb
转载时间:
2025/12/27 14:16:16