1.schema.sql
alter table student_course drop foreign key FKB0A3729FA6819B7;
alter table student_course drop foreign key FKB0A3729FA135F25D;
drop table if exists course;
drop table if exists student;
drop table if exists student_course;
create table course (cid integer not null auto_increment, name varchar(255), primary key (cid));
create table student (sid integer not null auto_increment, name varchar(255), primary key (sid));
create table student_course (student_id integer not null, course_id integer not null, primary key (student_id, course_id));
alter table student_course add index FKB0A3729FA6819B7 (student_id), add constraint FKB0A3729FA6819B7 foreign key (student_id) references student (sid);
alter table student_course add index FKB0A3729FA135F25D (course_id), add constraint FKB0A3729FA135F25D foreign key (course_id) references course (cid);
表结构如下图所示
2.Hibernate Configure File
<?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> <property name="connection.driver_class">com.mysql.jdbc.Driver</property> <property name="connection.url">jdbc:mysql://localhost:3306/test</property> <property name="connection.username">root</property> <property name="connection.password">123456</property> <property name="dialect">org.hibernate.dialect.MySQLDialect</property> <property name="show_sql">true</property> <property name="format_sql">false</property> <!-- <mapping resource="org/fool/model/Student.hbm.xml" /> --> <!-- <mapping resource="org/fool/model/Course.hbm.xml" /> --> <mapping class="org.fool.model.Student" /> <mapping class="org.fool.model.Course" /> </session-factory> </hibernate-configuration>
3.Hibernate Model Class
Student.java
package org.fool.model;
import java.util.Set;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.Table;
import org.hibernate.annotations.Cascade;
import org.hibernate.annotations.CascadeType;
@Entity
@Table(name = "student")
public class Student {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "sid")
private int id;
@Column(name = "name")
private String name;
@ManyToMany(fetch = FetchType.LAZY)
@Cascade(CascadeType.SAVE_UPDATE)
@JoinTable(name = "student_course", joinColumns = { @JoinColumn(name = "student_id") }, inverseJoinColumns = { @JoinColumn(name = "course_id") })
private Set<Course> courses;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Set<Course> getCourses() {
return courses;
}
public void setCourses(Set<Course> courses) {
this.courses = courses;
}
}
以上的Annotation代码就相当于以下的Student.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="org.fool.model.Student" table="student"> <id name="id" column="sid" type="integer"> <generator class="identity"> </generator> </id> <property name="name" column="name" type="string" /> <set name="courses" table="student_course" cascade="save-update"> <key column="student_id"></key> <many-to-many class="org.fool.model.Course" column="course_id"> </many-to-many> </set> </class> </hibernate-mapping>
Course.java
package org.fool.model;
import java.util.Set;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import javax.persistence.Table;
import org.hibernate.annotations.Cascade;
import org.hibernate.annotations.CascadeType;
@Entity
@Table(name = "course")
public class Course {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "cid")
private int id;
@Column(name = "name")
private String name;
@ManyToMany(fetch = FetchType.LAZY, mappedBy = "courses")
@Cascade(CascadeType.SAVE_UPDATE)
private Set<Student> students;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Set<Student> getStudents() {
return students;
}
public void setStudents(Set<Student> students) {
this.students = students;
}
}
以上的Annotation代码就相当于以下的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="org.fool.model.Course" table="course"> <id name="id" column="cid" type="integer"> <generator class="identity"> </generator> </id> <property name="name" column="name" type="string" /> <set name="students" table="student_course" cascade="save-update" inverse="true"> <key column="course_id"></key> <many-to-many class="org.fool.model.Student" column="student_id"> </many-to-many> </set> </class> </hibernate-mapping>
4 Test it
package org.fool.test;
import java.util.HashSet;
import java.util.Set;
import org.fool.model.Course;
import org.fool.model.Student;
import org.fool.util.HibernateUtil;
import org.hibernate.Session;
import org.hibernate.Transaction;
public class HibernateTest {
public static void main(String[] args) throws Exception {
// insert();
// select();
// update();
// delete();
}
public static void insert() {
Session session = HibernateUtil.openSession();
Transaction tx = null;
try {
tx = session.beginTransaction();
Student student = new Student();
student.setName("lisi");
Course course = new Course();
course.setName("music");
student.setCourses(new HashSet<Course>());
course.setStudents(new HashSet<Student>());
student.getCourses().add(course);
course.getStudents().add(student);
session.save(student);
tx.commit();
} catch (Exception ex) {
ex.printStackTrace();
if (null != tx) {
tx.rollback();
}
} finally {
HibernateUtil.closeSession(session);
}
}
public static void select() {
Session session = HibernateUtil.openSession();
Transaction tx = null;
try {
tx = session.beginTransaction();
Student student = (Student) session.get(Student.class, 1);
Set<Course> courses = student.getCourses();
for (Course course : courses) {
System.out.println(course.getName());
}
tx.commit();
} catch (Exception ex) {
ex.printStackTrace();
if (null != tx) {
tx.rollback();
}
} finally {
HibernateUtil.closeSession(session);
}
}
public static void update() {
Session session = HibernateUtil.openSession();
Transaction tx = null;
try {
tx = session.beginTransaction();
Student student = (Student) session.get(Student.class, 1);
Course course = (Course) session.get(Course.class, 1);
student.setName("zhangsan");
course.setName("hibernate");
session.update(student);
tx.commit();
} catch (Exception ex) {
ex.printStackTrace();
if (null != tx) {
tx.rollback();
}
} finally {
HibernateUtil.closeSession(session);
}
}
public static void delete() {
Session session = HibernateUtil.openSession();
Transaction tx = null;
try {
tx = session.beginTransaction();
Student student = (Student) session.get(Student.class, 1);
Course course = (Course) session.get(Course.class, 1);
student.getCourses().remove(course);
tx.commit();
} catch (Exception ex) {
ex.printStackTrace();
if (null != tx) {
tx.rollback();
}
} finally {
HibernateUtil.closeSession(session);
}
}
}
5.Result
6.小结
由于多对多的关系不论在哪一方来维护都非常的麻烦,而且很多时候,关联表中需要加入其它的属性,所以一般情况都是把多对多拆分为两个一对多。
最佳实践:一般不使用双向关联,特别不建议使用一的这一方的关联,因为从一的这一方取关联对象很有可能会涉及到分页操作,所以基本不会使用,在设计的时候不是特殊情况不要使用双向关联。