从 Spring 数据 JPA 中的一对多连接关系中获取列数据



假设我有两个数据库表,产品和产品详细信息。

create table Product
{
product_id int not null,
product_name varchar(100) not null,
PRIMARY KEY (product_id)
}
create table ProductDetails
{
detail_id int not null,
product_id int not null,
description varchar(100) not null,
PRIMARY KEY (detail_id,product_id),
FOREIGN KEY (product_id) REFERENCES Product(product_id)
}

每个产品可以有多个产品详细信息条目,但每个产品详细信息只能属于一个产品。在SQL中,我希望能够检索每个产品详细信息,但也使用产品名称,我将使用连接语句来执行此操作。

select p.product_id,pd.detail_id,p.product_name,pd.description
from Product p join ProductDetails pd on p.product_id=pd.product_id

现在我需要在 Spring 数据 JPA 表单中拥有这个概念。我目前的理解如下:

@Table(name = "Product")
public class ProductClass
{
private int productID;
private String productName;
}
@Table(name = "ProductDetails")
public class ProductDetailsClass
{
private int detailID;
private int productID;
// this is the part I don't know how to set. @OneToMany? @ManyToOne? @JoinTable? @JoinColumn?
private String productName;
private String description;
}

(我没有包含任何属性,例如@Id以保持代码最小化(

我需要写什么才能使这个private String productName;正常工作? 我对@JoinTable@OneToMany和其他属性的研究只会让我更加困惑。

附言这是我继承的遗留Java程序。private String productName;部分不在原始代码中,但现在我需要 ProductDetails 类才能使productName可用。

附言我想在尝试任何事情和部署之前清楚地了解我在做什么。这是一个部署到生产环境中的遗留程序,据我所知,这里的任何代码更改也会改变数据库结构,如果发生任何灾难性的事情,再多的钱也不足以让我想将 Java 程序、Spring 框架、Apache 服务器和 MySQL 数据库恢复到工作状态。此外,我实际上没有开发环境来测试这一点。帮助。。。

你的研究已经朝着正确的方向发展:你需要一个@OneToMany的关系。对Hibernate最好的描述是Vlad Mihalcea。在他的网页上,你也可以找到对这些关系的一个很好的解释:绘制与JPA和Hibernate@OneToMany关系的最佳方式。

首先,您必须正确创建实体(实体由关系数据库中的表表示(。

单向 (@OneToMany(

@Entity
@Table(name = "product")
public class Product
{
@Id
@GeneratedValue
private Long productID;
private String productName;
@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
private List<ProductDetail> productDetails;
//Constructors, getters and setters...
}
@Entity
@Table(name = "product_details")
public class ProductDetail
{
@Id
@GeneratedValue
private Long detailID;
private String description;
//Constructors, getters and setters...
}

这是基于单向关系。因此,每个产品都知道所有分配的产品详细信息。但产品详情没有指向其产品的链接。但是,不建议使用此单向实现。它导致数据库大小的增加,甚至使用@JoinColumn进行优化也不理想,因为有更多的 SQL 调用。

单向 (@ManyToOne(

@Entity
@Table(name = "product")
public class Product
{
@Id
@GeneratedValue
private Long productID;
private String productName;
//Constructors, getters and setters...
}
@Entity
@Table(name = "product_details")
public class ProductDetail
{
@Id
@GeneratedValue
private Long detailID;
private String description;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = product_id)
private Product product;
//Constructors, getters and setters...
}

在这种单向关系中,只有产品详细信息知道分配给他们的产品。对于每个产品的大量 ProductDetail 对象,请考虑这一点。

@JoinColumn注释指定保存产品外键(其 id(的表product_details列的名称。它也可以在没有的情况下工作,但使用此注释更有效。

双向(@OneToMany和@ManyToOne(

@Entity
@Table(name = "product")
public class Product
{
@Id
@GeneratedValue
private Long productID;
private String productName;
@OneToMany(mappedBy = "product", cascade = CascadeType.ALL, orphanRemoval = true)
private List<ProductDetail> productDetails;
//Constructors, add, remove method, getters and setters...
}
@Entity
@Table(name = "product_details")
public class ProductDetail
{
@Id
@GeneratedValue
private Long detailID;
private String description;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = product_id)
private Product product;
//Constructors, getters and setters...
}

通过双向关系,双方的对象(产品和产品详细信息(知道分配给它们的其他对象。

但根据 Vlad Mihalcea 的说法,如果每个产品存在太多的产品详细信息,则不应使用此方法。

还要记住为列表条目实现正确的添加和删除方法(再次参见文章,否则会出现奇怪的异常(。

杂项

通过级联,产品中的更改也会应用于其产品详细信息。孤立删除避免了没有产品的产品详细信息。

Product product = new Product("Interesting Product");
product.getProductDetails().add(
new ProductDetails("Funny description")
);
product.getProductDetails().add(
new ProductDetails("Different description")
);
entityManager.persist(product);

通常,关于正确的等号和哈希代码方法的问题在您脑海中是一个复杂的难题。特别是对于双向关系,但在依赖数据库连接的其他情况下,建议按照 Vlad 的描述非常简单地实现它们。

最好将对象用于基元数据类型。这使您可以选择在调用 getter 时检索正确的 null。

避免急切获取应该很清楚......

当您现在尝试从数据库中检索产品时,该对象会自动具有分配给它的所有产品详细信息的列表。为了实现这一点,可以使用 Spring 中的 JPA 存储库。不必实现简单的方法。当您需要更多地自定义功能时,请查看Baeldung的这篇文章。

最新更新