jpa和hibernate_JPA和Hibernate中的组合键

jpa和hibernate

每个JPA实体都有一个主键,但是某些实体具有多个值作为其主键。 在这种情况下,您需要使用组合键。 该Java技巧向您介绍如何在JPA和Hibernate中使用复合键。

请注意,我假设您已经通过JPA和Hibernate引入了Java持久性,包括如何使用主键为实体和关系建模。 如果您不熟悉这些概念,请参阅教程JPA和Hibernate的Java持久性

当您需要组合键时

考虑一个产品定价表,该表根据地区名称和产品ID来存储产品价格。 在这种情况下,您的表可能包含具有相同产品ID的多个行,但每个行都与一个不同的区域相关联。 您需要产品ID和地区名称,以唯一地区分不同地区的产品价格。

我们将使用两个JPA构造来解决此问题:

  • Embeddable Object :我们将创建一个新类ProductPriceId ,该类带有@Embeddable批注,同时包含产品ID和区域名称,该区域名称代表产品价格的主键。
  • 嵌入式ID :我们将创建ProductPrice实体,并使用@EmbeddableId批注将ProductPriceId引用为其id

首先,请研究如下所示的ProductPriceIdProductPrice类的源代码。

清单1. ProductPriceId.java

package com.geekcap.javaworld.jpa.model;

import javax.persistence.Embeddable;
import java.io.Serializable;

@Embeddable
public class ProductPriceId implements Serializable {
    private String region;
    private Integer productId;

    public ProductPriceId() {
    }

    public ProductPriceId(String region, Integer productId) {
        this.region = region;
        this.productId = productId;
    }

    public String getRegion() {
        return region;
    }

    public void setRegion(String region) {
        this.region = region;
    }

    public Integer getProductId() {
        return productId;
    }

    public void setProductId(Integer productId) {
        this.productId = productId;
    }

    @Override
    public String toString() {
        return "ProductPriceId{" +
                "region='" + region + '\'' +
                ", productId=" + productId +
                '}';
    }
}
清单2. ProductPrice.java

package com.geekcap.javaworld.jpa.model;

import javax.persistence.EmbeddedId;
import javax.persistence.Entity;
import javax.persistence.Table;

@Entity
@Table(name = "PRODUCT_PRICE")
public class ProductPrice {

    @EmbeddedId
    private ProductPriceId id;
    private Double price;

    public ProductPrice() {
    }

    public ProductPrice(ProductPriceId id, Double price) {
        this.id = id;
        this.price = price;
    }

    public ProductPriceId getId() {
        return id;
    }

    public void setId(ProductPriceId id) {
        this.id = id;
    }

    public Double getPrice() {
        return price;
    }

    public void setPrice(Double price) {
        this.price = price;
    }

    @Override
    public String toString() {
        return "ProductPrice{" +
                "id=" + id +
                ", price=" + price +
                '}';
    }
}

ProductPriceId类(清单1)是一个简单的Java类,具有两个成员变量: regionproductId 。 它带有@Embeddable注释。

ProductPrice类(清单2)是一个JPA实体,它映射到“ PRODUCT_PRICE”表并定义了ProductPriceId类型的id字段。 ProductPriceId字段类型使用@EmbeddedId注释进行注释。

具有复合键的示例应用程序

清单3显示了示例应用程序的源代码,该示例应用程序创建四个不同的产品价格,通过其ProductPriceId执行对产品的查询,查询所有产品价格,然后转储“ PRODUCT_PRICE”表的内容,以便我们了解如何Hibernate代表数据。

清单3. JpaExampleCompositeKey.java

package com.geekcap.javaworld.jpa;

import com.geekcap.javaworld.jpa.model.ProductPrice;
import com.geekcap.javaworld.jpa.model.ProductPriceId;
import org.hibernate.Session;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;

public class JpaExampleCompositeKey {
    public static void main(String[] args) {
        // Create our entity manager
        EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("SuperHeroes");
        EntityManager entityManager = entityManagerFactory.createEntityManager();

        // Create a product price
        ProductPrice productPrice1 = new ProductPrice(new ProductPriceId("EAST", 1), 500.0d);
        ProductPrice productPrice2 = new ProductPrice(new ProductPriceId("WEST", 1), 400.0d);
        ProductPrice productPrice3 = new ProductPrice(new ProductPriceId("EAST", 2), 200.0d);
        ProductPrice productPrice4 = new ProductPrice(new ProductPriceId("WEST", 2), 150.0d);

        try {
            // Save the product prices to the database
            entityManager.getTransaction().begin();
            entityManager.persist(productPrice1);
            entityManager.persist(productPrice2);
            entityManager.persist(productPrice3);
            entityManager.persist(productPrice4);
            entityManager.getTransaction().commit();
        } catch (Exception e) {
            e.printStackTrace();
        }

        // Query for product1 by its ID
        ProductPrice productPrice = entityManager.find(ProductPrice.class, new ProductPriceId("EAST", 1));
        System.out.println(productPrice);

        // Find all product prices
        List<ProductPrice> productPrices = entityManager.createQuery("from ProductPrice").getResultList();
        System.out.println("\nAll Product Prices:");
        productPrices.forEach(System.out::println);

        // DEBUG, dump our tables
        entityManager.unwrap(Session.class).doWork(connection ->
                JdbcUtils.dumpTables(connection, "PRODUCT_PRICE"));


        // Close the entity manager and associated factory
        entityManager.close();
        entityManagerFactory.close();
    }
}

此应用程序创建一个新的EntityManagerFactory ,该实体引用“ 包含JPA和Hibernate的Java持久性,第2部分 ”中的SuperHeroes持久性单元,其中包含ProductPrice实体。 然后,它从该持久性单元创建EntityManager 。 它创建四个产品价格:两个分别针对产品1和两个针对产品2,但位于两个不同的区域:“东”和“西”。 然后,使用EntityManager::persist方法将其EntityManager::persist到数据库中。

接下来,它使用EntityManager::find方法查询ProductPrice ,该方法需要检索的实体的类名称及其主键。 因为我们使用的是复合键,所以我们向它传递了一个新的ProductPriceId实例,该实例的区域名称设置为“ EAST”,产品ID设置为1。这将产生以下输出:


ProductPrice{id=ProductPriceId{region='EAST', productId=1}, price=500.0}

用组合键查询

使用复合键查询实体正是您所期望的:只需将主键传递给find()方法。 唯一的区别是,在这种情况下,我们没有传递StringInteger ,而是传递ProductPriceId

然后,示例应用程序使用JPQL查询“ from ProductPrice ”查询所有产品价格,这将产生以下输出:


ProductPrice{id=ProductPriceId{region='EAST', productId=1}, price=500.0}
ProductPrice{id=ProductPriceId{region='WEST', productId=1}, price=400.0}
ProductPrice{id=ProductPriceId{region='EAST', productId=2}, price=200.0}
ProductPrice{id=ProductPriceId{region='WEST', productId=2}, price=150.0}

我们将看到持久化到数据库中的所有四个产品价格。 “ PRODUCT_PRICE”表包含来自我们的JdbcUtils::dumpTables方法调用的以下数据:


Table: PRODUCT_PRICE
  {PRODUCTID: 1, REGION: EAST, PRICE: 500.0},
  {PRODUCTID: 1, REGION: WEST, PRICE: 400.0},
  {PRODUCTID: 2, REGION: EAST, PRICE: 200.0},
  {PRODUCTID: 2, REGION: WEST, PRICE: 150.0},
  

ProductPriceId中的字段以及我们的附加ProductPrice属性: price直接写入“ PRODUCT_PRICE”表中的数据库列。 Hibernate处理将字段填充到适当的类中。

Java持久性与Spring Data

想继续吗? 注意Java持久性系列中的下一个教程,介绍Spring Data作为Hibernate for JPA的替代方法。

这个故事“ JPA和Hibernate中的复合键”最初是由JavaWorld发布的

翻译自: https://www.infoworld.com/article/3391019/composite-keys-in-jpa-and-hibernate.html

jpa和hibernate

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值