我有jpa带注释的实体类,如:
@Configurable
@Entity
@Table(name="PLAYERS")
public class Player
{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name="ID")
private Integer id;
@Column(name="NAME")
private String name;
@PersistenceContext
public transient EntityManager entityManager;
...
}
这一直很好,直到我决定使用以下语法创建带有backuped yaml数据的表:
createNativeQuery("INSERT INTO PLAYERS ...")
成功创建后,我尝试创建一个实体:
Player player = new Player();
player.setName("new player");
player.persist();
我收到了错误:
SQL Error: -1, SQLState: 23505
与primary_keys的重复有关,因为为新实体生成的id = 1(与从备份数据中重新获取的行相同)。当然我可以使用jpa / java语法从备份文件中检索数据,但在这种情况下我无法控制插入数据的主键等。 如何解决这个问题呢 ?在插入备份数据后有没有办法更新id_generator?
答案 0 :(得分:2)
由于您手动插入数据,因此需要更改表以更改标识列的起始值:
ALTER TABLE PLAYERS ALTER COLUMN ID RESTART WITH 1234;
其中1234是备份数据的最大ID。
ALTER TABLE statement的文档中的更多详细信息:
RESTART WITH整数常量 指定下一个值 为标识列生成。 RESTART WITH对表很有用 它有一个标识列 定义为由DEFAULT和。生成 具有在其上定义的唯一键 身份栏。因为GENERATED BY DEFAULT允许手动插入和 系统生成的值,它是 可能是手动插入的值 可能与系统生成冲突 值。要解决这些冲突, 使用RESTART WITH语法指定 将生成的下一个值 对于标识列。考虑一下 以下示例,其中涉及到 自动生成的组合 数据和手动插入的数据:
CREATE TABLE tauto(i INT GENERATED BY DEFAULT AS IDENTITY, k INT) CREATE UNIQUE INDEX tautoInd ON tauto(i) INSERT INTO tauto(k) values 1,2系统会自动生成 标识列的值。但 现在你需要手动插入一些 数据进入标识栏:
INSERT INTO tauto VALUES (3,3) INSERT INTO tauto VALUES (4,4) INSERT INTO tauto VALUES (5,5)标识列使用了值1 此时通过5点。??如果你现在 希望系统生成一个值, 系统将生成一个3,其中 将导致唯一的密钥异常 因为价值3已经存在 手动插入。补偿 对于手动插入,发出ALTER 用于标识的TABLE语句 具有RESTART WITH 6的列:
ALTER TABLE tauto ALTER COLUMN i RESTART WITH 6