Org.Hibernate.AnnotationException: 实体没有指定标识符。我的表中没有id。

47

我正在使用数据库中的一张表,但这张表没有主键或一个适当的列来作为唯一值来充当主键,而且我没有权限更改该表。

那我该怎么办呢?我尝试在一个随机的列上放置@id注释,它确实起作用了,但我不知道以后是否会有任何问题。我应该怎么做?

我的类

@Entity
@Table(name="my_table")
public class TheTable {
@Column (name="name", nullable=false)
    private String name;

    @Id <--- I just put this id in this random column but this column should not be a id column
    @Column (name="anyfield", nullable=false)
    private String anyfield;
}

1
你无法做任何事情。Hibernate需要一种唯一标识行的方式。而且这个唯一值可能不会改变。 - JB Nizet
1
@JBNizet 在 Hibernate 中没有一种实现“复合键”的方法吗? - Kasun Siyambalapitiya
你能否注释来自 javax.persistence 包的 'Id'? - Kaumadie Kariyawasam
12个回答

186

我遇到了这个问题,使用了错误的 @id 导入。

确保导入的是:

import javax.persistence.Id;

而不是:

import org.springframework.data.annotation.Id;

@Id 需要是一个整数,或可转换为整数,或者我错了吗? - sMaN
我错了,我的问题出在其他地方。我已经成功使用@Enumerated(EnumType.STRING)列作为id。我正在返回单个列的单行,因此此枚举默认是唯一的。 - sMaN
OP特别询问当表没有主键列可以用@Id标记时该怎么办。 - Klesun

11

Hibernate是一个用于操作SQL数据库的中间件,由于SQL数据库中的每一行都应该有一个唯一标识符,因此Hibernate强制您定义一个。

这里是一个生成的主键示例,它将被自动添加(不要忘记getter和setter)

@Id 
@GeneratedValue
@Column(name = "id")
private int id;

由于不允许重复值,随意选择列并不是一个好的方法。


这需要一个名为“id”的实际列吗? - shanehoban
1
这个解决方案需要它,但是如果您有一个只有唯一值的列,那么它也可以是@Id列。 如果您决定自动生成一个,则还需要该列在数据库中存在。 - ThMBc
好的,如果存储过程没有返回唯一值列,您可以尝试以下代码:@Id \n @GeneratedValue \n private int id; - shanehoban
1
如果您想使用Hibernate和SQL,您需要定义一个唯一值列。提供的代码会自动创建此列并填充它。有一些替代存储系统不需要主键,但这不在本问题或答案的范围内。如果您没有提供@Column注释,它将为您创建它。 - ThMBc
每一行在 SQL 数据库中都应该有一个唯一标识符 - 这并不是正确的。 - Mike Argyriou

4

我也遇到了同样的问题。问题在于@Id注解的导入错误。因此,请确保您不仅注释了id,而且还使用javax.persistence.Id进行注释。


3

JPA(并非Hibernate本身)要求所有实体都具有唯一标识符。可悲的是,它不允许你所需的情况。

而另一方面,JDO允许持久化类映射到没有主键的表,并且可以处理您需要的内容。


什么是 JDO,你能给我一个学习它的链接吗?因为我对它一无所知。 - Kasun Siyambalapitiya
为什么不使用互联网搜索“Java数据对象”或JDO呢? - user3973283

3
You can solve this using embedded id 

示例:

@Entity
@Table(name = "my_table")
public class MyTable implements Serializable {

    private static final long serialVersionUID = 1L;

    // @Id
    @Column(name = "id", insertable = false, updatable = false)
    private String id;

    @EmbeddedId
    MYtablePK pk;

    public MYtablePK getPk() {
        return pk;
    }

    public void setPk(MYtablePK pk) {
        this.pk = pk;
    }

    @Column(name = "my_table_FirstName", insertable = false, updatable = false)
    private String name;

    @Transient
    public String getName() {
        return pk.getName();
    }

    public void setName(String mrn) {
        pk.setName(name);
    }
    @Transient
        public String getSeverity() {
        return pk.getSeverity();
    }
    public void setSeverity(String severity) {
        pk.setName(name);
    }

    public String getId() {
        return pk.getId();
    }
    public void setId(String id) {
        this.id = id;
    }
    public String getName() {
        return pk.getName();
    }
    public void setName(String name) {
        tpk.setName(name);
    }
}

@Embeddable
public class MyTablePK implements Serializable{

    /**
     * 
     */
    private static final long serialVersionUID = -1257821517891392898L;
    @Column(name = "id")
    private String id;
    @Column(name = "name")
    private String name;
    @Column(name = "dob")
    private Date dob;
    public Date getdob() {
        return dob;
    }
    public void setdob(Date dob) {
        this.pk.setdob(dob);
    }
    @Column(name = "severity")
    private String severity;
    public String getSeverity() {
        return severity;
    }
    public void setSeverity(String severity) {
        this.severity = severity;
    }

    public String getId() {
        return id;
    }
    public void setId(String id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name

1

不仅仅是Hibernate - 关系型数据模型需要主键。因此,如果没有主键,你所拥有的就是一个破损的数据模型,因为它不能是关系型的,这也是为什么使用ORM很困难的原因。

更多信息,请点击此处


0
使用@id注释作为主键

0

指定一个带有@Id注释的字段。每个@Entity都需要一个@Id(这是表中的主键)。 对于您来说,解决方案是使用@Embeddable而不是@Entity,然后您就不需要用@Id注释任何列了。将导入语句从javax.persistence.Entity;更改为javax.persistence.Embeddable;


0
要求:表格没有主键或适当的列具有唯一值 解决方案:只需为您的ID添加一个虚拟列,并在其余的选择语句中忽略它。想象一下,对于所有不需要主键的要求,该列不存在。为此列设置一些基于序列的自动增量机制或其他机制。 您需要:根据需要修改表的权限。

1
目前你的回答不够清晰,请编辑并添加更多细节,以帮助其他人理解它如何回答问题。你可以在帮助中心找到有关如何编写好答案的更多信息。 - Community

0

基本上,确保你的带有Column注释的字段与相关的数据库表匹配。


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