问题?hibernate的多对多的解析
环境:先搭建hibernate环境
注:在这里我们选择,由持久化类和映射文件来生成表(因为这样做的话,只在多对多的两个之间生成一个中间表。共三张表)。如果由表来生成持久化类和映射文件的话,它会生成一个联合组件类。相对来说在操作上。困难度加大了,也复杂化了。
案例:
先写两个持久化类和相应的映射文件
Course.java
package cn.itcast.hibernate.manyTOmanyDomain;
import java.io.Serializable;
import java.util.Set;
public class Course implements Serializable{
private Long cid;
private String cname;
private String description;
private Set<Students> students;//Students多的方
public Long getCid() {
return cid;
}
public void setCid(Long cid) {
this.cid = cid;
}
public String getCname() {
return cname;
}
public void setCname(String cname) {
this.cname = cname;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Set<Students> getStudents() {
return students;
}
public void setStudents(Set<Students> students) {
this.students = students;
}
}
package cn.itcast.hibernate.manyTOmanyDomain;
import java.io.Serializable;
import java.util.Set;
public class Students implements Serializable{
private Long sid;
private String sname;
private String description;
private Set<Course> courses;//Course多的一方
public Long getSid() {
return sid;
}
public void setSid(Long sid) {
this.sid = sid;
}
public String getSname() {
return sname;
}
public void setSname(String sname) {
this.sname = sname;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Set<Course> getCourses() {
return courses;
}
public void setCourses(Set<Course> courses) {
this.courses = courses;
}
}
Course.hbm.xml
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="cn.itcast.hibernate.manyTOmanyDomain.Course">
<id name="cid" length="5">
<generator class="increment"></generator>
</id>
<property name="cname" length="20"></property>
<property name="description" length="100"></property>
<set name="students" table="student_course" cascade="save-update">
<key>
<column name="cid"></column>
</key>
<many-to-many class="cn.itcast.hibernate.manyTOmanyDomain.Students" column="sid"></many-to-many>
</set>
</class>
</hibernate-mapping>
Students.hbm.xml
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="cn.itcast.hibernate.manyTOmanyDomain.Students">
<id name="sid" type="java.lang.Long" length="5">
<generator class="increment"></generator>
</id>
<property name="sname" type="java.lang.String" length="20"></property>
<property name="description" length="100"></property>
<!--
table就是用来描述第三张表
column,这个外键,就是在那张表,外键就填谁
-->
<set name="courses" table="student_course" cascade="save-update">
<key>
<column name="sid"></column>
</key>
<many-to-many class="cn.itcast.hibernate.manyTOmanyDomain.Course" column="cid"></many-to-many>
</set>
</class>
</hibernate-mapping>
最后就是配置文件了.hibernate.cfg.xml文件
因为在这里我是放再跟持久化文件和映射文件同一个包下的。所以相对来说。工具类就得采用上一次所说的第二种方式了(在configur(URL)中写配置文件的地址。第一种方式,是配置文件就根目录下,就不用写。)
hibernate.cfg.xml
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<!--
一个session-factory只能连接一个数据库,一般我们也只写一个。
-->
<session-factory>
<!--
数据库的用户名
-->
<property name="connection.username">root</property>
<!--
数据库的密码
-->
<property name="connection.password">root</property>
<!--
数据库的url:itcast_sh_hibernate是你用的数据库
-->
<property name="connection.url">
jdbc:mysql://localhost:3306/itcast_sh_hibernate
</property>
<!-- @hbm2ddl.auto
作用:根据持久化类和映射文件生成表
validate:验证持久化类在映射文件中描述正不正确,只验证
create-drop:hibernate容器开启的时候生成表,关闭的时候删除表(不用)
create:hibernate容器开启的时候生成表(不用)
update:表示hibernate开启的时候,先检查持久化类和映射问件和表到底对应不对应,
不对应的话,我新建一个表。对应的话,验证描述正不正确(validate)
-->
<property name="hbm2ddl.auto">update</property>
<!--
显示hibernate内部生成的sql语句
-->
<property name="show_sql">true</property>
<!--@mapping resource
表示和映射文件相对应
-->
<mapping
resource="cn/itcast/hibernate/manyTOmanyDomain/Course.hbm.xml" />
<mapping
resource="cn/itcast/hibernate/manyTOmanyDomain/Students.hbm.xml" />
</session-factory>
</hibernate-configuration>
最后就是写读取配置文件的工具类了。( 注:这里的@Before是指先执性子类的static,最后在执性父类的static,不然url就传不过去了)
HibernateUtil.java
package cn.itcast.hibernate.util;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.junit.Before;
public class HibernateUtil {
public static SessionFactory sessionfactory;
public static String url;
@Before
public void init(){
Configuration configuration=new Configuration();
configuration.configure(url);
sessionfactory=configuration.buildSessionFactory();
}
}
最后就是写测试文件了。注意,一定要先建库(MySql)
package cn.itcast.hibernate.manyTOmanyTest;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;
import cn.itcast.hibernate.manyTOmanyDomain.Course;
import cn.itcast.hibernate.manyTOmanyDomain.Students;
import cn.itcast.hibernate.util.HibernateUtil;
/**
* 1、新建一个课程
* 2、新建一个学生
* 3、新建课程的同时新建学生 级联
* 4、已经存在一个课程,新建一个学生,建立课程和学生之间的关系
* 5、已经存在一个学生,新建一个课程,建立课程和学生之间的关系
* 6、已经存在一个课程,已经存在一个学生,建立关联
* 7、把已经存在的一些学生加入到已经存在的一个课程中
* 8、把一个学生加入到一些课程中
* 9、把多个学生加入到多个课程中
* 10、把一个已经存在的学生从一个已经的课程中移除
* 11、把一些学生从一个已经存在的课程中移除
* 12、把一个学生从一个课程转向到另外一个课程
* 13、删除课程
* 14、删除学生
* @author Think
*
*/
public class CreateTable extends HibernateUtil{
static{
url="cn/itcast/hibernate/manyTOmanyDomain/hibernate.cfg.xml";
}
@Test
public void CreateTable1(){
}
/* * 1、新建一个课程
* 2、新建一个学生
* 3、新建课程的同时新建学生 级联*/
@Test
public void testSaveStudent_Cascade_Course_Save(){
Session session = sessionfactory.openSession();
Transaction transaction = session.beginTransaction();
Students student = new Students();
student.setSname("班长2");
student.setDescription("牛人");
Course course = new Course();
course.setCname("生理卫生");
course.setDescription("很好");
//通过操作student表级联操作course表(这个的要求是在students映射文件中,必须要有save-upate)
// Set<Course> courses = new HashSet<Course>();
// courses.add(course);
// student.setCourses(courses);
// session.save(student);
//
//通过course表级联操作操作student表(这个的要求是在course映射文件中,必须要有save-upate)
Set<Students> students=new HashSet<Students>();
students.add(student);
course.setStudents(students);
session.save(course);
transaction.commit();
session.close();
}
/**
* 已经存在一个课程,新建一个学生,建立课程和学生之间的关系
* 从课程角度出发
* 已经存在一个学生,新建一个课程,建立课程和学生之间的关系
*/
@Test
public void testUpdateCourse_Cascade_Student_Save_R(){
Session session = sessionfactory.openSession();
Transaction transaction = session.beginTransaction();
// Course course = (Course)session.get(Course.class, 1L);
// Students student = new Students();
// student.setSname("班迷");
// student.setDescription("班丝:班长的钢丝");
// course.getStudents().add(student);
// session.save(student);
//这个是在course映射文件中没有save-update的时候做,又student操作course
Students students=(Students)session.get(Students.class, 1L);
Course course=new Course();
course.setCname("大神2");
course.setDescription("非常牛逼");
students.getCourses().add(course);
transaction.commit();
session.close();
}
//已经存在一个课程,已经存在一个学生,建立关联
@Test
public void testR(){
Session session = sessionfactory.openSession();
Transaction transaction = session.beginTransaction();
Course course = (Course)session.get(Course.class, 1L);
Students student = (Students)session.get(Students.class, 2L);
// student.getCourses().add(course);
course.getStudents().add(student);
transaction.commit();
session.close();
}
/**
* 把学生3,4加入到课程1中
*/
@Test
public void testR_Some(){
Session session = sessionfactory.openSession();
Transaction transaction = session.beginTransaction();
Course course = (Course)session.get(Course.class, 1L);
Students student3 = (Students)session.get(Students.class, 3L);
Students student4 = (Students)session.get(Students.class, 4L);
course.getStudents().add(student3);//很明显较相对来说,由课程来加入学生效率高
course.getStudents().add(student4);
transaction.commit();
session.close();
}
/**
* 把一个学生加入到一些课程中
*/
@Test
public void testR_Some_2(){
Session session = sessionfactory.openSession();
Transaction transaction = session.beginTransaction();
Students student = (Students)session.get(Students.class, 3L);
List<Course> courseList = session.createQuery("from Course where cid in(1,2,3)").list();
student.getCourses().addAll(courseList);
transaction.commit();
session.close();
}
/**
* 把一个课程加入到一些学生中
*/
@Test
public void testR_Some_3(){
Session session = sessionfactory.openSession();
Transaction transaction = session.beginTransaction();
Course course = (Course)session.get(Course.class, 3L);
List<Students> studentsList = session.createQuery("from Students where sid in(1,2,3,4)").list();
course.getStudents().addAll(studentsList);
transaction.commit();
session.close();
}
/**
* 把学生从一个课程转移到另外一个课程
*/
@Test
public void testTransform(){
Session session = sessionfactory.openSession();
Transaction transaction = session.beginTransaction();
Students student = (Students) session.get(Students.class, 3L);
Course course2 = (Course)session.get(Course.class, 2L);
Course course3 = (Course)session.get(Course.class, 3L);
student.getCourses().remove(course3);
student.getCourses().add(course2);
transaction.commit();
session.close();
}
}
案例:下载 案例