首页 > 解决方案 > 无法保存到数据库外部表新记录生成休眠 jpa

问题描述

两个实体:PersonPet
一个人有多个宠物,由ownerId链接。Owner类扩展Person类。Person类扩展BaseEntityBaseEntity用于生成唯一的 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;
}

问题: 问题

标签: javahibernatejpaspring-data-jpa

解决方案


在宠物控制器中,您保存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)。你仍然不坚持这一点。您不会将此信息保存在数据库中,您只需在内部为您的代码执行此操作。

您应该尝试在代码上调试和设置断点,以便检查您保存的内容和实际收到的内容。

并尝试将所有业务逻辑委托给服务。因此,控制器仅用于处理特定端点调用上发生的事情。

祝你好运。


推荐阅读