0

在这里发布之前我已经在网上搜索过,但是我在一个重要的项目中,我没有更多的时间来浪费这个。好吧,这是交易:

我在数据库(SqlServer)中的表是由Hibernate自动创建的。因此,我有一个实体,并且该实体之前已使用 Id 注释进行映射,如下所示:

    @Id
    @GeneratedValue(strategy= GenerationType.AUTO)
    private int id;

Hibernate在sqlServer中创建了一个表dbo.Parcela,但是我们不得不改变生成 id 的方式,因为有时我们会收到 id 号并且我们希望将该 id 保存在我们的数据库中。所以我们的Entity现在是这样的:

@Id
private Integer id;

当我们第一次运行程序时一切正常,但是我们有一些客户已经使用旧的 Id 映射创建了他们的数据库,我们无法使用新的 Id 映射创建新表。因此,当我尝试插入新记录时,会收到以下消息:

SEVERE: Cannot insert explicit value for identity column
in table 'Parcela' when IDENTITY_INSERT is set to OFF.

任何帮助将不胜感激。

谢谢

4

2 回答 2

1

So you want your surrogate keys generated by the database, except when they were already generated by the customer. How are you going to avoid collisions, if the database wants to set id=12345, but a customer-imported entry with that id already exists?

The short answer to your question is: don't do this. I don't want to go into the old natural key vs surrogate key debate, this has been done already for example here. And google "codd surrogate keys" to learn how to properly use them. All i want to say is: if you use surrogate keys, then have your database generate them, and treat everything from outside as additional lookup key. That's the sane way.

The long answer is: if you really want to do this, and if you really know what you're doing, you can implement your own IdGenerator class. In JPA for example, you could annotate your id:

@Id
@GenericGenerator(name = "customId", strategy = "com.example.CustomIdGenerator", parameters = { @Parameter(name = "sequence", value = "SEQ_IDGENERATOR") })
@GeneratedValue(generator = "customId")
@Column(name = "ID", unique = true, nullable = false)
private Integer id;

Your customIdGenerator would then extend SequenceGenerator:

public class CustomIdGenerator extends SequenceGenerator {

  public Serializable generate(SessionImplementor session, Object obj) {
    // return o.getId() if obj.getId() is not null
    // newId = SEQ_IDGENERATOR.nextval
    // while (newId is already in db) newId = SEQ_IDGENERATOR.nextval
    // return newId
  }
}

and your database would provide SEQ_IDGENERATOR. Id would no longer be an autogenerated field but simply

create table foo( id integer not null primary key, ...);

But again: you don't want to do this. You want your surrogate keys to be irrelevant to the outside world and handled by the database.

于 2012-11-22T15:35:49.760 回答
0

你是如何让 Hibernate 为数据库创建模式的?如果您使用 hbm2ddl 可能会添加

<property name="hibernate.hbm2ddl.auto" value="update"/>

到您的 persistence.xml 或设置hbm2ddl.auto"update"可能让 Hibernate 在重新部署时自动更新数据库模式,让它修复插入问题。

当然,当您尝试插入已经存在的 id 时,它对您没有帮助,但我想您知道 :)

于 2012-11-22T12:11:56.907 回答