Java自定义注解配合反射实现简易ORM,通过@Table、@Id、@Column、@Transient标记映射关系,反射获取元数据生成SQL并填充对象,支持基本类型与时间类型转换、空值处理及列名自动转换。

Java 自定义注解配合反射实现简易 ORM,核心在于用注解标记字段与数据库的映射关系,再通过反射读取这些信息,动态生成 SQL 或填充对象。不依赖第三方框架,适合理解 ORM 底层原理。
定义关键注解
先设计几个基础注解,覆盖表名、主键、列名和忽略字段:
- @Table:标注在类上,指定对应数据库表名
- @Id:标注在字段上,标识主键(支持自增或手动赋值)
-
@Column:标注在字段上,指定列名;可设
nullable = false或length = 20等元数据 - @Transient:标注不需要持久化的字段(如临时计算值)
用反射解析注解并提取元数据
写一个工具类(如 EntityMapper),根据 Class 对象获取表名、主键字段、所有持久化字段及其列名:
- 调用
clazz.getAnnotation(Table.class)获取表名 - 遍历
clazz.getDeclaredFields(),跳过@Transient字段 - 对每个字段,检查是否有
@Id或@Column,记录字段名、列名、是否主键、是否可为空等 - 注意设置
field.setAccessible(true),否则私有字段无法读写
实现 insert 和 select 操作
基于元数据拼接 SQL 并绑定参数:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
立即学习“Java免费学习笔记(深入)”;
-
insert:提取非主键且非空字段(或按注解配置判断),生成
INSERT INTO table(col1,col2) VALUES(?,?),再用反射从对象中取值填入 PreparedStatement -
select:执行查询后,用 ResultSetMetaData 获取列名,匹配到对应字段(列名 → 字段名,可借助 @Column.name 或小写驼峰转换),再用
field.set(obj, value)赋值 - 主键字段若为自增,insert 后可通过
getGeneratedKeys()获取并回填到对象
处理类型映射与边界情况
反射本身不处理 JDBC 类型转换,需手动桥接:
- 基本类型(int/long/String/Date)直接对应 JDBC 类型(
setInt、setString、setTimestamp) - 字段类型为
java.time.LocalDateTime时,转为Timestamp再 set;读取时反向转换 - 空值处理:字段为 null 时调用
setNull(index, sqlType),避免 PreparedStatement 报错 - 字段名与列名不一致时,优先使用 @Column.name;未标注则默认用字段名转小写下划线(如
userName→user_name)
不复杂但容易忽略细节,比如访问权限、null 安全、时间类型适配和 SQL 注入防护(必须用 PreparedStatement)。真正工程级 ORM 还需事务、缓存、关联映射等,但这个轻量骨架已能跑通核心流程。

















