如何使用JPA GenerationType.AUTO提供初始值或增量ID

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何使用JPA GenerationType.AUTO提供初始值或增量ID相关的知识,希望对你有一定的参考价值。

我使用以下代码来定义MyEntity

@Entity
@Table(name = "MY_TABLE")
public class MyEntity {

@Id
@GeneratedValue(strategy=GenerationType.AUTO)
@Column(name = "MY_TABLE_ID")
private Integer myTableId;

@Column(name = "MY_TABLE_NM")
private String myTableName;

//Getters Setters
}

对于我申请开始后的第一个POST,我创建MyEntity一切正常,MY_TABLE_ID从1开始并按预期工作。

我的问题是,如果有人在我执行POST之前手动插入数据,那么我会得到重复的密钥异常,因为myTableId输入为1已经存在。

我的主要问题是我无法创建database sequence现在使用GenerationType.SEQUENCE解决此问题,因为数据库现在无法更改。我尝试了GenerationTypeTableGenerator的各种组合,但我无法成功解决它。

initialValue设置为更大的数字以避免重复值可以暂时解决我的问题,但我也无法做到。

如果有人可以用initialValue帮助我使用AUTO,或者在没有数据库更改的情况下给我一些其他更好的解决方案将会很棒:)

答案

如果需要更多控制,您还可以实现自己的生成器。请参阅此界面IdentifierGenerator。所以你可以得到记录的数量,例如通过@NamedQuery。然后你可以自己生成一个标识符。

public class MyEntityKeyGenerator implements IdentifierGenerator {
@Override
public Serializable generate(SessionImplementor session, Object object) {
    // SELECT count(ent) from MyEntity ent;
    Long count = (Long) session.getNamedQuery("count-query").uniqueResult();
    // calc and return id value
   }
}

实体:

class MyEntity {
@Id
@GenericGenerator(name = "my_generator",
        strategy = "org.common.MyEntityKeyGenerator")
@GeneratedValue(generator = "my_generator")
private Long id;...

只是不要忘记锁。

另一答案

由于MY_TABLE_ID是一个标识列,因此注释将起作用。

@Entity
@Table(name = "MY_TABLE")
public class MyEntity {

@Id
@GeneratedValue(strategy=GenerationType.IDENTITY) <-- IDENTITYinstead of AUTO
@Column(name = "MY_TABLE_ID")
private Integer myTableId;

@Column(name = "MY_TABLE_NM")
private String myTableName;

//Getters Setters
}

一旦提交了事务,标识列将自动分配值。您不应为标识列设置任何值,因为它是分配值的数据库的作用。因此,您也不需要考虑任何初始值(完全忘记它们的标识列)

另一答案

我使用生成类型Identity,这基本上意味着db,负责Id生成。

@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
@MappedSuperclass
@EntityListeners(EntityListener.class)
@EqualsAndHashCode(of = {"id", "createdAt"})
public abstract  class AbstractEntity<ID extends Serializable> implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private ID id;

    @Temporal(TemporalType.TIMESTAMP)
    @Column(name = "CREATED_AT", updatable = false)
    private Date createdAt;

    @Temporal(TemporalType.TIMESTAMP)
    @Column(name = "UPDATED_AT")
    private Date updatedAt;

}

你也可以使用,序列生成:

@Entity
@SequenceGenerator(name="seq", initialValue=1, allocationSize=100)
public class EntityWithSequenceId {
    @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="seq")
    @Id long id;
}
另一答案

我在这里提供的答案中尝试了各种选项,并在stackoverflow和其他论坛上提出了类似的问题,

我没什么限制,

  1. 我无法创建数据库序列,因为我的数据库更改已冻结。
  2. 我不想引入新的Custom IdGenerator类,因为它会给与我合作的其他人增加混乱。

它使用以下更改解决:

使用GenericGenerator策略添加increment帮助了我,我对我的代码进行了以下更改。

@Entity
@Table(name = "MY_TABLE")
public class MyEntity {

@Id
@GeneratedValue(strategy = GenerationType.AUTO, generator="seq")
@GenericGenerator(name = "seq", strategy="increment")
@Column(name = "MY_TABLE_ID")
private Integer myTableId;

@Column(name = "MY_TABLE_NM")
private String myTableName;

//Getters Setters
}

它帮助了我,因为,来自Hiberbate DOCs

增量

一个返回long的IdentifierGenerator,通过从启动时的最大主键值开始计算构造。在群集中使用不安全!

因为,即使手动插入,它已经增加已经存在的myTableId,这解决了我的问题。

以上是关于如何使用JPA GenerationType.AUTO提供初始值或增量ID的主要内容,如果未能解决你的问题,请参考以下文章

JPA JPQL IN 子句:如何在 JPA 中使用 IN 子句?

处理 JPA 规范和 spring-data-jpa 时如何使用声明 Stream 作为返回类型

JPA @Version:如何使用它?

如何使用 JPA 进行求和(案例)

如何使用 JPA 实现时态表?

JPA JPQL IN子句:如何在JPA中使用IN子句?