Hibernate 多对多关系详解(包括中间表,一对多字表)

jopen 12年前

Event事件表

Person 人员表

Person_Event 人员事件表

PersonEmailAddr邮件地址表

 关系图:

Hibernate 多对多关系详解(包括中间表,一对多字表)

事件对人员是多对多的关系,中间表Person_Event只有两个字段(PERSON_ID,EVENT_ID),邮件地址表只对应人员ID,一个人可以多个邮箱

 

*************** CLASS PERSON ***************

publicclass Person {

 

    private Longid; //ID主键

    privateintage; //属性

    private Stringfirstname;//属性

    private Stringlastname; //属性

    private SetemailAddresses =new HashSet();//与表PersonEmailAddr对应字段的属性,邮件地址可以多个不同,所以放入Set中而不放入List

    private Setevents = new HashSet();//与表Person_Event对应字段的属性,道理跟上面一样

 

    // Getter and Setter methods

 

    // Defensive, convenience methods .PERSON端维护关系,inverse=”false”

    publicvoid addToEvent(Event event) {

        this.getEvents().add(event);

        event.getParticipants().add(this);

    }

 

    publicvoid removeFromEvent(Event event) {

        this.getEvents().remove(event);

        event.getParticipants().remove(this);

    }

 

}

 

*************** CLASS EVENT ***************

publicclass Event {

   

    private Longid    //主键ID

    private Datedate;   //属性

    private Set<Person>participants =new HashSet<Person>(); //与表Person_Event对应字段的属性,道理跟上面一样

 

    private Stringtitle; //属性

 

    // Getter and Setter methods

 

}

 

******************* PERSON XML ******************

<hibernate-mapping>

 

    <classname="events.Person"table="PERSON"> <!-- class.name指向类class.table指向表-->

        <idname="id"column="PERSON_ID"> <!-- id.id指向属性 id.column指向字段-->

            <generatorclass="native"/> <!-- 主键生成方法-->

        </id>

        <propertyname="age"/> <!-- property.name指向类的属性-->

        <propertyname="firstname"/>

        <propertyname="lastname"/>

 

        <setname="events"table="PERSON_EVENT"><!-- set.name指向类的Set属性;set.table指向中间表名 inverse=”false” person端维护关系-->

            <keycolumn="PERSON_ID"/><!-- key.column指出本类提供中间表的字段-->

            <many-to-manycolumn="EVENT_ID"class="events.Event"/><!-- many-to-many.column指出另外的中间表的字段及刚才key的关系 many-to-many.class该字段对应的类名 -->

        </set>

       

        <setname="emailAddresses"table="PERSON_EMAIL_ADDR"><!-- set.name指向类的Set属性;set.table指向中间表名-->

            <keycolumn="PERSON_ID"/><!-- key.column指出本类提供表的字段-->

            <elementtype="string"column="EMAIL_ADDR"/><!-- element.column指出表的其他字段 element.type该字段的类型-->

        </set>

 

    </class>

 

</hibernate-mapping>

 

******************* EVENT XML ******************

<hibernate-mapping>

 

    <classname="events.Event"table="EVENTS">

        <idname="id"column="EVENT_ID">

            <generatorclass="native"/>

        </id>

        <propertyname="date"type="timestamp"column="EVENT_DATE"/>

        <propertyname="title"/>

 

        <setname="participants"table="PERSON_EVENT"inverse="true">

<!--  inverse=”true” event不管关系person端维护关系-->

            <keycolumn="EVENT_ID"/>

            <many-to-manycolumn="PERSON_ID"class="events.Person"/>

        </set>

 

    </class>

 

</hibernate-mapping>

 

******************* HIBERNATE CFG XML ******************

<session-factory>

 

        <!-- Database connection settings -->

        <propertyname="connection.driver_class">com.mysql.jdbc.Driver</property>

        <propertyname="connection.url">jdbc:mysql:///test</property>

        <propertyname="connection.username">root</property>

        <propertyname="connection.password">root</property>

 

        <!-- JDBC connection pool (use the built-in) -->

        <propertyname="connection.pool_size">1</property>

 

        <!-- SQL dialect -->

        <propertyname="dialect">org.hibernate.dialect.MySQLDialect</property>

 

        <!-- Enable Hibernate's automatic session context management -->

        <propertyname="current_session_context_class">thread</property>

 

        <!-- Disable the second-level cache -->

        <propertyname="cache.provider_class">org.hibernate.cache.NoCacheProvider</property>

 

        <!-- Echo all executed SQL to stdout -->

        <propertyname="show_sql">true</property>

 

        <!-- Drop and re-create the database schema on startup -->

        <propertyname="hbm2ddl.auto">create</property>

 

        <mappingresource="events/Event.hbm.xml"/>

        <mappingresource="events/Person.hbm.xml"/>

 

</session-factory>

 

******************** 测试类 ******************

publicclass EventManager {

 

    publicstaticvoid main(String[] args) {

        EventManager mgr = new EventManager();

 

       // if (args[0].equals("createAndStoreEvent")) {

            mgr.createAndStoreEvent("My Event",new Date());

        //}

        if (args[0].equals("listEvents")) {

            List events = mgr.listEvents();

            for (int i = 0; i < events.size(); i++) {

                Event theEvent = (Event) events.get(i);

                System.out.println("Event: " + theEvent.getTitle() +

                                   " Time: " + theEvent.getDate());

            }

        }

        elseif (args[0].equals("addpersontoevent")) {

        //store event

            Long eventId = mgr.createAndStoreEvent("My Event",new Date());

            //store Person

            Long personId = mgr.createAndStorePerson("Foo","Bar");

           

            mgr.addPersonToEvent(personId, eventId);

            System.out.println("Added person " + personId +" to event " + eventId);

        }

        elseif (args[0].equals("addemailtoperson")) {

            Long personId = mgr.createAndStorePerson("Foozy","Beary");

            mgr.addEmailToPerson(personId,"foo@bar");

           // mgr.addEmailToPerson(personId, "bar@foo");

            System.out.println("Added two email addresses (value typed objects) to person entity : " + personId);

        }

 

        HibernateUtil.getSessionFactory().close();

    }

 

    private Long createAndStoreEvent(String title, Date theDate) {

 

        Session session = HibernateUtil.getSessionFactory().getCurrentSession();

        session.beginTransaction();

 

        //theEvent is transient

        Event theEvent = new Event();

        theEvent.setTitle(title);

        theEvent.setDate(theDate);

 

        //theEvent turns to persistent

        session.save(theEvent);

 

        session.getTransaction().commit();

 

        return theEvent.getId();

    }

 

    private Long createAndStorePerson(String firstname, String lastname) {

 

        Session session = HibernateUtil.getSessionFactory().getCurrentSession();

        session.beginTransaction();

 

        Person thePerson = new Person();

        thePerson.setFirstname(firstname);

        thePerson.setLastname(lastname);

 

        session.save(thePerson);

 

        session.getTransaction().commit();

 

        return thePerson.getId();

    }

 

 

    private List listEvents() {

 

        Session session = HibernateUtil.getSessionFactory().getCurrentSession();

        session.beginTransaction();

 

        List result = session.createQuery("from Event").list();

 

        session.getTransaction().commit();

 

        return result;

    }

 

    privatevoid addPersonToEvent(Long personId, Long eventId) {

 

        Session session = HibernateUtil.getSessionFactory().getCurrentSession();

        session.beginTransaction();

 

        Person aPerson = (Person) session

                .createQuery("select p from Person p left join fetch p.events where p.id = :pid")

                .setParameter("pid", personId)

                .uniqueResult();// Eager fetch the collection so we can use it detached

 

        /*

        Event anEvent = (Event) session.load(Event.class, eventId);

        */

        // If we want to handle it bidirectional and detached, we also need to load this

        // collection with an eager outer-join fetch, this time with Criteria and not HQL:

       

        Event anEvent = (Event) session

                .createCriteria(Event.class).setFetchMode("participants", FetchMode.JOIN)

                .add( Expression.eq("id", eventId) )

                .uniqueResult();// Eager fetch the colleciton so we can use it detached

       

 

        System.out.println("session.getTransaction().commit();");

        session.getTransaction().commit();

 

        // End of first unit of work

 

        aPerson.getEvents().add(anEvent);// aPerson is detached

        // or bidirectional safety method, setting both sides: aPerson.addToEvent(anEvent);

 

        // Begin second unit of work

 

        Session session2 = HibernateUtil.getSessionFactory().getCurrentSession();

        session2.beginTransaction();

 

        session2.update(aPerson);// Reattachment of aPerson

       

        System.out.println("session2.getTransaction().commit();");

        session2.getTransaction().commit();

    }

 

    privatevoid addEmailToPerson(Long personId, String emailAddress) {

 

        Session session = HibernateUtil.getSessionFactory().getCurrentSession();

        session.beginTransaction();

 

        Person aPerson = (Person) session.load(Person.class, personId);

 

        // The getEmailAddresses() might trigger a lazy load of the collection

        aPerson.getEmailAddresses().add(emailAddress);

 

        session.getTransaction().commit();

    }

   

}

本文来源官方文档:hibernate3.2.5