discuz修改网站标题,网站制作案例价格,网站建设越来越便宜,怎样做QQ网站呢不同表之间的级联操作或者说关联查询是很多业务场景都会用到的。
对于这种需求最朴素的方法自然是手动写关联表#xff0c;然后对被关联的表也是手动插入数据。但是手写容易最后写成一堆shit代码#xff0c;而且修改起来也是非常麻烦的。
学会使用现成的工具还是非常有利的…不同表之间的级联操作或者说关联查询是很多业务场景都会用到的。
对于这种需求最朴素的方法自然是手动写关联表然后对被关联的表也是手动插入数据。但是手写容易最后写成一堆shit代码而且修改起来也是非常麻烦的。
学会使用现成的工具还是非常有利的。接下来就来说一说JPA如何关联查询和实现级联操作。 JsonManagedReference和JsonBackReference 这两个注解配套使用一般用在一对多关系也就是外键级联操作。 在注解OneToMany和ManyToOne的基础上一是用JsonManagedReference多用JsonBackReference。同时也可以搭配其他的设置如cascade和orphanRemoval来实现级联操作。
下面为一个示例
Entity
Data
Table(namemath_questions)
public class Question {IdGeneratedValue(strategy GenerationType.IDENTITY)private Long id;OneToMany(mappedBy question, cascade CascadeType.ALL, orphanRemoval true)JsonManagedReference(question-questionTags) // 指定唯一的引用名称private ListQuestionTag questionTags new ArrayList();
}
Entity
Data
Table(nametags)
public class Tag {IdGeneratedValue(strategy GenerationType.IDENTITY)private Long id;OneToMany(mappedBy tag, cascade CascadeType.ALL, orphanRemoval true)JsonManagedReference(tag-questionTags) // 指定唯一的引用名称private ListQuestionTag questionTags new ArrayList();
}
Entity
Data
Table(name question_tag)
public class QuestionTag {IdGeneratedValue(strategy GenerationType.IDENTITY)private Long id; // 主键ManyToOneJoinColumn(name question_id)JsonBackReference(question-questionTags) // 与 Question 中的 JsonManagedReference 对应private Question question;ManyToOneJoinColumn(name tag_id)JsonBackReference(tag-questionTags) // 与 Tag 中的 JsonManagedReference 对应private Tag tag;
}
那为什么要用到这两个注解呢直接使用OneToMany和ManyToOne不就可以实现级联操作了吗原因是我这里用的是双向关联也就是Question中有Question_tagTags中有Question_tag而Question_tag中又有Question和Tags。这样就会导致查询的时候无限递归下去查到任何一个都可以继续级联查下去。
所以使用JsonManagedReference和JsonBackReference可以做到只查一层也就是对Question表操作只会影响question_tag表。同样对tags表操作也只会影响question_tag表。这样就不会一直递归下去。 EntityGraph 但是这样在之后又遇到一个问题那就是在使用EntityGraph进行关联查询的时候发现只能从question查询到question_tag再往下就查询不到了实际上也是查询到了只不过是因为又JsonManagedReference和JsonBackReference导致在最后被过滤掉了。
于是我就在想有没有一种办法即能保证不无限递归下去又能做到查询到我想要的结果通过question查询到与之相关的标签 JsonIdentityInfo 之后发现用JsonIdentityInfo可以在查询到无限递归时自动停下来。乍一听似乎很好但实际操作结果是可能会有很多层嵌套只能说最后结果对了但是基本不可操作。 {id: 17,questionType: LATEX,questionImagePath: null,questionLatex: 测试添加标签,answerType: BOTH,answerImagePath: images/42f8099e-00ef-4485-a833-65541cb9b0d8_S2的配置命令.png,answerLatex: 1,uploadTime: 2025-02-24 11:25:41,lastPracticeTime: null,correctCount: 0,incorrectCount: 0,questionTags: [{id: 1,question: 17,tag: {id: 1,questionTags: [1,{id: 2,question: {id: 19,questionType: LATEX,questionImagePath: null,questionLatex: 多加一个标签,answerType: LATEX,answerImagePath: null,answerLatex: 现在是能搞到标签的id但是搞不到name,uploadTime: 2025-02-24 12:09:04,lastPracticeTime: null,correctCount: 0,incorrectCount: 0,questionTags: [{id: 3,question: 19,tag: {id: 2,questionTags: [3],tag_name: 测试用例1}},2]},tag: 1}],tag_name: 测试用例2}}]},
这么深的嵌套就不说了重复的内容还会再下次直接用数字代替这不又得多建立一层映射关系想想都麻烦。
最后感觉没啥办法了想着保留级联操作然后老老实实自己写SQL吧。手写的唯一好处就是可以定制化虽然可能会有很多bug不好维护但是在功能都实现不了的情况下就不要求这么多了。
不过自己动手造轮子是不可能的是绝对不允许的。
这不又找到了一个不错的好玩意起码能解决我的问题。依旧是使用cascade来保证级联操作。然后使用EntityGraph来关联查询。但是不使用JsonManagedReference和JsonBackReference因为这个其实适用于比较有明显的主次关系的结构。我的业务两者只能说使用频率有差距但地位是相同的。所以其实这个不合适。
那不使用JsonManagedReference和JsonBackReference如何保证不无限循环的呢 答案是JsonView 有点小麻烦需要在每个字段都标注不知道能不能批量标注但是正因为是具体到每个字段而且可以标注多个就可以非常灵活的选择展示哪些不展示哪些进而避免双向关联的循环。说白了就是把DTO换成了注解。靠人工手动标注来防止出错。
起码这个方法是解决了我的问题。
最后补充几点上述被我否定的几种方法不是不好只是不适用于我的业务罢了。其实EntityGraph挺好的就是搭配JsonView可以做到类似版本控制就是可以写多个controller给每个controller不同的JsonView就行不需要修改原有的就可以灵活调整展示内容有点类似增量开发。
再说一句JsonView不同模式之间可以继承挺不错的。