如何在带有@MappedSuperclass父类的JPA实体上自定义序列生成器
如何在带有@MappedSuperclass父类的JPA实体上自定义序列生成器
嘿,我太懂你这会儿的头疼了——父类定了序列生成策略,子类却得按DBA的规矩用自定义命名的序列,默认生成的表名序列不符合规范还报错InvalidDataAccessResourceUsageException对吧?别慌,咱们一步步把这个问题捋顺:
核心思路就是让父类提供通用的序列生成策略框架,每个子类自己绑定符合规范的数据库序列,具体操作分两步来:
1. 调整父类的ID生成配置
在你的@MappedSuperclass父类里,给@GeneratedValue指定一个通用的生成器名称(比如"ENTITY_SEQ"),但先不绑定具体的数据库序列名,把这个定制权留给子类:
@MappedSuperclass public abstract class BaseEntity { @Id @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "ENTITY_SEQ") private Long id; // 这里写id的getter、setter,以及其他通用字段/方法 }
2. 每个子类自定义序列生成器
在每个子类的类级别,用@SequenceGenerator注解覆盖父类里的那个通用生成器名称,同时指定DBA要求的序列名、增量值(这个增量值必须和数据库中对应序列的配置保持一致哦):
比如用户表的子类:
@Entity @Table(name = "USER") @SequenceGenerator( name = "ENTITY_SEQ", // 必须和父类指定的生成器名称完全一致 sequenceName = "SEQ_USER_ID", // 这里填DBA认可的序列名 allocationSize = 10 // 按数据库序列的实际增量设置,别乱改 ) public class User extends BaseEntity { // 子类专属的字段和方法 }
再比如订单表的子类:
@Entity @Table(name = "ORDER") @SequenceGenerator( name = "ENTITY_SEQ", sequenceName = "SEQ_ORDER_ID", // 另一个符合规范的序列名 allocationSize = 10 ) public class Order extends BaseEntity { // ... }
为啥之前会报错?
你之前碰到的InvalidDataAccessResourceUsageException,是因为父类只指定了GenerationType.SEQUENCE但没明确生成器时,JPA会默认用子类表名加_SEQ的序列名(比如USER_SEQ)去数据库查找,要是这个序列不存在就直接报错了。现在咱们让每个子类自己绑定合规的序列名,既解决了报错问题,又满足了DBA的命名要求。
小提醒
- 一定要保证
@SequenceGenerator里的allocationSize和数据库中对应序列的增量值完全匹配,不然可能会出现ID冲突或者莫名其妙的报错。 - 如果你的JPA实现是Hibernate,还可以用
@GenericGenerator做更灵活的配置,但上面的方法是JPA标准写法,兼容性更强。
备注:内容来源于stack exchange,提问作者Timothy Vogel
相关产品推荐
相关产品推荐

