我想将从@requestbody获得的数据插入mariadb数据库。目前我可以存储数据没有外键没有任何问题,但现在我需要存储外键,我不知道如何做到这一点。
我的实体现在是这样的:
超类:
package webtoolbackend.Model.Superclass;
import webtoolbackend.Model.Reference.Reference_Category;
import javax.persistence.*;
@MappedSuperclass
public abstract class Category {
private long category_ID;
private String title;
private String description;
public Category() {
}
public Category(long category_ID, String title, String description) {
this.category_ID = category_ID;
this.title = title;
this.description = description;
}
public Category(String title, String description) {
this.title = title;
this.description = description;
}
@Id
@Column(name ="Category_ID")
@GeneratedValue(strategy = GenerationType.IDENTITY)
public long getCategory_ID() {
return category_ID;
}
public void setCategory_ID(long category_ID) {
this.category_ID = category_ID;
}
@Column(name ="Title")
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
@Column(name ="Description")
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}
类别:
package webtoolbackend.Model.DE;
import webtoolbackend.Model.Reference.Reference_Category;
import webtoolbackend.Model.Superclass.Category;
import javax.persistence.*;
import java.util.Set;
@Entity
@Table(name="Category_DE")
public class Category_DE extends Category {
private Sector_DE sector_de;
private Set<Question_DE> questions_de;
private Set<Reference_Category> reference_categories;
private long sector_id;
public Category_DE() {
super();
}
public Category_DE(long category_ID, String title, String description) {
super(category_ID, title, description);
}
public Category_DE(String title, String description, Sector_DE sector_de) {
super(title, description);
this.sector_de = sector_de;
}
public Category_DE(String title, String description, long sector_id) {
super(title, description);
this.sector_id = sector_id;
}
@ManyToOne
@JoinColumn(name="Sector_IDFS")
public Sector_DE getSector_de(){
return sector_de;
}
public void setSector_de(Sector_DE sector_de) {
this.sector_de = sector_de;
}
@OneToMany(mappedBy="category_de", cascade=CascadeType.ALL)
public Set<Question_DE> getQuestions_de() {
return questions_de;
}
public void setQuestions_de(Set<Question_DE> questions_de) {
this.questions_de = questions_de;
}
@OneToMany(mappedBy="category_de", cascade = CascadeType.ALL)
public Set<Reference_Category> getReference_categories() {
return reference_categories;
}
public void setReference_categories(Set<Reference_Category> reference_categories) {
this.reference_categories = reference_categories;
}
}
我的控制器:
@CrossOrigin(origins = "*")
@RestController
@RequestMapping("/api")
public class Category_Controller {
@Autowired
Category_Repository category_repository;
@PostMapping("/category-de")
public ResponseEntity<Category> createCategory(@RequestBody Category_DE category_de) {
try{
Category_DE savedCategory = category_repository
.save(new Category_DE(category_de.getTitle(), category_de.getDescription(), category_de.getSector_de()));
return new ResponseEntity<>(savedCategory, HttpStatus.CREATED);
}
catch (Exception e){
return new ResponseEntity<>(null, HttpStatus.INTERNAL_SERVER_ERROR);
}
}
}
来自requestbody的我的json:
{
"title": "test",
"description": "testDesc",
"sector_de": {
"sector_id": 1,
"title": "test"
}
}
1条答案
按热度按时间wydwbb8l1#
因为您使用的实体对象与
@RequestBody
,您需要考虑一些事情来将它们保存到数据库中。让我们逐一看看当类别和扇区都是新对象时1
当您希望api每次都创建新的对象时,这种方法就会起作用,因为使用Map通过jpa将更改级联到子表是很容易的。假设你的要求是这样的
这里两个对象(主对象和内部对象)都缺少
id
字段,所以直接将其保存到数据库是安全的,如果我们在父表上使用它,两个表都将接收条目。因为,json将被序列化为Category
对象,如果已定义setter,则它也将具有父对象Sector_DE
对象已初始化。所以,spring-jpa将拯救
Category
对象和原因cascade
它还将拯救世界Sector_DE
对象也是。你的要求是不类似于这个,所以这将不适用于这个案件,但我提到它,因为这个信息将在您的情况下有用。当类别为新且扇区存在时(您的案例)
现在,你的请求
sector_id
假如所以你的
Category
请求对象将具有Sector_DE
对象初始化为sector_id
字段,如果您试图按照上面的代码直接保存它,spring data jpa可能会给您提供有关分离对象的错误。原因是,持久性上下文可能已经有了该对象,并且由于您的对象是从外部创建的,而不是从存储库中获取的,所以持久性上下文不知道它。如果没有任何扇区具有相同的
id
在数据库中。因此,这是一种更新请求,您正在更新/向现有扇区添加类别,因此需要从数据库中获取相关对象
sector_id
.在这种情况下,您必须首先检查是否有一个扇区具有相同的
id
,要做到这一点,您需要SectorRepository
类似于CategoryRepostiory
那你就这样检查因为我们在这里操作child,所以不需要将更改级联到parent,除非您也要更新parent(sector\u de)的某些属性,因此,您现有的Map就可以了。
脚注
1尽管我提到了第一种情况,说明了在两个对象都是新对象的情况下Map是如何工作的,但通常我们不会从子对象侧创建新对象,这种方法应该始终先保存父对象,然后再将子对象添加到其中。所以这是一个两步的过程,应该避免从子级到父级的级联更改。