`

[原]Hibernate多对多(双向)

阅读更多

[标题]:[原]Hibernate多对多(双向)
[时间]:2009-6-19
[摘要]:Hibernate双向多对多关联。如:一个学生对应多门课程,一门课程也对应多名学生。
[关键字]:Hibernate,ORM,关联,多对多,持久化,双向,映射
[环境]:MyEclipse7,Hibernate3.2,MySQL5.1
[作者]:Winty (wintys@gmail.com) http://www.blogjava.net/wintys

[正文]:
    Hibernate单向多对多关联。如:一个学生对应多门课程,一门课程也对应多名学生。本例单向关联,只考虑学生到课程的一对多关联。
1、概述
a.实体类
public class Student{
    ......
    private Set<Course> courses;
    ......
}

public class Course{
    ......
    private Set<Student> students;
    ......
}

b.数据库表
    Student与Course各对应一张数据库表,再建一张关联表student_course (studentid,courseid),保存多对多关联。其中,student_course表的主键为studentid与courseid的联合。

c.配置文件
Student.hbm.xml:
......
<set name="courses" table="student_course" cascade="all">
    <key column="studentid" />
    <many-to-many column="courseid" class="wintys.hibernate.manytomany.Course"/>
</set>
......

Course.hbm.xml:
......
<set name="students" table="student_course" inverse="true" >
    <key column="courseid"/>
    <many-to-many column="studentid" class="wintys.hibernate.manytomany.Student" />
</set>
......

2、实体类:
Student.java:

package wintys.hibernate.manytomany;

import java.util.Set;

/**
 * @version 2009-06-19
 * @author Winty (wintys@gmail.com)
 *
 */
public class Student {
    private Integer id;
    private String name;
    private Set<Course> courses;
    
    public Student(){
    }
    
    public Student(String name){
        this.name = name;
    }
                     
    public Integer getId() {
        return id;
    }
    public void setId(Integer 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;
    }
}



Course.java:

package wintys.hibernate.manytomany;

import java.util.Set;

/**
 * @version 2009-06-19
 * @author Winty (wintys@gmail.com)
 *
 */
public class Course {
    private Integer id;
    private String name;
    //实现双向"多对多"关联
    private Set<Student> students;
    
    public Course(){
    }
    
    public Course(String name){
        this.name = name;
    }
    
    public Integer getId() {
        return id;
    }
    public void setId(Integer 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;
    }
}



3、数据库表:
db.sql:

CREATE TABLE student(
    id int(4) NOT NULL UNIQUE,
    name varchar(100),
    PRIMARY KEY(id)
);

CREATE TABLE course(
    id int(4) NOT NULL UNIQUE,
    name varchar(100),
    PRIMARY KEY(id)
);

-- 关联表
CREATE TABLE student_course(
    studentid int(4) NOT NULL,
    courseid int(4) NOT NULL,
    PRIMARY KEY(studentid,courseid),
    CONSTRAINT FK_studentid FOREIGN KEY(studentid) REFERENCES student(id),
    CONSTRAINT FK_courseid  FOREIGN KEY(courseid) REFERENCES course(id)
);


4、映射文件:
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">
<!--
    Mapping file autogenerated by MyEclipse Persistence Tools
-->

<hibernate-mapping>
    <class name="wintys.hibernate.manytomany.Student" table="student" catalog="db">
        <id name="id" type="int">
            <column name="id" not-null="true"/>
            <generator class="increment" />
        </id>
        <property name="name" />
        
        <set name="courses" table="student_course" cascade="all">
            <key column="studentid" />
            <many-to-many column="courseid" class="wintys.hibernate.manytomany.Course"/>
        </set>
    </class>
</hibernate-mapping>



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">
<!--
    Mapping file autogenerated by MyEclipse Persistence Tools
-->

<hibernate-mapping>
    <class name="wintys.hibernate.manytomany.Course" table="course" catalog="db">
        <id name="id" type="int">
            <column name="id" not-null="true"/>
            <generator class="increment" />
        </id>
        <property name="name" />
        <!-- 实现双向"多对多"关联 -->    
        <set name="students" table="student_course" inverse="true" >
            <key column="courseid"/>
            <many-to-many column="studentid" class="wintys.hibernate.manytomany.Student" />
        </set>
    </class>
</hibernate-mapping>




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">

<!-- Generated by MyEclipse Hibernate Tools.                   -->
<hibernate-configuration>

<session-factory>
    <property name="connection.username">root</property>
    <property name="connection.url">
        jdbc:mysql://localhost:3306/db?useUnicode=true&amp;characterEncoding=utf-8
    </property>
    <property name="dialect">
        org.hibernate.dialect.MySQLDialect
    </property>
    <property name="myeclipse.connection.profile">MySQLDriver</property>
    <property name="connection.password">root</property>
    <property name="connection.driver_class">
        com.mysql.jdbc.Driver
    </property>
    <property name="show_sql">true</property>
    <mapping resource="wintys/hibernate/manytomany/Student.hbm.xml" />
    <mapping resource="wintys/hibernate/manytomany/Course.hbm.xml" />

</session-factory>

</hibernate-configuration>



4、使用测试:
DAO.java:

package wintys.hibernate.manytomany;

import java.util.List;

public interface DAO {
    public void insert();
    public <T> List<T> selectAll(String hql);
}


DAOBean.java:

package wintys.hibernate.manytomany;

import java.util.List;
import java.util.HashSet;
import java.util.Set;

import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;

/**
 * @version 2009-06-19
 * @author Winty (wintys@gmail.com)
 *
 */
public class DAOBean implements DAO {

    public void insert() {
        Transaction tc = null;
        try{
            Course c1,c2,c3;
            Student s1,s2;
            Set<Course> cs1 , cs2;
            
            c1 = new Course("Course 1");
            c2 = new Course("Course 2");
            c3 = new Course("Course 3");
            s1 = new Student("Student 1");
            s2 = new Student("Student 2");
            cs1 = new HashSet<Course>();
            cs2 = new HashSet<Course>();
            
            //c2为两个集合共有
            cs1.add(c1);
            cs1.add(c2);
            cs2.add(c2);
            cs2.add(c3);
            
            s1.setCourses(cs1);
            s2.setCourses(cs2);         
            
            Session session = HibernateUtil.getSession();
            tc = session.beginTransaction();
                        
            /*
            在Student.hbm.xml中设置了cascade="all",就不需要手动保存c1/c2/c3
            session.save(c1);
            session.save(c2);
            session.save(c3);
            */
            session.save(s1);
            session.save(s2);
        
            tc.commit();
        }catch(HibernateException e){
            try{
                if(tc != null)
                    tc.rollback();
            }catch(Exception ex){
                System.err.println(ex.getMessage());
            }
            System.err.println(e.getMessage());
        }finally{
            HibernateUtil.closeSession();           
        }       
    }

    @SuppressWarnings("unchecked")
    public <T> List<T> selectAll(String hql) {
        List<T> items = null;
        Transaction tc = null;
        try{
            Session session = HibernateUtil.getSession();
            tc = session.beginTransaction();
                        
            Query query = session.createQuery(hql);
            items = query.list();
            
            tc.commit();
        }catch(HibernateException e){
            try{
                if(tc != null){
                    tc.rollback();
                    items = null;
                }
            }catch(Exception ex){
                System.err.println(ex.getMessage());
            }
            System.err.println(e.getMessage());
        }finally{
            //HibernateUtil.closeSession();         
        }
        
        return items;
    }
}



HibernateUtil.java:

package wintys.hibernate.manytomany;

import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

/**
 * Hibernate Session管理
 * @author Winty
 */
public class HibernateUtil {
    private static SessionFactory factory = null;
    private static ThreadLocal<Session> threadLocal;
        
    static {
        try{
            factory = new Configuration()
                    .configure()
                    .buildSessionFactory();
        }catch(HibernateException e){
            System.err.println(e.getMessage());
        }
        
        threadLocal = new ThreadLocal<Session>();
    }
    
    private HibernateUtil(){    
    }
    
    public static Session getSession()throws HibernateException{
        Session session = threadLocal.get();
        if(session == null){
            session = factory.openSession();
            threadLocal.set(session);
        }
        
        return session;
    }
    
    public static void closeSession()throws HibernateException{
        Session session = threadLocal.get();
        if(session != null){
            session.close();
        }
        threadLocal.set(null);
    }
}



course.jsp:查询Course及其学生列表

<%@ page language="java" import="java.util.*" pageEncoding="ISO-8859-1"%>
<%@ page import="wintys.hibernate.manytomany.*"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>My JSP 'index.jsp' starting page</title>
  </head>
 
  <body>
    <%
        List<Course> courses = null;
        DAO dao = new DAOBean();
        //dao.insert();
        courses = dao.selectAll("from Course");
            
        Iterator<Course> it = courses.iterator();
        while(it.hasNext()){
            Course course = it.next();
            int id = course.getId();
            String name = course.getName();
            out.println("id:" + id + "<br />");
            out.println("name:" + name + "<br />");
            out.println("students:<br />");
            
            Set<Student> students = course.getStudents();
            Iterator<Student> itc = students.iterator();
            while(itc.hasNext()){
                Student student = itc.next();
                int studentId = student.getId();
                String studentName = student.getName();
                out.println("&nbsp;&nbsp;&nbsp; id:" + studentId + "<br />");
                out.println("&nbsp;&nbsp;&nbsp; name:" + studentName + "<br />");
            }
            out.println("<hr/>");
        }
    %>

  </body>
</html>



5、运行结果



 


Web页面显示:
id:1
name:Course 1
students:
    id:1
    name:Student 1
--------------------------------------------------------------------------------
id:2
name:Course 2
students:
    id:2
    name:Student 2
    id:1
    name:Student 1
--------------------------------------------------------------------------------
id:3
name:Course 3
students:
    id:2
    name:Student 2
--------------------------------------------------------------------------------


[参考资料]:
Hibernate 多对多双向关联-熔岩 : http://lavasoft.blog.51cto.com/62575/39344

原创作品,转载请注明出处。
作者:Winty (wintys@gmail.com)
博客:http://www.blogjava.net/wintys

 

  • 大小: 82 KB
分享到:
评论

相关推荐

    myeclipse试用小记----Hibernate多对一双向关联(2)

    在本篇【myeclipse试用小记----Hibernate多对一双向关联(2)】中,博主主要探讨了使用MyEclipse集成开发环境与Hibernate框架进行多对一双向关联的配置与实现。MyEclipse是Eclipse的一个强大扩展,特别适合Java Web...

    hibernate 多表关联 中间表

    而多对多关系是通过在两个参与实体之间创建一个额外的中间表来实现的,这个中间表通常包含两个外键,分别指向原表的主键。例如,User表和Role表通过UserRoles表进行关联,UserRoles表有User_id和Role_id字段。 在...

    Hibernate+中文文档

    7.5.1. 一对多(one to many) /多对一( many to one) 7.5.2. 一对一(one to one) 7.5.3. 多对多(many to many) 7.6. 更复杂的关联映射 8. 组件(Component)映射 8.1. 依赖对象(Dependent objects) ...

    Hibernate.zip

    12. **实体关系映射(E-R Mapping)**:Hibernate支持多种关联关系,如一对一(@OneToOne)、一对多(@OneToMany)、多对一(@ManyToOne)和多对多(@ManyToMany),以及自关联和双向关联。 13. **实体状态**:...

    hibernate源码分析过程

    双向映射可以通过多对一、一对一、一对多关系来实现。 控件映射 Hibernate 的控件映射可以将一个对象的控件属性映射到数据库中。控件映射可以使用 Map 实现动态控件。 继承映射 Hibernate 的继承映射可以将一个...

    hibernate3.2中文文档(chm格式)

    7.5.1. 一对多(one to many) /多对一( many to one) 7.5.2. 一对一(one to one) 7.5.3. 多对多(many to many) 7.6. 更复杂的关联映射 8. 组件(Component)映射 8.1. 依赖对象(Dependent objects) ...

    HibernateAPI中文版.chm

    7.5.1. 一对多(one to many) /多对一( many to one) 7.5.2. 一对一(one to one) 7.5.3. 多对多(many to many) 7.6. 更复杂的关联映射 8. 组件(Component)映射 8.1. 依赖对象(Dependent objects) ...

    Java开源项目Hibernate深度探险

    对于更复杂的关系,例如一对一、一对多、多对一、多对多的关联,Hibernate提供了多种解决方案。例如,`Class1`和`Class2`的一对一双向关联,可以在两个类中都添加对方的引用,并在数据库中通过外键关联两个表的主键...

    Hibernate中文详细学习文档

    7.5.1. 一对多(one to many) /多对一( many to one) 7.5.2. 一对一(one to one) 7.5.3. 多对多(many to many) 7.6. 更复杂的关联映射 8. 组件(Component)映射 8.1. 依赖对象(Dependent objects) ...

    Hibernate 中文 html 帮助文档

    7.5.1. 一对多(one to many) /多对一( many to one) 7.5.2. 一对一(one to one) 7.5.3. 多对多(many to many) 7.6. 更复杂的关联映射 8. 组件(Component)映射 8.1. 依赖对象(Dependent objects) 8.2. 在...

    最全Hibernate 参考文档

    7.5.1. 一对多(one to many) /多对一( many to one) 7.5.2. 一对一(one to one) 7.5.3. 多对多(many to many) 8. 组件(Component)映射 8.1. 依赖对象(Dependent objects) 8.2. 在集合中出现的依赖对象 ...

    hibernate 体系结构与配置 参考文档(html)

    一对多(one to many) /多对一( many to one) 7.5.2. 一对一(one to one) 7.5.3. 多对多(many to many) 7.6. 更复杂的关联映射 8. 组件(Component)映射 8.1. 依赖对象(Dependent objects) 8.2. 在...

    Hibernate教程

    8.4.1. 一对多(one to many) / 多对一(many to one) 8.4.2. 一对一(one to one) 8.5. 使用连接表的双向关联(Bidirectional associations with join tables) 8.5.1. 一对多(one to many) /多对一( many ...

    hibernate 教程

    值集合和多对多关联(Collections of Values and Many-To-Many Associations) 6.4. 一对多关联(One-To-Many Associations) 6.5. 延迟初始化(延迟加载)(Lazy Initialization) 6.6. 集合排序(Sorted ...

    Hibernate_3.2.0_符合Java习惯的关系数据库持久化

    7.5.1. 一对多(one to many) /多对一( many to one) 7.5.2. 一对一(one to one) 7.5.3. 多对多(many to many) 7.6. 更复杂的关联映射 8. 组件(Component)映射 8.1. 依赖对象(Dependent objects) ...

    hibernate_reference中文文档.pdf

    - **7.5.3 多对多 (many-to-many)**:解释使用连接表的双向多对多关联映射。 - **7.6 更复杂的关联映射**:探讨更复杂的关联映射场景。 #### 8. 组件 (Component) 映射 这部分讲述了 Hibernate 中组件映射的技术...

    Hibernate4(关系映射-事务-原理-性能和二级缓存-最佳实践)

    关系的数据库表示可以分为一对一、一对多和多对多三种类型。例如,一个部门表和一个部门主管表之间是一对一关系,而一个部门表和下属人员表之间则是一对多关系。对象表示方面,对象关系分为单向和双向。双向关系意味...

    Hibernate实战(第2版 中文高清版)

     7.3.1 多态的多对一关联   7.3.2 多态集合   7.3.3 对联合的多态关联   7.3.4 每个具体类一张多态表   7.4 小结   第8章 遗留数据库和定制SQL   8.1 整合遗留数据库   8.1.1 处理主键   8.1.2 带...

    Hibernate各种数据库关联annotatian和XML的配置集锦

    对于一对一、一对多、多对一和多对多关联,可以分别使用以下注解: - @OneToOne:用于表示一对一关联,如`@OneToOne(cascade = CascadeType.ALL)`, cascade属性可以设置级联操作。 - @OneToMany:用于表示一对多...

Global site tag (gtag.js) - Google Analytics