如何使用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
解决此问题,因为数据库现在无法更改。我尝试了GenerationType
,TableGenerator
的各种组合,但我无法成功解决它。
将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和其他论坛上提出了类似的问题,
我没什么限制,
- 我无法创建数据库序列,因为我的数据库更改已冻结。
- 我不想引入新的
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 子句?