因此,我在spring应用程序中建立了一个现有的ManyToMany关系。看来我使用@ManyToMany批注进行了设置,这是一个错误,因为现在我需要向联接表中添加一个字段,而这似乎并不容易。
我的结构是发货和产品。货件表存储有关货件发送给谁,货件发送日期等信息。产品表存储有关货品,制造者,描述,尺寸等信息。
在构建此产品时,我没有考虑的是,创建货件时我需要跟踪已发货的产品数量,这应该在联接表上完成。
更新: 我一直在研究上面的示例,并遇到了产品和发货表之间无限递归调用的问题。我的结构如下:
ShipmentProductID.java:
// Package and Imports here
@Embeddable
public class ShipmentProductId
implements Serializable {
@Column(name = "product_id")
private Long productId;
@Column(name = "shipment_id")
private Long shipmentId;
private ShipmentProductId() {}
public ShipmentProductId(
Long productId,
Long shipmentId) {
this.productId = productId;
this.shipmentId = shipmentId;
}
// Getters and Setters here
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass())
return false;
ShipmentProductId that = (ShipmentProductId) o;
return Objects.equals(productId, that.productId) &&
Objects.equals(shipmentId, that.shipmentId);
}
@Override
public int hashCode() {
return Objects.hash(productId, shipmentId);
}
}
ShipmentProduct.java:
// Package and Imports here
@Entity(name = "ShipmentProduct")
@Table(name = "shipment_product")
public class ShipmentProduct {
@EmbeddedId
private ShipmentProductId id;
@ManyToOne(fetch = FetchType.LAZY)
@MapsId("productId")
private Product product;
@ManyToOne(fetch = FetchType.LAZY)
@MapsId("shipmentId")
private Shipment shipment;
@Column(name = "created_on")
private Date createdOn = new Date();
private ShipmentProduct() {}
public ShipmentProduct(Product product, Shipment shipment) {
this.product = product;
this.shipment = shipment;
this.id = new ShipmentProductId(product.getId(),
shipment.getId());
}
// Getters and Setters here
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass())
return false;
ShipmentProduct that = (ShipmentProduct) o;
return Objects.equals(product, that.product) &&
Objects.equals(shipment, that.shipment);
}
@Override
public int hashCode() {
return Objects.hash(product, shipment);
}
}
Product.java:
// Package and Imports here
@Entity
@Data
@Cache( usage = CacheConcurrencyStrategy.READ_WRITE )
public class Product extends AbstractEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private Long id;
@JsonIgnoreProperties("products")
// Have tried @JsonIgnore as well
@OneToMany(
mappedBy = "product",
orphanRemoval = true
)
private List<ShipmentProduct> shipments = new ArrayList<>();
@NotNull
private Integer quantity;
public boolean isAssociated(Client client){
if( this.client == null || this.client.getId() == null ||
client == null || client.getId() == null ) return
false;
return this.client.getId() == client.getId();
}
public boolean isAssociated(Expression expression){
if( this.expression == null || this.expression.getId() == null
||
expression == null || expression.getId() == null )
return false;
return this.expression.getId() == expression.getId();
}
public void addShipment(Shipment shipment) {
ShipmentProduct shipmentProduct = new ShipmentProduct(this,
shipment);
shipments.add(shipmentProduct);
shipment.getProducts().add(shipmentProduct);
}
public Set<Shipment> getAllShipments(){
Set<Shipment> shipmentList = new HashSet<>();
for (ShipmentProduct shipmentProduct : shipments) {
shipmentList.add(shipmentProduct.getShipment());
}
return shipmentList;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Product product = (Product) o;
return Objects.equals(id, product.id);
}
@Override
public String toString(){
return "";
}
@Override
public int hashCode() {
return Objects.hash(id);
}
}
Shipment.java:
// Package and Imports here
@Entity
@Data
@ToString(exclude = {"products", "contacts"})
@EqualsAndHashCode(exclude = {"products", "contacts"})
public class Shipment extends AbstractEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@JsonIgnoreProperties("shipments")
@OneToMany(
mappedBy = "shipment",
orphanRemoval = true
)
private List<ShipmentProduct> products = new ArrayList<>();
public Set<Product> getAllProducts(){
Set<Product> productList = new HashSet<>();
for (ShipmentProduct shipmentProduct : products) {
productList.add(shipmentProduct.getProduct());
}
return productList;
}
public void addProduct(Product product) {
ShipmentProduct shipmentProduct = new ShipmentProduct(product,
this);
products.add(shipmentProduct);
product.getShipments().add(shipmentProduct);
}
public void removeProduct(Product product) {
for (Iterator<ShipmentProduct> iterator = products.iterator();
iterator.hasNext(); ) {
ShipmentProduct shipmentProduct = iterator.next();
if (shipmentProduct.getShipment().equals(this) &&
shipmentProduct.getProduct().equals(product)) {
iterator.remove();
shipmentProduct.getProduct().getShipments().remove(shipmentProduct);
shipmentProduct.setShipment(null);
shipmentProduct.setProduct(null);
}
}
}
public Optional<Product> getProductById(Long productId){
Optional<ShipmentProduct> shipmentProduct =
products.stream().filter(product ->
product.getId().equals(productId)).findFirst();
return productId == null ? Optional.empty() :
Optional.of(shipmentProduct.get().getProduct());
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Shipment shipment = (Shipment) o;
return Objects.equals(id, shipment.id);
}
@Override
public String toString(){
return "";
}
@Override
public int hashCode() {
return Objects.hash(id);
}
}
似乎我正在接近,因为这似乎在创建无限大的JSON对象之外起作用。我尝试了EAGER vs LAZY和JsonIgnore和JsonIgnoreProperties的各种组合。关于如何解决这个问题有什么想法吗?我最好的猜测是与Lombok有一些互动,但我无法弄清楚。
答案 0 :(得分:1)
您可以保留@ManyToMany
批注,只需在数据库中添加联接表并将其映射:
@JoinTable(
name = "joining_table",
joinColumns = @JoinColumn(
name = "this_id_in_jt",
referencedColumnName = "this_id"
),
inverseJoinColumns = @JoinColumn(
name = "other_id_in_jt",
referencedColumnName = "other_id"
)
)
@ManyToMany
private List<Other> others;
答案 1 :(得分:1)
看起来我终于想通了...我删除了以下方法:
getAllProducts()
getAllShipments()
,并将它们替换为:
allProducts()
allShipments()
将它们作为吸气剂总是将它们添加到我的返回对象中,而不会被@JsonIgnore或其他任何东西切断。
接下来,我更新了ShipmentProduct.java,并向货运和产品添加了 @JsonIgnore ,同时删除了 @JsonIgnore 和/或 @JsonIgnoreProperties 。
然后,为了在使用allProducts()或allShipments()时不会出现错误,我将其添加到了application.properties文件中: spring.jackson.serialization.fail-on-empty-beans = false
一旦全部完成,我也可以保留龙目岛。
希望这可以帮助处于类似情况的其他人。另外,如果有人还有其他建设性的批评,请让我知道!