我正在使用以下代码来定义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。 / p>
我的主要问题是我现在无法创建database sequence
来使用GenerationType.SEQUENCE
来解决此问题,因为现在无法更改数据库。
我尝试了GenerationType
,TableGenerator
的各种组合,但无法成功解决。
将initialValue
设置为更大的数字以避免重复的值可以暂时解决我的问题,但我也做不到。
如果有人可以在initialValue
和AUTO
的帮助下为我提供帮助,或者在不更改数据库的情况下为我提供其他更好的解决方案,那将是很棒的:)
答案 0 :(得分:1)
如果需要更多控制,也可以实现自己的生成器。 请参见此界面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;...
别忘了锁。
答案 1 :(得分:1)
由于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
}
标识列将在提交事务后立即自动分配一个值。您不要为标识列设置任何值,因为它是数据库分配值的工作。因此,您也无需考虑任何初始值(对于标识列完全忽略它们)
答案 2 :(得分:0)
我使用生成类型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;
}
答案 3 :(得分:0)
在这里提供的答案中以及在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
增量
一个IdentifierGenerator,它返回一个long,通过计数来构造 从启动时的最大主键值开始。不安全用于 集群!
因为,即使它是手动插入的,它也会增加已经存在的myTableId
,这解决了我的问题。