【问题标题】:Curectly save OneToMany entity if parent has not ID如果父级没有 ID,则正确保存 OneToMany 实体
【发布时间】:2017-11-22 08:03:31
【问题描述】:

我有 2 个实体:

@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString(exclude = "products")
@Entity
@Table(name = "categories")
public class Category {
  @Id
  @GeneratedValue(strategy = GenerationType.AUTO)
  private Long id;
  private String categoryName;
  private String categoryType;
  @OneToMany(mappedBy = "category", cascade = CascadeType.ALL)
  private List<Product> products;
}

第二个实体:

@Data
@AllArgsConstructor
@NoArgsConstructor
@Entity
@Table(name = "products")
public class Product {
  @Id
  @GeneratedValue(strategy = GenerationType.AUTO)
  private Long id;
  private String productName;
  private String productDescription;
  @ManyToOne()
  private Category category;
}

每个实体都有 2 个存储库:

@Repository
public interface ProductRepository extends JpaRepository<Product, Long> {
}

@Repository
public interface CategoryRepository extends JpaRepository<Category, Long> {
}

然后我将此 JSON 发送到 cintroller 并注意保存所有产品:

{
    "products": [{
        "productName": "product1",
        "productDescription": "productDescription1",
        "category": {
            "categoryName": "catName1",
            "categoryType": "type1"
        }
    },
    {
        "productName": "product2",
        "productDescription": "productDescription2",
        "category": {
            "categoryName": "catName1",
            "categoryType": "type1"
        }
    },
    {
        "productName": "product3",
        "productDescription": "productDescription3",
        "category": {
            "categoryName": "catName2",
            "categoryType": "type2"
        }
    }]
}

然后我需要保存它:

@PostMapping(value = "test")
public Category test(@RequestBody() RequestTest products) {

  List<Product> productList = products.getProducts();
  for (Product product : productList) {
  //save all
  }
}

类别没有 id,当我得到这个 JSON 时,我需要创建所有产品并设置类别,但我没有类别 id,如果我接下来要做:

for (Product product : productList) {
      Category category = product.getCategory();
      Category save = categoryRepository.save(category);
      product.setCategory(save);
      productRepository.save(product);
}

我为每个产品创建了新的 ctegore,我得到了这个:

49  catName1    type1
51  catName1    type1
53  catName2    type2
                                        cat_id
50  productDescription1 product1        49
52  productDescription2 product2        51
54  productDescription3 product3        53

但我需要:

49  catName1    type1
51  catName2    type2
                                        cat_id
50  productDescription1 product1        49  
52  productDescription2 product2        49  
54  productDescription3 product3        51  

【问题讨论】:

    标签: java hibernate spring-data-jpa one-to-many spring-repositories


    【解决方案1】:

    如果类别对象已经存在,您可能需要先查找。

    您可以创建一个查询来搜索一个类别是否存在相同的名称和类型。如果存在,请使用该对象,该对象也将具有 ID,否则继续使用当前代码。

    【讨论】:

      【解决方案2】:

      在我看来,最好的方法是通过引入地图来跟踪保存的类别。

      假设 categoryName 是一个独特的列,那么您可以执行以下操作:

      Map<String,Category> categoryMap = new HashMap<>();
      
      for (Product product : productList) {
            String categoryName = product.getCategory().getCategoryName(); 
            Category category = categoryMap.get(categoryName);
      
            if(category == null){
               category = categoryRepository.save(product.getCategory());
               categoryMap.put(categoryName,category);
            }       
      
            product.setCategory(save);
            productRepository.save(product);
      }
      

      【讨论】:

      • 您也可以尝试 categoryRepository.findByCategoryName 而不是地图。那不是按 id 进行的搜索,因此可能会跳过持久性上下文。
      • 是的,我愿意。指定它的含义“因此可能会跳过持久性上下文。”?
      • 保存时.. 没有插入到数据库中.. 事务提交后发生。当您通过 id 查询时,持久性提供程序首先进入持久性上下文以查看那里是否有任何实体缓存.. 如果不是通过 id.. 它可能会到达数据库.. 那里还没有条目。试试看吧
      【解决方案3】:

      首先插入所有唯一的类别并检查数据库中是否存在相同的类别。 确保类别应该是唯一的。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-11-06
        • 2019-11-24
        • 2023-03-30
        • 1970-01-01
        • 2021-12-20
        • 1970-01-01
        • 2017-05-11
        • 1970-01-01
        相关资源
        最近更新 更多