Hibernate fetch lazy cascade 的解释

2024-04-23 05:18

本文主要是介绍Hibernate fetch lazy cascade 的解释,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Hibernate 反向生成 产生BigInteger的解决方法:

你应该用的Oracle吧,不要用里面的number作为主键,数据库中使用long或者int.这样反响工程的到的主键就是Long或者Intger类型的了。

问题解决了,只要给主键加个精度就好了使用Number(20)

 
1.cascade是否执行级联操作

                     <set name="children" lazy="true" cascade="all">

   在保存主表的时候,如果没有保存从表信息,会抛出异常,如果设置了级联关系,可以自动先保存从表,在保存主表

    all: 所有情况下均进行关联操作,即save-update和delete。
    none: 所有情况下均不进行关联操作。这是默认值。
    save-update: 在执行save/update/saveOrUpdate时进行关联操作。

2.inverse指定哪一方不控制关联关系,一般在set上(1端不维护)

<set name="children" lazy="true" inverse="true">

3.lazy  :延迟加载

<class name=”mypack.Customer” table=”CUSTOMER” lazy=”false”>

laz    Lazy属性为false:立即检索,一次性访问有关联关系的所有表。

llaz   Lazy属性为true:(默认)延迟检索,只访问主表数据,从表数据不会立即访问,只有当用到从表的时候会自动访问。

Lazy的有效期:只有在session打开的时候才有效;session关闭后lazy就没效了。

4.fetch :抓取策略,类似于lazy

<class name=”mypack.Customer” table=”CUSTOMER” fetch =”join”>

fetch="join”:类似于lazy=false,一次性查完

fetch="select”:类似于lazy=true

 

 

 

 

Hibernate 的延迟加载(lazy load)本质上就是代理模式的应用

实体是Employee和Department,它们之间是多对一的关系。

Department类:

Java代码 复制代码 收藏代码
  1. public class Department { 
  2.     private int id; 
  3.     private String name; 
  4.  
  5.     public Department() { 
  6.     } 
  7.     public Department(String name) { 
  8.         this.name = name; 
  9.     } 
  10.     // getters and setters are omitted 
public class Department {private int id;private String name;public Department() {}public Department(String name) {this.name = name;}// getters and setters are omitted
}



Employee类:

Java代码 复制代码 收藏代码
  1. public class Employee { 
  2.     private int id; 
  3.     private String name; 
  4.     private Department department; 
  5.  
  6.     public Employee() { 
  7.     } 
  8.     public Employee(String name) { 
  9.         this.name = name; 
  10.     } 
  11.     // getters and setters are omitted 
public class Employee {private int id;private String name;private Department department;public Employee() {}public Employee(String name) {this.name = name;}// getters and setters are omitted



Department.hbm.xml:

Xml代码 复制代码 收藏代码
  1. <hibernate-mapping 
  2.     package="com.john.myhibernate.domain"> 
  3.  
  4.     <class name="Department"> 
  5.         <id name="id"> 
  6.             <generator class="native"/> 
  7.         </id> 
  8.         <property name="name" length="20" not-null="true"/> 
  9.     </class> 
  10. </hibernate-mapping> 



Employee.hbm.xml:

Xml代码 复制代码 收藏代码
  1. <hibernate-mapping package="com.john.myhibernate.domain"> 
  2.  
  3. <class name="Employee"> 
  4.     <id name="id"> 
  5.         <generator class="native"/> 
  6.     </id> 
  7.     <property name="name" length="20" not-null="true"/> 
  8.     <many-to-one name="department" column="department_id" class="Department" fetch="select"/> 
  9. </class> 
  10. </hibernate-mapping> 


many-to-one没有inverse属性,因为关系的维护是many的一方,不可能放弃对关系的维护。
many-to-one的lazy属性有三个取值:false, proxy, no-proxy。

1. 测试cascade属性:

Java代码 复制代码 收藏代码
  1. public void testSaveCascade() { 
  2.     Session s = null
  3.     Transaction tx = null
  4.      
  5.     Department depart = new Department(); 
  6.     depart.setName("FCI"); 
  7.      
  8.     Employee em1 = new Employee("John"); 
  9.     em1.setDepartment(depart); 
  10.      
  11.     Employee em2 = new Employee("Lucy"); 
  12.     em2.setDepartment(depart); 
  13.      
  14.     try
  15.         s = HibernateUtil.getSession(); 
  16.         tx = s.beginTransaction(); 
  17.         s.save(em1); 
  18.         s.save(em2); 
  19.         tx.commit(); 
  20.     } catch (HibernateException e) { 
  21.         tx.rollback(); 
  22.         e.printStackTrace(); 
  23.     } finally
  24.         if (s != null
  25.             s.close(); 
  26.     } 
	public void testSaveCascade() {Session s = null;Transaction tx = null;Department depart = new Department();depart.setName("FCI");Employee em1 = new Employee("John");em1.setDepartment(depart);Employee em2 = new Employee("Lucy");em2.setDepartment(depart);try {s = HibernateUtil.getSession();tx = s.beginTransaction();s.save(em1);s.save(em2);tx.commit();} catch (HibernateException e) {tx.rollback();e.printStackTrace();} finally {if (s != null)s.close();}}


结果是报org.hibernate.TransientObjectException异常,因为没有保存Department实例。

可以加cascade属性,解决问题:

Xml代码 复制代码 收藏代码
  1. <many-to-one name="department" column="department_id" class="Department" fetch="select" cascade="save-update"/> 



2. 测试fetch

Java代码 复制代码 收藏代码
  1. Session s = null
  2.  
  3. s = HibernateUtil.getSession(); 
  4. Employee em = (Employee) s.get(Employee.class, 2); 
  5. System.out.println(em.getName()); 
  6. System.out.println(em.getDepartment()); 
	Session s = null;s = HibernateUtil.getSession();Employee em = (Employee) s.get(Employee.class, 2);System.out.println(em.getName());System.out.println(em.getDepartment());


查询语句如下:
Hibernate: select employee0_.id as id1_0_, employee0_.name as name1_0_, employee0_.department as department1_0_, employee0_.skill as skill1_0_, employee0_.sell as sell1_0_, employee0_.type as type1_0_ from Employee employee0_ where employee0_.id=?

Hibernate: select department0_.id as id0_0_, department0_.name as name0_0_ from Department department0_ where department0_.id=?
因为fetch设置为select,所以对每个实体,都分别用一个SELECT语句

如果把fetch设置为join,也就是连表查询,只使用一个SELECT语句。如下:
Hibernate: select employee0_.id as id1_1_, employee0_.name as name1_1_, employee0_.department as department1_1_, employee0_.skill as skill1_1_, employee0_.sell as sell1_1_, employee0_.type as type1_1_, department1_.id as id0_0_, department1_.name as name0_0_ from Employee employee0_ left outer join Department department1_ on employee0_.department=department1_.id where employee0_.id=?

3. 测试lazy
当fetch为select时,设置lazy为proxy或者no-proxy。

Xml代码 复制代码 收藏代码
  1. <many-to-one name="department" column="department_id" class="Department" fetch="select" cascade="save-update" lazy="no-proxy"/> 


 

Java代码 复制代码 收藏代码
  1. Session s = null
  2.  
  3. s = HibernateUtil.getSession(); 
  4. Employee em = (Employee) s.get(Employee.class, 2); 
  5. s.close(); 
  6. System.out.println(em.getName()); 
  7. System.out.println(em.getDepartment()); 
	Session s = null;s = HibernateUtil.getSession();Employee em = (Employee) s.get(Employee.class, 2);s.close();System.out.println(em.getName());System.out.println(em.getDepartment());


结果是报org.hibernate.LazyInitializationException异常。
因为fetch为select,而且lazy为proxy或者no-proxy,所以开始仅仅查询Employee,当需要用SELECT语句查询Department时,Session已经关闭。

解决办法:
1. 设置lazy为false,hibernate会第一时间把Employee和Department查询出来。
   如果fetch为select,使用两个SELECT查询语句。
   如果fetch为join,使用一个SELECT连表查询语句。
2. 设置fetch为join,这时不管lazy的取值,hibernate会进行连表查询,把两个实体都查询出来。

 

Hibernate中的fetch, lazy, inverse和cascade

 

English Title:The Fetch in Hibernate, lazy, inverse and Cascade
1.fetch 和 lazy 主要用于级联查询(select) 而 inverse和cascade主要用于级联增、加删、除修

改(sava-update,delete)

2.想要删除父表中的记录,但希望子表中记录的外键引用值设为null的情况:

父表的映射文件应该如下配置:

<set name="emps" inverse="false" cascade="all">

<key>

<column name="DEPTNO" precision="2" scale="0" />

</key>

<one-to-many class="com.sino.hibernate.Emp" />

</set>

inverse="false"是必须的,cascade可有可无,并且子表的映射文件中inverse没必要设置,cascade也可以不

设置,如果设置就设置成为cascade="none"或者cascade="sava-update"

<many-to-one name="dept" class="com.sino.hibernate.Dept" fetch="select" cascade="save-update">

<column name="DEPTNO" precision="2" scale="0" />

</many-to-one>

3.关于级联查找对子表的持久化类进行查找的时候,会一起把子表持久化类中的父表持久化类的对象一起查询

出来,在页面中可以直接取值的情况:要把父表的映射文件中设置 lazy 属性如下:

<class name="com.sino.hibernate.Emp" table="EMP" schema="SCOTT" lazy="false">

这样就可以直接在页面中取值 (类似于这样的取值 client.cmanager.id)如果没有设置 lazy="false" 则会抛

出异常javax.servlet.ServletException: Exception thrown by getter for property cmanager.realName

of bean cl在Action中取值的话就会抛出 could not initialize proxy - the owning Session was closed

的异常

--------------------------------------------------------------------------------------------------

1、outer-join关键字(many-to-one的情况)

outer-join关键字有3个值,分别是true,false,auto,默认是auto。
true: 表示使用外连接抓取关联的内容,这里的意思是当使用load(OrderLineItem.class,"id")时,Hibernate只生成一条SQL语句将OrderLineItem与他的父亲Order全部初始化。

select * from OrderLineItem o left join Order p on o.OrderId=p.OrderId where o.OrderLineItem_Id=?

false:表示不使用外连接抓取关联的内容,当load(OrderLineItem.class,"id")时,Hibernate生成两条SQL语句,一条查询OrderLineItem表,另一条查询Order表。这样的好处是可以设置延迟加载,此处要将Order类设置为lazy=true。

select * from OrderLineItem o where o.OrderLineItem_Id=?
select * from Order p where p.OrderId=?

auto:具体是ture还是false看hibernate.cfg.xml中的配置

注意:如果使用HQL查询OrderLineItem,如 from OrderLineItem o where o.id='id',总是不使用外部抓取,及outer-join失效。

2、outer-join(集合)

由于集合可以设置lazy="true",所以lazy与outer-join不能同时为true,当lazy="true"时,outer-join将一直是false,如果lazy="false",则outer-join用法与1同

3、HQL语句会将POJO配置文件中的关联一并查询,即使在HQL语句中没有明确join

4、In HQL, the "fetch join" clause can be used for per-query specific outer join fetching. One important thing many people miss there, is that HQL queries will ignore the outer-join attribute you specified in your mapping. This makes it possible to configure the default loading behaviour of session.load() and session.get() and of objects loaded by navigating relationship. So if you specify

and then do
MyObject obj = session.createQuery("from MyObject").uniqueResult(); obj.getMySet().iterator().next();

you will still have an additional query and no outer-join. So you must explicily request the outer-join fetching:

MyObject obj = session.createQuery( "from MyObject mo left join fetch mo.mySet").uniqueResult();                                  

Another important thing to know is that you can only fetch one collection reference in a query. That means you can just use one fetch join. You can however fetch "one" references in addition, as this sample from the Hibernate Docs demonstrates:

from eg.Cat as cat inner join fetch cat.mate left join fetch cat.kittens

We have once considered lifting this limitation, but then decided against it, because using more than one fetch-join would be a bad idea generally: The generated ResultSet becomes huge and is a major performance loss.

So alltogether the "fetch join" clause is an important instrument Hibernate users should learn how to leverage, as it allows tuning the fetch behaviour of a certain use case.

5、join fetchjoin 的区别

如果HQL使用了连接,但是没有使用fetch关键字,则生成的SQL语句虽然有连接,但是并没有取连接表的数据,还是需要单独的sql取数据,也就是 select a,b,d...中没有连接表的字段

6、如果集合被声明为lazy=true,在HQL中如果显式的使用 join fetch 则延迟加载失效。

7、在one-to-many的one端显式设置fecth="join",则无论如何都采取预先抓取(生成一个SQl),延迟加载失效(生成两个SQL)

8、many-to-one的延迟加载是在配置文件的class标签设置lazy="true",one-to-many和many-to-many的延迟加载是在set标签中设置lazy="true"。而one-to-one不只要在calss标签设置lazy="true",而且要在one-to-one标签中设置constrained="true".

 

 

 

 

 

 

这篇关于Hibernate fetch lazy cascade 的解释的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/927880

相关文章

wolfSSL参数设置或配置项解释

1. wolfCrypt Only 解释:wolfCrypt是一个开源的、轻量级的、可移植的加密库,支持多种加密算法和协议。选择“wolfCrypt Only”意味着系统或应用将仅使用wolfCrypt库进行加密操作,而不依赖其他加密库。 2. DTLS Support 解释:DTLS(Datagram Transport Layer Security)是一种基于UDP的安全协议,提供类似于

java面试常见问题之Hibernate总结

1  Hibernate的检索方式 Ø  导航对象图检索(根据已经加载的对象,导航到其他对象。) Ø  OID检索(按照对象的OID来检索对象。) Ø  HQL检索(使用面向对象的HQL查询语言。) Ø  QBC检索(使用QBC(Qurey By Criteria)API来检索对象。 QBC/QBE离线/在线) Ø  本地SQL检索(使用本地数据库的SQL查询语句。) 包括Hibern

org.hibernate.hql.ast.QuerySyntaxException:is not mapped 异常总结

org.hibernate.hql.ast.QuerySyntaxException: User is not mapped [select u from User u where u.userName=:userName and u.password=:password] 上面的异常的抛出主要有几个方面:1、最容易想到的,就是你的from是实体类而不是表名,这个应该大家都知道,注意

Caused by: org.hibernate.MappingException: Could not determine type for: org.cgh.ssh.pojo.GoodsType,

MappingException:这个主要是类映射上的异常,Could not determine type for: org.cgh.ssh.pojo.GoodsType,这句话表示GoodsType这个类没有被映射到

Hibernate框架中,使用JDBC语法

/*** 调用存储过程* * @param PRONAME* @return*/public CallableStatement citePro(final String PRONAME){Session session = getCurrentSession();CallableStatement pro = session.doReturningWork(new ReturningWork<C

hibernate修改数据库已有的对象【简化操作】

陈科肇 直接上代码: /*** 更新新的数据并并未修改旧的数据* @param oldEntity 数据库存在的实体* @param newEntity 更改后的实体* @throws IllegalAccessException * @throws IllegalArgumentException */public void updateNew(T oldEntity,T newEntity

嵌入式技术的核心技术有哪些?请详细列举并解释每项技术的主要功能和应用场景。

嵌入式技术的核心技术包括处理器技术、IC技术和设计/验证技术。 1. 处理器技术    通用处理器:这类处理器适用于不同类型的应用,其主要特征是存储程序和通用的数据路径,使其能够处理各种计算任务。例如,在智能家居中,通用处理器可以用于控制和管理家庭设备,如灯光、空调和安全系统。    单用途处理器:这些处理器执行特定程序,如JPEG编解码器,专门用于视频信息的压缩或解压。在数字相机中,单用途

请解释Java Web应用中的前后端分离是什么?它有哪些好处?什么是Java Web中的Servlet过滤器?它有什么作用?

请解释Java Web应用中的前后端分离是什么?它有哪些好处? Java Web应用中的前后端分离 在Java Web应用中,前后端分离是一种开发模式,它将传统Web开发中紧密耦合的前端(用户界面)和后端(服务器端逻辑)代码进行分离,使得它们能够独立开发、测试、部署和维护。在这种模式下,前端通常通过HTTP请求与后端进行数据交换,后端则负责业务逻辑处理、数据库交互以及向前端提供RESTful

OpenStack:Glance共享与上传、Nova操作选项解释、Cinder操作技巧

目录 Glance member task Nova lock shelve rescue Cinder manage local-attach transfer backup-export 总结 原作者:int32bit,参考内容 从2013年开始折腾OpenStack也有好几年的时间了。在使用过程中,我发现有很多很有用的操作,但是却很少被提及。这里我暂不直接

OpenStack实例操作选项解释:启动和停止instance实例

关于启动和停止OpenStack实例 如果你想要启动和停止OpenStack实例时,有四种方法可以考虑。 管理员可以暂停、挂起、搁置、停止OpenStack 的计算实例。但是这些方法之间有什么不同之处? 目录 关于启动和停止OpenStack实例1.暂停和取消暂停实例2.挂起和恢复实例3.搁置(废弃)实例和取消废弃实例4.停止(删除)实例 1.暂停和取消暂停实例