欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

03. 关联关系映射(一对一)

程序员文章站 2022-04-22 22:20:52
...

关联关系映射

一对一关联关系

表结构中关系为一对一,那么类结构中也是一对一的关系。表结构层面上,一对一的关系都是双向的,从任何一侧表都可以访问到对方另一侧表中的内容。而类一对一的关联关系可以分为单向和双向两种。双向表示在两个关联的类中,都存放对方类信息,并提供相应的获取和设置方法;单向表示只在某一侧存放另一方的信息,我们只能从这一方去访问另一方,而不能从另一方访问这一方。

一对一单向关联关系

由于一对一单向关联关系稍微简单些,而且当我们清楚双向关联关系之后,单向的也自然清楚,所以此处省略。

一对一双向关联关系表结构

如Person和Passport

Person类中:id(Long),name(String),gender(String),age(Integer),passport(Passport)。并提供相应的get、set方法。

Passport类中:id(Long),bh(String),person(Person)。并提供相应的get、set方法。

  • 基于外键映射

    Persion表

    CREATE TABLE t_person{
        id NUMBER(10) PRIMERY KEY,
        name VARCHAR2(20) NOT NULL,
        gender VARCHAE2(10),
        age NUMBER(3),
        CHECK (age BETWEEN 1 and 100)
    };

    Passport表

    CREATE TABLE t_passport{
        id NUMBER(10) PRIMERY KEY,
        bh VARCHAR2(30) NOT NULL UNIQUE,
        person_id NUMBER(10) REFERENCES t_person(id) UNIQUE
    };
  • 基于主键映射

    Persion表(父表)

    CREATE TABLE t_person{
        id NUMBER(10) PRIMERY KEY,
        name VARCHAR2(20) NOT NULL,
        gender VARCHAE2(10),
        age NUMBER(3),
        CHECK (age BETWEEN 1 and 100)
    };

    Passport表(子表)

    CREATE TABLE t_passport{
        id NUMBER(10) PRIMERY KEY REFERENCES t_person(id),
        bh VARCHAR2(30) NOT NULL UNIQUE,
    };

一对一双向关联关系类结构

  • Person类

    public class Person{
        private Long id;
        private String name;
        private String gender;
        private Integer age;
        private Passport passport;
        ......
    }
  • Passport类

    public class Passport{
        private Long id;
        private String bh;
        private Person person;
        ......
    }

一对一双向关联关系的映射文件

  • 基于外键映射

    Person类映射(父表)

    前一个one可以认为是Person,后一个one是Passport。name属性值”passport“对应的是property而不是attribute,即此处的passport对应的是Person类中的getPassport和setPassport方法(按照标准的方式来生成的setter和getter方法)。property-ref是指参考引用,在Passport类中应该要有一个属性(此属性为property)为person。cascade表示级联,”all”值是指级联所有CRUD操作。

    <class name="Person" table="T_PERSON">
        ......
        <one-to-one name="passport" class="Passport"
        property-ref="person" cascade="all"/>
    </class>

    Passport类映射(子表)

    many对应的是Passport,one对应的是Person。在Hibernate中不管是一对一还是一对多的关系,都当成一对多的关系来处理,所以我们将子表配置成多对一的关系。此时,我们加unique属性来限定外键是唯一的,建议加上此属性。
    column指示处Passport表中的外键列。name的含义依旧如上:Passport类结构中需要有此属性(property)。

    <class name="Passport" table="T_PASSPORT">
        ......
        <many-to-one name="person" class="Person"
        column="PERSON_ID" unique="true"/>
    </class>
    1. Person类
    package com.li.association.one2one.pojo;
    
    import java.io.Serializable;
    
    public class Person implements Serializable{
    
        private static final long serialVersionUID = -6152698999047898223L;
    
        private Long id;
        private String name;
        private String gender;
        private Integer age;
        private Passport passport;
    
        public Person() {
        }
    
        public Person(Long id, String name, String gender, Integer age, Passport passport) {
            super();
            this.id = id;
            this.name = name;
            this.gender = gender;
            this.age = age;
            this.passport = passport;
        }
    
        public Long getId() {
            return id;
        }
        public void setId(Long id) {
            this.id = id;
        }
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public String getGender() {
            return gender;
        }
        public void setGender(String gender) {
            this.gender = gender;
        }
        public Integer getAge() {
            return age;
        }
        public void setAge(Integer age) {
            this.age = age;
        }
        public Passport getPassport() {
            return passport;
        }
        public void setPassport(Passport passport) {
            this.passport = passport;
        }
        public static long getSerialversionuid() {
            return serialVersionUID;
        }
    
        @Override
        public String toString() {
            return "Person [id=" + id + ", name=" + name + ", gender=" + gender + ", age=" + age + ", passport=" + passport
                    + "]";
        }
    
    }
    

    映射文件(Person_FK.hbm.xml)

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE hibernate-mapping PUBLIC
            "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
            "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
    
    <hibernate-mapping package="com.li.association.one2one.pojo">
        <class name="Person" table="T_PERSON">
            <id name="id" type="long" column="ID"></id> 
            <property name="name" type="string" column="NAME"></property>
            <property name="gender" type="string" column="GENDER"></property>
            <property name="age" type="integer" column="AGE"></property>
    
            <one-to-one name="passport" class="Passport" property-ref="person" cascade="all"></one-to-one>
        </class>
    </hibernate-mapping>
    1. Passport类
    package com.li.association.one2one.pojo;
    
    import java.io.Serializable;
    
    public class Passport implements Serializable {
    
        private static final long serialVersionUID = -1819074069116356352L;
    
        private Long id;
        private String bh;
        private Person person;
    
        public Passport() {
    
        }
        public Passport(Long id, String bh, Person person) {
            super();
            this.id = id;
            this.bh = bh;
            this.person = person;
        }
    
        public Long getId() {
            return id;
        }
        public void setId(Long id) {
            this.id = id;
        }
        public String getBh() {
            return bh;
        }
        public void setBh(String bh) {
            this.bh = bh;
        }
        public Person getPerson() {
            return person;
        }
        public void setPerson(Person person) {
            this.person = person;
        }
        public static long getSerialversionuid() {
            return serialVersionUID;
        }
        @Override
        public String toString() {
            return "Passport [id=" + id + ", bh=" + bh + "]";
        }
    
    }
    

    映射文件(Passport_FK.hbm.xml)

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE hibernate-mapping PUBLIC
            "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
            "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
    
    <hibernate-mapping package="com.li.association.one2one.pojo">
        <class name="Passport" table="T_PASSPORT">
            <id name="id" type="long" column="ID"></id>
    
            <property name="bh" type="string" column="BH"></property>
    
            <many-to-one name="person" class="Person" column="PERSON_ID" unique="true"></many-to-one>
        </class>
    </hibernate-mapping>
    1. 将映射文件配置的核心配置文件中
    <mapping resource="com/li/association/one2one/pojo/Passport_FK.hbm.xml"/>
    <mapping resource="com/li/association/one2one/pojo/Person_FK.hbm.xml"/>
    1. 测试
    package com.li.test;
    
    import org.hibernate.Session;
    import org.hibernate.Transaction;
    
    import com.li.association.one2one.pojo.Passport;
    import com.li.association.one2one.pojo.Person;
    import com.li.common.CurrentSession;
    
    public class Association1 {
    
        public static void main(String[] args) {
            Person p=new Person();
            p.setId(123L);
            p.setName("jack");
            p.setGender("male");
            p.setAge(20);
    
            Passport pp=new Passport();
            pp.setId(456L);
            pp.setBh("G123456");
            /*建立双向关联关系*/
            p.setPassport(pp);
            pp.setPerson(p);
    
            Session session=CurrentSession.getSession();
            Transaction trans=null;
    
            try {
                trans=session.beginTransaction();
    
                /*保存Person对象的同时会级联保存Passport对象*/
                //session.save(p);
    
                /*使用反射从数据库中获取数据,级联查询,Passport的信息也被查询出来*/
                Person person=(Person) session.get(Person.class, 123L);
                /*在重写toString方法时,只从Person输出Passport即可,Passport中不要输出Person,不然会出栈溢出异常*/
                System.out.println(person);
    
                /*级联更新*/
                person.setName("Lee");
                person.setAge(21);
                person.getPassport().setBh("G456789");
                session.update(person);
    
                /*级联删除*/
                session.delete(person);
    
                trans.commit();
            } catch (Exception e) {
                e.printStackTrace();
                trans.rollback();
            }
        }
    
    }
    
  • 基于主键的映射

    Person类配置

    <class name="Person" table="T_PERSON">
        ......
        <one-to-one name="passport" class="Passport" cascade="all"/>
    </class>

    Passport类配置

    其中主键生成策略中,name=”property”表示基于Passport类中person属性来生成主键。基于主键映射后面的对应关系配置应为one-to-one,因为主键不应该重复。

    <class name="Passport" table="T_PASSPORT">
        <id name="id" column="ID" type="long">
        <generator class=foreign>
            <param name="property">person</param>
        </generator>
        ......
        <one-to-one name="person" class="Person"/>
    </id>
    </class>

    其余部分与基于外键部分操作类似

相关标签: 关联关系