正在加载...

hibernate入门使用系列 4-- xml关系映射篇(下)

我写的前3篇中,分别讲了one-to-one, one--to-many, many-to-one 。

这篇,主要讲的是 n:n 的关系。即:many-to-many。

我们以老师和学生为例,一个老师可以交很多学生,同样一个学生可以拥有多个老师,所以,他们之间的关系就是n:n的。

实体模型: many2many

从实体模型来看。有2个对象,但是为了在数据库中表示出2者的n:n的关系,我们还得引入一张表。

sql脚本如下:

use HibernateQuickUse;
drop table if exists teacher_student_relation;
drop table if exists Teacher;
drop table if exists Student;

create table Teacher (
    tid varchar(32) primary key,
    name varchar(32) not null
);

create table Student (
    sid varchar(32) primary key,
    name varchar(128) not null
);

create table teacher_student_relation (
    id integer auto_increment primary key,
    teacher_id varchar(32) not null,
    student_id varchar(32) not null,
    foreign key(teacher_id) references Teacher(tid),
    foreign key(student_id) references Student(sid)
);

通过模型,创建java类如下:

Student.java

package org.py.hib.relation.many2many;

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

/**
 * Student entity.
 */

@SuppressWarnings("serial")
public class Student implements java.io.Serializable
{
    private String id;

    private String name;

    private Set teachers = new HashSet(0);

    public Student()
    {
    }

    public String getId()
    {
        return this.id;
    }

    public void setId(String id)
    {
        this.id = id;
    }

    public String getName()
    {
        return this.name;
    }

    public void setName(String name)
    {
        this.name = name;
    }

    public Set getTeachers()
    {
        return teachers;
    }

    public void setTeachers(Set teachers)
    {
        this.teachers = teachers;
    }
}[/code]

Teacher.java:

[code="java"]package org.py.hib.relation.many2many;

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

/**
 * Teacher entity.
 */

@SuppressWarnings("serial")
public class Teacher implements java.io.Serializable
{
    private String id;

    private String name;

    private Set students = new HashSet(0);

    public Teacher()
    {
    }

    public String getId()
    {
        return this.id;
    }

    public void setId(String id)
    {
        this.id = id;
    }

    public String getName()
    {
        return this.name;
    }

    public void setName(String name)
    {
        this.name = name;
    }

    public Set getStudents()
    {
        return students;
    }

    public void setStudents(Set students)
    {
        this.students = students;
    }

}

xml映射文件如下

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.py.hib.relation.many2many.Student"  
        table="student">  
        <id name="id" type="java.lang.String" column="sid" length="32">  
            <generator class="uuid" />  
        </id>  

        <property name="name" type="java.lang.String" column="name"  
            length="128" not-null="true" />  

        <set name="teachers" table="teacher_student_relation" cascade="save-update" inverse="false">  
            <key column="student_id" not-null="true" />  

            <many-to-many column="teacher_id"  
                class="org.py.hib.relation.many2many.Teacher"   
                />  
        </set>  
    </class>  
</hibernate-mapping>
  1. 注意:

    • set中的 table 指向的是数据库中的关联表。
    • cascade 用的是save-update , 且inverse用的是false,这样的话,当进行修改和保存和删除时,关联表中的记录也会删掉.
    • 如果cascade 用的是 all 那么连同student表中的记录也会被删除掉。
    • key中的column指的是: 关联表中与Student发生关系的字段。
    • 而many-to-many中的column指的是:关联表中,与class(这里是:org.py.hib.relation.many2many.Teacher)发生关系的字段。

    • 关于inverse,请参考上篇:hibernate入门使用系列 3-- xml关系映射篇(中)

Teacher.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.py.hib.relation.many2many.Teacher"  
        table="teacher">  
        <id name="id" type="java.lang.String" column="tid"  
            length="32">  
            <generator class="uuid" />  
        </id>  

        <property name="name" type="java.lang.String" column="name"  
            length="32" not-null="true" />  

        <set name="students" table="teacher_student_relation" cascade="save-update"  
            inverse="false">  
            <key column="teacher_id" not-null="true" />  
            <many-to-many class="org.py.hib.relation.many2many.Student"  
                column="student_id" />  
        </set>  
    </class>  
</hibernate-mapping>

注意:

这里的inverse也采用了false,这样子的话,Teacher和Student都维护关系表中的关系。

测试类,Many2ManyTest.java

package org.py.hib.relation.many2many;

import java.util.Iterator;
import java.util.List;
import java.util.Set;

import junit.framework.Assert;
import junit.framework.TestCase;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.junit.After;
import org.junit.Before;

public class Many2ManyTest extends TestCase
{
    private SessionFactory factory;

    @Before
    public void setUp() throws Exception
    {
        Configuration conf = new Configuration().configure();
        factory = conf.buildSessionFactory();
    }

    /**
     * 测试添加
     * @throws Exception
     */
    public void testSave() throws Exception
    {
        System.out.println("\n=== test save ===");

        Teacher teacher1 = new Teacher();
        teacher1.setName("teacher_1");

        Teacher teacher2 = new Teacher();
        teacher2.setName("teacher_2");

        Student stu1 = new Student();
        stu1.setName("student_1");

        Student stu2 = new Student();
        stu2.setName("student_2");

        stu1.getTeachers().add(teacher1);
        stu1.getTeachers().add(teacher2);

        stu2.getTeachers().add(teacher2);
        teacher1.getStudents().add(stu2);

        Session session = null;
        Transaction tran = null;
        try
        {
            session = factory.openSession();
            tran = session.beginTransaction();

            session.save(stu1);
            session.save(stu2);
            tran.commit();

            Assert.assertNotNull(teacher1.getId());
            Assert.assertNotNull(teacher2.getId());

            Assert.assertNotNull(stu1.getId());
            Assert.assertNotNull(stu2.getId());

        } catch (Exception ex)
        {
            tran.rollback();
            throw ex;
        } finally
        {
            if (session != null)
            {
                try
                {
                    session.close();
                } catch (Exception ex)
                {
                    // nothing to do
                } finally
                {
                    if (session != null)
                        session = null;
                }
            }
        }
    }

    /**
     * 测试从Teacher查询
     * @throws Exception
     */
    @SuppressWarnings("unchecked")
    public void testFindFromTeacher() throws Exception
    {
        System.out.println("\n=== test find from Teacher ===");
        Session session = null;
        try
        {
            session = factory.openSession();
            Iterator iter = session.createQuery("from Teacher").iterate();
            while (iter.hasNext())
            {
                Teacher teacher = iter.next();
                Assert.assertNotNull(teacher.getId());
                String teacherName = teacher.getName();
                if ("teacher_1".equals(teacherName))
                {
                    Set stus = teacher.getStudents();
                    Assert.assertEquals(stus.size(), 2);
                    for (Student stu : stus)
                    {
                        String stuName = stu.getName();
                        Assert.assertNotNull(stu.getId());
                        Assert.assertTrue(stuName.equals("student_1") || stuName.equals("student_2"));
                    }
                } else if ("teacher_2".equals(teacherName))
                {
                    Set stus = teacher.getStudents();
                    Assert.assertEquals(stus.size(), 2);

                    for (Student stu : stus)
                    {
                        String stuName = stu.getName();
                        Assert.assertNotNull(stu.getId());
                        Assert.assertTrue(stuName.equals("student_1") || stuName.equals("student_2"));
                    }
                } else
                {
                    throw new Exception("teacher name error exception.");
                }
            }
        } catch (Exception ex)
        {
            throw ex;
        } finally
        {
            if (session != null)
            {
                try
                {
                    session.close();
                } catch (Exception ex)
                {
                    // nothing to do
                } finally
                {
                    if (session != null)
                        session = null;
                }
            }
        }
    }

    /**
     * 测试从Student查询
     * @throws Exception
     */
    @SuppressWarnings("unchecked")
    public void testFindFromStudent() throws Exception
    {
        System.out.println("\n=== test find from Student ===");
        Session session = null;
        try
        {
            session = factory.openSession();
            Iterator iter = session.createQuery("from Student").iterate();
            while (iter.hasNext())
            {
                Student stu = iter.next();
                Assert.assertNotNull(stu.getId());
                String stuName = stu.getName();
                if ("student_1".equals(stuName))
                {
                    Set teachers = stu.getTeachers();
                    Assert.assertEquals(teachers.size(), 2);
                    for (Teacher teacher : teachers)
                    {
                        String tName = teacher.getName();
                        Assert.assertNotNull(teacher.getId());
                        Assert.assertTrue(tName.equals("teacher_1") || tName.equals("teacher_2"));
                    }
                } else if ("student_2".equals(stuName))
                {
                    Set teachers = stu.getTeachers();
                    Assert.assertEquals(teachers.size(), 2);
                    for (Teacher teacher : teachers)
                    {
                        String tName = teacher.getName();
                        Assert.assertNotNull(teacher.getId());
                        Assert.assertTrue(tName.equals("teacher_1") || tName.equals("teacher_2"));
                    }
                } else
                {
                    throw new Exception("student name error exception.");
                }
            }
        } catch (Exception ex)
        {
            throw ex;
        } finally
        {
            if (session != null)
            {
                try
                {
                    session.close();
                } catch (Exception ex)
                {
                    // nothing to do
                } finally
                {
                    if (session != null)
                        session = null;
                }
            }
        }
    }

    /**
     * 测试修改
     * @throws Exception
     */
    public void testModify() throws Exception
    {
        System.out.println("\n=== test modify ===");
        Session session = null;
        Transaction tran = null;
        try
        {
            session = factory.openSession();
            tran = session.beginTransaction();

            Teacher t1 = (Teacher) session.createQuery("from Teacher t where t.name='teacher_1'").list().get(0);
            t1.setName("new_teacher_1"); // 修改用户名 = m_name2.(原来用户名= m_name)

            Set stus = t1.getStudents();
            for (Student stu : stus)
            {
                if (stu.getName().equals("student_1"))
                {
                    stus.remove(stu);
                    break;
                }
            }

            tran.commit();

        } catch (Exception ex)
        {
            throw ex;
        } finally
        {
            if (session != null)
            {
                try
                {
                    session.close();
                } catch (Exception ex)
                {
                    // nothing to do
                } finally
                {
                    if (session != null)
                        session = null;
                }
            }
        }

        /*
         * 修改后再查询
         */
        System.out.println("\n=== test find from Teacher after modify===");
        try
        {
            session = factory.openSession();
            Iterator iter = session.createQuery("from Teacher").iterate();
            while (iter.hasNext())
            {
                Teacher teacher = iter.next();
                Assert.assertNotNull(teacher.getId());
                String teacherName = teacher.getName();
                if ("new_teacher_1".equals(teacherName))
                {
                    Set stus = teacher.getStudents();
                    Assert.assertEquals(stus.size(), 1);
                    for (Student stu : stus)
                    {
                        String stuName = stu.getName();
                        Assert.assertNotNull(stu.getId());
                        Assert.assertTrue(stuName.equals("student_2"));
                    }
                } else if ("teacher_2".equals(teacherName))
                {
                    Set stus = teacher.getStudents();
                    Assert.assertEquals(stus.size(), 2);

                    for (Student stu : stus)
                    {
                        String stuName = stu.getName();
                        Assert.assertNotNull(stu.getId());
                        Assert.assertTrue(stuName.equals("student_1") || stuName.equals("student_2"));
                    }
                } else
                {
                    throw new Exception("teacher name error exception.");
                }
            }
        } catch (Exception ex)
        {
            throw ex;
        } finally
        {
            if (session != null)
            {
                try
                {
                    session.close();
                } catch (Exception ex)
                {
                    // nothing to do
                } finally
                {
                    if (session != null)
                        session = null;
                }
            }
        }
    }

    /**
     * 测试删除
     * @throws Exception
     */
    public void testDelete() throws Exception
    {
        System.out.println("\n=== test delete ===");
        Session session = null;
        Transaction tran = null;
        try
        {
            session = factory.openSession();
            tran = session.beginTransaction();

            Iterator iter = session.createQuery("from Teacher").iterate();
            while (iter.hasNext())
                session.delete(iter.next());

            tran.commit();

            Integer count = (Integer) session.createQuery("select count(*) from Teacher").list().get(0);
            Assert.assertEquals(0, count.intValue());

        } catch (Exception ex)
        {
            throw ex;
        } finally
        {
            if (session != null)
            {
                try
                {
                    session.close();
                } catch (Exception ex)
                {
                    // nothing to do
                } finally
                {
                    if (session != null)
                        session = null;
                }
            }
        }

        /*
         * 删除后再查询
         */
        System.out.println("\n=== test find after delete ===");
        try
        {
            session = factory.openSession();

            Integer num = (Integer) session.createQuery("from Teacher").list().size();
            Assert.assertEquals(0, num.intValue());

            num = (Integer) session.createQuery("from Student").list().size();
            Assert.assertEquals(0, num.intValue());

        } catch (Exception ex)
        {
            throw ex;
        } finally
        {
            if (session != null)
            {
                try
                {
                    session.close();
                } catch (Exception ex)
                {
                    // nothing to do
                } finally
                {
                    if (session != null)
                        session = null;
                }
            }
        }
    }

    /**
     * 
     */
    @After
    public void tearDown() throws Exception
    {
        factory.close();
    }

}

从这个例子中可以看出,many-to-many中,需要引入第3张表来表示关系。

附件中有源代码。