`

hibernate03:多对一单向关联、多对一双向关联

 
阅读更多

第一:概念

hibernate框架如何管理session对象(该对象是当局部变量还是当成员变量)?
答:通过ThreadLocal机制。在我们自动生成的hibernatesessionfactory类里面体现了工厂模式,ThreadLocal是该类中的一个熟悉。
打开和关闭session也用到了ThreadLocal对象。ThreadLocal的意思是本地的线程,我们把对象放入ThreadLocal中(因为ThreadLocal有map结构,以当前线程做键来取这个对象)
2.单例对象:用静态变量来表示对象,构造方法是私有的。
3.针对单条查询:立即加载和延时加载:
---1.get是立即加载:创建对象并立即发送select语句,直接向数据库查询数据 :select * from user;
---2.load是先创建proxy对象(代理对象,只包含标识性的属性,只有id属性),此时不发送select语句,知道使用代理对象的其他属性的时候,才会发送select语句并填充代理对象
也就是说load方法的返回值返回的对象是个代理对象。
---3.延时加载:最初对象只有id属性,没有其他属性,如果session没有关闭的情况下,通过get属性方法,可以获得
对象的其他属性,但是一旦session关闭,就无法获得其他属性。也就是说这个代理对象没有获得一个完整的对象,而是什么时候用到其他属性的时候才会加载其他属性
---4.立即加载:创建对象的时候立刻加载所有属性(怎么加载?当发发送select语句的时候就是在加载,因此也就是立刻发送select语句)。而调用load方法的时候不会发送select语句而是产生代理对象,当我们使用代理对象的其他属性的时候才会发送select语句
4.针对多条查询:Query查询的list方法和iterate方法
(1)Query的list查询,将越过Session对象,直接向数据库查询数据(也就是说即使有缓存也没用到缓存);
    list:select * from t_user;
(2)Query的iterate(因特瑞的)查询的步骤:
        ①首先向数据库发送select t_id from t_user,并获得对象的id;(也就是先只查id这一个属性)
        ②根据id,在Session对象的map结构(一级缓存)中寻找对象;(然后根据id找对象)
        ③如果没有找到,再向数据库发送select-where语句(根据上面查出来的id去查询该对象): select * from t_user where id=?
    自我总结:首先产生id字段的查询,然后去session中查看(也就是去缓存中查看),如果有就直接使用缓存(session)中的数据,如果没有的话在向数据库发送完整的sql语句
    问:为什么说是完整的sql语句?
    答:因为第一次先只查id属性,并不是查所有的属性,因此第一次查询的时候是不完整的。
(3)Query对象中的iterate查询方法的利弊,详见程序
        问题:最坏的情况下(也就是查询的每个对象都不在缓存中),iterate方法会产生n+1条sql语句(n指的是遍历,集合遍历n次就是n,1指的是iterate方法首先会先有一次只查id)。而list查询只产生一个sql语句。这里我们看上面几行中的sql语句就能发现。
总结list和iterate:
list的特点
  ----1.是一次查询全部数据:select * from t_user;(查询所有对象的所有属性,有点慢),如果下次在查的时候又会去数据库中去查。
  ----2.不管缓存中有没有,都不会去管缓存,而是直接去数据库查。
iterate的特点
  ----1.先只查询id(主键)属性:select t_id from t_user(只查一个字段比较快),然后根据查询到的主键去缓存中找该主键对应的对象,如果找到了就不会去数据库查该对象了,而是直接使用缓存的,如果没找到在向数据库发送sql语句:select * from t_user where id=?
  ----2,如果缓存中有就使用缓存中的数据。
比较这两种:当缓存中有数据的时候,使用iterate查询比较好(因此此时iterate只查一次id,然后使用缓存的数据。而list是查询所有字段,比较慢),当缓存中没有该数据的时候,使用list查询比较好(因此此时iterate会产生n+1条sql语句,而list只查一条sql语句)
5.多表操作添加关联属性:
在一的一方写的是个集合属性,也就是一个对象(看当前类)包含多个其他对象(看集合属性的泛型)。
<set name="items"  cascade="save-update" inverse="true">
      <!-- 指明多方对象的表的外键字段 -->
      <!-- 本表的主键字段所对应的外键字段 -->
      <key column="t_order_id" />
      <one-to-many class="Item"/>
     </set>在这里用外键字段说明关联关系
----------------------------
在多的一方写一个一的一方的对象类型的属性。
    <many-to-one name="order"
   class="Order"
       column="t_order_id" />  

6.在主表的配置文件中的cascade是级联的意思,里面可以写save-update
inverse="true"  。如果不设置inverse=true表明由一的一方来维护关联关系 。inverse=true表示多的一方来维护关联,inverse的中文意思是反向。
总结:
inverse=true是避免产生过多的sql语句。
1.也就是cascade=save-update表示先插入主表对象(产生一条insert语句),在插入从表对象(但是此时的从表对象的外键还没给值)(产生多条insert语句),然后在给外键自动赋值(产生多条update语句)
2.cascade=save-update和inverse=true都写的话表示由多的一方维护关联关系,结果是先插入主表对象(产生一条insert语句),在插入从表对象(产生的是完整的从表对象)
3.总结:一的一方维护关联关系会产生多余的sql语句,因此要用多的一方来维护关联关系。
4.在主表(一的一方)的映射文件中写级联的话,要在web层的代码中写响应的代码。由一的一方来维护的时候web层要写order.getItems().add(item1);order.getItems().add(item2);
由多的一方来维护的时候要写item1.setOrder(order);item2.setOrder(order);
5.cascade=delete是级联删除,是先删除所有对应着的从表对象,在删除主表中的这个对象。
6.孤儿删除:只删除从表中的记录,不删对应着主表对象。cascade=delete-orphan。orphan是孤儿的意思。通过迭代器的remove方法
7.cascade的属性:save-update(添加的时候用),delete(级联删除的时候用),delete-orphan(孤儿删除的时候用),all(全能)none(不级联)
8.无论什么时候都要设置成inverse=true

 

 

第二:代码(单向关联)

1.员工表的实体类:

package com.model.pojo;
// default package

 

/**
 * Emp entity. @author MyEclipse Persistence Tools
 */

public class Emp  implements java.io.Serializable {


    // Fields   

     private int eid;
     private String ename;
     private String job;


    // Constructors

    /** default constructor */
    public Emp() {
    }

 /** minimal constructor */
    public Emp(int eid) {
        this.eid = eid;
    }
   
    /** full constructor */
    public Emp(int eid, String ename, String job) {
        this.eid = eid;
        this.ename = ename;
        this.job = job;
    }

  
    // Property accessors

    public int getEid() {
        return this.eid;
    }
   
    public void setEid(int eid) {
        this.eid = eid;
    }

 
    public String getEname() {
        return this.ename;
    }
   
    public void setEname(String ename) {
        this.ename = ename;
    }

    public String getJob() {
        return this.job;
    }
   
    public void setJob(String job) {
        this.job = job;
    }
}

 

2.部门表的实体类:

package com.model.pojo;
// default package

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


/**
 * Dept entity. @author MyEclipse Persistence Tools
 */

public class Dept  implements java.io.Serializable {


    // Fields   

     private int did;
     private String dname;
     private Set emps = new HashSet(0);


    // Constructors

    /** default constructor */
    public Dept() {
    }

 /** minimal constructor */
    public Dept(int did) {
        this.did = did;
    }
   
    /** full constructor */
    public Dept(int did, String dname, Set emps) {
        this.did = did;
        this.dname = dname;
        this.emps = emps;
    }

  
    // Property accessors

    public int getDid() {
        return this.did;
    }
   
    public void setDid(int did) {
        this.did = did;
    }

    public String getDname() {
        return this.dname;
    }
   
    public void setDname(String dname) {
        this.dname = dname;
    }

    public Set getEmps() {
        return this.emps;
    }
   
    public void setEmps(Set emps) {
        this.emps = emps;
    }


}

 

3.员工表的对象关系映射

<?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">
<!--
    Mapping file autogenerated by MyEclipse Persistence Tools
-->
<hibernate-mapping package="com.model.pojo">
    <class name="Emp" table="HIB_EMP" schema="CHU1">
        <id name="eid" type="int">
            <column name="EID" precision="3" scale="0" />
            <generator class="assigned"></generator>
        </id>
        <property name="ename" type="string">
            <column name="ENAME" length="10" />
        </property>
        <property name="job" type="string">
            <column name="JOB" length="10" />
        </property>
    </class>
</hibernate-mapping>

 

4.部门表的对象关系映射

<?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">
<!--
    Mapping file autogenerated by MyEclipse Persistence Tools
-->
<hibernate-mapping  package="com.model.pojo">
    <class name="Dept" table="HIB_DEPT" schema="CHU1">
        <id name="did" type="int">
            <column name="DID" precision="3" scale="0" />
            <generator class="assigned"></generator>
        </id>
        <property name="dname" type="string">
            <column name="DNAME" length="10" />
        </property>
        <!--inverse反向默认是false,相当于没写。lazy懒加载是true,表示是启动懒加载模式  -->
        <set name="emps" inverse="false" cascade="all" lazy="true" >
            <key>
                <column name="DID" precision="3" scale="0" />
            </key>
            <one-to-many class="Emp" />
        </set>
    </class>
</hibernate-mapping>

 

 

5.hibernate主配置文件

<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
          "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
          "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">

<!-- Generated by MyEclipse Hibernate Tools.                   -->
<hibernate-configuration>

<session-factory>
 <property name="dialect">
  org.hibernate.dialect.Oracle9Dialect
 </property>
 <property name="connection.url">
  jdbc:oracle:thin:@localhost:1521:ORCL
 </property>
 <property name="connection.username">chu1</property>
 <property name="connection.password">1234</property>
 <property name="connection.driver_class">
  oracle.jdbc.OracleDriver
 </property>
 <property name="myeclipse.connection.profile">chu</property>
 <property name="hbm2ddl.auto">update</property>
 <property name="show_sql">true</property>
 <property name="format_sql">true</property>
 <mapping resource="com/model/pojo/Emp.hbm.xml" />
 <mapping resource="com/model/pojo/Dept.hbm.xml" />

</session-factory>

</hibernate-configuration>

 

 

6.dao层

package com.model.dao;

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

import org.hibernate.Session;
import org.hibernate.Transaction;

import com.comm.BaseDao;
import com.model.pojo.Dept;
import com.model.pojo.Emp;

//项目里有个说明文档,里面有详细注释
public class TestDao extends BaseDao{
 //添加
 public void addDept(){
  //使用反向生成(由表到类),此操作是添加,主表是部门表dept,子表是员工表emp,在添加部门的时候部门表的时候数据库只会添加部门表的内容,
  //为了实现级联添加(添加部门表的时候顺便把员工表的内容也添加上),就要在映射文件中写cascade属性
  Session session=super.getSession();
  Dept d=new Dept();
  d.setDid(5);
  d.setDname("我是5");
  Set set=d.getEmps();
  Emp e=new Emp();
  e.setEid(5);
  e.setEname("项目5");
  e.setJob("程序员5");
  set.add(e);
  Transaction tr = session.beginTransaction();
  session.save(d);
  tr.commit();
  session.close();
 }
 public void delete(){
  Session session=super.getSession();
  Dept d=new Dept();
  d.setDid(4);
  Transaction tr = session.beginTransaction();
  session.delete(d);
  tr.commit();
  session.close();
 }
 public void search(){
  Session session=super.getSession();
  Dept d=(Dept) session.get(Dept.class, 2);
  Set<Emp> eset=d.getEmps();
  Iterator<Emp> it = eset.iterator();
  while(it.hasNext()){
   Emp e=it.next();
   System.out.println(e.getEname()+" "+e.getJob());
  }
  System.out.println(d.getDid()+"\t"+d.getDname()+"\t"+d.getEmps());
 }
 public void search2(){
  Session session=super.getSession();
  Dept d=(Dept) session.get(Dept.class, 2);
  Set<Emp> eset=d.getEmps();
  System.out.println(d.getDid()+"\t"+d.getDname());
 }
 public void search3(){
  Session session=super.getSession();
  Dept d=(Dept) session.load(Dept.class, 2);
  System.out.println(d.getDid());
 }
 
 public void search4(){
  Session session=super.getSession();
  Dept d=(Dept) session.load(Dept.class, 2);
  System.out.println(d.getDid()+d.getDname());
 }
 public void search5(){
  Session session=super.getSession();
  Dept d=(Dept) session.load(Dept.class, 2);
  System.out.println(d.getDid()+d.getDname());
  Set<Emp> set=d.getEmps();
  Iterator<Emp> it = set.iterator();
  while(it.hasNext()){
   System.out.println(it.next().getEname());
  }
 }
 
 public static void main(String[] args) {
  TestDao tdao=new TestDao();
  tdao.addDept();
  //tdao.delete();
  //tdao.search();
  //tdao.search2();
  //tdao.search3();
  //tdao.search4();
  //tdao.search5();
 }

}

 

7.控制台输出的sql语句

此项目是测试多对一单向关联:
第一:添加操作:(我们会遇到下面的几种问题)
1.在做部门表的添加的时候,只会添加部门表的信息,不会添加与之相对应的员工表的信息,此时产生一条添加语句,是添加部门的语句。控制台输出如下代码:
Hibernate:
    insert
    into
        CHU1.HIB_DEPT
        (DNAME, DID)
    values
        (?, ?)
2.如果想实现级联添加的话,就要在部门表的映射文件中的set属性中加上cascade=all属性,该属性表示级联添加,此时产生四条sql语句。
第一条语句是查询子表,表明在添加主表的时候级联添加从表,但是要先查询要添加的这个子表是不是已经存在了(如果存在就不能实现级联添加了)。第二三条语句分别是部门表和员工的insert语句。
第四条是更新员工表,因为添加员工表的时候没有给外键赋值(员工表中的外键为null),看下面的sql语句能够看出来。因此最后一个sql语句是把那个不完整的员工表补充完整,添加了外键。
写了cascade=all:
Hibernate:
    select
        emp_.EID,
        emp_.ENAME as ENAME0_,
        emp_.JOB as JOB0_
    from
        CHU1.HIB_EMP emp_
    where
        emp_.EID=?
Hibernate:
    insert
    into
        CHU1.HIB_DEPT
        (DNAME, DID)
    values
        (?, ?)
Hibernate:
    insert
    into
        CHU1.HIB_EMP
        (ENAME, JOB, EID)
    values
        (?, ?, ?)
Hibernate:
    update
        CHU1.HIB_EMP
    set
        DID=?
    where
        EID=?
       
3.如果想实现级联添加的话,就要在部门表(主表,一的一方)的映射文件中的set属性中加上cascade=all属性,并添加inverse="true",该属性表示反向,也就是说控制权交给了多的一方,此时产生三条sql语句。
第一条语句是查询子表,表明在添加主表的时候级联添加从表,但是要先查询要添加的这个子表是不是已经存在了(如果存在就不能实现级联添加了)。第二三条语句分别是部门表和员工的insert语句。
这表明:控制权交给了多的一方后(交给了emp表),我们发现,虽然输出的sql语句减少了(有助于提高程序运行速度),但是当我们查询数据库的时候发现emp(子表)表中的外键字段为null。
出现这中情况的原因是:在dept表中写inverse="true"表示dept表把关联的权利交给了emp表,而我们现在这个项目做的是单向关联(在实体类中只给主表dept设置了set属性,而没给子表emp设置Dept属性),因此只能是dept表关联emp表。
所以添加inverse="true"属性后没能关联起来,也就是子表的外键没能填充值。(如果是双向关联就能填充了)
写了cascade=all,inverse="true":
Hibernate:
    select
        emp_.EID,
        emp_.ENAME as ENAME0_,
        emp_.JOB as JOB0_
    from
        CHU1.HIB_EMP emp_
    where
        emp_.EID=?
Hibernate:
    insert
    into
        CHU1.HIB_DEPT
        (DNAME, DID)
    values
        (?, ?)
Hibernate:
    insert
    into
        CHU1.HIB_EMP
        (ENAME, JOB, EID)
    values
        (?, ?, ?)
 第二:删除操作:
 1、当我们找到部门id的时候,根据部门id进行删除。控制台输出如下代码:
 第一个sql语句表明:删除之前应该确保数据库中有这个要删除的数据。第二条sql语句是删除主表之前应该把主表跟从表的主外键关系断开。第三条sql语句表明删除主表中的这条数据。
 Hibernate:
    select
        dept_.DID,
        dept_.DNAME as DNAME1_
    from
        CHU1.HIB_DEPT dept_
    where
        dept_.DID=?
Hibernate:
    update
        CHU1.HIB_EMP
    set
        DID=null
    where
        DID=?
Hibernate:
    delete
    from
        CHU1.HIB_DEPT
    where
        DID=?
  ------------------------------------
  小插曲:    
1. 单条查询中的两种方法:get立即加载和load延时加载
 hibernate中的get方法是立即加载,是立即向数据库发送sql语句并加载出全部数据。    
 hibernate中的load方法是延时加载,延时加载的步骤是在查询的时候首先会查询
 2.在session的load方法表示懒加载,意思是只加载id,暂时不加载其他属性。执行load方法的时候会创建一个代理对象proxy,此代理对象只包含id属性。当我们在代码中只使用id属性的时候(不适用其他属性),就直接来代理对象里面取。一旦
 用到其他对象的时候才会向数据库发送sql语句执行查询。也就是说延时加载了,什么时候使用这个对象里面的其他属性就是什么时候向数据库发送sql语句并加载数据。
 在映射文件中也有个懒加载,表示在加载(使用)主表的时候暂时不加载从表
 ----------------------------------------
第三:查询:
1.search()方法:当我们设置lazy=“true”的时候(意思是启动懒加载模式,也就是说在加载主表的时候会懒加载从表),同样会输出两条sql语句。
虽然我们在映射文件中设置了懒加载,但是我们在dao层的代码中的system.out.print中输出了从表的内容(也就是使用了从表),因此控制台会把从表也输出(没能懒加载)
写了:lazy=“true”和get方法立即加载:
Hibernate:
    select
        dept0_.DID as DID1_0_,
        dept0_.DNAME as DNAME1_0_
    from
        CHU1.HIB_DEPT dept0_
    where
        dept0_.DID=?
Hibernate:
    select
        emps0_.DID as DID1_,
        emps0_.EID as EID1_,
        emps0_.EID as EID0_0_,
        emps0_.ENAME as ENAME0_0_,
        emps0_.JOB as JOB0_0_
    from
        CHU1.HIB_EMP emps0_
    where
        emps0_.DID=?
2.search2()方法:同样在映射文件中设置了懒加载,代码里面也没有用到从表的东西,因此就只产生一条sql语句 。
写了:lazy=“true”和get方法立即加载:
Hibernate:
    select
        dept0_.DID as DID1_0_,
        dept0_.DNAME as DNAME1_0_
    from
        CHU1.HIB_DEPT dept0_
    where
        dept0_.DID=? 
 3.search3()方法:使用load方法查询,代码中使用没有使用dept主表的其他字段,因此控制台不产生主表的select语句,由于映射文件没有设置lazy=true属性,表示主从表之间懒加载 ,因此不产生从表的select语句   。因此不产生表
 写了:lazy=true和load方法延时加载。
 
 4.search4():当方法体中输出的不只是该对象的id属性,还有其他属性的时候,此时会产生主表dept的select语句,此时表明load方法的延时加载在此时开始加载了。
  写了:lazy=true和get方法延时加载:
 Hibernate:
    select
        dept0_.DID as DID1_0_,
        dept0_.DNAME as DNAME1_0_
    from
        CHU1.HIB_DEPT dept0_
    where
        dept0_.DID=?
5.search5():该方法调用的时候产生两条sql语句,那是因为在4的基础上,产生了第一条sql语句。但是我们在代码中还用到了从表的属性,因此此时lazy=true这个属性失效了,执行出从表的sql语句。
 写了:lazy=true和load方法延时加载:
Hibernate:
    select
        dept0_.DID as DID1_0_,
        dept0_.DNAME as DNAME1_0_
    from
        CHU1.HIB_DEPT dept0_
    where
        dept0_.DID=?
Hibernate:
    select
        emps0_.DID as DID1_,
        emps0_.EID as EID1_,
        emps0_.EID as EID0_0_,
        emps0_.ENAME as ENAME0_0_,
        emps0_.JOB as JOB0_0_
    from
        CHU1.HIB_EMP emps0_
    where
        emps0_.DID=?
       

 

 

 

 

第三:代码(双向关联)

1.员工表的映射文件

<?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">
<!--
    Mapping file autogenerated by MyEclipse Persistence Tools
-->
<hibernate-mapping package="com.model.pojo">
    <class name="Emp" table="HIB_EMP" schema="CHU1">
        <id name="eid" type="int">
            <column name="EID" precision="10" scale="0" />
            <generator class="assigned"></generator>
        </id>
        <many-to-one name="dept" class="com.model.pojo.Dept" fetch="join">
            <column name="DID" precision="10" scale="0" />
        </many-to-one>
        <property name="ename" type="string">
            <column name="ENAME" length="20" />
        </property>
        <property name="job" type="string">
            <column name="JOB" length="20" />
        </property>
    </class>
</hibernate-mapping>

 

2.部门表的映射文件

<?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">
<!--
    Mapping file autogenerated by MyEclipse Persistence Tools
-->
<hibernate-mapping package="com.model.pojo">
    <class name="Dept" table="HIB_DEPT" schema="CHU1">
        <id name="did" type="int">
            <column name="DID" precision="10" scale="0" />
            <generator class="assigned"></generator>
        </id>
        <property name="dname" type="string">
            <column name="DNAME" length="20" />
        </property>
        <!-- inverse="true"表明由多方维护关联关系,  如果由one方维护关联关系的话,会产生多余的update语句 -->
        <set name="emps" cascade="all" inverse="true">
            <key>
            <!-- 指明多方对象的表的外键字段 -->
      <!-- 本表的主键字段所对应的外键字段 -->
                <column name="DID" precision="10" scale="0" />
            </key>
            <one-to-many class="com.model.pojo.Emp" />
        </set>
    </class>
</hibernate-mapping>

 

3.dao层

package com.model.dao;

import java.io.Serializable;
import java.util.Set;

import org.hibernate.Session;
import org.hibernate.Transaction;

import com.comm.BaseDao;
import com.model.pojo.Dept;
import com.model.pojo.Emp;

public class TestDao extends BaseDao{
 public void search(){
  Session session=super.getSession();
  Emp emp=(Emp) session.get(Emp.class, 5);
  System.out.println(emp.getEid()+emp.getEname()
    +emp.getDept()+emp.getDept().getDname());
  
 }
 public void add(){
  Session session=super.getSession();  
  Dept d=new Dept();
  d.setDid(112);
  d.setDname("测试部2");
  Set set = d.getEmps();
  Emp e=new Emp();
  e.setEid(112);
  e.setEname("小二2");
  e.setJob("测试人员2");
  set.add(e);
  Transaction tr = session.beginTransaction();
  session.save(d);
  //Serializable s=set.add(e);
  //System.out.println(s);//true
  tr.commit();
  session.close();
  
 }
 public static void main(String[] args) {
  TestDao d=new TestDao();
  //d.search();
  d.add();
 }

}

 

 

4.控制台的sql语句

1.search()方法:在查询的时候:由于使用了对象.对象属性.属性,因此控制台把两个表的select语句都输出来了。那是由于在从表emp中的映射文件中写了fetch="select"属性
Hibernate:
    select
        emp0_.EID as EID1_0_,
        emp0_.DID as DID1_0_,
        emp0_.ENAME as ENAME1_0_,
        emp0_.JOB as JOB1_0_
    from
        CHU1.HIB_EMP emp0_
    where
        emp0_.EID=?
Hibernate:
    select
        dept0_.DID as DID0_0_,
        dept0_.DNAME as DNAME0_0_
    from
        CHU1.HIB_DEPT dept0_
    where
        dept0_.DID=?
  
2.search()方法:此时与1不同的是,在从表(emp)中的映射文件中的属性写了fetch="join",表明的是左连接查询。此时控制台只输出一条语句,明显效率提高了,是个左连接查询的语句。
Hibernate:
    select
        emp0_.EID as EID1_1_,
        emp0_.DID as DID1_1_,
        emp0_.ENAME as ENAME1_1_,
        emp0_.JOB as JOB1_1_,
        dept1_.DID as DID0_0_,
        dept1_.DNAME as DNAME0_0_
    from
        CHU1.HIB_EMP emp0_
    left outer join
        CHU1.HIB_DEPT dept1_
            on emp0_.DID=dept1_.DID
    where
        emp0_.EID=?
       
 添加操作:
 1.写完添加的方法:控制台只输出了一条sql语句,数据库中的dept(主表)中增加了一条记录,从表emp表中没有增加
 Hibernate:
    insert
    into
        CHU1.HIB_DEPT
        (DNAME, DID)
    values
        (?, ?)

2.在主表的映射文件中增加级联属性cascade=all。此时控制台产生4条sql语句。第一条是查看子表(select),第二条是添加主表(insert),第三条是添加子表(insert),第四条是填充子表的外键(update)。
并把数据库中的两个表个多了一条完整的记录。
Hibernate:
    select
        emp_.EID,
        emp_.DID as DID1_,
        emp_.ENAME as ENAME1_,
        emp_.JOB as JOB1_
    from
        CHU1.HIB_EMP emp_
    where
        emp_.EID=?
Hibernate:
    insert
    into
        CHU1.HIB_DEPT
        (DNAME, DID)
    values
        (?, ?)
Hibernate:
    insert
    into
        CHU1.HIB_EMP
        (DID, ENAME, JOB, EID)
    values
        (?, ?, ?, ?)
Hibernate:
    update
        CHU1.HIB_EMP
    set
        DID=?
    where
        EID=?

3.在主表的映射文件中加入 inverse="true"。此时控制台只产生了三条sql语句。因为在主表中使用了inverse="true",所以表示由从表控制关联关系,从表控制关联关系会避免产生多余代码。
我们现在这个项目测试的是双向关联(也就是在两个实体类上都加了主外键关系),因此当主表把控制权交给从表以后,由于从表里也有主外键关系,因此可以把两个表联系起来,因此添加的结果是数据库中产生两个完整的数据。
当我们测试单向关联的时候,由于只在主表的实体类中写了主外键关系(从表上没有主外键关系,不能主动与主表建立联系),所以当主表把控制权交给从表的时候  ,从表并不能跟主表产生主外键关系,因此数据库中的从表的外键仍然是null.
Hibernate:
    select
        emp_.EID,
        emp_.DID as DID1_,
        emp_.ENAME as ENAME1_,
        emp_.JOB as JOB1_
    from
        CHU1.HIB_EMP emp_
    where
        emp_.EID=?
Hibernate:
    insert
    into
        CHU1.HIB_DEPT
        (DNAME, DID)
    values
        (?, ?)
Hibernate:
    insert
    into
        CHU1.HIB_EMP
        (DID, ENAME, JOB, EID)
    values
        (?, ?, ?, ?)
  =-----------------------
  其他操作跟单向关联一样了。。。。。     
  

 

 

分享到:
评论

相关推荐

    hibernate主键实现一对一单向关联关系源码

    本主题将深入探讨如何使用Hibernate通过主键来实现一对一的单向关联关系,并提供相关的源码分析。 首先,我们需要理解一对一关联关系的基本概念。在数据库中,一对一关系意味着两个表中的每一条记录都对应另一表中...

    hibernate一对多,多对一,一对多双向关联

    “Hibernate 一对多,多对一,一对多双向关联”是指在Java持久化框架Hibernate中,实体间常见的三种关联关系。在数据库设计中,这种关联关系是常见的,例如一个用户可以有多个订单(一对多),一个订单对应一个用户...

    Hibernate双向一对一关联映射(注解版)

    在Hibernate中,一对一关联映射分为单向和双向。单向一对一映射通常涉及一个实体持有另一个实体的引用,而双向一对一映射则意味着两个实体都可以互相引用。这种关联关系在数据库层面通常通过主键外键约束来实现,但...

    hibernate 多对多全注解(单向关联、双向关联)

    hibernate关联映射注解多对多单向关联、

    hibernate多对多双向关联

    多对多双向关联 &lt;br&gt;注意映射规则: &lt;set name="roles" table="t_user_role"&gt;&lt;br&gt; &lt;key column="userid"/&gt;&lt;br&gt; &lt;many-to-many class="com.bjsxt.hibernate.Role" column="roleid"/&gt; &lt;/set&gt;&lt;br&gt; table...

    Hibernate一对一主键关联映射(单向关联)

    总结来说,Hibernate中的一对一主键关联映射允许两个实体共享同一个主键,实现单向关联时只需在依赖方添加对另一方的引用。在实际应用中,应根据业务需求谨慎选择关联类型,以确保数据的完整性和一致性。

    hibernate一对一之唯一外键关联(双向关联)

    - 虽然一对一关联提供了便利,但过多的一对一关联可能会影响性能,因为每次查询可能涉及多个表,增加数据库访问的复杂性。因此,应谨慎设计实体间的关系。 8. **实例应用** - 在实际项目中,一对一关联常用于用户...

    hibernate关联映射详解

    包含《多对多双向关联映射》《多对一单向关联映射》《多对一双向关联映射》《一对多单向关联映射》等文档,并有图解及例子,非常适合新手学习,尤其是刚刚接触hibernate,对映射关系不清楚的。。。。

    Hibernate关联映射

    9. Hibernate 一对一外键双向关联、主键双向关联、连接表双向关联、一对多外键双向关联、一对多连接表双向关联、多对多双向关联: 这些关联方式与单向关联类似,区别在于两个实体类都知道彼此的关联。在双向关联中...

    Hibernate一对多单向关联映射

    通过以上内容,我们对Hibernate中的一对多单向关联映射有了全面的理解,包括其配置方式、代码实现、使用技巧以及需要注意的细节。在实际项目开发中,正确理解和运用这些知识能够有效地提升数据操作的效率和代码的可...

    hibernate一对一关联关系

    在实体类之间,Hibernate支持多种关联关系,包括一对一(One-to-One)、一对多(One-to-Many)和多对多(Many-to-Many)。本资源主要探讨的是“hibernate一对一关联关系”。 一对一关联关系在现实世界中很常见,...

    Hibernate一对一唯一外键关联映射(单向关联)

    在Java的持久化框架Hibernate中,一对一(One-to-One)关联映射是常见的...以上就是关于Hibernate一对一唯一外键关联映射(单向关联)的详细说明。通过这种方式,我们可以轻松地在Java应用中处理数据库的一对一关系。

    hibernate多对多关联映射(单项关联)

    总的来说,这篇博客和相关代码示例为开发者提供了一个理解和实现Hibernate中多对多单向关联的起点,帮助他们更好地处理复杂的数据库关系映射。学习和实践这部分内容对于提升Java后端开发能力,特别是使用Hibernate...

    hibernate关联关系之一对一双向关联

    在Java持久化框架Hibernate中,一对一双向关联是一种常见的实体关系映射,它反映了数据库中的两个表之间一对一的对应关系。这种关联关系可以是单向的,也可以是双向的,而这里的"hibernate关联关系之一对一双向关联...

    Hibernate教程04_关系映射之一对一单向外键关联

    在Hibernate中,一对一关系有多种实现方式,包括单向和双向关联,以及外键在主表还是从表等不同形式。 **压缩包子文件的文件名称列表:s2sh_relation01_one2one_uni_fk** 这个文件名暗示了这是一组基于Spring、...

    hibernate one-to-one 一对一唯一外键关联映射_单向 and 双向

    Hibernate 一对一唯一外键关联映射详解 Hibernate是一种流行的Java持久层框架,提供了多种关联映射方式,其中一对一唯一外键关联映射是一种常见的关联方式。在本文中,我们将详细介绍Hibernate一对一唯一外键关联...

Global site tag (gtag.js) - Google Analytics