@GeneratedValue(strategy = GenerationType.AUTO) 没有像想象的那样工作

Posted

技术标签:

【中文标题】@GeneratedValue(strategy = GenerationType.AUTO) 没有像想象的那样工作【英文标题】:@GeneratedValue(strategy = GenerationType.AUTO) not working as thought 【发布时间】:2011-07-05 00:18:43 【问题描述】:

我正在尝试将对象持久化到数据库中。不断收到“列 ID 不能接受空值错误”。我的对象如下所示:

    @Entity
public class TestTable 
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Integer id = 0;

    @Column(nullable=false, length=256)
    private String data = "";

    public Integer getId() 
        return id;
    

    public void setId(Integer id) 
        this.id = id;
    

    public String getData() 
        return data;
    

    public void setData(String data) 
        this.data = data;
    


我的持久化功能:

public static synchronized boolean persistObject(Object obj)
        boolean success = true;
        EntityManager em = null;
        EntityTransaction tx = null;
        try
            em = getEmf().createEntityManager();
            tx = em.getTransaction();
            tx.begin();
            em.persist(obj);
            tx.commit();

         catch (Exception e)
            success = false;
         finally
            try
                em.close();
             catch(Exception e)
                //nothing
            
        
        return success;
    

【问题讨论】:

【参考方案1】:

您可以使用 GenerationType.TABLE。 这样,jpa 使用序列表进行 id 分配,您可能永远不需要生成降低可移植性的序列或自动增量值或触发器。

另请注意,在 java 中 int 类型默认为 0,因此您也可以摆脱它。

【讨论】:

@Null:然后接受答案(通过单击旁边的复选标记),以便 cguler 因提供它而获得小额奖励。这样做也有助于鼓励其他人很好地回答您的其他问题。 @cguler 这也对我有用,但我不知道为什么 GenerationType.Table 有效而 Auto 无效。你能解释一下或推荐我吗? @ChristianVielma 关键是,AUTO 默认为 IDENTITY。您可能需要明确尝试 GenerationType.IDENTITY 并查看它是否有效,以查看它是否是 AUTO 设置的问题。但可能您的数据库配置不支持它。但是 GenerationType.TABLE 创建一个表并将其用于生成密钥,并且此设置应适用于所有 rdbms。希望这会有所帮助:) 非常感谢@cguler,我会在文档中查看更多相关信息,看看为什么它不适用于我的 Postgres 配置。【参考方案2】:

在我的情况下,这是关于糟糕的方言:

hibernate.dialect=org.hibernate.dialect.H2Dialect

代替:

hibernate.dialect=org.hibernate.dialect.PostgreSQL9Dialect

当我切换到生产数据库时。 Hibernate 尝试使用为不同的数据库引擎准备的策略。

【讨论】:

【参考方案3】:

我遇到了与你类似的表现形式的问题。我最终发现我的数据库连接的配置是错误的:我正在连接一个架构不正确的旧数据库。新架构将主键列声明为

"ID" BIGINT NOT NULL GENERATED ALWAYS AS IDENTITY (START WITH 1, INCREMENT BY 1)

所以the database itself automatically generated the primary key 而旧架构将其声明为

"ID" INTEGER NOT NULL

Hibernate 为新架构执行了正确的代码,但在旧架构上失败了,因为旧架构要求 SQL INSERTID 列提供值。

【讨论】:

【参考方案4】:

当 ID 列是 Int 时,Hibernate 会以静默和神秘的方式失败。尝试在代码中将其更改为 Long 并在数据库中将其更改为无符号 64 位整数。这解决了我的问题。

【讨论】:

【参考方案5】:

以防万一有人遇到与我相同的问题。我已经为此苦苦挣扎了几个小时,只想发布我的解决方案。似乎 ID 总是设置为 0,这引发了错误。

模型中的 id 属性必须是“Long”或“Integer”类型,而不是“long”或“integer”(注意大写)。我放了“long”,这是一种原始类型,不能为空。因此默认值为 0,Hibernate 没有意识到它是一个新实体,并试图将其保存为 ID = 0,这显然不起作用。

把这个改成引用类型“Long”,可以为null,解决了。

【讨论】:

【参考方案6】:

或者试试@GeneratedValue(strategy = GenerationType.AUTO) 而不是@GeneratedValue(strategy = GenerationType.SEQUENCE)

【讨论】:

或尝试@Id @GeneratedValue(strategy=GenerationType.IDENTITY)【参考方案7】:

我在同样的问题上苦苦挣扎,不知何故对我来说是长时间的工作而不是 LONG 类型:)。作为一种解决方法,我将数据库中的 id 列转换为 SERIEL。我正在使用 postgres 数据库。

【讨论】:

以上是关于@GeneratedValue(strategy = GenerationType.AUTO) 没有像想象的那样工作的主要内容,如果未能解决你的问题,请参考以下文章

@GeneratedValue(strategy = GenerationType.AUTO) 没有像想象的那样工作

HSQL 中的@GeneratedValue(strategy=GenerationType.IDENTITY) 不会自动生成主键

使用 MariaDB 10.4 和 eclipselink 的 java @GeneratedValue (strategy = GenerationType.IDENTITY) 问题

在插入之前,我需要在其他列上使用 @Id @GeneratedValue(strategy = GenerationType.IDENTITY)

JPA之@GeneratedValue注解(转)

JAVA中JPA的主键自增长注解设置