jpa 多表关联,头痛,求大佬指点

2021-02-09 12:05:35 +08:00
 NoKey

之前用的 mybatis,各种查询都是自己写,非常快捷

最近开始练习使用 jpa

涉及到多表关联,用起来有点头痛

我写了一个 demo,涉及 3 张表,学生,老师,学生-老师关联表

Student

@Entity
@Table
@Data
public class Student {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(length = 32)
    private String name;

    @JoinTable(name = "student_and_teacher",
            joinColumns = {@JoinColumn(name = "studentId", referencedColumnName = "id")},
            inverseJoinColumns = {@JoinColumn(name = "teacherId", referencedColumnName = "id")},
            foreignKey = @ForeignKey(name = "none", value = ConstraintMode.NO_CONSTRAINT),
            inverseForeignKey = @ForeignKey(name = "none", value = ConstraintMode.NO_CONSTRAINT))
    @ManyToMany
    private List<Teacher> teachers;



}

其中的 @JoinTable 就是表明要关联到学生-老师关联表中去

Teacher 类

@Entity
@Table
@Data
public class Teacher {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(length = 32)
    private String name;


}

然后就是学生-老师关联

student-teacher

@Entity
@Table(name = "teacher_and_lesson")
@Data
public class StudentAndTeacher {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column
    private Long studentId;

    @Column
    private Long teacherId;
}

这一套工作的很好,可以查询出学生-老师关系,添加一些数据后,执行查询学生的方法,可以得到

{"id":1,"name":"Joe","teachers":[{"id":1,"name":"王老师"},{"id":2,"name":"李老师"}]}

但是,这个时候,我想增加一个 课程表,设定每个老师教一个课程

Lesson

@Entity
@Table
@Data
public class Lesson {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(length = 32)
    private String name;
}

然后,就是增加老师-课程关联关系

TeacherAndLesson

@Entity
@Table
@Data
public class TeacherAndLesson {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column
    private Long lessonId;

    @Column
    private Long teacherId;
}

这样的话,就需要在老师实体类中,增加一个课程的关联关系


@Entity
@Table
@Data
public class Teacher {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(length = 32)
    private String name;

    @JoinTable(name = "teacher_and_lesson",
            joinColumns = {@JoinColumn(name = "teacherId", referencedColumnName = "id")},
            inverseJoinColumns = {@JoinColumn(name = "lessonId", referencedColumnName = "id")},
            foreignKey = @ForeignKey(name = "none", value = ConstraintMode.NO_CONSTRAINT),
            inverseForeignKey = @ForeignKey(name = "none", value = ConstraintMode.NO_CONSTRAINT))
    @OneToOne
    private Lesson lesson;

}

这样写了之后,程序启动完成,自动创建的 teacher_and_lesson 表中,会多出一个 student_id 出来,

没搞懂是为啥。😭

求大佬指点,谢谢。。。

3600 次点击
所在节点    程序员
30 条回复
overthemoon
2021-02-09 16:03:40 +08:00
多表打死不用 jpa,mybatis 不香吗
hly9469
2021-02-09 16:15:19 +08:00
我最终体会就是别用 jpa 的表关联了,关联资源代码里手动组装
yaojiarui
2021-02-09 16:20:47 +08:00
不用加上那些约束注解,直接在 jpaRepository 里面写原生 sql 就好
@Query(value = "select * from a inner join b on a.id = b.id inner join c on a.id = c.id", nativeQuery = true)
Obj someMethod()
gengzi
2021-02-09 16:23:22 +08:00
写原生 sql 即可
seashell84
2021-02-09 16:23:54 +08:00
有关联别用 jpa,换 jdbctemplate
themostlazyman
2021-02-09 16:44:33 +08:00
@NoKey
“@Entity
@Table(name = "teacher_and_lesson")
@Data
public class StudentAndTeacher {”
你这个表名指定的对吗?
AkideLiu
2021-02-09 16:44:37 +08:00
jpa 一时爽,多表火葬场
AkideLiu
2021-02-09 16:48:09 +08:00
Cryse
2021-02-09 17:17:19 +08:00
只有 #6 认真看代码了,其他人代码都没看就喷 JPA 多表是什么鬼...

你的 Teacher 表和 Lesson 表关联用的是 teacher_and_lesson, 而 StudentAndTeacher 的 @Table 你也指定的是 teacher_and_lesson, 这个 StudentAndTeacher 里面还有个 @Column 是 studentId, 这不就是原因吗?
22k
2021-02-09 19:07:06 +08:00
试试用 querydsl-jpa,java 式编程
NoKey
2021-02-09 22:10:13 +08:00
@themostlazyman 谢谢,修改了,然后跑不起来了,报错
is javax.persistence.PersistenceException: [PersistenceUnit: default] Unable to build Hibernate SessionFactory; nested exception is org.hibernate.tool.schema.spi.SchemaManagementException: Export identifier [student_and_teacher] encountered more than once
NoKey
2021-02-09 22:10:44 +08:00
@Cryse 谢谢,修改过来了,但是现在跑不起来了😓
crclz
2021-02-09 23:00:07 +08:00
1. 业务类的,手动查
2. 查询类的,用 EntityManager 写 SQL ( JPQL )查询,反正 IDEA 的提示是挺好用的。
NoKey
2021-02-09 23:02:01 +08:00
我重新调整了一下代码
student teacher student-teacher 这三个一起,ok 了
teacher lesson teacher-lesson 这三个一起,ok 了
然而,这几个混到一起的时候,就运行不起来了,报错

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Invocation of init method failed; nested exception is javax.persistence.PersistenceException: [PersistenceUnit: default] Unable to build Hibernate SessionFactory; nested exception is org.hibernate.tool.schema.spi.SchemaManagementException: Export identifier [student_and_teacher] encountered more than once
bestu
2021-02-09 23:34:48 +08:00
one to one 不应该 join column 吗
evi1j
2021-02-10 08:27:22 +08:00
EntityManager 不是美滋滋
Thetruechar
2021-02-10 09:15:18 +08:00
别用 orm 直接写 sql
chanchan
2021-02-10 09:30:17 +08:00
中间表不需要自己管理,我平时用 join column 感觉更方便。
NoKey
2021-02-10 10:12:39 +08:00
@chanchan join column 就是往某个表加个字段,是么,这个不是中间表吧
NoKey
2021-02-10 10:13:07 +08:00
@bestu join column 造不出中间表吧

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/752577

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX