JPA中的IDENTITY_INSERT

3

我正在尝试将一些假数据插入到SQL Server Express数据库中。我使用的是像下面这样的简单代码:

@Entity
@Table(name = "People")
public class Peeps implements Serializable {

    @Id
    @Column(name = "ID", columnDefinition = "Decimal(10,0)")
    private String id;

    @Column(name = "PERSON_NAME")
    private String name;

}

我使用实体管理器按照以下方式创建上述类:
private EntityManager em = createManager();
private EntityTransaction utx = em.getTransaction();

final Peeps entity = new Peeps();
entity.setId("10002");
entity.setName("Joe");
utx.begin();
em.persist(entity);
utx.commit();

然而,当我这样做时,会出现一个错误:
 Cannot insert explicit value for identity column in table 'People' when IDENTITY_INSERT is set to OFF

我尝试做的是这样的:

em.createNativeQuery("SET IDENTITY_INSERT People ON").executeUpdate();
em.persist(entity);
em.createNativeQuery("SET IDENTITY_INSERT People OFF").executeUpdate();

然而,我仍然得到了相同的错误。我的直觉告诉我,连接没有被共享。有没有什么我可以做来指示Hibernate在调用持久性之前设置IDENTITY_INSERTON


你需要明确设置实体的标识符吗?还是可以让数据库自动处理呢? - Naros
@Naros 说实话,看着我的一些逻辑,我相信我的实体在生产代码中永远不会被写入数据库。因此,我认为默认策略需要手动输入标识符到数据库中。考虑到这一点,我已经在我的实体中添加了@GeneratedValue(strategy = GenerationType.IDENTITY),以允许表生成该ID并在提交后将其返回给实体。你认为这是一个好策略吗? - angryip
一些相关讨论:https://dev59.com/cF8e5IYBdhLWcg3wcKAq - Alan Hay
1个回答

12

你的 id 字段下面缺少下一行:

@GeneratedValue(strategy=GenerationType.IDENTITY)

所以你的id字段应该是这样的:

@Entity
@Table(name = "People")
public class Peeps implements Serializable {

    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    @Column(name = "ID", columnDefinition = "Decimal(10,0)")
    private String id;

    @Column(name = "PERSON_NAME")
    private String name;

}

其次,您不应该手动为实体设置 ID,使用 Hibernate 持久化时,ID 将会自动生成。

因此,请删除以下代码:entity.setId("10002");

并改为:

private EntityManager em = createManager();
private EntityTransaction utx = em.getTransaction();

final Peeps entity = new Peeps();
entity.setName("Joe");
utx.begin();
em.persist(entity);
utx.commit();

确保已在数据库表中将主键配置为自增,以免出现其他问题。


1
使用生成的值注释只会依赖于实体关联的表来设置ID,对吗? - angryip
我不确定你在问什么。 - Moshe Arad
这个表必须分配主键并返回它吗?试图理解文档:http://docs.oracle.com/javaee/5/api/javax/persistence/GenerationType.html#IDENTITY - angryip
它的意思是:“表示持久性提供程序必须使用数据库标识列为实体分配主键。”持久性提供程序=Hibernate,因此实际上意味着:表示Hibernate必须使用数据库标识列为实体分配主键。 - Moshe Arad
我明白了。这只是用于插入记录吗? - angryip
@MosheArad 实际上,您只是删除了显式 ID 设置,这正是 angryip 实际想要的,并且会导致错误。因此,您没有回答问题。 - Artem Novikov

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接