【问题标题】:Can't create composite primary key with foreign key in PLAY 2.0无法在 PLAY 2.0 中使用外键创建复合主键
【发布时间】:2012-05-23 15:43:51
【问题描述】:

这是我想在我的 PLAY 项目中表现的情况:

table clients {
     client_id (pk),
     description
}

table items {
     client_id (fk, pk),
     item_id (pk)
}

在“items”表中,我想要一个复合主键,它将由组合的 client_id 和 item_id 组成。我已阅读 JPA 文档以及有关该主题的许多帖子,但一切都一次又一次地失败。这是我尝试过的众多版本之一 - 最接近 JPA 文档。

@Entity
@Table(name = "items")
public class Items extends Model {
    ItemsPK primaryKey;

    public Items() {
    }

    @EmbeddedId
    public ItemsPK getPrimaryKey() {
        return primaryKey;
    }

    public void setPrimaryKey(ItemsPK pk) {
        primaryKey = pk;
    }
}

@Embeddable
public class ItemsPK implements Serializable {
    private long itemId;
    private Client client;

    public ItemsPK() {
    }

    @Column(name = "item_id")
    @GeneratedValue(strategy = GenerationType.AUTO)
    public long getItemId() {
        return itemId;
    }

    public void setItemId(long itemId) {
        this.itemId = itemId;
    }

    @ManyToOne
    @JoinColumn(name = "client_id", nullable = false)
    public Client getClient() {
        return client;
    }

    public void setClient(Client client) {
        this.client = client;
    }

    //public int hashCode() {...
    //public boolean equals(Object obj) {...
}

上述代码(以及许多其他不同的设置)在播放启动期间产生以下错误:

java.lang.RuntimeException:读取注释时出错 模型.ItemsPK 在 com.avaje.ebeaninternal.server.deploy.parse.ReadAnnotations.readAssociations(ReadAnnotations.java:73) ~[ebean.jar:na] 在 com.avaje.ebeaninternal.server.deploy.BeanDescriptorManager.readDeployAssociations(BeanDescriptorManager.java:1100) ~[ebean.jar:na]

我不知道我的代码可能有什么问题。我开始认为这是一个 PLAY 错误。有什么想法吗?

【问题讨论】:

  • 你有充分的理由坚持复合PK吗?即使您设法处理了这个问题,您也可能因此面临其他几个问题。为什么不向 items 表添加一个额外的列(比如 items_id)并在(client_id,item_id)上放置一个唯一索引。 (我想 item_id 指的是 item 表,就像 client_id 指的是客户表一样)。
  • @bpgergo 感谢您的回答。您的解决方案是可以接受的,但我宁愿避免额外的列和索引。令我惊讶的是,需要解决这样一个简单的案例。如果几天后没有解决方案,我会重新考虑。至于item_id,目前它没有引用任何其他表,但将来可能会改变。
  • 标签:hibernate** 在这里不正确。没有 Hibernate 也没有 JPA

标签: java jpa playframework-2.0 ebean


【解决方案1】:

切希奇,

这不是答案,而是建议。您能告诉我在您的案例中使用复合 PK 的主要目标是什么吗?使用 Ebean ORM,您的两个模型都将非常小且容易

models/Client.java

package models;

import play.db.ebean.Model;
import javax.persistence.Entity;
import javax.persistence.Id;

@Entity
public class Client extends Model {
    @Id
    public Long id;
    public String description;
}

模型/Item.java

package models;

import play.db.ebean.Model;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.ManyToOne;

@Entity
public class Item extends Model {
    @Id
    public Long id;

    @ManyToOne
    public Client client;
}

仅此而已。除了复合 PK 之外,它为您提供所需的一切

【讨论】:

  • 在这个系统中,每个 item_id 应该只在一个 client_id 中是唯一的。换句话说,两个不同的客户端可以拥有具有相同 id 的项目,但一个客户端不能拥有两个相同的 item_id。 Item_id 是用户定义的值。每个用户都可以拥有自己的一组项目。在这方面你的回答并没有解决我的问题。
  • 嗯,只是常见的@ManyToMany 关系,当然Ebean 会为此创建ItemClient 表+ 你必须确保在保存新关系之前不存在该关系,但是我还在想这是更容易和更便宜的解决方案。恕我直言
【解决方案2】:

根据我的经验,您不能在 EmbeddedId 中使用 GeneratedValue,必须分配复合键中的值。请参阅下面的摘录。

使用 GeneratedValue 注解只需要 支持简单的主键。 GeneratedValue 的使用 派生主键不支持注释。

http://docs.oracle.com/javaee/6/api/javax/persistence/GeneratedValue.html

http://www.objectdb.com/api/java/jpa/GeneratedValue

我建议不要为此使用复合键,因为 itemId 足以生成唯一标识符。

【讨论】:

    【解决方案3】:

    我认为您没有禁用 Ebean。 Ebean 是 Play 2 的默认 ORM。如果你想使用 JPA,你必须禁用 Ebean。

    所以在你的 Build.scala 中,添加这个:

    val main = PlayProject(appName, appVersion, appDependencies, mainLang = JAVA).settings(
        ebeanEnabled := false
    )
    

    在你的 application.conf 中编辑这一行:

    ebean.default="models.*"
    

    【讨论】:

    • 您可以将 ebean 与 JPA 注释一起使用,因此没有理由禁用 ebean。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-07-22
    • 1970-01-01
    • 2011-12-23
    • 1970-01-01
    • 2020-04-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多