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
<code>@Entity</code>
<code>@Table</code><code>(name=</code><code>"c_course"</code><code>)</code>
<code>public</code> <code>class</code> <code>Course {</code>
<code> </code><code>private</code> <code>Integer id;</code>
<code> </code><code>private</code> <code>String coursename;</code>
<code> </code><code>private</code> <code>Set<Student> students=</code><code>new</code> <code>HashSet<Student>();</code>
<code> </code><code>private</code> <code>Set<Score> scores=</code><code>new</code> <code>HashSet<Score>();</code>
<code> </code>
<code> </code><code>@OneToMany</code><code>(mappedBy=</code><code>"course"</code><code>)</code><code>//必须指定关系由多的一方维护</code>
<code> </code><code>public</code> <code>Set<Score> getScores() {</code>
<code> </code><code>return</code> <code>scores;</code>
<code> </code><code>}</code>
<code> </code><code>public</code> <code>void</code> <code>setScores(Set<Score> scores) {</code>
<code> </code><code>this</code><code>.scores = scores;</code>
<code> </code><code>@ManyToMany</code><code>//指定中间表是s_score</code>
<code> </code><code>@JoinTable</code><code>(name=</code><code>"s_score"</code><code>,joinColumns={</code><code>@JoinColumn</code><code>(name=</code><code>"course_id"</code><code>)},</code>
<code> </code><code>inverseJoinColumns={</code><code>@JoinColumn</code><code>(name=</code><code>"student_id"</code><code>)})</code>
<code> </code><code>public</code> <code>Set<Student> getStudents() {</code>
<code> </code><code>return</code> <code>students;</code>
<code> </code><code>public</code> <code>void</code> <code>setStudents(Set<Student> students) {</code>
<code> </code><code>this</code><code>.students = students;</code>
<code> </code><code>@Id</code>
<code> </code><code>@GeneratedValue</code>
<code> </code><code>public</code> <code>Integer getId() {</code>
<code> </code><code>return</code> <code>id;</code>
<code> </code><code>public</code> <code>void</code> <code>setId(Integer id) {</code>
<code> </code><code>this</code><code>.id = id;</code>
<code> </code><code>@Column</code><code>(name=</code><code>"c_coursename"</code><code>)</code>
<code> </code><code>public</code> <code>String getCoursename() {</code>
<code> </code><code>return</code> <code>coursename;</code>
<code> </code><code>public</code> <code>void</code> <code>setCoursename(String coursename) {</code>
<code> </code><code>this</code><code>.coursename = coursename;</code>
<code>}</code>
(课程表Course)
41
<code>@Table</code><code>(name=</code><code>"t_student"</code><code>)</code>
<code>public</code> <code>class</code> <code>Student {</code>
<code> </code><code>private</code> <code>String name;</code>
<code> </code><code>private</code> <code>Set<Course> courses=</code><code>new</code> <code>HashSet<Course>();</code>
<code> </code><code>@OneToMany</code><code>(mappedBy=</code><code>"student"</code><code>)</code>
<code> </code><code>@ManyToMany</code>
<code> </code><code>@JoinTable</code><code>(name=</code><code>"s_score"</code><code>,joinColumns={</code><code>@JoinColumn</code><code>(name=</code><code>"student_id"</code><code>)},</code>
<code> </code><code>inverseJoinColumns={</code><code>@JoinColumn</code><code>(name=</code><code>"course_id"</code><code>)})</code>
<code> </code><code>public</code> <code>Set<Course> getCourses() {</code>
<code> </code><code>return</code> <code>courses;</code>
<code> </code><code>public</code> <code>void</code> <code>setCourses(Set<Course> courses) {</code>
<code> </code><code>this</code><code>.courses = courses;</code>
<code> </code><code>@Column</code><code>(name=</code><code>"s_name"</code><code>)</code>
<code> </code><code>public</code> <code>String getName() {</code>
<code> </code><code>return</code> <code>name;</code>
<code> </code><code>public</code> <code>void</code> <code>setName(String name) {</code>
<code> </code><code>this</code><code>.name = name;</code>
(Student学生表)
<code>@Table</code><code>(name=</code><code>"s_score"</code><code>)</code>
<code>public</code> <code>class</code> <code>Score {</code>
<code> </code><code>private</code> <code>String score;</code>
<code> </code><code>private</code> <code>Student student;</code>
<code> </code><code>private</code> <code>Course course;</code>
<code> </code><code>@ManyToOne</code><code>(cascade={CascadeType.ALL})</code><code>//配置级联操作</code>
<code> </code><code>@JoinColumn</code><code>(name=</code><code>"student_id"</code><code>)</code>
<code> </code><code>public</code> <code>Student getStudent() {</code>
<code> </code><code>return</code> <code>student;</code>
<code> </code><code>public</code> <code>void</code> <code>setStudent(Student student) {</code>
<code> </code><code>this</code><code>.student = student;</code>
<code> </code><code>@ManyToOne</code><code>(cascade={CascadeType.ALL})</code>
<code> </code><code>@JoinColumn</code><code>(name=</code><code>"course_id"</code><code>)</code>
<code> </code><code>public</code> <code>Course getCourse() {</code>
<code> </code><code>return</code> <code>course;</code>
<code> </code><code>public</code> <code>void</code> <code>setCourse(Course course) {</code>
<code> </code><code>this</code><code>.course = course;</code>
<code> </code><code>@Column</code><code>(name=</code><code>"s_score"</code><code>)</code>
<code> </code><code>public</code> <code>String getScore() {</code>
<code> </code><code>return</code> <code>score;</code>
<code> </code><code>public</code> <code>void</code> <code>setScore(String score) {</code>
<code> </code><code>this</code><code>.score = score;</code>
(分数表,也是中间关联表,Score)
那么问题来了,采用Hibernate自动建表,我们看一下建表语句
<code>12:11:08,169 DEBUG SchemaExport:415 - </code>
<code> </code><code>create</code> <code>table</code> <code>c_course (</code>
<code> </code><code>id </code><code>integer</code> <code>not</code> <code>null</code> <code>auto_increment,</code>
<code> </code><code>c_coursename </code><code>varchar</code><code>(255),</code>
<code> </code><code>primary</code> <code>key</code> <code>(id)</code>
<code> </code><code>)</code>
<code>12:11:08,333 DEBUG SchemaExport:415 - </code>
<code> </code><code>create</code> <code>table</code> <code>s_score (</code>
<code> </code><code>id </code><code>integer</code> <code>not</code> <code>null</code><code>,</code>
<code> </code><code>s_score </code><code>varchar</code><code>(255),</code>
<code> </code><code>course_id </code><code>integer</code><code>,</code>
<code> </code><code>student_id </code><code>integer</code> <code>not</code> <code>null</code> <code>auto_increment,</code>
<code> </code><code>primary</code> <code>key</code> <code>(student_id, course_id)</code>
<code>12:11:08,455 DEBUG SchemaExport:415 - </code>
<code> </code><code>create</code> <code>table</code> <code>t_student (</code>
<code> </code><code>s_name </code><code>varchar</code><code>(255),</code>
我们发现在建表是Hibernate默认将student_id和course_id联合作为主键使用,且student_id还是自增
这样显然是不对的,在这里我也实在想不到,好的办法,智能采用一个笨的办法,手动改回来!
大家最好是采用工具操作,因为,你直接create的话,student_id和course_id关联不上student,course的主键ID
ok,到这里,我们的建表基本完成,下面JunitTest
<code> </code><code>@Test</code>
<code> </code><code>public</code> <code>void</code> <code>add(){</code>
<code> </code><code>try</code> <code>{</code>
<code> </code><code>Configuration cfg=</code><code>new</code> <code>Configuration();</code>
<code> </code><code>cfg.configure();</code>
<code> </code><code>SessionFactory sessionFactory=cfg.buildSessionFactory();</code>
<code> </code><code>Session session=sessionFactory.openSession();</code>
<code> </code><code>session.beginTransaction();</code>
<code> </code><code>Student student1=</code><code>new</code> <code>Student();</code>
<code> </code><code>student1.setName(</code><code>"张三1"</code><code>);</code>
<code>// Student student2=new Student();</code>
<code>// student2.setName("李四");</code>
<code> </code><code>Course c1=</code><code>new</code> <code>Course();</code>
<code> </code><code>c1.setCoursename(</code><code>"数学1"</code><code>);</code>
<code> </code><code>Course c2=</code><code>new</code> <code>Course();</code>
<code> </code><code>c2.setCoursename(</code><code>"语文1"</code><code>);</code>
<code>// session.save(student1);</code>
<code>// session.save(c1);</code>
<code>// session.save(student2);</code>
<code>// session.save(c2);</code>
<code> </code><code>Score score=</code><code>new</code> <code>Score();</code>
<code> </code><code>score.setScore(</code><code>"901"</code><code>);</code>
<code> </code><code>score.setCourse(c1);</code>
<code> </code><code>score.setStudent(student1);</code>
<code> </code><code>//张三数学90分</code>
<code> </code><code>session.save(score);</code>
<code> </code><code>Score score2=</code><code>new</code> <code>Score();</code>
<code> </code><code>score2.setCourse(c2);</code>
<code> </code><code>score2.setScore(</code><code>"100"</code><code>);</code>
<code> </code><code>score2.setStudent(student1);</code>
<code> </code><code>session.save(score2);</code>
<code> </code><code>session.getTransaction().commit();</code>
<code> </code><code>session.close();</code>
<code> </code><code>sessionFactory.close();</code>
<code> </code><code>} </code><code>catch</code> <code>(HibernateException e) {</code>
<code> </code><code>e.printStackTrace();</code>
<code> </code><code>}</code>
ok,大家可以看出,为什么我们最后只需要保存score就行呢?没有session.save()student和course,为什么也能直接保存数据库中?这就是
<code>cascade={CascadeType.ALL}</code>
级联操作,当然我这里配置的是ALL,其实还有4个参数,大家可以自己慢慢研究!
以上添加成功,那么我们直接load试一下
<code>public</code> <code>void</code> <code>findTest(){</code>
<code> </code><code>Configuration cfg=</code><code>new</code> <code>Configuration();</code>
<code> </code><code>cfg.configure();</code>
<code> </code><code>SessionFactory sessionFactory=cfg.buildSessionFactory();</code>
<code> </code><code>Session s=sessionFactory.openSession();</code>
<code> </code><code>s.beginTransaction();</code>
<code> </code><code>Student student=(Student)s.load(Student.</code><code>class</code><code>, </code><code>2</code><code>);</code>
<code> </code><code>System.out.println(</code><code>"学生姓名"</code><code>+student.getName());</code>
<code> </code><code>for</code><code>(Course course:student.getCourses()){</code>
<code> </code><code>System.out.print(</code><code>"--------"</code><code>+</code><code>"课程名称"</code><code>+course.getCoursename());</code>
<code> </code><code>for</code><code>(Score score:course.getScores()){</code>
<code> </code><code>System.out.println(</code><code>"--------"</code><code>+</code><code>"课程分数"</code><code>+score.getScore());</code>
<code> </code><code>}</code>
<code> </code><code>s.getTransaction().commit();</code>
<code> </code><code>s.close();</code>
<code> </code><code>sessionFactory.close();</code>
也没问题
update呢?
<code>public</code> <code>void</code> <code>update(){</code>
<code> </code><code>Student student=(Student)s.load(Student.</code><code>class</code><code>,</code><code>1</code><code>);</code>
<code> </code><code>//我们现在把查询出来语文成绩改为0分</code>
<code> </code><code>System.out.println(course.getCoursename());</code>
<code> </code><code>if</code><code>(</code><code>"语文"</code><code>.equals(course.getCoursename())){</code>
<code> </code><code>for</code><code>(Score score:course.getScores()){</code>
<code> </code><code>if</code><code>(score.getStudent().getId().equals(student.getId())){</code>
<code> </code><code>score.setScore(</code><code>"0"</code><code>);</code>
<code> </code><code>s.update(score);</code>
<code> </code><code>}</code>
<code> </code><code>}</code>
<code> </code><code>} </code>
删除?
<code>@Test</code>
<code> </code><code>public</code> <code>void</code> <code>deleteObj(){</code>
<code> </code><code>Student student=(Student)s.load(Student.</code><code>class</code><code>,</code><code>3</code><code>);</code>
<code> </code><code>s.delete(student);</code>
<code> </code>
ok,到这里基本上,完成Hibernate关联映射的基本操作!
注意,多对多删除的时候,我们一般删除的是中间表数据?但是往往由于外键关联的关系,Hibernate会删除另一张表中的数据来解除关联关系,这就不对了!后续再探讨!
本文转自 小夜的传说 51CTO博客,原文链接:http://blog.51cto.com/1936625305/1569149,如需转载请自行联系原作者