当前位置: 首页 > 知识库问答 >
问题:

在hibernate中使用复合密钥

申屠亦
2023-03-14

假设我想要一个复合键作为采购订单实体的street,city。

下面是我如何识别做这件事,

    @Embeddable
    public class BillingAddress implements Serializable {

        private String street;
        private String city;

        public BillingAddress(){

        }

        public BillingAddress(String street, String city) {
            this.street = street;
            this.city = city;
        }
        //with getters and setters
}



@Entity
@IdClass(BillingAddress.class)
public class PurchaseOrder {

    public PurchaseOrder(BillingAddress billingAddress) {
        street = billingAddress.getStreet();
        city = billingAddress.getCity();

    }

    @Id
    @AttributeOverrides({
            @AttributeOverride(name = "street", column = @Column(name = "STREET")),
            @AttributeOverride(name = "city", column = @Column(name = "CITY")) })
    private String street;
    private String city;
    private String itemName;

    public String getItemName() {
        return itemName;
    }

    public void setItemName(String itemName) {
        this.itemName = itemName;
    }

}

我想明白@AttributeOverrides注释到底是做什么的?即使我将colomn name更改为something STREET1,我仍然看到使用列名street创建的表。那么column=@column(name=“street”))在这里做什么。

另外,我可以将它作为PurchaseOrder类的一个字段使用,而不是构造性地使用BillingAddress,

 public class PurchaseOrder {
     BillingAddress billingAddress;

}

在这种情况下,这将如何改变?我还需要有私家串街;私弦城;在采购订单中?

最后,我读到了在新的数据库系统设计中应该避免使用复合键,其中使用复合主键是适用于这样一种情况,即为了映射遗留的数据库表而不改变数据库表结构,对吗?那句话有效吗?

//编辑问题

保存开票地址在字段中的采购订单,

PurchaseOrder purchaseOrder = new PurchaseOrder();
purchaseOrder.setItemName("name");

BillingAddress billingAddress = new BillingAddress();
billingAddress.setCity("c1"); billingAddress.setStreet("s1");                                                              purchaseOrder.setBillingAddress(billingAddress); 
session.save(purchaseOrder);

共有2个答案

郑博厚
2023-03-14

您的PurchaseOrder类不是从任何类型的映射实体扩展的,您(当前)应用@AttributeOverride的属性也不是。因此,实际上没有什么可以重写的,您的JPA提供程序只是忽略了注释。我认为您试图做的是为一个实体定义一个嵌入式id,同时覆盖该id的一些列映射。您可以通过对当前代码进行一些修改来完成此操作:

@Entity
public class PurchaseOrder {
    @EmbeddedId
    @AttributeOverrides({
            @AttributeOverride(name = "street", column = @Column(name = "BILLING_STREET")),
            @AttributeOverride(name = "city", column = @Column(name = "BILLING_CITY")) })
    private BillingAddress billingAddress;

    private String itemName;

    // Constructors, Getters/Setters
}

注意,我更改了重写属性的名称,因为在当前示例中,嵌入的id名称和重写的名称是相同的。

班景龙
2023-03-14

你问的问题不多,我试着把所有的问题都看一遍,然后一一回答:

@AnnotationOverride做什么?

在这里回答:@AttributeOverride是什么意思?

第二个问题对我来说有点不清楚,但我想您是在问是否必须在PurchaseOrder类中包含来自复合键的所有字段。

不,我不这么认为。下面是我快速拼凑的一个例子:

@Entity
@Table(name = "PURCHASE_ORDER")
public class PurchaseOrder{

    @Id
    private BillingAddress billingAddress;

    //getters & setters

    @Embeddable
    public static class BillingAddress implements Serializable {
        @Column(name = "street")
        private String street;
        @Column(name = "city")
        private String city;
        @Column(name = "itemName")
        private String itemName;

        //getters & setters

    }
}

不用担心语法,只担心结构。您甚至可以在不是ID的PurchaseOrder中添加额外的字段。

我是否应该使用复合键?

在这里回答:我是否应该使用复合主键?

 类似资料:
  • 对于和,我有如下表格结构。的复合键有三列——,,,但部门只有两列与Employee的复合键匹配——,

  • 用户详细信息 有人能看出我做错了什么吗?

  • 问题内容: 所以我对数据库中的某些表进行了反向工程,当我尝试将对象保存到数据库中时,出现以下错误: 初始SessionFactory创建失败。org.hibernate.AnnotationException:从com.mycode.Account引用com.mycode.Block的外键具有错误的列数。在线程“ main”中应为2异常java.lang.ExceptionInInitialize

  • 我的主要问题是用复合分区键对表上的Cassandra resultset进行分页。然而,我试图用一个简单的场景来缩小范围。喂,我有桌子, 我有一个数据, 我的模式使用默认的分区器(Murmur3Partitioner)。这是完全可以实现的吗?

  • 当目标实体使用复合连接时,其中一列是使用转换器的自定义类型,Hibernate(使用Spring Boot JPA)无法插入。 简化实体定义: converter类使用简单的字符串操作,TableId类实现可序列化。从Spring Boot应用程序的上下文中保存元素时,出现以下异常: 我验证了将列更改为简单字符串可以解决问题。我还应该应用什么来使其与此连接查询一起工作吗?

  • notification_detail-单个主键 我想使用JPA持久化和读取这些对象,但无法使ManyToOne映射工作。 许多通知映射到一个notification_detail。 我试过所有类型的不同配置。我能想到的最好的办法是,我的情况很复杂,因为父对象“notification_detail_id”有一个复合键“notification_detail_id”,它也是子对象的主键。这使得Hi