9.27 Hibernate 完全大复习(全部)

   今天呢,我开始巩固下hibernate,当然还是跟着老师的讲课班,不过第二次听,那感觉就是不一样。早在过去蒙蒙懂懂,或者根本不知道的知识,全部回顾了解了一遍。     正所谓:书读百变,其义自见~!  太爽了,好开心~!  既然学,那就认真点。 此贴陆续把每次巩固的收获写上来的。

 

hibernate建立数据的的映射是完全可以通过eclips自动导入实现的,不过,基础还是要学的。知其解决方法,也要知其理才行~!

(~ o ~)~zZ  以下是收获:

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

xml形式的实体化映射:

 

*.hbm.xml
<hibernate-mapping>
<class name="实体化类名" table="表名">
   <id> 定义一个单主键,一个字段  属性作为实体类的主键
   <composite-id> 复合主键,多个字段  一组属性作为主键的定义方式 (主键类,实现序列化接口)
   <property> 字段---》属性的映射
  </class>

</hibernate-mapping>

 

练习:
emp-->dept   多对一  实现级联,添加,删除操作

 

首先写好emp和dept实体化类   emp为主表实体化类,所以emp有dept类的对象作为属性

接着写映射文件.hbm.xml

emp.hbm.xml如下:

dept.hbm.xml 如下:

 

 注意了:
在写pojo类时,*.hbm.xml写完之后,
还要将hibernate.cfg.xml之后加入
<mapping resource="cn/com/vo/Emp.hbm.xml" />
<mapping resource="cn/com/vo/Dept.hbm.xml" />类似这样的地址,实现pojo类在hibernate中的关系映射


(自动通过数据库导入的pojo类,eclips会自动将其地址加在hibernate.cfg.xml中

hbm2ddl.auto  这个在hibernate.cfg.xml中若是设置为true,则会根据映射关系在数据库中建立相应的table,假如数据有了~就不会建了。

 

cascade 有以下取值:

 

all : 所有操作都传递到相关联的对象
save-update 保存和更新传递到相关联的对象
delete 删除操作传递到相关联的对象
delete-orphan : 所有操作都传递到相关联的对象 并删除不再与父对象关联的对象。

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

级联删除这要找到数据库里的对象
用Emp emp=(Emp)session.get(Emp.class,7935");
  session.delete(emp);
这样会把emp表和相关联的dept表中的数据都删掉

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

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

 

从表---主表, 一对多的关系 (Onetomany)
hibernate 之中的集合有 list,map,set,bag 在一对多中经常用的时set--原理:去空值,去重复 (难怪呢)
类之间用set实现1 对n
配置上,
<one-to-many>

<set 的属性有 :>
name 属性名 
table 基于关联表的一对多关系
lazy="true/false"是否使用延迟加载技术——不错!true,没有用到关联表,则不会把关联表的信息搜出来,加载到缓存中,反之则会严重影响其性能~ 平时就要检查设置为true hibernate 3.0以后基本默认都是true
inverse(true/false) 关联关系由哪一方来维护 true--会根据从表实体类维护 false--会根据主表实体类维护
out-join
fetch
orderby 对关联表排序
---
 <key column="设置从表的外键字段'></key>
   <one-to-many class="从表实体类"/>

dept和emp是 1对多的关系

1 将dept实体类中加入emps 的set集,然后get/set方法

只需要将dept.hbm.xml改下即可:

 

 

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

<many-to-many> 多对多
例子:学生表 关联表 老师表
<set >的属性
name
table 中间表
<key column="中间表的与当前表所映射的外键字段">
<many-to-many culumn="中间表与关系的另一个表所建立的关联字段">

这里给出一个写在一起的many-to-many.hbm.xml

 

9.28 Hibernate 特殊表的关联 和  继承在hibernate 实现持久化的作用

1对1(外主)
1对多(中间表的)
继承,通过继承实现hibernate数据化的持久性操作

1对1关系
 第一种情况:a表引用b表的主键做外键具有唯一性约束
一个人对应一个地址
 person    address
-------------------
 p_id        a_id
 p_name      a_name
 a_id 外键+了唯一性约束
<many-to-one>
将many改成unique="true"
这个还是比较容易理解的。

 

 

第二中情况:a表引用b表的主键,在a表中既做主键,也做外键
person  address
----------------
p_id     a_id( 它是引用p_id的外键)
p_name   a_name
<one-to-one name="person" constrained="true"></one-to-one>只对主键进行描述

<one-to-one name="关联属性"> 在hibernate机制上描述两个实体1对1的关系
在操作时基于两个标的主键进行关联操作

基于该关系生成外键约束,或在某一键上加上某一属性
将contraonted="true"基于关系生成外键约束

column 描述关联字段(外键1对1关系,需要从主表这边描述的时候)

在它的<id 属性上>
  <genertor ,,
</id>

 

继承 在 hibernate中的作用
单表继承
在一个表中,通过一个标识来区分不同的数据类型,如type字段
用户有:学生,老师的例子不错啊
type属性 

<id...>
<discrimininator column="type类型的字段名 user_type">
</discrimininator>
<property...>
<subclass name="子类的名称" discriminator-value="标识字段为何值用该子类">
  <property name="teacherPhoto" column="teacher_photo"></property>
</subclass>

 继承在hibernate中的强势应用。这是单表的继承。
(类之间要有继承user被student 和teacher继承,配置如上)

 

关联表的继承。
用户表是双方都有的信息
学生,老师是自己独有的基础信息表
         用户
           |
           |
----------------------------
学生                    老师

配置中用<joined-subclass>---继承关联
<joined-subclass name="类名" table="表名">
<key clumn="关联外键字段"/>
<property name="" clumn=""/>
<many-to-one>..</...>
</joined-subclass>

 

 

 在上面的特殊表关联中,要体会其原理,还有对 unique="true"的理解。。这个理解真的挺重要的。

-------------------------------------------------
会用hibernate做项目和你懂hibernate完全是两个概念。。  是的,知道原理,写起代码不再是机械式的填充。

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

hibernate 持久化对象的生命周期
session作为持久化对象 有3个状态:
1 瞬时状态--由new关键字创建生成的对象状态,这种对象只会在内存中存在
            状态没有和数据库同步
            session中没有持久该对象的引用。(数据对象有可能丢失)
2 持久状态--对象是由session创建生成(如session.save()   session.update())
            session持有该对象引用后,将其状态也入到数据库中
3 离线状态--原本为持久状态的对象,因session.close() 即 session资源的关闭或者session清空实体对象的            引用,导致该对象不再由session管理,称作离线状态

new(新生)----get/load()--》持久状态 session.load是按主键检索数据,创建持有对象,以及持久对象的代理对象,返回的是代理对象。
  |
  |
  |
瞬时状态   ----save(),saveOrUpdate() ----》持久状态 ---evict()清除指定类型id clear()清除所有 close()-----》离线状态

离线对象---update(),saveOrUpdate(),lock()-->持久对象-----delete()--》瞬时状态

hibernate每一个类都要配置一个id,表示唯一性。那么session的表示id也只有一个,因为唯一性的存在,反之,数据的维护变的相当混乱
---------------------------------------------------------------------------------
Hibernate 检索语言 Hql
"from 类名 where 属性名=? ";将查询的结果封装成类名所对应的类实例对象

hql的关联查询:
select a.dept.deptno from Emp a 会根据实体类之间的关联,自动生成多表关联的sql
from Emp a where a.dept.dname=?     hql果然强大~!

Query query=session.createQuery("from Emp a where a.dept.dname=?");
query.setString(0,"教育部");
List<Emp> result=query.list();

在hql中一旦出现select子句,它肯能查询出的结果不按照from的类名封装对象,而是将结果放在Object[]中

Query query=session.createQuery("select a.dept.dname.a.sal from Emp a where a.dept.dname=?");
query.setString(0,"教育部");
List<Object[]> result=query.list();

如果这样你用着还不是很爽,可以利用hibernate实现有参的构造函数
Query query=session.createQuery("select new Emp(a.dept.dname.a.sal) from Emp a where a.dept.dname=?");//前提Emp有这样一个构造函数。
query.setString(0,"教育部");
List<Emp> result=query.list();

------------------------hibernate的强大在于你可以根据自己的需求设计出合理的方式完成检索操作~赞一个!

hql函数的使用:
聚合函数:avg()  sum() max() count()
查询关键字:distinct
集合操作函数:size(),minelement(),minindex(),maxindex()
Orderby  子句   group by 子句

例子:"from Dept a where size(a.emps)>=2";
---------------------------------------------------
连接查询
inner join  基于关联属性经行操作       inner join fetch

Query query=session.createQuery("from Dept dept inner join fetch dept.emps");
query.list();

Left outer join                     left outer join fecth
Right outer hoin 
Fetch只对inner join 和Left join 有效,Right outer join返回的是数组

-----------------------------
Query query=session.getNamedQuery("leftjoin");//这个是在xml的配置文件中写的cdata..这个问题解决就好了
query.list();

 

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

补充的知识:
标准查询
SQL查询
附:拦截器
    验证器
    锁策略--乐观锁,悲观锁的操作实现


标准查询---面向对象技术//这个没有sql,或者hql语句灵活,也没他们可读性强。这种语言只能作为辅助
 sql---------->对象的方法
Criteria cr=session.createCriteria(Emp.class);
cr.add(Expression.gt("sal",1000));//Expression是一个接口关于Criteria
List result=cr.list();
Emp emp=null;
for(int i=0;i<result.size();i++){
  emp=(Emp)result.get(i);
}


标准查询是基于Critera.add(查询条件)    查询条件由Experssion生成对象,根据不同的条件方法调度,生成对应的查询条件  Experssion方法有很多(eq,gt,like等)

-------------------
SQl 查询
sql语句的通用性很差。不同的版本oracle会使用到不同的sql语句语法。容易出错。 了解下了
而HQL则无需考虑这些。
SQLQuery sqlQuery=session.createSQLQuery("select ename,job,sal from emp where deptno=?");
Query query=session.getNamedQuery("leftjoin");//这个是在xml的配置文件中写的cdata..
sqlQuery.setInteger(0,10);
List list=sqlQuery.list();

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

拦截器--设置在sessionFactory之上,对session的持久化操作就行拦截
EmptyInterceptor  是个抽象类,我们的类需要实现它。
加入方法用eclipse的 overwrite中找到对应的方法即可!!!
onDelete()
onLoad()
onSave()
这是继承EmptyInterceptor 的类例如MyInterceptor
那么在实现类中 加入
Configuration  configuration = new Configuration().configure();
configuration.setInterceptor(new MyInterceptor())//这个是加入的。。!!!
SessionFactory sessionFactory = configuration.buildSessionFactory();
------------------------------------
验证器
验证接口--用于在数据的添加,修改时,在持久化操作之前,对数据有效性验证。
validator---validate() throws ValidationFailure
validate()可以终止原有的持久化操作。

-----------------------------------
锁策略 
锁机制 ---在并发访问下,保护资源有序的被使用
乐观锁  悲观锁
Hibernate 锁策略

Hibernate 内部锁机制

LockMode.NONE 无锁机制

LockMode.WRITE  hibernate 进行保存和更新时自动使用的锁机制。

LockMode.READ hibernate 读取纪录时的机制

悲观锁

整个数据处理过程中,将数据处于锁定
状态。悲观锁的实现,往往依靠数据库提供的锁机制

LockMode.UPGRADE

LockMode.UPGRADE_NOWAIT

 //相当于SQL(for update  中的 wait 或者nowaite)

实现机制如下:

Criteria.setLockMode

Query.setLockMode(Strng指hql语句中实体类的别名,LockMode.UPGRADE);
例如:
Query query=session.createQuery("from Emp a");
Query.setLockMode(a,LockMode.UPGRADE_NOWAIT);

Emp emp=(Emp)session.load(Emp.class,1,LockMode.UPGRADE_NOWAIT);//悲观锁

session.lock (实例对象,LockMode.READ);
缺点:资源开销大,一般不用这种,通常推荐使用乐观锁机制

乐观锁

更加宽松的加锁机制,悲观锁对长事务而言,开销往往无法承受;避免死锁。

实现机制:
Hibernate在o/R中映射特殊字段<timestamp>  或者<version>
采用特殊字段来做判断,平时操作不等待,但是保存或者更新时会进行判断。


Version

Dirty

ALL

主要介绍 Version

官方推荐的乐观锁实现策略,广泛使用,具有经验可借鉴性

实现举例:在每一次进行读取操作时取出版本号,在进行更新时同时刷新版本号,更新时只能更新低版本的数据,从而完成锁策略。 Hibernate 的 Session 会在等待用户交互时 ,Session 断开数据库连接。在整个应用事务过程中, Hibernate 使用单例 Session 和单例类来实现。

使用方法:

<class name="UserVo" table="uservo" schema="SPRINGDEV" optimistic-lock="version">

< 主键 >

<version name="version"  column="version"   type="java.lang.Integer"  /> 

同时数据库表中增加字段  version ,version无须设置,它会随着操作自动增加。

总结:在一般性的事务中,大可将锁机制抛开不用,这样不可否认增加了复杂性,你不得不面对不少的版本异常信息,只有在涉及关键业务如进行网上购物的付款等就必须进行加锁管理,当然推荐基于 version 的乐观锁管理。

 

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

hibernate 空值异常
     
     字段 ---》属性(基本数据类型)(包装类型,字符,日期)
  基本数据类型(int,double,char等)
        优:性能好
      缺点:不能接受空字段的值
  包装类:如Double,String,Date,Integer(就是java.lang.*这种包装类)
        优:能包装空值在内的所有有效数值
      缺点:资源开销大

提示:如果数据封装不上pojo类,有可能就是数据类型选择的错误!
----------------------------------------------------------------------------
这样的错误:
<c:forEach var="dt" items="${requestScope.list}">
   <tr>
  <td>${dt.empno}</td>
  <td>${dt.ename}</td>
  <td>${dt.job}</td>
  <td>${dt.sal}</td>
  <td>${dt.dept.deptno}</td>//可以显示的,它在emp表中作为外键<many-to-one name="dept".. ><column

name="DEPTNO"/></many-to-one>
  <td>${dt.dept.dname}</td>//这个不可以显示,它跟emp无任何关联。是dept独有的。会报session已经关闭。以下

有解决办法。
  </tr>
</c:forEach>

session是线程不安全,不能被多个线程同时使用
web-线程->请求处理  一个请求可以对应一个session线程。

利用java.lang.ThreadLocal  会为每一个当前线程分配一个独立的存储空间
Map<key,value>会为这一个线程保存独有的线程信息
以下为代码:
--------------------------------------------------------
view plaincopy to clipboardprint?
package cn.com.csuinfosoft.hibernate;  
 
import org.hibernate.Session;  
import org.hibernate.SessionFactory;  
import org.hibernate.cfg.Configuration;  
 
public class HibernateUtil {  
 
 private static SessionFactory sessionFactory = null;  
   
 private static ThreadLocal threadLocal = new ThreadLocal();  
   
 static {  
  try {  
   Configuration config = new Configuration().configure();  
   sessionFactory = config.buildSessionFactory();  
  } catch (Exception ex) {  
   ex.printStackTrace();  
  }  
 }  
   
 public static Session getSession() {  
  Session session = (Session)threadLocal.get();//获取当前线程对应的内存空间中,存储的对象  
  if(session == null) {  
   session = sessionFactory.openSession();  
   threadLocal.set(session);  
  }  
  return session;  
 }  
   
 public static void closeSession() {  
  Session session = (Session)threadLocal.get();  
  if(session != null) session.close();  
  threadLocal.set(null);  
 }  
   

package cn.com.csuinfosoft.hibernate;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

public class HibernateUtil {

 private static SessionFactory sessionFactory = null;
 
 private static ThreadLocal threadLocal = new ThreadLocal();
 
 static {
  try {
   Configuration config = new Configuration().configure();
   sessionFactory = config.buildSessionFactory();
  } catch (Exception ex) {
   ex.printStackTrace();
  }
 }
 
 public static Session getSession() {
  Session session = (Session)threadLocal.get();//获取当前线程对应的内存空间中,存储的对象
  if(session == null) {
   session = sessionFactory.openSession();
   threadLocal.set(session);
  }
  return session;
 }
 
 public static void closeSession() {
  Session session = (Session)threadLocal.get();
  if(session != null) session.close();
  threadLocal.set(null);
 }
 
}
 
//在实现类中通过 Session session=HibernateUtil.getSession()这样得到的session是在同一个请求中保持不变的


然后当我们需要在请求结束关闭这样个一session可以写filter文件:
-------------------------
view plaincopy to clipboardprint?
package cn.com.csuinfosoft.filter;  
 
import java.io.IOException;  
 
import javax.servlet.Filter;  
import javax.servlet.FilterChain;  
import javax.servlet.FilterConfig;  
import javax.servlet.ServletException;  
import javax.servlet.ServletRequest;  
import javax.servlet.ServletResponse;  
 
import cn.com.csuinfosoft.hibernate.HibernateUtil;  
 
public class HibernateFilter implements Filter {  
 
 public void destroy() {  
 
 }  
 
 public void doFilter(ServletRequest request, ServletResponse response,  
   FilterChain filterChain) throws IOException, ServletException {  
  try {  
   System.out.println("============ Filter try ====== Thread:" +   
 
Thread.currentThread().getName());  
   filterChain.doFilter(request, response);  
  } finally {  
   System.out.println("============ Filter finally ======Thread:" +   
 
Thread.currentThread().getName());  
   HibernateUtil.closeSession(); //每次请求结束前关闭Session  
  }  
    
 }  
 
 public void init(FilterConfig filterConfig) throws ServletException {  
    
 }  
 

package cn.com.csuinfosoft.filter;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

import cn.com.csuinfosoft.hibernate.HibernateUtil;

public class HibernateFilter implements Filter {

 public void destroy() {

 }

 public void doFilter(ServletRequest request, ServletResponse response,
   FilterChain filterChain) throws IOException, ServletException {
  try {
   System.out.println("============ Filter try ====== Thread:" +

Thread.currentThread().getName());
   filterChain.doFilter(request, response);
  } finally {
   System.out.println("============ Filter finally ======Thread:" +

Thread.currentThread().getName());
   HibernateUtil.closeSession(); //每次请求结束前关闭Session
  }
 
 }

 public void init(FilterConfig filterConfig) throws ServletException {
 
 }

}

 

最后将这样一个filter配置在web.xml中,是相当容易的。
----------------------------

 
补充:SessionFactory可以在监听器控制下, 是要在程序卸载的时候关闭掉。

在过去所学的线程中Thread 中获得当前线程方法为currentThread()

 hibernate的配置优化
<property name="jdbc.batch_size">30</property>   这个用于管理数据库批量处理的,如批量删除
<property name="jdbc.fetch_size">50</property> 在jdbc抓取数据时采用分批抓取,一次可以抓取50条

做一个简单 批量删除 实现,不是很难哦!

 

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

不懂得问题:

<class name="UserVo" table="uservo" schema="SPRINGDEV" optimistic-lock="version">

< 主键 >

<version name="version"  column="version"   type="java.lang.Integer"  /> 

</class>

 

解释下schema="SPRINGDEV" 和optimistic-lock="version":

1)其中<class name="UserVo" table="uservo" schema="SPRINGDEV" optimistic-lock="version">中的schema="SPRINGDEV"表示数据库的用户名。如果当前链接数据库的用户名称不是SPRINGDEV的话,实际操作中还是会用SPRINGDEV这个用户来操作。这就会产生一系列问题。

 

2)optimistic-lock属性有如下可选取值:
? none 无乐观锁
? version 通过版本机制实现乐观锁
? dirty 通过检查发生变动过的

 

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

 

Hibernate 关闭sessionFactory :

  关闭sessionFactory是应在服务器被关闭,程序被卸载时关闭,所以需要写一个sessionFactory特有的监听类,当服务器被关闭时,自动关闭sessionFactory.
写个监听类 实现ServletContextListener 在该类中关闭关闭sessionFactory ,以下就是:

 


将监听类配置在web.xml 中


 <listener>
  <listener-class>cn.com.csuinfosoft.listener.HibernateListener</listener-class>
 </listener>

 

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

 

---------------------------------------------------------------以下转载的,一些关键字的注意,配合着学习:

重点学习 Hibernate fetch lazy cascade inverse 关键字

 

Hibernate最让人头大的就是对集合的加载形式。
书看了N次了,还是没有真正理解Hibernate。所以下午专门做了下测试,对配置文件的意思加深了认识。

假设有两个表,Photos(一) --- picture(多)Photo包含picture集合

结论1: HQL代码 > fetch(配置) > lazy (配置)
结论2: 默认 lazy="true"
结论3: fetch 和 lazy 主要是用来级联查询的,   而 cascade 和 inverse 主要是用来级联插入和修改的

             fetch参数指定了关联对象抓取的方式是select查询还是join查询,select方式时先查询返回要查询的主体对象(列表),再根据关联外键id,每一个对象发一个select查询,获取关联的对象,形成n+1次查 询; 而join方式,主体对象和关联对象用一句外键关联的sql同时查询出来,不会形成多次查询。
如果你的关联对象是延迟加载的,它当然不会去查询关联对象。 另外,在hql查询中配置文件中设置的join方式是不起作用的(而在所有其他查询方式如get、criteria或再关联获取等等都是有效的),会使用select方式,除非你在hql中指定join fetch某个关联对象。fetch策略用于定义 get/load一个对象时,如何获取非lazy的对象/集合。 这些参数在Query中无效。

在某种特殊的场合下,fetch在hql中还是起作用的。
例如
现有message(回帖)-->topic(主贴)-->forum(版块) 的多级many-to-one结构:
第一级:message-->topic many-to-one配置lazy="false" fetch="join"
第二级:topic-->forum many-to-one配置lazy="false" fetch="join"
这时如果"from message",则第二级:topic-->forum中的fetch策略会起作用

查询抓取(默认的)在N+1查询的情况下是极其脆弱的,因此我们可能会要求在映射文档中定义使用连接抓取:

<set name="permissions"
fetch="join">
<key column="userId"/>
<one-to-many class="Permission"/>
</set
<many-to-one name="mother" class="Cat" fetch="join"/>
在映射文档中定义的抓取策略将会有产生以下影响:

通过get()或load()方法取得数据。

只有在关联之间进行导航时,才会隐式的取得数据(延迟抓取)。

条件查询

在映射文档中显式的声明 连接抓取做为抓取策略并不会影响到随后的HQL查询。

通常情况下,我们并不使用映射文档进行抓取策略的定制。更多的是,保持其默认值,然后在特定的事务中, 使用HQL的左连接抓取(left join fetch) 对其进行重载。这将通知 Hibernate在第一次查询中使用外部关联(outer join),直接得到其关联数据。 在条件查询 API中,应该调用 setFetchMode(FetchMode.JOIN)语句。


其实这并不能说明hql能够按照配置文件设置的join进行抓取,这时 第二级:topic-->forum 的抓取其实已经和hql没有关系了,因为前面已经产生了另一个select方式的抓取语句。
而是对象的关联获取,假如查询message时topic是设置为延迟加载的,那么在后面获取message.topic时,如topic.forum不延迟加载,那么topic-->forum会实现配置的join方式的抓取,这个显然和hql查询没有关系。

结论4: 如果你是用spring来帮你管理你的session, 并且是自动提交,延迟加载就等于没加载~_~(当然
                除非你手动重新打开session然后手动Hibernate.initialize(set);然后关闭session.
结论5:      cascade主要是简化了在代码中的级联更新和删除。
j结论6:老爸可以有多个孩子,一个孩子不能有多个老爸,而且老爸说的算, 孩子围着老爸转。
                所以Photos老爸要有权力所以 cascade 这个关键子都是送给老爸的, 也就是级联更新,
               老爸改姓了,儿子也得跟着改,呵呵。“不然,就没有零花钱咯”。
                而Picture儿子整体挨骂,但是还是要维护父子之间良好的关系,对老爸百依百顺,所
               以老爸就说,儿子,“关系,由你来维护(inverse="true") ,不然就不给零花钱。呵。”。
               <set name="pictures" inverse="true" cascade="all">
                    <key>
                       <column name="photosid" not-null="true" />
                    </key>
                 <one-to-many class="girl.domain.Picture" />
             </set>
               
测试代码:

    Photos p = ps.getById(1);
   Set<Picture> set = p.getPictures();
   for(Picture pic : set){
    System.out.println(pic.getId());
   }

配置文件的一部分:
       <set name="pictures" inverse="true" cascade="all" >
            <key>
                <column name="photosid" not-null="true" />
            </key>
            <one-to-many class="girl.domain.Picture" />
        </set>

测试过程会对配置文件不断修改:并且从来不曾手动重新打开session

测试结构:

当配置条件为 lazy=true 一句查询 测试代码中没有调用getPicture() 正常
Hibernate: select photos0_.id as id0_0_, photos0_.userid as userid0_0_, photos0_.typeid as typeid0_0_, photos0_.name as name0_0_, photos0_.createtime as createtime0_0_, photos0_.description as descript6_0_0_, photos0_.faceid as faceid0_0_, photos0_.uri as uri0_0_ from super.photos photos0_ where photos0_.id=?

lazy=true 一句查询 有getPicture()
Hibernate: select photos0_.id as id0_0_, photos0_.userid as userid0_0_, photos0_.typeid as typeid0_0_, photos0_.name as name0_0_, photos0_.createtime as createtime0_0_, photos0_.description as descript6_0_0_, photos0_.faceid as faceid0_0_, photos0_.uri as uri0_0_ from super.photos photos0_ where photos0_.id=?


lazy=true 一句查询 有getPicture() 并且访问了里面的元数Picture 且有异常抛出
Hibernate: select photos0_.id as id0_0_, photos0_.userid as userid0_0_, photos0_.typeid as typeid0_0_, photos0_.name as name0_0_, photos0_.createtime as createtime0_0_, photos0_.description as descript6_0_0_, photos0_.faceid as faceid0_0_, photos0_.uri as uri0_0_ from super.photos photos0_ where photos0_.id=?


lazy="false" 两句查询 肯定没问题,因为全部数据都个查了出来 所以怎么调用都正常
Hibernate: select photos0_.id as id0_0_, photos0_.userid as userid0_0_, photos0_.typeid as typeid0_0_, photos0_.name as name0_0_, photos0_.createtime as createtime0_0_, photos0_.description as descript6_0_0_, photos0_.faceid as faceid0_0_, photos0_.uri as uri0_0_ from super.photos photos0_ where photos0_.id=?
Hibernate: select pictures0_.photosid as photosid1_, pictures0_.id as id1_, pictures0_.id as id2_0_, pictures0_.photosid as photosid2_0_, pictures0_.name as name2_0_, pictures0_.clicked as clicked2_0_, pictures0_.uploaddate as uploaddate2_0_, pictures0_.size as size2_0_, pictures0_.description as descript7_2_0_, pictures0_.uri as uri2_0_ from super.picture pictures0_ where pictures0_.photosid=?


fetch="join" 一句查询 效果 == lazy="false" 呵呵,哪个效率高,我就不知道了。。。。。。。。。。。
Hibernate: select photos0_.id as id0_1_, photos0_.userid as userid0_1_, photos0_.typeid as typeid0_1_, photos0_.name as name0_1_, photos0_.createtime as createtime0_1_, photos0_.description as descript6_0_1_, photos0_.faceid as faceid0_1_, photos0_.uri as uri0_1_, pictures1_.photosid as photosid3_, pictures1_.id as id3_, pictures1_.id as id2_0_, pictures1_.photosid as photosid2_0_, pictures1_.name as name2_0_, pictures1_.clicked as clicked2_0_, pictures1_.uploaddate as uploaddate2_0_, pictures1_.size as size2_0_, pictures1_.description as descript7_2_0_, pictures1_.uri as uri2_0_ from super.photos photos0_ left outer join super.picture pictures1_ on photos0_.id=pictures1_.photosid where photos0_.id=?

不加fetch="join" 一句查询 没有getPicture() 正常
Hibernate: select photos0_.id as id0_0_, photos0_.userid as userid0_0_, photos0_.typeid as typeid0_0_, photos0_.name as name0_0_, photos0_.createtime as createtime0_0_, photos0_.description as descript6_0_0_, photos0_.faceid as faceid0_0_, photos0_.uri as uri0_0_ from super.photos photos0_ where photos0_.id=?

不加fetch="join" 一句查询 有getPicture() 正常
Hibernate: select photos0_.id as id0_0_, photos0_.userid as userid0_0_, photos0_.typeid as typeid0_0_, photos0_.name as name0_0_, photos0_.createtime as createtime0_0_, photos0_.description as descript6_0_0_, photos0_.faceid as faceid0_0_, photos0_.uri as uri0_0_ from super.photos photos0_ where photos0_.id=?

不加fetch="join" 一句查询 有getPicture() 并且访问里面的元素Picture的ID 有异常抛出
Hibernate: select photos0_.id as id0_0_, photos0_.userid as userid0_0_, photos0_.typeid as typeid0_0_, photos0_.name as name0_0_, photos0_.createtime as createtime0_0_, photos0_.description as descript6_0_0_, photos0_.faceid as faceid0_0_, photos0_.uri as uri0_0_ from super.photos photos0_ where photos0_.id=?

来个两兵交战 fetch="join" lazy="true" 呵呵 结果,一句查询, 结构正常 所以就当lazy不存在好了。 看来fetch 是老大。、、、、、、、、、、、、、
Hibernate: select photos0_.id as id0_1_, photos0_.userid as userid0_1_, photos0_.typeid as typeid0_1_, photos0_.name as name0_1_, photos0_.createtime as createtime0_1_, photos0_.description as descript6_0_1_, photos0_.faceid as faceid0_1_, photos0_.uri as uri0_1_, pictures1_.photosid as photosid3_, pictures1_.id as id3_, pictures1_.id as id2_0_, pictures1_.photosid as photosid2_0_, pictures1_.name as name2_0_, pictures1_.clicked as clicked2_0_, pictures1_.uploaddate as uploaddate2_0_, pictures1_.size as size2_0_, pictures1_.description as descript7_2_0_, pictures1_.uri as uri2_0_ from super.photos photos0_ left outer join super.picture pictures1_ on photos0_.id=pictures1_.photosid where photos0_.id=?

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值