【发布时间】:2021-11-03 16:43:01
【问题描述】:
我正在开发一个 @RestController 类,它应该返回一个 JSON 数据,其中包含 Teacher 和 1 个或多个 Sections 的数组。
我目前在 teacher_section 表中只有 2 条不同的记录
我相信这种关系是:
-
1
Teacher可以处理 MANYSection(s) -
1
Section可以由 MANY 不同的Teacher(s) 处理
这让我认为要使用的正确关系注释是@ManyToMany
数据库表
CREATE TABLE `teacher_section` (
`teacher_id` int(11) NOT NULL,
`section_id` int(11) NOT NULL,
KEY `teacher_id` (`teacher_id`),
KEY `section_id` (`section_id`),
CONSTRAINT `teacher_section_ibfk_2` FOREIGN KEY (`teacher_id`) REFERENCES `teacher` (`id`),
CONSTRAINT `teacher_section_ibfk_3` FOREIGN KEY (`section_id`) REFERENCES `section` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='This is a join table';
CREATE TABLE `teacher` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`employee_id` int(11) NOT NULL,
`first_name` varchar(45) NOT NULL,
`middle_name` varchar(45) NOT NULL,
`last_name` varchar(45) NOT NULL,
`is_adviser` bit(1) NOT NULL DEFAULT b'0',
`is_active` bit(1) NOT NULL DEFAULT b'1',
`date_created` timestamp NOT NULL DEFAULT current_timestamp(),
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4;
CREATE TABLE `section` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`section_name` varchar(45) NOT NULL,
`is_active` bit(1) NOT NULL DEFAULT b'1',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4;
Java 类如下。
抽象实体
@MappedSuperclass
public class AbstractEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name="is_active")
private boolean isActive;
//getters and setters....
}
老师
@Entity
@Table(name="teacher")
public class Teacher extends AbstractEntity{
@Column(name="employee_id")
private int employeeId;
@Column(name="first_name")
private String firstName;
@Column(name="middle_name")
private String middleName;
@Column(name="last_name")
private String lastName;
@Column(name="is_adviser")
private boolean isAdviser;
@Column(name="date_created")
private Timestamp dateCreated;
@ManyToMany(cascade = {
CascadeType.PERSIST,
CascadeType.MERGE
})
@JoinTable(
name = "teacher_section",
joinColumns = @JoinColumn(name = "teacher_id"),
inverseJoinColumns = @JoinColumn(name = "section_id"))
Set<Section> sections;
//getters and setters.....
}
部分
@Entity
@Table(name="section")
public class Section extends AbstractEntity{
@Column(name = "section_name")
private String sectionName;
@ManyToMany (mappedBy = "sections")
private Set<Teacher> teachers;
//getters and setters...
}
TeacherRestController
@RestController
@RequestMapping("/teachers")
@CrossOrigin(origins = "http://localhost:4200")
public class TeacherRestController {
@Autowired
TeacherRepository teacherRepository;
@GetMapping
public List<Teacher> getTeachers(){
//GET localhost:8080/grading/teachers
return teacherRepository.findAll();
}
}
TeacherRepository
public interface TeacherRepository extends JpaRepository<Teacher, Long>{
}
问题
端点GETlocalhost:8080/grading/teachers返回的json数据在Teacher内嵌套Section多次。
Postman 中的响应如下所示:
[
{
"id": 1,
"employeeId": 20210001,
"firstName": "John",
"middleName": "Someone",
"lastName": "Doe",
"dateCreated": "2021-08-29T13:13:29.000+00:00",
"adviser": false,
"section": [
{
"id": 1,
"sectionName": "Unity",
"teacher": [
{
"id": 1,
"employeeId": 20210001,
"firstName": "John",
"middleName": "Someone",
"lastName": "Doe",
"dateCreated": "2021-08-29T13:13:29.000+00:00",
"adviser": false,
"section": [
{
"id": 1,
"sectionName": "Unity",
"teacher": [
{
"id": 1,
"employeeId": 20210001,
"firstName": "John",
"middleName": "Someone",
"lastName": "Doe",
"dateCreated": "2021-08-29T13:13:29.000+00:00",
"adviser": false, .....
我不知道出了什么问题。我什至尝试按照以下 2 个网站中有关如何正确实施 @ManyToMany 的在线指南进行操作,但仍然无法解决问题。
https://www.baeldung.com/jpa-many-to-many
https://vladmihalcea.com/the-best-way-to-use-the-manytomany-annotation-with-jpa-and-hibernate/
我使用 Spring Tool Suite IDE 和 MySQL 作为数据库。
提前致谢。
【问题讨论】:
-
您必须决定要序列化哪种关系。请阅读baeldung.com/…
-
您需要
@JsonIdentityInfo,或者更好的是,单独的 DTO 表示。 -
@SimonMartinelli 感谢您分享参考资料。它有很多我还不知道的信息。
-
@chrylis-cautiouslyoptimistic-
@JsonIdentityInfo解决了我的问题!非常感谢!!我将详细了解与 Json 和实验替代方案相关的注释。 -
不要在控制器中使用实体对象,这是非常糟糕的做法。创建单独的 dto 对象和地图实体。
标签: java spring spring-boot jackson jackson-databind