一.数据库自带策略
1.@GeneratedValue
@GeneratedValue 用于标注主键的生成策略,通过 strategy 属性指定。
默认情况下,JPA 自动选择一个最适合底层数据库的主键生成策略:SqlServer 对应 identity,MySQL 对应 auto increment
① @GeneratedValue(strategy = GenerationType.AUTO) JPA自动选择合适的策略,是默认选项
②@GeneratedValue(strategy = GenerationType.IDENTITY) 采用数据库 ID自增长的方式来自增主 键字段,Oracle 不支持这种方式
③@GeneratedValue(strategy = GenerationType.TABLE) 通过表产生主键,框架借由表模拟序列产生主键,使用该策略可以使应用更易于数据库移植。
④@GeneratedValue(strategy = GenerationType.SEQUENCE)
通过序列产生主键,通过 @SequenceGenerator 注解指定序列名,MySql 不支持这种方式
二.自定义id自增策略
1.自定义主键生成器AutoGenerator
需要实现IdentifierGenerator并实现 generate()方法。在generate()方法里面去写自定义的主键生成策略
@Component
public class AutoGenerator implements IdentifierGenerator {
protected static final String COL_ALIAS = "maxidval";
@Override
public Serializable generate(SharedSessionContractImplementor session, Object object)
throws HibernateException {
//获取table注解,通过table获取表名
Table table = object.getClass().getAnnotation(Table.class);
if (ObjectUtils.isEmpty(table) || ObjectUtils.isEmpty(table.name()))
return PKGenerator.getPK(); //如果获取不到Table则返回随机ID
// 获取表名
String tablename = table.name();
DynamicTableService dynamicTableService = SpringContextUtils.getBean(DynamicTableService.class);
// 获取实体中的自增列,这里认为@javax.persistence.Id或@org.springframework.data.annotation.Id修饰的属性就是我们要的
Field pkCol = getPKCol(object.getClass());
if (ObjectUtils.isEmpty(pkCol) || ObjectUtils.isEmpty(pkCol.getName()))
return PKGenerator.getPK();
String pk = pkCol.getName();
// 获取自增列最大值, 用mybatis查询最大ID,dynamicTableService.selectByConditions方法可以自定义。参数是传入表名和自增列名
List<Map<String, Object>> resultList = dynamicTableService.selectByConditions(new DynamicSelectDTO(tablename,
CollectionUtil.fastList("max(" + pk + ") " + COL_ALIAS), CollectionUtil.fastList()));
// 下面各种找不到值的情况统一返回1
if (ObjectUtils.isEmpty(resultList))
return 1L;
Map<String, Object> map = resultList.get(0);
if (ObjectUtils.isEmpty(map))
return 1L;
Object maxid = map.get(COL_ALIAS);
if (ObjectUtil.isEmpty(maxid))
return 1L;
// 找到了+1返回
Long idLong = ObjectUtil.toLong(maxid);
return ++idLong;
}
/**
* @description 获取实体中的自增列,这里认为@javax.persistence.Id或@org.springframework.data.annotation.Id修饰的属性就是我们要的
* @param clz
* @return
*/
protected Field getPKCol(Class<?> clz) {
//获取实体的所有元素
Field[] allFields = ReflectUtil.getAllFields(clz);
for (Field field : allFields) {
//如果字段有javax.persistence.Id或者org.springframework.data.annotation.Id注解则返回此字段
if (!ObjectUtils.isEmpty(field.getAnnotation(javax.persistence.Id.class)) ||
!ObjectUtils.isEmpty(field.getAnnotation(org.springframework.data.annotation.Id.class)))
return field;
}
return null;
}}
2.主键上加注解
@GenericGenerator(name="id",strategy="cn.qingsec.test.report.utils.AutoGenerator") @GeneratedValue(generator = "id") @Column(name="id",columnDefinition = "varchar(15) comment 'ID'") private String id;
注意:@GeneratedValue 里面的generator 要和 @GenericGenerator 里面的name 相同,@GenericGenerator里面的strategy 要和自己定义的主键生成器SeqPKGenerator一致,需要包括包名
参考:JPA不依赖数据库用程序实现自增ID,@GeneratedValue,@GenericGenerator,IdentifierGenerator_jpa 自增_maqinghui的博客-CSDN博客