简体   繁体   English

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

[英]How to provide Initial value OR Increment ID with JPA GenerationType.AUTO

I am using following code to define MyEntity ,我使用以下代码来定义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
}

For the first POST after my application starts, I create MyEntity everything works fine, MY_TABLE_ID starts with 1 and works as expected.对于我的应用程序启动后的第一次POST ,我创建MyEntity一切正常, MY_TABLE_ID从 1 开始并按预期工作。

My issue is, If somebody inserts data manually before I do my POST then I get duplicate key exception as myTableId is entered as 1 which is already present.我的问题是,如果有人在我执行POST之前手动插入数据,那么我会收到重复的键异常,因为myTableId输入为 1,它已经存在。

My main problem is I can't create database sequence for using GenerationType.SEQUENCE now to resolve this as database can't be altered now.我的主要问题是我现在无法创建使用GenerationType.SEQUENCE database sequence来解决这个问题,因为现在无法更改数据库。 I have tried various combinations of GenerationType , TableGenerator but I am unable to successfully tackle it.我尝试了GenerationTypeTableGenerator各种组合,但我无法成功解决它。

Setting initialValue to some larger number to avoid duplicate values can temporarily resolve my problem but I am unable to do it too.initialValue设置为更大的数字以避免重复值可以暂时解决我的问题,但我也无法做到。

If someone can help me with initialValue with AUTO or give me some other better solution without database changes will be great :)如果有人可以帮助我使用AUTO initialValue或给我一些其他更好的解决方案,而无需更改数据库,那就太好了:)

As MY_TABLE_ID is an identity column, following annotations will work.由于MY_TABLE_ID是标识列,因此以下注释将起作用。

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

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

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

//Getters Setters
}

The identity column will automatically assign an value as soon as the transaction is committed.事务提交后,标识列将自动分配一个值。 You are not to set any values for an identity column, as its the job of the database to assign the values.您不必为标识列设置任何值,因为分配值是数据库的工作。 Therefore you also don't need to think about any initial values (forget them completely for identity columns)因此,您也不需要考虑任何初始值(对于标识列完全忘记它们)

I tried various options in answers provided here and for similar questions on stackoverflow and other forums,我在此处提供的答案中尝试了各种选项,并尝试了有关 stackoverflow 和其他论坛的类似问题,

I had few limitations,我有一些限制,

  1. I couldn't create database sequence as my database changes were freezed.由于我的数据库更改被冻结,我无法创建数据库序列。
  2. I didn't want to introduce new Custom IdGenerator class because it would add confusion to other people working with me.我不想引入新的Custom IdGenerator 类,因为它会给与我一起工作的其他人增加混乱。

It was resolved using following change:它已使用以下更改解决:

Adding GenericGenerator with increment strategy helped me, I made following changes to my code.添加具有increment策略的GenericGenerator对我有帮助,我对代码进行了以下更改。

@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
}

It helped me because, From Hiberbate DOCs它帮助了我,因为,来自Hiberbate DOC

increment增量

An IdentifierGenerator that returns a long, constructed by counting from the maximum primary key value at startup.一个返回 long 的 IdentifierGenerator,通过从启动时的最大主键值开始计数来构造。 Not safe for use in a cluster!在集群中使用不安全!

Since, it was incrementing already existing myTableId even if it was manually inserted, this resolved my issue.由于即使手动插入它也会增加已经存在的myTableId ,这解决了我的问题。

You can also implement your own generator if you need more control.如果您需要更多控制,您也可以实现自己的生成器。 See this interface IdentifierGenerator .请参阅此接口IdentifierGenerator So you can get the count of records, for example through a @NamedQuery .因此,您可以获取记录数,例如通过@NamedQuery Then you can generate an identifier yourself.然后你可以自己生成一个标识符。

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
   }
}

Entity:实体:

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

Just do not forget about the lock.只是不要忘记锁。

I use the generation type Identity, which basically means that the db, takes care of Id generation.我使用生成类型 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;

}

You can also use, Sequence generation:您还可以使用,序列生成:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM