Hibernate 是否不允许嵌入式 ID 复合主键类中的 @Column 为只读(错误?)?

发布于 2024-10-04 03:08:19 字数 2709 浏览 0 评论 0原文

这是数据库设计 (DDL):

CREATE TABLE Countries
(
  iso_code CHAR(2) NOT NULL,
  name VARCHAR(50) NOT NULL,
  PRIMARY KEY (iso_code)
);

CREATE TABLE Zips
(
  country_code CHAR(2) NOT NULL,
  code VARCHAR(10) NOT NULL,
  PRIMARY KEY (country_code, code),
  FOREIGN KEY (country_code) REFERENCES Countries (iso_code)
);

这是 Zip 类 + 复合主键类:

@Entity
@Table(name = "Zips")
public class Zip implements Serializable
{
    @EmbeddedId
    private ZipId embeddedId;

    @ManyToOne
    @JoinColumn(name = "country_code", referencedColumnName = "iso_code")
    private Country country = null;

    ...
}

@Embeddable
public class ZipId implements Serializable
{
    @Column(name = "country_code", insertable = false, updatable = false)
    private String countryCode;

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

    ...
}

Hibernate 堆栈跟踪:

Exception in thread "main" javax.persistence.PersistenceException: [PersistenceUnit: zips] Unable to build EntityManagerFactory
    at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:911)
    at org.hibernate.ejb.HibernatePersistence.createEntityManagerFactory(HibernatePersistence.java:57)
    at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:48)
    at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:32)
    at tld.zips.Main.main(Main.java:27)
Caused by: org.hibernate.MappingException: Repeated column in mapping for entity: tld.zips.model.Zip column: country_code (should be mapped with insert="false" update="false")
    at org.hibernate.mapping.PersistentClass.checkColumnDuplication(PersistentClass.java:675)
    at org.hibernate.mapping.PersistentClass.checkPropertyColumnDuplication(PersistentClass.java:697)
    at org.hibernate.mapping.PersistentClass.checkColumnDuplication(PersistentClass.java:719)
    at org.hibernate.mapping.PersistentClass.validate(PersistentClass.java:473)
    at org.hibernate.mapping.RootClass.validate(RootClass.java:235)
    at org.hibernate.cfg.Configuration.validate(Configuration.java:1332)
    at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1835)
    at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:902)
    ... 4 more

这是什么? Country_code 在复合主键类中映射为只读(insertable = false、updatable = false)。这与 EclipseLink 完美配合! IIRC @Embeddable 类允许在其列上使用 @Basic、@Column、@Enumerated、@Temporal、@Lob 和 @Embedded,因此这应该可行。请注意,代码与 JPA 1.0 兼容。

当将 insertable = false, updateable = false 放在 @JoinColumn 上时,异常消失,但这不是我想要的。我更喜欢我的关联是可写的...

这是一个 Hibernate bug 吗?我正在使用 Hibernate 3.6 稳定版。

Here's the DB design (DDL):

CREATE TABLE Countries
(
  iso_code CHAR(2) NOT NULL,
  name VARCHAR(50) NOT NULL,
  PRIMARY KEY (iso_code)
);

CREATE TABLE Zips
(
  country_code CHAR(2) NOT NULL,
  code VARCHAR(10) NOT NULL,
  PRIMARY KEY (country_code, code),
  FOREIGN KEY (country_code) REFERENCES Countries (iso_code)
);

Here's the Zip class + composite primary key class:

@Entity
@Table(name = "Zips")
public class Zip implements Serializable
{
    @EmbeddedId
    private ZipId embeddedId;

    @ManyToOne
    @JoinColumn(name = "country_code", referencedColumnName = "iso_code")
    private Country country = null;

    ...
}

@Embeddable
public class ZipId implements Serializable
{
    @Column(name = "country_code", insertable = false, updatable = false)
    private String countryCode;

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

    ...
}

Hibernate stack trace:

Exception in thread "main" javax.persistence.PersistenceException: [PersistenceUnit: zips] Unable to build EntityManagerFactory
    at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:911)
    at org.hibernate.ejb.HibernatePersistence.createEntityManagerFactory(HibernatePersistence.java:57)
    at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:48)
    at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:32)
    at tld.zips.Main.main(Main.java:27)
Caused by: org.hibernate.MappingException: Repeated column in mapping for entity: tld.zips.model.Zip column: country_code (should be mapped with insert="false" update="false")
    at org.hibernate.mapping.PersistentClass.checkColumnDuplication(PersistentClass.java:675)
    at org.hibernate.mapping.PersistentClass.checkPropertyColumnDuplication(PersistentClass.java:697)
    at org.hibernate.mapping.PersistentClass.checkColumnDuplication(PersistentClass.java:719)
    at org.hibernate.mapping.PersistentClass.validate(PersistentClass.java:473)
    at org.hibernate.mapping.RootClass.validate(RootClass.java:235)
    at org.hibernate.cfg.Configuration.validate(Configuration.java:1332)
    at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1835)
    at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:902)
    ... 4 more

What's this? country_code is mapped as read-only (insertable = false, updatable = false) in the composite primary key class. This works perfectly with EclipseLink! IIRC @Embeddable classes allow @Basic, @Column, @Enumerated, @Temporal, @Lob, and @Embedded on its columns, so this should work. Note the code is JPA 1.0 compatible.

The exception vanishes when putting the insertable = false, updatable = false on the @JoinColumn, but this is not what I want. I prefer my associations to be writable...

Is this a Hibernate bug? I'm using Hibernate 3.6 stable.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

陈年往事 2024-10-11 03:08:19

看起来像一个错误。作为解决方法,您可以将 country 放入 ZipId 而不是 countryCode

@Entity 
@Table(name = "Zips") 
public class Zip implements Serializable 
{ 
    @EmbeddedId 
    private ZipId embeddedId;  
    ... 
} 

@Embeddable 
public class ZipId implements Serializable 
{ 
    @ManyToOne 
    @JoinColumn(name = "country_code", referencedColumnName = "iso_code") 
    private Country country = null; 

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

    ... 
} 

Looks like a bug. As a workaround you can place country into ZipId instead of countryCode:

@Entity 
@Table(name = "Zips") 
public class Zip implements Serializable 
{ 
    @EmbeddedId 
    private ZipId embeddedId;  
    ... 
} 

@Embeddable 
public class ZipId implements Serializable 
{ 
    @ManyToOne 
    @JoinColumn(name = "country_code", referencedColumnName = "iso_code") 
    private Country country = null; 

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

    ... 
} 
二手情话 2024-10-11 03:08:19

是的,看起来像一个错误。无论如何,我想你可以这样做。不过我自己还没有尝试过。

@Entity
@Table(name = "Zips")
public class Zip implements Serializable
{
    @EmbeddedId
    @AttributeOverrides({
        @AttributeOverride(name="countryCode", column=@Column(name="country_code", insertable = false, updatable = false))
        @AttributeOverride(name="code", column=@Column("code"))
    })
    private ZipId embeddedId;

    @ManyToOne
    @JoinColumn(name = "country_code", referencedColumnName = "iso_code")
    private Country country;

    ...
}

@Embeddable
public class ZipId implements Serializable
{
    private String countryCode;
    private String code;    

    ...
}

Yeah, seems like a bug. Anyway, you can do it like this, I suppose. Haven't tried it myself, though.

@Entity
@Table(name = "Zips")
public class Zip implements Serializable
{
    @EmbeddedId
    @AttributeOverrides({
        @AttributeOverride(name="countryCode", column=@Column(name="country_code", insertable = false, updatable = false))
        @AttributeOverride(name="code", column=@Column("code"))
    })
    private ZipId embeddedId;

    @ManyToOne
    @JoinColumn(name = "country_code", referencedColumnName = "iso_code")
    private Country country;

    ...
}

@Embeddable
public class ZipId implements Serializable
{
    private String countryCode;
    private String code;    

    ...
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文