当前位置: 首页 > 知识库问答 >
问题:

Spring:嵌套实体保存空值问题

闻人和泽
2023-03-14

我是JPA和Spring的初学者。这也是我的第一个问题。所以,为我的错误道歉。我正在练习以简单的场景作为开始。我有两个实体作为产品和类别,具有双向多对一/一对多关联。

类别类:

@Entity
@Table(name = "categories")
@NoArgsConstructor
@AllArgsConstructor
@Data
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id", scope = Long.class)

public class Category implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private Long id;

    @Column(name = "name", length = 50, nullable = false)
    private String name;

    @OneToMany(cascade = CascadeType.ALL, mappedBy = "category")
    private List<Product> products = new ArrayList<Product>();
}

产品类别:

@Table(name = "products")
@NoArgsConstructor
@AllArgsConstructor
@Data
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id", scope = Long.class)

public class Product implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private Long id;

    @Column(name = "title", nullable = false, length = 50)
    private String title;

    @Column(name = "price", precision = 4, scale = 2, nullable = false)
    private Double price;

    @Column(name = "quantity", nullable = false)
    private int quantity;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "category_id", foreignKey = @ForeignKey(name = "FK_product_category"))
    private Category category;
}

CategoryRepository和ProductRepository都是从JpaRepository实现的。很少有带有@Query注释的方法签名。

使用@autowmed存储库的服务。没有任何商业逻辑

类别服务类:

@Transactional
public class CategoryService implements IRepositoryService<Category, Long> {

    private ICategoryRepository categoryRepository;

    @Autowired
    public CategoryService(ICategoryRepository categoryRepository) {
        this.categoryRepository = categoryRepository;
    }

    @Override
    public List<Category> findAllOrderById() {
        return categoryRepository.findAllOrderById();
    }

    @Override
    public Category findById(Long id) {
        return categoryRepository.findById(id).orElseThrow(EntityNotFoundException::new);
    }

    @Override
    public List<Category> findByForeignKey(Long categoryId) {
        return null;
    }

    @Override
    public void add(Category category) {
        category.getProducts().forEach(product -> product.setCategory(category));
        categoryRepository.save(category);
    }

    @Override
    public void update(Category category) {
        categoryRepository.save(category);
    }

    @Override
    public void deleteById(Long id) {
        categoryRepository.deleteById(id);
    }

产品服务类别:

@Transactional
public class ProductService implements IRepositoryService<Product, Long>{

    @Autowired
    private IProductRepository productRepository;

    @Override
    public List<Product> findAllOrderById() {
        return productRepository.findAllOrderById();
    }

    @Override
    public Product findById(Long id) {
        return productRepository.findById(id).orElseThrow(EntityNotFoundException::new);
    }

    @Override
    public List<Product> findByForeignKey(Long categoryId) {
        return productRepository.findByCategoryId(categoryId);
    }

    @Override
    public void add(Product entity) {
        productRepository.save(entity);
    }

    @Override
    public void update(Product entity) {
        productRepository.save(entity);
    }

    @Override
    public void deleteById(Long id) {
        productRepository.deleteById(id);
    }
}

最后,两个实体都有单独的restControler类。我添加了一个类别从邮递员只有名称,所以产品是null(这部分是正常的)。但是当我从Postman或其他前端应用程序添加产品时,产品的类别没有设置(我用json设置category_id)。但是在数据库中,产品表的category_id列值为null. json字符串

我还遇到了延迟获取类型和json问题。但首要问题是。

谢谢你的任何帮助。

共有2个答案

步德宇
2023-03-14

这是使用jackson数据类型模块的唯一配置。

@Configuration
public class JacksonConfig {

    @Bean
    public Hibernate5Module hibernate5Module() {
        return new Hibernate5Module();
    }

    @Bean
    public AfterburnerModule afterburnerModule() {
        return new AfterburnerModule();
    }
}

这样的响应是:json响应

储臻
2023-03-14

只要传递正确的json请求体,上述JPA实体映射就应该有效。此外,您可能需要使用@JsonBackReference/@JsonManagedReference来避免堆栈溢出异常(有关更多信息,请参阅JsonManagedReference vs JsonBackReference)

请求:POST:localhost:/cat

{ "name" :"Construction" }

POST:localhost:/prod,这里我们使用的是category id=1。将其更改为与“构造”类别的id匹配

{
"title" :"Bricks",
"price" :"1.2",
"quantity": "100",
"category": {
        "id": 1 
    }
}

将此类添加到jpademo包并运行。

package jpademo;

import com.fasterxml.jackson.annotation.*;
import lombok.*;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.web.bind.annotation.*;

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

@SpringBootApplication
public class DemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}

@RestController
@RequiredArgsConstructor
class Ctrl {

    final CategoryRepo categoryRepo;
    final ProductRepo prodRepo;

    @PostMapping("/cat")
    void cat(@RequestBody Category cat) {
        categoryRepo.save(cat);
    }

    @PostMapping("/prod")
    void prod(@RequestBody Product p) {
        prodRepo.save(p);
    }

    @GetMapping("/cat")
    List<Category> cats() {
        return categoryRepo.findAll();
    }

    @GetMapping("/prod")
    List<Product> prods() {
        return prodRepo.findAll();
    }

}

interface CategoryRepo extends JpaRepository<Category, Long> {}

interface ProductRepo extends JpaRepository<Product, Long> {}

@Entity
@NoArgsConstructor
@AllArgsConstructor
@Data
class Category {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;

    @OneToMany(cascade = CascadeType.ALL, mappedBy = "category")
    @JsonManagedReference //to avoid Stackoverflow
    private List<Product> products = new ArrayList<>();
}

@Entity
@NoArgsConstructor
@AllArgsConstructor
@Data
class Product {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String title;

    private Double price;

    private int quantity;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "category_id", foreignKey = @ForeignKey(name = "FK_product_category"))
    @JsonBackReference
    private Category category;
}
 类似资料:
  • 我有GWT的Spring入学申请。在服务器端,我为所有实体提供了简单的JpaRepository接口,例如: 有一个MyEntity类与My其他Entity类有一对一的关系。当我调用我的实体服务持久化方法时 将只保存myEntity对象。MyEntity的所有子对象都被忽略。保存myEntity对象和myOtherEntity对象的唯一方法是调用 在上面的代码之前。那么有没有更优雅的方法来使用Jp

  • 我对Spring和JPA等比较陌生。我试图在标签和客户之间建立一种多对多的关系(双向) 我想我的关系是对的。除了一个问题外,一切都很好。标记值保存到数据库后为“Null”。 因此,我要做的是——向客户添加一个新的标签列表,然后在保存客户时使用级联选项来保存它。在调用CustomerRepository之前,我设置了一个调试点。保存(customer),标记都有值。在保存操作(在客户存储库上)后,我

  • 我试图创建一个注册用户的功能。 我遵循了这篇文章中的建议:将空作为id保存,并Hibernate,但解决方案对我不起作用。这是我的用户类 这是我的账户类 我的日志显示了以下输出

  • 我有实体 和EcranChampId 每次尝试保存EcranChamp元素时,我都会出现以下错误 2018-09-25 12:15:42.889警告14216---[nio-8092-exec-8]。w、 s.m.s.DefaultHandlerExceptionResolver:无法转换请求元素:org。springframework。豆子。ConversionNotSupportedExcep

  • 我有两个实体 实体1 实体2 我对Jpa不是很熟悉,所以如果您需要对我的问题进行任何澄清,或者您需要任何更多的信息,请告诉我。

  • 我有一个问题,Spring数据没有保存实体。应用程序逻辑如下: 另一个应用程序正在监听负载相当重的Kafka主题(每秒数十条消息)并将消息插入数据库中具有“NEW”状态的表中。 @调度方法加载一个具有“NEW”状态的实体列表,这些实体被一个接一个地传输到FixedThreadPool(20个线程),它们的状态设置为“PROCESSING”和一个saveAll方法调用同一个表。 这两种日志方法都显示