客户信息建模需注重约束与可扩展性:身份证用String加@Pattern校验,手机号存国际格式并规范命名,状态用枚举映射tinyint,避免冗余关联集合。

客户信息类怎么建才不容易出错
客户信息不是字段堆砌,关键在约束和可扩展性。直接用 String 存身份证号或手机号,后续校验、索引、脱敏都会踩坑。
- 身份证号用
String但加@Pattern(regexp = "^\\d{17}[\\dXx]$")注解(配合 Hibernate Validator),别自己写校验逻辑 - 手机号字段命名用
phoneNo而非phone,避免和Phone类冲突;存前缀+号码(如"+86-13812345678"),方便国际化扩展 - 客户状态用枚举而非
int或String:public enum CustomerStatus { ACTIVE, INACTIVE, BANNED },数据库对应 tinyint,查起来快,改起来安全 - 别在客户类里塞订单列表——那是关联查询的事,留个
customerId外键字段就够了
订单创建时怎么保证房态同步不超卖
超卖不是并发量大才发生,单线程反复提交也可能——因为“查房态→扣库存→生成订单”不是原子操作。
- 别依赖应用层锁(如
synchronized),跨 JVM 无效;改用数据库行锁:SELECT * FROM room WHERE room_id = ? AND status = 'AVAILABLE' FOR UPDATE - 订单表必须有唯一约束,比如
(room_id, check_in_date, check_out_date)组合,防止同一房间同天被重复预定 - 事务隔离级别至少设为
READ_COMMITTED,Spring 中用@Transactional(isolation = Isolation.READ_COMMITTED) - 如果用 Redis 缓存房态,记得用 Lua 脚本做原子扣减,否则缓存和 DB 易不一致
为什么 OrderService.save() 总抛 OptimisticLockException
这不是代码写错了,是版本控制策略没对齐。JPA 的 @Version 字段默认只校验更新,但订单创建时若关联了已加载的客户实体,客户版本也会被一并检查。
- 确认
Order实体的@Version字段类型是Integer或Long,别用int基本类型(null 判定会出错) - 创建订单时,别把客户对象整个
merge()进来;改用em.getReference(Customer.class, customerId)获取代理,避免触发客户版本校验 - 如果订单要记客户姓名等快照信息,直接冗余字段
customerNameSnapshot,而不是强依赖关联实体 - 日志里看到
Row was updated or deleted by another transaction,说明乐观锁生效了——这时不该重试创建,而是提示用户“房态已变,请重新查看”
查询“某客户所有未完成订单”为何越来越慢
随着订单表数据过百万,WHERE customer_id = ? AND status IN ('BOOKED', 'CHECKED_IN') 没走索引就成定时炸弹。
系统功能强大、操作便捷并具有高度延续开发的内容与知识管理系统,并可集合系统强大的新闻、产品、下载、投票、人才、留言、在线订购、搜索引擎优化、等功能模块,为企业部门提供一个简单、易用、开放、可扩展的企业信息门户平台或电子商务运行平台。开发人员为脆弱页面专门设计了防刷新系统,自动阻止恶意访问和攻击;安全检查应用于每一处代码中,每个提交到系统查询语句中的变量都经过过滤,可自动屏蔽恶意攻击代码,从而全面防
立即学习“Java免费学习笔记(深入)”;
- 必须建联合索引:
CREATE INDEX idx_customer_status ON `order` (customer_id, status),注意字段顺序:等值查询字段在前 - 避免在
status上用ENUM或CHAR(20),统一用TINYINT(如 1=BOOKED, 2=CHECKED_IN),索引更紧凑 - 分页慎用
LIMIT 10000, 20,偏移量大时全表扫描;改用游标分页:WHERE customer_id = ? AND status IN (...) AND order_id > ? ORDER BY order_id LIMIT 20 - 如果只是展示列表,别在查询里
JOIN客户表取姓名——用应用层两次查询,或冗余客户姓名字段,减少锁竞争
实际跑通的关键不在功能多全,而在客户ID和订单ID是否全局唯一、房态变更是否原子、查询是否始终走索引——这些点漏一个,上线后就是凌晨三点的告警电话。









