告别繁琐配置:Easy-Query中@Column注解的10个高级属性让ORM开发效率提升300%
你是否还在为复杂的数据库字段映射而烦恼?在实体类与数据库表字段的映射过程中,传统ORM框架往往需要大量XML配置或重复代码。Easy-Query作为一款高性能轻量级ORM框架,通过@Column注解的灵活设计,将字段映射的控制权交还给开发者。本文将深入解析@Column注解的10个核心扩展属性,带你掌握从基础映射到高级功能的全场景应用,让你的数据访问层代码更简洁、更强大。
读完本文你将获得:
- 掌握@Column注解10+核心属性的实战用法
- 学会实现字段加密、类型转换等高级功能
- 解决分表分库、复杂查询等场景下的映射难题
- 提升ORM层代码质量和开发效率的最佳实践
@Column注解核心能力概览
@Column注解是Easy-Query实现对象-关系映射(ORM)的核心组件,通过它可以将Java实体类字段与数据库表列建立灵活的映射关系。与传统ORM框架相比,Easy-Query的@Column注解提供了更丰富的扩展属性,支持从简单映射到复杂业务场景的全链路覆盖。
注解定义结构
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.ANNOTATION_TYPE})
public @interface Column {
boolean primaryKey() default false; // 是否主键
boolean generatedKey() default false; // 是否数据库生成键
String value() default EasyStringUtil.EMPTY; // 数据库列名
// 更多属性...
}
核心功能矩阵
| 功能分类 | 关键属性 | 应用场景示例 |
|---|---|---|
| 基础映射 | value, exist, autoSelect | 列名映射、临时字段、查询控制 |
| 主键策略 | primaryKey, generatedKey | 自增主键、UUID生成、分布式ID |
| 数据转换 | conversion, sqlConversion | 加解密、类型转换、格式处理 |
| 数据库特性 | dbType, dbDefault, comment | 字段类型定义、默认值、迁移支持 |
| 高级查询 | sqlExpression, jdbcType | 函数列、复杂查询条件构建 |
基础映射能力:从简单到复杂
列名映射与字段忽略
最基础也最常用的功能是指定数据库列名,当实体类字段名与数据库列名不一致时,可以通过value属性显式指定:
public class BlogEntityVO1 {
@Id
private String id;
@Column(value = "status1") // 映射到数据库status1列
private Integer status;
@Column(exist = false) // 非数据库字段,仅内存使用
private String tempProperty;
}
exist=false属性非常实用,它相当于同时设置:
autoSelect=false(查询时不自动加载)@InsertIgnore(插入时忽略)@UpdateIgnore(更新时忽略)
查询加载控制
autoSelect属性用于控制字段是否默认被查询加载,适用于大字段或敏感字段的按需加载:
public class Topic {
@Id
private String id;
private String title;
@Column(autoSelect = false) // 不自动查询,需显式指定
private String content; // 大文本内容字段
}
当autoSelect=false时,常规查询不会返回该字段,需要通过select方法显式指定:
// 只查询id和title
List<Topic> topics = easyQuery.queryable(Topic.class)
.select(Topic::getId, Topic::getTitle)
.toList();
// 需要查询content时显式指定
List<Topic> topicsWithContent = easyQuery.queryable(Topic.class)
.select(Topic::getId, Topic::getContent)
.toList();
主键策略:灵活应对各种ID生成需求
基础主键配置
通过primaryKey属性标记主键字段,Easy-Query会在CRUD操作中自动将该字段作为主键使用:
public class SysUserVersionLong {
@Column(primaryKey = true) // 标记为主键
private Long id;
private String name;
// 其他字段...
}
数据库生成键
对于自增主键或数据库函数生成的主键(如MySQL的AUTO_INCREMENT、PostgreSQL的SERIAL),只需添加generatedKey=true:
public class TopicY {
@Column(primaryKey = true, generatedKey = true)
private Long id; // 数据库自增主键
private String title;
}
插入后自动回填生成的主键值:
TopicY topic = new TopicY();
topic.setTitle("测试标题");
easyQuery.insertable(topic).executeRows(true); // 参数true表示回填主键
System.out.println("生成的ID: " + topic.getId()); // 输出数据库生成的ID
自定义主键生成器
对于分布式ID等复杂场景,Easy-Query支持通过primaryKeyGenerator属性配置自定义主键生成器:
public class CustomSnowflakeGenerator implements PrimaryKeyGenerator {
@Override
public Object generate(Class<?> entityClass, String propertyName) {
return SnowflakeIdWorker.nextId(); // 自定义雪花算法实现
}
}
// 在实体类中使用
public class UserExtra2 {
@Column(primaryKey = true, primaryKeyGenerator = CustomSnowflakeGenerator.class)
private Long id; // 使用自定义ID生成器
private String name;
}
数据转换:实现字段级别的业务逻辑
内存级转换(conversion)
conversion属性允许你定义Java对象在内存中的转换逻辑,适用于VO/DTO与数据库实体之间的类型转换:
// 定义一个金额转换处理器
public class MoneyConverter implements ValueConverter<BigDecimal, Long> {
@Override
public Long serialize(BigDecimal value) {
return value.multiply(new BigDecimal("100")).longValue(); // 元转分
}
@Override
public BigDecimal deserialize(Long value) {
return new BigDecimal(value).divide(new BigDecimal("100")); // 分转元
}
}
// 在实体类中使用
public class OrderEntity {
@Id
private String id;
@Column(conversion = MoneyConverter.class) // 应用金额转换
private BigDecimal totalAmount; // Java中使用BigDecimal(元),数据库存储Long(分)
}
数据库级转换(sqlConversion)
sqlConversion属性用于生成数据库级别的转换SQL,适用于加密存储、地理信息处理等场景:
// 定义AES加密转换处理器
public class MySQLAesEncryptColumnValueSQLConverter implements ColumnValueSQLConverter {
@Override
public String convert(String propertyName, String sqlColumn) {
// 生成加密SQL: AES_ENCRYPT(sqlColumn, 'secret_key')
return String.format("AES_ENCRYPT(%s, 'secret_key')", sqlColumn);
}
@Override
public String revert(String propertyName, String sqlColumn) {
// 生成解密SQL: AES_DECRYPT(sqlColumn, 'secret_key')
return String.format("AES_DECRYPT(%s, 'secret_key')", sqlColumn);
}
}
// 在实体类中使用
public class SysUserEncrypt {
@Id
private String id;
@Column(sqlConversion = MySQLAesEncryptColumnValueSQLConverter.class)
private String phone; // 加密存储手机号
@Column(sqlConversion = MySQLAesEncryptColumnValueSQLConverter.class)
private String idCard; // 加密存储身份证号
}
使用加密字段进行查询时,Easy-Query会自动应用解密逻辑:
// 自动应用解密SQL,无需手动处理
List<SysUserEncrypt> users = easyQuery.queryable(SysUserEncrypt.class)
.where(o -> o.eq(SysUserEncrypt::getPhone, "13800138000"))
.toList();
数据库特性支持:DDL与迁移
字段元数据定义
dbType、dbDefault和comment属性用于定义数据库字段的元数据信息,主要配合Easy-Query的数据库迁移功能使用:
public class MyMigrationBlog0 {
@Id
private String id;
@Column(comment = "标题", length = 200) // 字段注释和长度
private String title;
@Column(comment = "内容", dbType = "TEXT") // 指定数据库类型
private String content;
@Column(comment = "点赞数", dbDefault = "0") // 默认值
private Integer starCount;
@Column(comment = "发布时间", dbDefault = "CURRENT_TIMESTAMP")
private LocalDateTime createTime;
}
这些属性会影响自动生成的DDL语句,例如:
CREATE TABLE my_migration_blog0 (
id VARCHAR(32) NOT NULL PRIMARY KEY,
title VARCHAR(200) COMMENT '标题',
content TEXT COMMENT '内容',
star_count INT DEFAULT 0 COMMENT '点赞数',
create_time DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '发布时间'
);
字段重命名支持
renameFrom属性解决了数据库字段重命名时的数据迁移问题:
public class UserInfo {
@Id
private String id;
@Column(renameFrom = "user_name") // 从旧字段名user_name迁移而来
private String userName; // 新字段名
}
在数据库迁移时,Easy-Query会自动生成包含数据迁移的SQL:
ALTER TABLE user_info ADD COLUMN user_name VARCHAR(50);
UPDATE user_info SET user_name = user_name; -- 从旧字段复制数据
ALTER TABLE user_info DROP COLUMN user_name; -- 删除旧字段
高级查询能力:SQL函数与表达式
复杂SQL表达式(sqlExpression)
sqlExpression属性允许你为字段指定自定义SQL表达式,实现复杂的数据库计算或函数调用:
public class UserExtra2 {
@Id
private Long id;
private String firstName;
private String lastName;
// 组合字段:CONCAT(firstName, lastName)
@Column(sqlExpression = @ColumnSQLExpression(sql="CONCAT({0},{1})", args = {
"#{firstName}", "#{lastName}"
}))
private String fullName;
}
在查询时,Easy-Query会自动将fullName字段替换为指定的SQL表达式:
// 查询结果中的fullName会自动使用CONCAT(firstName, lastName)计算
List<UserExtra2> users = easyQuery.queryable(UserExtra2.class).toList();
数据库类型控制(jdbcType)
jdbcType属性用于显式指定字段对应的JDBC类型,解决类型映射模糊问题:
public class MyALLTYPE {
@Id
private String id;
@Column(jdbcType = JDBCType.DATE) // 明确指定为DATE类型
private LocalDate birthday;
@Column(jdbcType = JDBCType.TIMESTAMP) // 明确指定为TIMESTAMP类型
private LocalDateTime createTime;
}
实战案例:构建企业级用户实体
综合运用@Column注解的各项属性,我们可以构建一个满足企业级需求的用户实体类:
public class EnterpriseUser {
// 主键:使用自定义雪花ID生成器
@Column(primaryKey = true, primaryKeyGenerator = SnowflakeIdGenerator.class)
private Long id;
// 用户名:非空约束
@Column(nullable = false, comment = "登录用户名")
private String username;
// 密码:使用BCrypt加密存储
@Column(sqlConversion = BCryptColumnValueSQLConverter.class, comment = "加密存储的密码")
private String password;
// 手机号:AES加密
@Column(sqlConversion = MySQLAesEncryptColumnValueSQLConverter.class, comment = "加密手机号")
private String phone;
// 头像URL:长字符串类型
@Column(dbType = "VARCHAR(512)", comment = "头像图片URL")
private String avatarUrl;
// 创建时间:数据库自动生成
@Column(generatedKey = true, dbDefault = "CURRENT_TIMESTAMP", comment = "创建时间")
private LocalDateTime createTime;
// 扩展信息:JSON格式存储
@Column(dbType = "JSON", complexPropType = JsonComplexPropType.class, comment = "用户扩展信息")
private UserExtInfo extInfo;
// 临时字段:不持久化到数据库
@Column(exist = false)
private String verificationCode;
}
这个实体类实现了:
- 分布式ID生成
- 敏感信息加密存储
- 复杂类型(JSON)映射
- 数据库自动生成时间
- 临时字段处理
最佳实践与性能优化
注解组合使用技巧
| 常见场景 | 推荐注解组合 |
|---|---|
| 逻辑删除字段 | @Column + @LogicDelete |
| 版本控制字段 | @Column + @Version |
| 乐观锁实现 | @Column(primaryKey=true) + @Version |
| 软删除+版本控制 | @Column + @LogicDelete + @Version |
性能优化建议
- 大字段处理:对TEXT、BLOB等大字段使用
autoSelect=false,避免默认查询加载 - 加密字段索引:加密字段无法直接索引,考虑使用哈希值冗余字段建立索引
- 批量操作优化:对
generatedKey=true的字段,批量插入时建议使用数据库自增而非自定义生成器 - 类型匹配:合理使用
jdbcType属性,避免不必要的类型转换开销
避坑指南
- 主键策略冲突:
primaryKey=true时,generatedKey和primaryKeyGenerator只能二选一 - 转换器作用范围:
conversion(内存转换)和sqlConversion(数据库转换)的作用时机不同 - 迁移注意事项:
renameFrom属性仅在数据库迁移时生效,生产环境使用前建议备份数据 - 复杂类型限制:
complexPropType需要配合对应的TypeHandler,自定义时需注意线程安全
总结与展望
Easy-Query的@Column注解通过精心设计的属性体系,将简单易用性与强大功能完美结合。从基础的字段映射到复杂的加密转换,从主键生成到数据库迁移,一个注解即可满足ORM开发的全场景需求。
随着数据访问层技术的发展,未来@Column注解可能会引入更多创新特性:
- AI辅助的字段类型推荐
- 基于机器学习的查询性能优化
- 多数据库适配的智能转换
掌握@Column注解的高级用法,不仅能提升日常开发效率,更能帮助我们构建更健壮、更安全、更高性能的数据访问层。现在就将这些技巧应用到你的项目中,体验Easy-Query带来的ORM开发新范式!
如果你觉得本文对你有帮助,请点赞收藏并关注项目仓库,持续获取Easy-Query的最新技术动态和最佳实践。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



