`

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 多对多单向关联 Hibernate 一对一外键双向关联 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,对映射关系不清楚的。。。。

    hibernate核心,一对多,多对多映射讲解,看了就完全搞明白了

    hibernate核心,一对多,多对多映射讲解,看了就完全搞明白了

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

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

    hibernate学习笔记

    hibernate一对一主键关联映射(单向关联Person----&gt;IdCard) 8 hibernate一对一主键关联映射(双向关联Person&lt;----&gt;IdCard) 9 hibernate一对一唯一外键关联映射(单向关联Person----&gt;IdCard) 10 hibernate一对一...

    Hibernate_Annotation关联映射

    在EJB3规范中多对一这端几乎总是双向关联中的主体(owner)端,而一对多这端关联批注为@OneToMany(mappedBy...) @Entity Public class Troop{ @OneToMany(mappedBy=”troop”) Public Set&lt;Soldier&gt; getSoldiers(){ .....

    hibernate一对多与多对一

    该中有一对多,多对一,多对多,单向的双向都具有

    Hibernate学习笔记

    008 多对一 关联映射 009 一对一 主键关联映射_单向 010 一对一 主键关联映射_双向 011 一对一 唯一外键关联映射_单向 012 一对一 唯一外键关联映射_双向 013 session_flush 014 一对多关联映射 单向 015 一对多关联...

    Java的Hibernate框架中一对多的单向和双向关联映射

    建立对SQL语句的映射是Hibernate框架操作数据库的主要手段,这里我们列举实例来为大家讲解Java的Hibernate框架中一对多的单向和双向关联映射

    eshop1.0(ssh电子商城)

    6.配置商品到商品分类的多对一单向关联关系 7.配置会员到会员级别的多对一单向关联关系 8.配置会员到订单的一对多双向关联关系 9.配置会员到留言的一对多单向关联关系 10.配置管理员到留言的一对多单向关联关系 11....

    精通Java Web整合开发(第2版)

    12.4.5 多对一单向关联的annotation注解实现538 12.4.6 一对多双向关联的annotation注解实现540 12.4.7 一对多双向自身关联的annotation注解实现542 12.4.8 多对多单向关联的annotation注解实现543 12.4.9 多对多...

    精通 Hibernate:Java 对象持久化技术详解(第2版).part2

     7.1 建立多对一的单向关联关系  7.1.1 元素的not-null属性  7.1.2 级联保存和更新  7.2 映射一对多双向关联关系  7.2.1 元素的inverse属性  7.2.2 级联删除  7.2.3 父子关系  7.3 映射一对多双向自身关联...

    Hibernate_实体关联关系映射--学习总结

    Hibernate 实体关联关系映射 学习总结 把一对一 一对多 单向 双向 主键 外键 链接表等讲的比较清楚

    精通hibernate:对象持久化技术孙卫琴第二版part2

    7.1 建立多对一的单向关联关系 148 7.1.1 [many-to-one]元素的not-null属性 153 7.1.2 级联保存和更新 155 7.2 映射一对多双向关联关系 156 7.2.1 [set]元素的inverse属性 161 7.2.2 级联删除 163 7.2.3 父子...

    Hibernate+中文文档

    7.5.1. 一对多(one to many) /多对一( many to one) 7.5.2. 一对一(one to one) 7.5.3. 多对多(many to many) 7.6. 更复杂的关联映射 8. 组件(Component)映射 8.1. 依赖对象(Dependent objects) ...

Global site tag (gtag.js) - Google Analytics