• Hibernate多对多两种情况


    Hibernate在做多对多映射的时候,除了原先的两张表外,会多出一个中间表做关联,根据中间表的会有两种不同的配置情况:

    1.中间表不需要加入额外数据。

    2.中间表有其他字段,需记录额外数据。

    下面,我们就以address、person这两张表根据这两种情况做下相应的配置:

    情况1:

    我们需要建三张表,一张address表,一张person表,一张中间表(其实中间表可以不用建,配置好后运行会自动生成),如下:

    复制代码
    delimiter $$
    
    CREATE TABLE `address` (
      `address_id` int(11) NOT NULL,
      `address_name` varchar(50) default NULL,
      PRIMARY KEY  (`address_id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8$$
    
    delimiter $$
    
    CREATE TABLE `person` (
      `person_id` int(11) NOT NULL,
      `person_name` varchar(20) default NULL,
      PRIMARY KEY  (`person_id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8$$
    
    delimiter $$
    
    CREATE TABLE `person_address` (
      `person_id` int(11) NOT NULL,
      `address_id` int(11) NOT NULL,
      PRIMARY KEY  (`address_id`,`person_id`),
      KEY `FK23F8B90AAAA29DA8` (`person_id`),
      KEY `FK23F8B90AB52F16EC` (`address_id`),
      CONSTRAINT `FK23F8B90AB52F16EC` FOREIGN KEY (`address_id`) REFERENCES `address` (`address_id`),
      CONSTRAINT `FK23F8B90AAAA29DA8` FOREIGN KEY (`person_id`) REFERENCES `person` (`person_id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8$$
    复制代码

    表建好后,我们需要写相应的实体类:

    复制代码
    public class Address {
        
        private int addressId;
        private String addressName;
        private Set<Person> person;
        
        public int getAddressId() {
            return addressId;
        }
        public void setAddressId(int addressId) {
            this.addressId = addressId;
        }
        public String getAddressName() {
            return addressName;
        }
        public void setAddressName(String addressName) {
            this.addressName = addressName;
        }
        public Set<Person> getPerson() {
            return person;
        }
        public void setPerson(Set<Person> person) {
            this.person = person;
        }
        
    }
    
    
    public class Person {
        
        private int personId;
        private String personName;
        private Set<Address> address;
        
        public int getPersonId() {
            return personId;
        }
        public void setPersonId(int personId) {
            this.personId = personId;
        }
        
        public String getPersonName() {
            return personName;
        }
        public void setPersonName(String personName) {
            this.personName = personName;
        }
        public Set<Address> getAddress() {
            return address;
        }
        public void setAddress(Set<Address> address) {
            this.address = address;
        }
            
    }
    复制代码

    在这里,我们只需要配置两个实体类与相应配置文件即可,中间表无须建实体类与配置文件,hibernate会帮你自动关连。

    复制代码
    <?xml version="1.0"?>
    <!DOCTYPE hibernate-mapping PUBLIC 
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
    <hibernate-mapping package="com.test.web.model">
    
        <class name="Address" table="address">
            <id name="addressId" type="int" >
                <column name="address_id" length="11"></column> 
            </id>
            <property name="addressName" type="string" >
                <column name="address_name" length="50"></column>
            </property>
            <set name="person" cascade="all" table="person_address">
                <key column="address_id"></key>
                <many-to-many class="Person" column="person_id"/>
            </set>
        </class>
    </hibernate-mapping>
    
    
    <?xml version="1.0"?>
    <!DOCTYPE hibernate-mapping PUBLIC 
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
    <hibernate-mapping package="com.test.web.model">
    
        <class name="Person" table="person">
            <id name="personId" type="int" >
                <column name="person_id" length="11"></column> 
            </id>
            <property name="personName" type="string" >
                <column name="person_name" length="20"></column>
            </property>
            <set name="address" cascade="all" table="person_address">
                <key column="person_id"></key>
                <many-to-many class="Address" column="address_id"/>
            </set>
        </class>
    </hibernate-mapping>
    复制代码

    测试类:

    复制代码
    public void insert() {
            
            Person p = new Person();
            p.setPersonId(1);
            p.setPersonName("newUser");
            Address ad = new Address();
            ad.setAddressId(2);
            ad.setAddressName("here");
            Set<Address> setAd = new HashSet<Address>();
            setAd.add(ad);
             p.setAddress(setAd);
            sf.getCurrentSession().persist(p);
    }
    复制代码

    以上,便是一般的多对多关系。

    情况2:

      当需要向中间表写数据时,单纯的多对多已经满足不了了,所以在这里,我们可以将其设成两个一对多的关系,即person表与person_address是一对多关系,address与person_address表也是一对多关系,这样,但可以完成相应的多对多功能了。在情况2中,我们不单单需要对person表与address表写相应的实体类与配置文件,还需要对person_address表写实体类与配置文件。

         在第二种情况中,我们又可以分成两种小的情况:

      1)中间表新增主键,另有两个字段做为外键对应另外两张表。

          2)中间表采用复合主键,同时做为外键分别对应另外两张表。

    下面我们分别对两种情况做相应配置。

    情况1)中间表新增主键,另有两个字段做为外键对应另外两张表。数据表结构为:

    复制代码
    delimiter $$
    
    CREATE TABLE `address` (
      `address_id` int(11) NOT NULL,
      `address_name` varchar(50) default NULL,
      PRIMARY KEY  (`address_id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8$$
    
    delimiter $$
    
    CREATE TABLE `person` (
      `person_id` int(11) NOT NULL,
      `person_name` varchar(20) default NULL,
      PRIMARY KEY  (`person_id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8$$
    
    
    delimiter $$
    
    CREATE TABLE `person_address` (
      `pa_id` int(11) NOT NULL,
      `person_id` int(11) default NULL,
      `address_id` int(11) default NULL,
      `pa_describe` varchar(50) default NULL,
      PRIMARY KEY  (`pa_id`),
      KEY `FK23F8B90AAAA29DA8` (`person_id`),
      KEY `FK23F8B90AB52F16EC` (`address_id`),
      CONSTRAINT `FK23F8B90AB52F16EC` FOREIGN KEY (`address_id`) REFERENCES `address` (`address_id`),
      CONSTRAINT `FK23F8B90AAAA29DA8` FOREIGN KEY (`person_id`) REFERENCES `person` (`person_id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8$$
    复制代码

    对应的类为:

    复制代码
    public class Address {
        
        private int addressId;
        private String addressName;
        private Set<PersonAddress> pa;
        
        public int getAddressId() {
            return addressId;
        }
        public void setAddressId(int addressId) {
            this.addressId = addressId;
        }
        public String getAddressName() {
            return addressName;
        }
        public void setAddressName(String addressName) {
            this.addressName = addressName;
        }
        public Set<PersonAddress> getPa() {
            return pa;
        }
        public void setPa(Set<PersonAddress> pa) {
            this.pa = pa;
        }
        
    }
    
    
    public class Person {
        
        private int personId;
        private String personName;
        private Set<PersonAddress> personAddress;
        
        public int getPersonId() {
            return personId;
        }
        public void setPersonId(int personId) {
            this.personId = personId;
        }
        
        public String getPersonName() {
            return personName;
        }
        public void setPersonName(String personName) {
            this.personName = personName;
        }
        public Set<PersonAddress> getPersonAddress() {
            return personAddress;
        }
        public void setPersonAddress(Set<PersonAddress> personAddress) {
            this.personAddress = personAddress;
        }    
    }
    
    
    
    public class PersonAddress{
    
        
        private int paid;
        private String paDescribe;
        private Person person;
        private Address address;
        
        
        public int getPaid() {
            return paid;
        }
        public void setPaid(int paid) {
            this.paid = paid;
        }
        public String getPaDescribe() {
            return paDescribe;
        }
        public void setPaDescribe(String paDescribe) {
            this.paDescribe = paDescribe;
        }
        public Person getPerson() {
            return person;
        }
        public void setPerson(Person person) {
            this.person = person;
        }
        public Address getAddress() {
            return address;
        }
        public void setAddress(Address address) {
            this.address = address;
        }
        
    }
    复制代码

    配置文件:

    复制代码
    <?xml version="1.0"?>
    <!DOCTYPE hibernate-mapping PUBLIC 
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
    <hibernate-mapping package="com.test.web.model">
    
        <class name="Address" table="address">
            <id name="addressId" type="int" >
                <column name="address_id" length="11"></column> 
            </id>
            <property name="addressName" type="string" >
                <column name="address_name" length="50"></column>
            </property>
            <set name="pa" cascade="all">
                <key column="address_id"></key>
                <one-to-many class="PersonAddress"/>
            </set>
        </class>
    </hibernate-mapping>
    
    <?xml version="1.0"?>
    <!DOCTYPE hibernate-mapping PUBLIC 
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
    <hibernate-mapping package="com.test.web.model">
    
        <class name="Person" table="person">
            <id name="personId" type="int" >
                <column name="person_id" length="11"></column> 
            </id>
            <property name="personName" type="string" >
                <column name="person_name" length="20"></column>
            </property>
            <set name="personAddress" cascade="all">
                <key column="person_id"></key>
                <one-to-many class="PersonAddress"/>
            </set>
        </class>
    </hibernate-mapping>
    
    
    <?xml version="1.0"?>
    <!DOCTYPE hibernate-mapping PUBLIC 
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
    <hibernate-mapping package="com.test.web.model">
    
        <class name="PersonAddress" table="person_address">
            <id name="paid" type="int">
                <column name="pa_id" length="11"></column>
            </id>
            <property name="paDescribe" type="string" >
                <column name="pa_describe" length="50"></column>
            </property>
            <many-to-one name="person" class="Person" cascade="all">
                <column name="person_id" length="11" ></column>
            </many-to-one>
            <many-to-one name="address" class="Address" cascade="all">
                <column name="address_id" length="11" ></column>
            </many-to-one>
        </class>
    </hibernate-mapping>
    复制代码

    以上,便完成了相应的配置,进行数据插入时,只需应对相应的保存即可,如:

    复制代码
    public void insert() {
            
            Person p = new Person();
            p.setPersonId(1);
            p.setPersonName("newUser");
            Address ad = new Address();
            ad.setAddressId(2);
            ad.setAddressName("here");
            PersonAddress pa = new PersonAddress();
            pa.setPaid(1);
            pa.setPerson(p);
            pa.setAddress(ad);
            pa.setPaDescribe("this is a test");
            sf.getCurrentSession().persist(pa);
    }
    复制代码

     情况2)中间表采用复合主键,同时做为外键分别对应另外两张表。由于采用复合主键,在hibernate模型中,需要有另一个类来对应,并实现Serializable接口:

    复制代码
    public class PersonAddressPK implements Serializable{
        
        /**
         * 
         */
        private static final long serialVersionUID = 1L;
        
        private int person;
        private int address;
        public int getPerson() {
            return person;
        }
        public void setPerson(int person) {
            this.person = person;
        }
        public int getAddress() {
            return address;
        }
        public void setAddress(int address) {
            this.address = address;
        }
        
    
    }
    复制代码

    Person表与address表不变,主要是在person_address表上做修改,如下:

    delimiter $$
     
    CREATE TABLE `person_address` (
      `person_id` int(11) NOT NULL,
      `address_id` int(11) NOT NULL,
      `pa_describe` varchar(50) default NULL,
      PRIMARY KEY  (`person_id`,`address_id`),
      KEY `FK23F8B90AAAA29DA8` (`person_id`),
      KEY `FK23F8B90AB52F16EC` (`address_id`),
      CONSTRAINT `FK23F8B90AB52F16EC` FOREIGN KEY (`address_id`) REFERENCES `address` (`address_id`),
      CONSTRAINT `FK23F8B90AAAA29DA8` FOREIGN KEY (`person_id`) REFERENCES `person` (`person_id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8$$

    相应的类:

    复制代码
    public class PersonAddress{
    
        
        
        private String paDescribe;
        private PersonAddressPK paPK;
        private Person person;
        private Address address;
        
        public String getPaDescribe() {
            return paDescribe;
        }
        public void setPaDescribe(String paDescribe) {
            this.paDescribe = paDescribe;
        }
        public PersonAddressPK getPaPK() {
            return paPK;
        }
        public void setPaPK(PersonAddressPK paPK) {
            this.paPK = paPK;
        }
        public Person getPerson() {
            return person;
        }
        public void setPerson(Person person) {
            this.person = person;
        }
        public Address getAddress() {
            return address;
        }
        public void setAddress(Address address) {
            this.address = address;
        }
        
        
    }
    复制代码

    配置文件:

    复制代码
    <?xml version="1.0"?>
    <!DOCTYPE hibernate-mapping PUBLIC 
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
    <hibernate-mapping package="com.test.web.model">
    
        <class name="PersonAddress" table="person_address">
            <composite-id class="PersonAddressPK" name="paPK">
                <key-property name="person">
                    <column name="person_id" length="11"></column>
                </key-property>
                <key-property name="address">
                    <column name="address_id" length="11"></column>
                </key-property>
            </composite-id>
            <property name="paDescribe" type="string" >
                <column name="pa_describe" length="50"></column>
            </property>
            <many-to-one name="person" class="Person" column="person_id" insert="false" update="false"/>  
            <many-to-one name="address" class="Address" column="address_id" insert="false" update="false"/>
        </class>
    </hibernate-mapping>
    复制代码

    插入的时候,需先保存person与address表,再保存person_address表:

    复制代码
    public void insert() {
            
            Person p = new Person();
            p.setPersonId(1);
            p.setPersonName("newUser");
            Address ad = new Address();
            ad.setAddressId(2);
            ad.setAddressName("here");
            sf.getCurrentSession().persist(p);
            sf.getCurrentSession().persist(ad);
            PersonAddress pa = new PersonAddress();
            PersonAddressPK paPK = new PersonAddressPK();
            paPK.setPerson(p.getPersonId());
            paPK.setAddress(ad.getAddressId());
            pa.setPaPK(paPK);
            pa.setPaDescribe("this is a test");
            sf.getCurrentSession().persist(pa);
    }
    复制代码

     以上,便是hibernate多对多时可采用的几种方法了。

  • 相关阅读:
    spark hbase
    Benchmark简介
    Flink的安装配置
    Hive入门及常用指令
    hadoop+yarn+hbase+storm+kafka+spark+zookeeper)高可用集群详细配置
    Linux最常用的命名
    数据库的零散的总结
    DBA总结
    MySQL主从架构配置
    mysql主从读写分离,分库分表
  • 原文地址:https://www.cnblogs.com/GotoJava/p/6689603.html
Copyright © 2020-2023  润新知