jpa中id自增策略

一.数据库自带策略

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博客

JPAJava Persistence API),如果你想要禁止单独通过JPA框架对自增identity)列插入数据,可以采取以下几种方式: 1. **手动控制**:你可以直接在实体类的方法处理插入操作,比如使用`EntityManager`的`persist()`方法时,跳过对自增属性的赋值,让数据库根据配置自动处理。 ```java User user = new User(); // ... 设置所有非自增属性 em.persist(user); // 不指定id数据库会自动分配 ``` 2. **延迟加载**:如果希望在保存时保持程序简洁,可以设置为延迟加载,直到第一次查询时才会获取自增ID。 ```java @Embeddable public class UserPK implements Serializable { @Id private Long id; // 其他字段... } @Entity public class User { @EmbeddedId private UserPK id; // ... } ``` 然后在保存时只设置非自增属性,并在查询结果时填充ID。 3. **预设值策略**:JPA允许你在实体注解上指定`GeneratedValue`策略,如`GenerationType.AUTO`表示数据库管理,`GenerationType.IDENTITY`则表示数据库自增。如果你想禁止JPA介入,可以选择`GenerationType.USER_DEFINED`并提供自己的生成机制。 ```java @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; // 修改为USER_DEFINED 或其他策略 ``` 4. **事务回滚**:在一个事务,如果不需要保存并立即获取自增ID,可以在事务结束前手动回滚,避免生成ID。 ```java try { em.getTransaction().begin(); user.setId(null); // 避免自动设置 em.persist(user); em.getTransaction().commit(); } catch (Exception e) { em.getTransaction().rollback(); // 处理错误... } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lyt5701

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值