hibernate之关于关联映射的综合应用

简介:

1、关联映射如何处理业务逻辑

2、如何指定中间表

3、如何进行级联操作

4、如何解决Hibenrate建表过程中主键错乱问题


现在有三张表


Student(学生表),Course(课程表),Score(学生,课程,分数,表)


那么我们分析业务逻辑可知,学生和课程是多对多的关系,学生和分数表是一对多的关系,课程和分数也是一对多的关系


直接看Annotations配置,在这里我所有的配置都是双向关联,这样在分数,课程,学生,之中,可以任意找到彼此!


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
@Entity
@Table (name= "c_course" )
public  class  Course {
     private  Integer id;
     private  String coursename;
     private  Set<Student> students= new  HashSet<Student>();
     private  Set<Score> scores= new  HashSet<Score>();
     
     @OneToMany (mappedBy= "course" ) //必须指定关系由多的一方维护
     public  Set<Score> getScores() {
         return  scores;
     }
     public  void  setScores(Set<Score> scores) {
         this .scores = scores;
     }
     @ManyToMany //指定中间表是s_score
     @JoinTable (name= "s_score" ,joinColumns={ @JoinColumn (name= "course_id" )},
             inverseJoinColumns={ @JoinColumn (name= "student_id" )})
     public  Set<Student> getStudents() {
         return  students;
     }
     public  void  setStudents(Set<Student> students) {
         this .students = students;
     }
     @Id
     @GeneratedValue
     public  Integer getId() {
         return  id;
     }
     public  void  setId(Integer id) {
         this .id = id;
     }
     @Column (name= "c_coursename" )
     public  String getCoursename() {
         return  coursename;
     }
     public  void  setCoursename(String coursename) {
         this .coursename = coursename;
     }
}

(课程表Course)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
@Entity
@Table (name= "t_student" )
public  class  Student {
     private  Integer id;
     private  String name;
     private  Set<Course> courses= new  HashSet<Course>();
     private  Set<Score> scores= new  HashSet<Score>();
     
     @OneToMany (mappedBy= "student" )
     public  Set<Score> getScores() {
         return  scores;
     }
     public  void  setScores(Set<Score> scores) {
         this .scores = scores;
     }
     @ManyToMany
     @JoinTable (name= "s_score" ,joinColumns={ @JoinColumn (name= "student_id" )},
             inverseJoinColumns={ @JoinColumn (name= "course_id" )})
     public  Set<Course> getCourses() {
         return  courses;
     }
     public  void  setCourses(Set<Course> courses) {
         this .courses = courses;
     }
     @Id
     @GeneratedValue
     public  Integer getId() {
         return  id;
     }
     public  void  setId(Integer id) {
         this .id = id;
     }
     @Column (name= "s_name" )
     public  String getName() {
         return  name;
     }
     public  void  setName(String name) {
         this .name = name;
     }
     
}

(Student学生表)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
@Entity
@Table (name= "s_score" )
public  class  Score {
     private  Integer id;
     private  String score;
     private  Student student;
     private  Course course;
     
     @ManyToOne (cascade={CascadeType.ALL}) //配置级联操作
     @JoinColumn (name= "student_id" )
     public  Student getStudent() {
         return  student;
     }
     public  void  setStudent(Student student) {
         this .student = student;
     }
     @ManyToOne (cascade={CascadeType.ALL})
     @JoinColumn (name= "course_id" )
     public  Course getCourse() {
         return  course;
     }
     public  void  setCourse(Course course) {
         this .course = course;
     }
     @Id
     @GeneratedValue
     public  Integer getId() {
         return  id;
     }
     public  void  setId(Integer id) {
         this .id = id;
     }
     @Column (name= "s_score" )
     public  String getScore() {
         return  score;
     }
     public  void  setScore(String score) {
         this .score = score;
     }
     
}

(分数表,也是中间关联表,Score)

那么问题来了,采用Hibernate自动建表,我们看一下建表语句

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
12:11:08,169 DEBUG SchemaExport:415 - 
     create  table  c_course (
         id  integer  not  null  auto_increment,
         c_coursename  varchar (255),
         primary  key  (id)
     )
12:11:08,333 DEBUG SchemaExport:415 - 
     create  table  s_score (
         id  integer  not  null ,
         s_score  varchar (255),
         course_id  integer ,
         student_id  integer  not  null  auto_increment,
         primary  key  (student_id, course_id)
     )
12:11:08,455 DEBUG SchemaExport:415 - 
     create  table  t_student (
         id  integer  not  null  auto_increment,
         s_name  varchar (255),
         primary  key  (id)
     )


我们发现在建表是Hibernate默认将student_id和course_id联合作为主键使用,且student_id还是自增

这样显然是不对的,在这里我也实在想不到,好的办法,智能采用一个笨的办法,手动改回来!

大家最好是采用工具操作,因为,你直接create的话,student_id和course_id关联不上student,course的主键ID


ok,到这里,我们的建表基本完成,下面JunitTest

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
     @Test
     public  void  add(){
         try  {
             Configuration cfg= new  Configuration();
             cfg.configure();
             SessionFactory  sessionFactory=cfg.buildSessionFactory();
             Session session=sessionFactory.openSession();
             session.beginTransaction();
             Student student1= new  Student();
             student1.setName( "张三1" );
//          Student student2=new Student();
//          student2.setName("李四");
             Course c1= new  Course();
             c1.setCoursename( "数学1" );
             Course c2= new  Course();
             c2.setCoursename( "语文1" );
//          session.save(student1);
//          session.save(c1);
//          session.save(student2);
//          session.save(c2);
             Score score= new  Score();
             score.setScore( "901" );
             score.setCourse(c1);
             score.setStudent(student1);
             //张三数学90分
             session.save(score);
             Score score2= new  Score();
             score2.setCourse(c2);
             score2.setScore( "100" );
             score2.setStudent(student1);
             session.save(score2);
             session.getTransaction().commit();
             session.close();
             sessionFactory.close();
         catch  (HibernateException e) {
             e.printStackTrace();
         }
     }


ok,大家可以看出,为什么我们最后只需要保存score就行呢?没有session.save()student和course,为什么也能直接保存数据库中?这就是

1
cascade={CascadeType.ALL}

级联操作,当然我这里配置的是ALL,其实还有4个参数,大家可以自己慢慢研究!


以上添加成功,那么我们直接load试一下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public  void  findTest(){
         Configuration cfg= new  Configuration();
         cfg.configure();
         SessionFactory  sessionFactory=cfg.buildSessionFactory();
         Session s=sessionFactory.openSession();
         s.beginTransaction();
         Student student=(Student)s.load(Student. class 2 );
         System.out.println( "学生姓名" +student.getName());
         for (Course course:student.getCourses()){
             System.out.print( "--------" + "课程名称" +course.getCoursename());
             for (Score score:course.getScores()){
                 System.out.println( "--------" + "课程分数" +score.getScore());
             }
         }
         s.getTransaction().commit();
         s.close();
         sessionFactory.close();
     }

也没问题

update呢?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public  void     update(){
         Configuration cfg= new  Configuration();
         cfg.configure();
         SessionFactory  sessionFactory=cfg.buildSessionFactory();
         Session s=sessionFactory.openSession();
         s.beginTransaction();
         Student student=(Student)s.load(Student. class , 1 );
         //我们现在把查询出来语文成绩改为0分
         for (Course course:student.getCourses()){
             System.out.println(course.getCoursename());
             if ( "语文" .equals(course.getCoursename())){
                 for (Score score:course.getScores()){
                     if (score.getStudent().getId().equals(student.getId())){
                         score.setScore( "0" );
                         s.update(score);
                     }
                 }
             }
        
         s.getTransaction().commit();
         s.close();
         sessionFactory.close();
     }


删除?


1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Test
     public  void  deleteObj(){
         Configuration cfg= new  Configuration();
         cfg.configure();
         SessionFactory  sessionFactory=cfg.buildSessionFactory();
         Session s=sessionFactory.openSession();
         s.beginTransaction();
         Student student=(Student)s.load(Student. class , 3 );
         s.delete(student);
         s.getTransaction().commit();
         s.close();
         sessionFactory.close();
         
     }



ok,到这里基本上,完成Hibernate关联映射的基本操作!


注意,多对多删除的时候,我们一般删除的是中间表数据?但是往往由于外键关联的关系,Hibernate会删除另一张表中的数据来解除关联关系,这就不对了!后续再探讨!










本文转自 小夜的传说 51CTO博客,原文链接:http://blog.51cto.com/1936625305/1569149,如需转载请自行联系原作者
目录
相关文章
|
4月前
|
SQL Java 数据库连接
从理论到实践:Hibernate与JPA在Java项目中的实际应用
【6月更文挑战第25天】在Java持久层,Hibernate与JPA提供ORM及数据库操作简化。JPA是EE规范,定义ORM接口;Hibernate是其实现,功能丰富。在一个在线书店项目中,使用@Entity标注实体类如Book,通过JpaRepository接口(如BookRepository)进行数据访问。服务层调用仓库接口方法,如搜索书籍。当需自定义查询时,可使用JPQL或SQL。Spring的@Transactional注解处理事务管理,展示出高效开发流程。
36 0
|
4月前
|
Java 数据库连接 API
数据库与Java的无缝对接:Hibernate与JPA的集成与应用
【6月更文挑战第25天】Java企业级应用中,Hibernate和JPA是ORM主流框架。JPA是标准API,定义对象-关系映射规范,强调标准化和可移植性。Hibernate是JPA的具体实现,扩展了更多功能,如强大的查询语言和缓存机制。两者集成允许开发者利用Hibernate性能,通过JPA注解保持代码规范。示例展示了如何使用JPA注解定义实体和Hibernate执行查询,实现数据库操作。这种方式提升了开发效率和应用质量。
50 0
|
4月前
|
缓存 Java 数据库连接
Java开发者必备:Hibernate与JPA在企业级应用中的最佳实践
【6月更文挑战第25天】Java企业开发常用Hibernate和JPA,两者通过ORM简化数据库操作,提升开发效率。它们支持复杂查询,具有良好的可扩展性。最佳实践中,应注意映射配置的合理性,优化查询性能,利用缓存提升性能,以及妥善管理事务。示例代码展示了使用JPA进行分页查询的方法。
35 0
|
4月前
|
SQL Java 数据库连接
Java持久化革命:Hibernate与JPA的实战应用
【6月更文挑战第25天】Java世界中,JPA作为ORM规范简化了数据库交互,而Hibernate是其实现者。通过引入依赖、定义注解实体类、配置 Hibernate,开发者能便捷地进行数据操作。Hibernate的使用减少了手动SQL的需求,提升了开发和维护效率,展示了其在持久化技术中的革命性影响和价值。
27 0
|
开发框架 缓存 安全
Hibernate Validator的应用实践
Hibernate Validation目前最新的稳定版本是:5.1.3。 下载地址 官网地址 官方英文使用手册 官方中文使用手册地址 (中文版目前最新的是4.3版本) 具体用法可以参考官方文档。
223 0
|
SQL 存储 数据可视化
Java Web之Hibernate的高级应用(数据库实体关联之间的映射规则、实体继承关系映射、Hibernate查询语言)
Java Web之Hibernate的高级应用(数据库实体关联之间的映射规则、实体继承关系映射、Hibernate查询语言)
182 0
Java Web之Hibernate的高级应用(数据库实体关联之间的映射规则、实体继承关系映射、Hibernate查询语言)
|
缓存 Java 数据库连接