【问题标题】:JPA - Data not getting saved in mapped entity while using many to many relationshipJPA - 使用多对多关系时数据未保存在映射实体中
【发布时间】:2020-04-08 03:59:50
【问题描述】:

我正在开发一个JPA 应用程序,其中我在两个实体之间有一个many-to-many relationship小队和产品

Squad.java

import javax.persistence.*;
import java.util.HashSet;
import java.util.Set;

@Entity(name = "SQUAD")
public class Squad extends AuditModel {

    private long id;
    private String name;
    private Set<Product> products = new HashSet<>();

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    public long getId() {
        return id;
    }

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

    @Column(name = "NAME")
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return super.toString();
    }

    @ManyToMany(fetch = FetchType.LAZY,
            cascade = {
                    CascadeType.PERSIST,
                    CascadeType.MERGE
            })
    @JoinTable(name = "SQUAD_PRODUCT",
            joinColumns = {@JoinColumn(name = "SQUAD_ID")},
            inverseJoinColumns = {@JoinColumn(name = "PRODUCT_ID")})
    public Set<Product> getProducts() {
        return products;
    }

    public void setProducts(Set<Product> products) {
        this.products = products;
    }
}

Product.java

import javax.persistence.*;
import java.util.HashSet;
import java.util.Set;

@Entity(name = "PRODUCT")
public class Product extends AuditModel {

    private long id;
    private String name;
    private Set<Squad> squads = new HashSet<>();

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    public long getId() {
        return id;
    }

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

    @Column(name = "NAME")
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @ManyToMany(fetch = FetchType.LAZY,
            cascade = {
                    CascadeType.PERSIST,
                    CascadeType.MERGE
            },
            mappedBy = "products")
    public Set<Squad> getSquads() {
        return squads;
    }

    public void setSquads(Set<Squad> squads) {
        this.squads = squads;
    }
}

我正在使用@RepositoryRestResource(第一次)生成基本的休息控制器:

SquadRepository.java

@RepositoryRestResource(collectionResourceRel = "squad", path = "squad")
public interface SquadRepository  extends CrudRepository<Squad, Long> {

    List<Squad> findByName(@Param("name") String name);

}

ProductRepository.java

@RepositoryRestResource(collectionResourceRel = "product", path = "product")
public interface ProductRepository extends CrudRepository<Product, Long> {

    List<Product> findByName(@Param("name") String name);

}

现在我想使用 REST 调用将数据存储在 Squad 中。我还想在这个 Squad 中存储一个产品,所以我使用下面的 Rest 调用:

http://localhost:8080/squad

{
    "name": "MyFirstSquad",
    "product": 
        {
            "name": "MyFirstProduct"
        }

}

我得到的回应是:

{
  "createDateTime": "2019-12-15T17:53:37.234",
  "updateDateTime": "2019-12-15T17:53:37.234",
  "name": "MyFirstSquad",
  "_links": {
    "self": {
      "href": "http://localhost:8080/squad/1"
    },
    "squad": {
      "href": "http://localhost:8080/squad/1"
    },
    "products": {
      "href": "http://localhost:8080/squad/1/products"
    }
  }
}

但是当我打开 http://localhost:8080/squad/1/products 时,它是空的:

{
  "_embedded" : {
    "product" : [ ]
  },
  "_links" : {
    "self" : {
      "href" : "http://localhost:8080/squad/1/products"
    }
  }
}

任何建议,我做错了什么?我的 rest 调用是否不正确,或者我的代码中缺少某些内容?

谢谢

【问题讨论】:

    标签: java hibernate spring-boot jpa


    【解决方案1】:

    您是否在查看器中检查过您的数据库? 当您使用多对多关系时,会创建一个中间表 - SQUAD_PRODUCT。它包含成对的数字。这意味着,在您可以添加产品的编号/ID 之前,它必须存在于表 PRODUCTS 中。因此,首先,您通过 POST 请求创建产品。其次,使用其生成的 id 添加到集合中。我想,可以这样做:

    1st step, POST
    {"name": "MyFirstProduct"}
    
    2nd step POST to create squad
    {"name": "MyFirstSquad"}
    
    3rd step PATCH created squad (alter it) - request PATCH http://localhost:8080/squad/1 - assuming it was created with id 1
    {"name": "MyFirstSquad", "product":["http://localhost:8080/products/1"]} - assuming the product was created with id 1. 
    

    您可以在此处列出多个产品。请注意,它将重写 DB 中的列表。

    我无法检查这些 JSON,因此您可能需要进行一些修改。

    就我个人而言,我会检查 java 代码中的相同保存,以防 repos 中出现问题。

    我推荐 FireFox 插件 RESTClient。

    可能无关,但我不喜欢这些行:

     private Set<Squad> squads = new HashSet<>();
     private Set<Product> products = new HashSet<>();
    

    他们可能会放弃收藏。但我可能太谨慎了:)

    【讨论】:

    • 感谢您的建议。你能详细说明删除集合部分吗?
    • 我会尝试:私人 Set 小队;私人设置产品;
    • 补充一下,关联请求的内容类型应该是Content-Type:text/uri-list
    • 我有一个关于这个主题的帖子(REST + spring),也许可以在其中找到其他内容outofrange.ru/2016/10/json-for-spring-data-rest
    猜你喜欢
    • 2010-12-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多