【问题标题】:Column 'brand_id' cannot be null列“brand_id”不能为空
【发布时间】:2021-01-26 14:55:53
【问题描述】:

我使用 Spring Boot / Hibernate / JPA 创建新产品并获得列 'brand_id' cannot be null 错误。我不知道为什么会发生这个错误。谁能解释我哪里错了?

产品:

@Entity
public class Product {

@javax.persistence.Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long Id;
@NotBlank(message = "Product name is required")
private String name;
private String image;
private String description;
private double price;
private int countInStock;
private double rating;
private int numReviews;

@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "brand_id", updatable = false, nullable = false)
@JsonIgnore
private Brand brand;
@ManyToMany
@JoinTable(name = "product_category", joinColumns = @JoinColumn(name = "product_id"), inverseJoinColumns = @JoinColumn(name = "category_id"))
@JsonIgnore
private List<Category> categories;

品牌:

@Entity
public class Brand {

@javax.persistence.Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long Id;
@NotBlank(message = "Brand name is required")
private String name;
@OneToMany(cascade = CascadeType.REFRESH, fetch = FetchType.LAZY, mappedBy = "brand", orphanRemoval = true)
private List<Product> products;

类别:

@Entity
public class Category {

@javax.persistence.Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long Id;
@NotBlank(message = "Category name is required")
private String name;
@ManyToMany(mappedBy = "categories")
private List<Product> products;

还有我用来输入的产品对象创建新产品:

{
     "name": "test",
     "image": "/images/test.jpg",
     "description": "test",
     "brand_id": 4,
     "category_id": 1,
     "price": 99.99,
     "countInStock": 100,
     "rating": 4.5,
     "numReviews": 120
}

【问题讨论】:

  • 我想我可以帮助你,但我需要更多信息。我相信您在创建产品而不提供品牌变量时会遇到此异常?
  • 好吧。我已经通过了“brand_id”:4,所以我认为这对于“品牌变量”就足够了吗?
  • 我的品牌 ID 为 4:{ "id" : 1, "name" : "Apple" }, { "id" : 2, "name" : "Cannon" }, { " id”:3,“名称”:“索尼”},{“id”:4,“名称”:“罗技”},{“id”:5,“名称”:“亚马逊”}
  • 您确实传递了数据 brand_id:4 ,但是您的代码是否在任何时候都将整数 4 转换为带有 Id=4 的 Brand 对象?这就是我所说的更多信息。您没有显示失败操作的实际代码。
  • 你能告诉我将整数 4 转换为带有 Id=4 的 Brand 对象的代码吗?

标签: java mysql spring spring-mvc spring-data-jpa


【解决方案1】:

无论您在何处创建此 Product 对象,都必须为其提供 Brand 对象。 目前,您只为它提供一个整数作为品牌。

您需要做的是从数据库中获取您所引用的品牌对象,并将其包含在新产品的实例化中。 可能最好和最简单的方法是使用 EntityManager 来获取对该品牌的引用。

使用spring时获取EntityManager非常简单。

@PersistenceContext
private EntityManager entityManager;

现在,只需使用它来获取对目标品牌的引用。

Brand brand = entityManager.getReference(Brand.class , brand_id);

使用此品牌实例化您的新Product 并将其插入数据库,无任何异常。


如何将此逻辑自动化到解组过程中

如果您在创建产品时总是想使用此逻辑,则可以在构造函数中使用此逻辑。如果您只想在解组时使用此方法,这里有一个基于我最近写的东西的示例。我正在使用 XmlAdapter,但您也可以查看 JSONAdapter 类,并且应该以相同的方式工作。

创建你的适配器类。该类将用于将 JSON 解析为 java 对象。

//Once again, I am using an XmlAdapter, but the idea should be similar with JSONAdapters
@Service
public class BrandIdXmlAdapter extends XmlAdapter<String, Brand> {

@PersistenceContext
private EntityManager entityManager;
//v is the String that is going to be unmarshalled.
//In our case, its going to be the brand_id String.
@Override
public Brand unmarshal(String v) {
    Brand brand = entityManager.getReference(Brand.class, v);
    return brand;

}

也有可能覆盖 marshal() 方法以将 POJO 解析为 XML/JSON。

这里唯一的问题是能够使用PersistenceContext 注释,这个类必须是一个EJB。 我们将通过告诉 Spring 这是一项必要的服务来解决这个问题。

第一步是给适配器类Service注解(在上面的例子中完成)。

下一步是转到您希望将输入解组到 POJO 的位置​​(如果您将其作为请求接收,则为控制器;如果您要从另一个服务请求它,则为服务)并自动装配适配器

@Autowired
private BrandIdXmlAdapter xmlAdapter;

下一步是创建将使用此适配器的解组器。

JAXBContext context = JAXBContext.newInstance(Product.class);
        brandIdUnmarshaller = context.createUnmarshaller();
        brandIdUnmarshaller.setAdapter(xmlAdapter);

现在接收数据时,使用brandIdUnmarshaller.unmarhsall()方法。

最后一步是在 Product 中注释您的 Brand 变量,告诉它在解析这个特定变量时使用适配器。

public class Product {
.
.
.
//again, find the right annotation according to your JSONAdapter
@XmlJavaTypeAdapter(BrandIdXmlAdapter.class)
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "brand_id", updatable = false, nullable = false)
@JsonIgnore
private Brand brand;
}

现在每次从 JSON 解析到 Product 时,都会自动获得包含有效 Brand 对象的 Product。

【讨论】:

  • 我知道我的错误:我必须通过 JSON 传递 DTO 而不是对象。非常感谢您的帮助
猜你喜欢
  • 2021-06-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-10
  • 2019-07-10
  • 2020-06-12
  • 2019-12-29
相关资源
最近更新 更多