java 如何获取医生的类别列表?Spring Rest API

sxpgvts3  于 2023-03-25  发布在  Java
关注(0)|答案(2)|浏览(80)

我遇到了这样一个问题,当为医生调用GET(getDoctorByName)方法时,我得到了关于医生的所有信息,除了categories字段(其中有条目,但它返回给我一个空数组)。创建医生记录和类别工作,并为医生添加一个类别。在数据库中创建数据:第一节第一节第一节第一节第一节第二节第一节
我需要改变什么,或者我做错了什么?
医生实体:

@Data
@AllArgsConstructor
@NoArgsConstructor
@Entity
@Table(name = "doctor")
public class Doctor {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String email;
    private String password;
    @Column(name = "first_name")
    private String fname;
    @Column(name = "last_name")
    private String lname;
    private String description;
    private String number;
    @ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
    @JoinTable(
            name = "doctor_category",
            joinColumns = @JoinColumn(name = "doctor_id"),
            inverseJoinColumns = @JoinColumn(name = "category_id")
    )
    private Set<Category> categories;
}

类别实体:

@Data
@AllArgsConstructor
@NoArgsConstructor
@Entity
@Table(name = "category")
public class Category {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
    @ManyToMany(mappedBy = "categories", fetch = FetchType.LAZY)
    private Set<Doctor> doctors;
}

类别和医生库:

@Repository
public interface CategoryRepository extends JpaRepository<Category, Long> {
    List<Category> findByName(String name);
}

@Repository
public interface DoctorRepository extends JpaRepository<Doctor, Long> {
    @EntityGraph(attributePaths = "categories")
    List<Doctor> findByFnameAndLname(String fname, String lname);
    @EntityGraph(attributePaths = "categories")
    List<Doctor> findByFname(String fname);
    @EntityGraph(attributePaths = "categories")
    List<Doctor> findByLname(String lname);
}

分类服务:

@Service
public class CategoryService {
    @Autowired
    private CategoryRepository categoryRepository;

    public Category createCategory(Category category) {
        return categoryRepository.save(category);
    }

    public Category editCategory(Long categoryId, Category myCategory) {
        Category category = categoryRepository.findById(categoryId)
                .orElseThrow(() -> new ResourceNotFoundException("Категория с id: " + categoryId + " не найден"));
        category.setName(myCategory.getName());
        categoryRepository.save(category);
        return category;
    }

    public List<Category> getCategoryByName(String name) {
        List<Category> categories;
        if (name != null) {
            categories = categoryRepository.findByName(name);
        } else categories = categoryRepository.findAll();
        return categories;
    }

    public HttpStatus deleteCategory(Long categoryId) {
        categoryRepository.deleteById(categoryId);
        return HttpStatus.OK;
    }

}

医生服务:

@Service
public class DoctorService {
    @Autowired
    private DoctorRepository doctorRepository;
    @Autowired
    private CategoryRepository categoryRepository;

    public Doctor createDoctor(Doctor doctor) {
        return doctorRepository.save(doctor);
    }

    public Doctor editDoctor(Long doctorId, Doctor myDoctor) {
        Doctor doctor = doctorRepository.findById(doctorId)
                .orElseThrow(() -> new ResourceNotFoundException("Доктор с id: " + doctorId + " не найден"));
        doctor.setEmail(myDoctor.getEmail());
        doctor.setPassword(myDoctor.getPassword());
        doctor.setFname(myDoctor.getFname());
        doctor.setLname(myDoctor.getLname());
        doctor.setDescription(myDoctor.getDescription());
        doctor.setNumber(myDoctor.getNumber());
        return doctorRepository.save(doctor);
    }

    public Doctor addCategoryForDoctor(Long doctorId, Long categoryId) {
        Doctor doctor = doctorRepository.findById(doctorId)
                .orElseThrow(() -> new ResourceNotFoundException("Доктор с id: " + doctorId + " не найден"));
        Category category = categoryRepository.findById(categoryId)
                .orElseThrow(() -> new ResourceNotFoundException("Категория с id: " + categoryId + " не найден"));
        Set<Category> categories = doctor.getCategories();
        categories.add(category);
        doctor.setCategories(categories);
        return doctorRepository.save(doctor);
    }

    public List<Doctor> getAllDoctors() {
        List<Doctor> doctors = doctorRepository.findAll();
        for (Doctor doctor : doctors) {
            // вызовите getCategories() у каждого доктора, чтобы загрузить связанные категории
            doctor.getCategories().size();
        }
        return doctors;
    }

    public List<Doctor> getDoctorByName(String fname, String lname) {
        List<Doctor> doctors;
        if (fname != null && lname != null) {
            doctors = doctorRepository.findByFnameAndLname(fname, lname);
        } else if (fname != null) {
            doctors = doctorRepository.findByFname(fname);
        } else if (lname != null) {
            doctors = doctorRepository.findByLname(lname);
        } else {
            doctors = doctorRepository.findAll();
        }
        return doctors;
    }

    public HttpStatus deleteDoctor(Long doctorId) {
        doctorRepository.deleteById(doctorId);
        return HttpStatus.OK;
    }
}

医生控制器:

@RestController
@RequestMapping("/doctor")
public class DoctorController {
    @Autowired
    private DoctorService doctorService;

    @PostMapping
    public ResponseEntity<Doctor> createDoctor(@RequestBody Doctor doctor) {
        return ResponseEntity.ok(doctorService.createDoctor(doctor));
    }

    @PutMapping
    public ResponseEntity<Doctor> editDoctor(@RequestParam Long doctorId, @RequestBody Doctor doctor) {
        return ResponseEntity.ok(doctorService.editDoctor(doctorId, doctor));
    }

    @PutMapping("/add/category")
    public ResponseEntity<Doctor> addCategoryForDoctor(@RequestParam Long doctorId, @RequestParam Long categoryId) {
        return ResponseEntity.ok(doctorService.addCategoryForDoctor(doctorId, categoryId));
    }

    @GetMapping("/all")
    public ResponseEntity<List<Doctor>> get() {
        return ResponseEntity.ok(doctorService.getAllDoctors());
    }

    @GetMapping
    public ResponseEntity<List<Doctor>> getDoctorByName(@RequestParam(required = false) String fname,
                                                        @RequestParam(required = false) String lname) {
        return ResponseEntity.ok(doctorService.getDoctorByName(fname, lname));
    }

    @DeleteMapping
    public ResponseEntity<HttpStatus> deleteDoctor(@RequestParam Long doctorId) {
        return ResponseEntity.ok(doctorService.deleteDoctor(doctorId));
    }
}

类别控制器:

@RestController
@RequestMapping("/category")
public class CategoryController {
    @Autowired
    private CategoryService categoryService;

    @PostMapping
    public ResponseEntity<Category> createCategory(@RequestBody Category category) {
        return ResponseEntity.ok(categoryService.createCategory(category));
    }

    @PutMapping
    public ResponseEntity<Category> editCategory(@RequestParam Long categoryId, @RequestBody Category category) {
        return ResponseEntity.ok(categoryService.editCategory(categoryId, category));
    }

    @GetMapping
    public ResponseEntity<List<Category>> getCategoryByName(@RequestParam(required = false) String name) {
        return ResponseEntity.ok(categoryService.getCategoryByName(name));
    }

    @DeleteMapping
    public ResponseEntity<HttpStatus> deleteCategory(@RequestBody Long categoryId) {
        return ResponseEntity.ok(categoryService.deleteCategory(categoryId));
    }
}
ckocjqey

ckocjqey1#

一个解决方案是将Doctor类中的FetchType.LAZY更改为FetchType.EAGER。您可以在此here中找到更多信息。
在“医生实体”中更改此

@ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)

变成这样

@ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)

解决此问题的另一种方法是在Category和Doctor类上将@Data注解替换为@Getter和@Setter注解。
此外,通过控制器传递实体并不是一个好的做法。最好使用DTO来代替。您可以阅读有关here的更多信息。
以下是类别和医生的DTO类示例:
DoctorDTO

@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
public class DoctorDTO {
    private Long id;
    private String email;
    private String password;
    private String fname;
    private String lname;
    private String description;
    private String number;
    private List<CategoryDTO> categories;

    public static DoctorDTO convertEntityToDto(Doctor doctor) {
        DoctorDTO dto = new DoctorDTO();

        dto.setId(doctor.getId());
        dto.setEmail(doctor.getEmail());
        dto.setPassword(doctor.getPassword());
        dto.setFname(doctor.getFname());
        dto.setLname(doctor.getLname());
        dto.setDescription(doctor.getDescription());
        dto.setNumber(doctor.getNumber());
        dto.setCategories(CategoryDTO.convertEntitySetToDTOList(doctor.getCategories()));

        return dto;
    }

    public static List<DoctorDTO> convertEntityListToDTOList(List<Doctor> doctors) {
        return doctors.stream().map(DoctorDTO::convertEntityToDto).collect(Collectors.toList());
    }

    public static List<DoctorDTO> convertEntitySetToDTOList(Set<Doctor> doctors) {
        return doctors.stream().map(DoctorDTO::convertEntityToDto).collect(Collectors.toList());
    }

    public static Set<CategoryDTO> convertEntitySetToDTOSet(Set<Category> doctors) {
        return doctors.stream().map(CategoryDTO::convertEntityToDto).collect(Collectors.toSet());
    }

    public static Page<DoctorDTO> convertEntityPageToDTOPage(Page<Doctor> doctors) {
        return new PageImpl<>(convertEntityListToDTOList(doctors.getContent()), doctors.getPageable(), doctors.getTotalElements());
    }
}

分类DTO

@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
public class CategoryDTO {
    private Long id;
    private String name;

    public static CategoryDTO convertEntityToDto(Category category) {
        CategoryDTO dto = new CategoryDTO();

        dto.setId(category.getId());
        dto.setName(category.getName());

        return dto;
    }

    public static List<CategoryDTO> convertEntityListToDTOList(List<Category> categories) {
        return categories.stream().map(CategoryDTO::convertEntityToDto).collect(Collectors.toList());
    }

    public static List<CategoryDTO> convertEntitySetToDTOList(Set<Category> categories) {
        return categories.stream().map(CategoryDTO::convertEntityToDto).collect(Collectors.toList());
    }

    public static Set<CategoryDTO> convertEntitySetToDTOSet(Set<Category> categories) {
        return categories.stream().map(CategoryDTO::convertEntityToDto).collect(Collectors.toSet());
    }

    public static Page<CategoryDTO> convertEntityPageToDTOPage(Page<Category> categories) {
        return new PageImpl<>(convertEntityListToDTOList(categories.getContent()), categories.getPageable(), categories.getTotalElements());
    }
}

另外,将DoctorController中的“get”函数更改为使用DTO。我的建议是对所有其他函数也这样做,以便通过DTO而不是实体来完成与外部世界的通信。

@GetMapping("/all")
public ResponseEntity<List<DoctorDTO>> get() {
    List<DoctorDTO> doctorDTOS = DoctorDTO.convertEntityListToDTOList(doctorService.getAllDoctors());
    return ResponseEntity.ok(doctorDTOS);
}

最后,修改DoctorService中的getAllDoctors函数如下所示:

@Transactional
public List<Doctor> getAllDoctors() {
    List<Doctor> doctors = doctorRepository.findAll();
    for (Doctor doctor : doctors) {
        // вызовите getCategories() у каждого доктора, чтобы загрузить связанные категории
        Hibernate.initialize(doctor.getCategories());
        int size = doctor.getCategories().size();
        System.out.println("size: " + size);
    }
    return doctors;
}
g2ieeal7

g2ieeal72#

在实体Doctor中,你已经为类别集合定义了fetch type lazy。这意味着直到你用代码访问它,集合才从数据库中加载。
解决办法
1.将提取类型更改为渴望或
1.在服务类中为所有医生调用getCategories.size()
1.在存储库中,您可以使用EntityGraph注解,如:
(请注意使用{},因为 attributePaths 是一个数组)

@EntityGraph(attributePaths = {"categories"})
List<Doctor> findByLname(String lname);

相关问题