Hibernate一对一关联关系的使用

    技术2022-05-19  20

    以主键关联

             关联的两个实体共享一个主键。给一个表(Student)设定主键,另个一表(Certificate)使用的是学生表的主键,即主键的foreign生成机制。

    Student.hbm.xml

    <class name="model.Student" table="student" lazy="true"><!--把类和数表关联起来-->

           <id name="id" unsaved-value="null"><!--id的产生方式是uuid.hex-->

               <generator class="uuid.hex" />

           </id>

           <property name="cardId" type="string" /><!--映射号-->

           <property name="name" type="string" /><!--映射学生名-->

           <property name="age" type="int" /><!--映射学生岁数-->

           <one-to-one name="cer"

               class="model.Certificate" 

               fetch="join"

               cascade="all" 

            /><!--映射对应的身分证对象-->

        </class>

    Certificate.hbm.xml

    <class name="model.Certificate" table="certificate" lazy="true">

           <id name="id">

           <!-- 外键生成机制,引用stu对象的主键作为certificate数据表的外键和主键 -->

               <generator class="foreign"><!-- 以主键关联 -->

                  <param name="property">stu</param>

               </generator>

           </id>

           <!-- 下面的column属性加上了引号,是因为describemysql的关键字 -->

           <property name="describe" column="`describe`" type="string" />

           <one-to-one name="stu"

                class="model.Student"

                fetch="select"

                constrained="true"

                cascade="none"

           />

           <!--constrained="true" 表示certificate应用了stu的主键作为外键 -->

        </class>

    一对一的关系是通过主键值得以关联的,而主键id在配置文件中已经设置过了,hibernate找到student,通过一对一关系找到certificate.hbm.xml,该配置文件中没有设置主键的列名,则默认列名为id,再去取得certificate的响应id的对象。

     

    测试类:

    Student stu = new Student();

          stu.setName("spark");

          stu.setCardId("200211332");

          stu.setAge(33);

     

          Certificate cer=new Certificate();

          cer.setDescribe("spark");

     

          stu.setCer(cer);

          cer.setStu(stu);

        

          StudentDAO.saveObj(stu);

    控制台输出:

    Hibernate: insert into student (cardId, name, age, id) values (?, ?, ?, ?)

    Hibernate: insert into certificate (`describe`, id) values (?, ?)

     

    以外键关联

             重点是两个实体各有不相同的主键,其中一个实体有一个外键应用了另一个实体的主键。

    Student.hbm.xml

    <class name="model.Student" table="student" lazy="true"><!--把类和数表关联起来-->

           <id name="id" unsaved-value="null"><!--id的产生方式是uuid.hex-->

               <generator class="uuid.hex" />

           </id>

           <property name="cardId" type="string" /><!--映射号-->

           <property name="name" type="string" /><!--映射学生名-->

           <property name="age" type="int" /><!--映射学生岁数-->

           <one-to-one name="cer" class="model.Certificate"  fetch="join" cascade="all"  /><!--映射对应的身分证对象-->

        </class>

    Certificate.hbm.xml

    <class name="model.Certificate" table="certificate" lazy="true">

           <id name="id">

               <generator class="uuid.hex" />

           </id>

           <property name="describe" column="`describe`" type="string" />

           <many-to-one name="stu"

               class="model.Student" 

               unique="true" <!—唯一的多对一,也就成了一对一-->

               column="stu_id"

           />

        </class>

    测试类:

    Student stu = new Student();

          stu.setName("spark");

          stu.setCardId("200211332");

          stu.setAge(33);

     

          Certificate cer=new Certificate();

          cer.setDescribe("spark");

     

          stu.setCer(cer);

          cer.setStu(stu);

        

          StudentDAO.saveObj(stu);

    控制台输出:

    Hibernate: insert into student (cardId, name, age, id) values (?, ?, ?, ?)

    Hibernate: insert into certificate (`describe`, id) values (?, ?)

     

    默认的级联关系:

    one-to-one关联默认的级联关系是预先抓取,而一对多,多对多的默认加载策略是立即记载。

     

     

    延迟加载:

    one-to-one关系进行延迟加载和其他关系相比稍微不同。Many-to-one的延迟加载是在配置文件的class标签设置lazy=true”,one-to-manymany-to-many的延迟加载是在set标签中设置lazy=true”,而one-to-one不仅要在class标签设置lazy=true”,而且要在one-to-one标签中设置constrained=true

    Student.hbm.xml

    <class name="model.Student" table="student" ><!--把类和数表关联起来-->

           <id name="id" unsaved-value="null"><!--id的产生方式是uuid.hex-->

               <generator class="uuid.hex" />

           </id>

           <property name="cardId" type="string" /><!--映射号-->

           <property name="name" type="string" /><!--映射学生名-->

           <property name="age" type="int" /><!--映射学生岁数-->

           <one-to-one name="cer"

               class="model.Certificate"  

               cascade="all" 

           /><!--映射对应的身分证对象-->

        </class>

    Certificate.hbm.xml

    <class name="model.Certificate" table="certificate" lazy="true">

           <id name="id">

               <generator class="uuid.hex" />

           </id>

           <property name="describe" column="`describe`" type="string" />

           <many-to-one name="stu"

               class="model.Student" 

               unique="true"

               column="stu_id"

           />

             </class>

    测试类:

    StudentDAO.getById(Student.class,"5abfa70605c5356f0105c535730e0001");

    控制台输出:

    Hibernate: select student0_.id as id0_1_, student0_.cardId as cardId0_1_, student0_.name as name0_1_, student0_.age as age0_1_, certificat1_.id as id1_0_, certificat1_.`describe` as describe2_1_0_, certificat1_.stu_id as stu3_1_0_ from student student0_ left outer join certificate certificat1_ on student0_.id=certificat1_.id where student0_.id=?

    此时在certificateclass标签中设置了lazy=true”,但是没有在studentone-to-one标签中设置constrained=true”,所以延迟加载不起作用,而是使用了默认的预先抓取策略。

     

    在原来的student.hbm.xml文件做一点小改动,

        <class name="model.Student" table="student" ><!--把类和数表关联起来-->

           <id name="id" unsaved-value="null"><!--id的产生方式是uuid.hex-->

               <generator class="uuid.hex" />

           </id>

           <property name="cardId" type="string" /><!--映射号-->

           <property name="name" type="string" /><!--映射学生名-->

           <property name="age" type="int" /><!--映射学生岁数-->

           <one-to-one name="cer"

               class="model.Certificate"  

               constrained="true"

               cascade="all" 

           /><!--映射对应的身分证对象-->

        </class>

    控制台输出:

    Hibernate: select student0_.id as id0_0_, student0_.cardId as cardId0_0_, student0_.name as name0_0_,

    student0_.age as age0_0_

    from student student0_ where student0_.id=?

    one-to-one关系,constrained=true 附属类的lazy=true才能实现延迟加载,并且将忽略默认的预先抓取策略。


    最新回复(0)