Hibernate:“实体中的重复列映射”与“不允许在属性中混合可更新和不可更新的列”

Posted

技术标签:

【中文标题】Hibernate:“实体中的重复列映射”与“不允许在属性中混合可更新和不可更新的列”【英文标题】:Hibernate: 'Repeated column mapping in entity' vs 'Mixing updatable and non updatable columns in a property is not allowed' 【发布时间】:2013-08-17 21:34:36 【问题描述】:

我有旧版数据库。

+----+  +------------+ +------------+
|Site|  |Content     | |Program     |
+----+  +------------+ +------------+
|id  |  |id:PK       | |siteId:PK,FK|
|name|  |siteId:FK   | |code:PK     |
+----+  |prog_code:FK| |name        |
        |prog_param  | +------------+
        +------------+  

表格内容有一个 PK 列。 siteId 列不是 PK 的一部分。 Table Program 有两个 PK 列(siteId,code)。是复合PK。该表用作模板。程序中唯一的变量是参数,它位于表 Content 的 prog_param 列上。

我想将此表映射到这样的对象。

+-----------+  +------------+  +-----------+  +---------------+
|Site       |  |Program     |  |ProgramId  |  |Content        |
+-----------+  +------------+  +-----------+  +---------------+
|id:long    |  |id:ProgramId|  |site:Site  |  |id:long        |
|name:String|  |name:String |  |code:String|  |site:Site      |
+-----------+  |param:String|  +-----------+  |program:Program|
               +------------+                 +---------------+

但我不知道如何在这种复杂情况下映射“内容”和“程序”。

所以,我试图让情况变得简单。 我已将 prog_param 映射到 Content

+-----------+  +------------+  +-----------+  +-------------------+
|Site       |  |Program     |  |ProgramId  |  |Content            |
+-----------+  +------------+  +-----------+  +-------------------+
|id:long    |  |id:ProgramId|  |site:Site  |  |id:long            |
|name:String|  |name:String |  |code:String|  |site:Site          |
+-----------+  +------------+  +-----------+  |program:Program    |
                                              |programParam:String|
                                              +-------------------+

作为代码

@Entity
@Table(name = "SITE")
@Getter @Setter
public class Site 
    @Id
    @Column(name = "SITE")
    protected String id;

    @Column(name = "NAME")
    protected String name;



@Entity
@Table(name = "PROGRAM")
@Getter @Setter
public class Program 
    @EmbeddedId
    protected ProgramId id;
    @Column(name = "NAME")
    protected String name;


@Embeddable
@Getter @Setter @EqualsAndHashCode
public class ProgramId implements Serializable
    @ManyToOne
    @JoinColumn(name = "SITE")
    protected Site site;

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


@Entity
@Table(name="CONTENT")
@Getter
@Setter
public class Content 
    @Id
    @Column(name = "ID")
    protected Long id;

    @ManyToOne
    @JoinColumn(name = "SITEID",referencedColumnName="SITE")
    protected Site site;


    @OneToOne
    @JoinColumns(
        @JoinColumn(name="SITEID",referencedColumnName="SITE"),
        @JoinColumn(name="PROG_CODE",referencedColumnName="CODE"), 
    )
    protected Program program;

但这行不通。 Hibernate 抛出“实体映射中的重复列”异常。

所以我研究了一些解决方案。 最后,当休眠无法确定使用哪个属性时,我发现了这个“实体映射中的重复列”异常。

***s 的解决方案是将'insertable=false, updatable=false' 设置为@JoinColumn,所以让hibernate 可以决定使用哪个属性。

我想使用 Content 的属性“site”,因为它使用频率很高。并且 Site 和 Program 属性在我的应用程序中单独使用。

所以我尝试将 'insertable=false, updatable=false' 设置为 Content 的属性 'program'

    @OneToOne
    @JoinColumns(
        @JoinColumn(name="SITEID",referencedColumnName="SITE", insertable=false, updatable=false),
        @JoinColumn(name="PROG_CODE",referencedColumnName="CODE"), 
    )
    protected Program program;

这也行不通。 '不允许在属性中混合可更新和不可更新的列' 引发异常。

所以我设置了 set 'insertable=false, updatable=false' 为 'PROG_CODE',当然,当我设置不同的 prog_code 时,Hibernate 不会更改 PROG_CODE。

在这一点上,我不知道。

请告诉我一些解决这种情况的想法。

【问题讨论】:

【参考方案1】:

我遇到了同样的问题,共享一个属性的两个复合键因“实体映射中的重复列”而失败。我认为这可能是一个错误,参考:https://hibernate.atlassian.net/browse/HHH-4582。我正在使用休眠 3.6.4

【讨论】:

以上是关于Hibernate:“实体中的重复列映射”与“不允许在属性中混合可更新和不可更新的列”的主要内容,如果未能解决你的问题,请参考以下文章

Java类的继承与权限控制

hibernate.properties 与 hibernate.cfg.xml

Spring与Hibernate整合

Hibernate 的查询语言 HQL 与高级查询

hibernate与spring整合

Hibernate ORM框架——第一章:Hibernate简介与操作基础