java - 无法保存到数据库外部表新记录生成休眠 jpa
问题描述
两个实体:Person、Pet。
一个人有多个宠物,由ownerId链接。Owner
类扩展Person
类。Person
类扩展BaseEntity
。BaseEntity
用于生成唯一的 id 值。使用 thymeleaf Web 部件为特定所有者输入/插入更多宠物。宠物确实插入到 h2 数据库中。但 ownerId 为空。这就是问题所在。存储库代码:
public interface OwnerRepository extends JpaRepository<Owner, Long>{}
public interface PetRepository extends JpaRepository<Pet, Long> {}
完整代码:https ://github.com/jianheMark/springpetsimplified
基本实体代码:
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@MappedSuperclass
public class BaseEntity implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
public boolean isNew() {
return this.id == null;
}
}
PetController 部分代码:
@GetMapping("/pets/new")
public String initCreationForm(Owner owner, Model model) {
Pet pet = new Pet();
owner.getPets().add(pet);
pet.setOwner(owner);
model.addAttribute("pet", pet);
return VIEWS_PETS_CREATE_OR_UPDATE_FORM;
}
@PostMapping("/pets/new")
public String processCreationForm(Owner owner, Pet pet, BindingResult result, ModelMap model) {
if (StringUtils.hasLength(pet.getName()) && pet.isNew() && owner.getPet(pet.getName(), true) != null){
result.rejectValue("name", "duplicate", "already exists");
}
owner.getPets().add(pet);
if (result.hasErrors()) {
model.put("pet", pet);
return VIEWS_PETS_CREATE_OR_UPDATE_FORM;
} else {
petService.save(pet);
return "redirect:/owners/" + owner.getId();
}
}
所有者部分代码:
@Setter
@Getter
@NoArgsConstructor
@Entity
@Table(name = "owners")
public class Owner extends Person {
@Builder
public Owner(Long id, String firstName, String lastName, String address, String city,
String telephone, Set<Pet> pets) {
super(id, firstName, lastName);
this.address = address;
this.city = city;
this.telephone = telephone;
if(pets != null) {
this.pets = pets;
}
}
@Column(name = "address")
private String address;
@Column(name = "city")
private String city;
@Column(name = "telephone")
private String telephone;
@OneToMany(cascade = CascadeType.ALL, mappedBy = "owner")
private Set<Pet> pets = new HashSet<>();
宠物代码:
@Setter
@Getter
@NoArgsConstructor
@AllArgsConstructor
@Entity
@Table(name = "pets")
public class Pet extends BaseEntity{
@Builder
public Pet(Long id, String name, Owner owner, LocalDate birthDate) {
super(id);
this.name = name;
this.owner = owner;
this.birthDate = birthDate;
}
@Column(name = "name")
private String name;
@ManyToOne
@JoinColumn(name = "owner_id")
private Owner owner;
@Column(name = "birth_date")
@DateTimeFormat(pattern = "yyyy-MM-dd")
private LocalDate birthDate;
}
解决方案
在宠物控制器中,您保存pet
但不设置owner
宠物的。
更改您的代码:
@PostMapping("/pets/new")
public String processCreationForm(Owner owner, Pet pet, BindingResult result, ModelMap model) {
if (StringUtils.hasLength(pet.getName()) && pet.isNew() && owner.getPet(pet.getName(), true) != null){
result.rejectValue("name", "duplicate", "already exists");
}
owner.getPets().add(pet);
if (result.hasErrors()) {
model.put("pet", pet);
return VIEWS_PETS_CREATE_OR_UPDATE_FORM;
} else {
pet.setOwner(owner) // This line here was missing!
petService.save(pet);
return "redirect:/owners/" + owner.getId();
}
}
你也说owner.getPets().add(pet)
。你仍然不坚持这一点。您不会将此信息保存在数据库中,您只需在内部为您的代码执行此操作。
您应该尝试在代码上调试和设置断点,以便检查您保存的内容和实际收到的内容。
并尝试将所有业务逻辑委托给服务。因此,控制器仅用于处理特定端点调用上发生的事情。
祝你好运。