关于hibernate的理解及用法 关于hibernate的理解及用法 我想听听大家 是如何学习这个的 说下大家的见解 应该怎么去理解和学习呢 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 如果连 JDBC 都用不熟的话,不建议去看 Hibernate 什么的。 hibernate 入门就容易...想精通就难了... 首先要有JDBC的基础才行~然后先看看视频,做做实例,然后再去看看相关的书。 有数据库基础的学起来就好一些,Hibernate入门简单,想搞清楚到底是为什么那么配置的要下点功夫,建议先看书,再做一些小练习 HIBERNATE //冬眠 Hibernate是一个Java持久化解决方案,对象-关系映射工具。要学找一本在下一个和书上所说的工具慢慢的就应该会拉(数据库要回,Jdbc要回)。 ORM 对象关系模型将数据库中的表映射为对象 并提供了 对对象的持久化 缓存等基本的功能提高效率另外 Hibernate 是jdbc的进一步封装 并提供了hbm2java hmb2ddl java2hbm 等基本的工具供开发者使用 想用大腿想想为什么要连接数据库、应该怎样连数据库???然后你再去看看hibernate就明白了。不要动不动就使命的翻书。关键在于思维 hibernate是一个持久层的ORM框架,主要是对象关系模型。。LZ最好是先对jdbc操作熟练了再去学习hibernate... 看看视频,到网上查些关于hibernate的资料,,了解hibernate里面的关联关系(一对多,多对多,一对一),掌握几个重点的接口 session query Transaction Critira 还有一点要学习的是hql语言,hibernate查询语言。 最好还是先了解JDBC是如何工作的,再去学习Hibernate 这时我的总结:O/R映射框架 反射技术 优点: 1.提高生产力,不用再写sql语句,不用遍历结果集,代码量减少, 2.使开发更对象化了,只要操纵session对象save方法就保存数据了 3.移植性好,也就是方言的配置,适配器的配置, 4.支持透明持久化,实体没有侵入性,可以复用, 试用hibernate先建立对象模型,也就是领域模型,再建立映射关系,都是一对象为中心 注意:这里是斜杠啊<mapping resource="com/landy/hibernate/User.hbm.xml"/> hibernate的映射工具: 1.Configuration(根启动) cfg=new Configuration.configure();------>读取hibernate的配置文件hibernate.cfg.xml,加入内存 2.SessionFactory factory=cfg.bulidSessionFactory();存储sql语句和映射源数据(连接池) ,SessionFactory适合数据库绑定的,一个数据库对应一个Sessionfactory,他是重量级的对象,就是创建比较耗时,消耗资源,最好只创建一次,他是线程安全的,可以对个线程用它,SessionFactory和二级缓存相关, 3.Session 存放当前工作单元所加载的对象,他不同于Connection,是有SessionFactory创建出来的,他对Connection进行了封装,Session他管理了缓存,对实体对象生命周期管理,一般是一个业务对应一个Session, Session用完后必须关闭,是非线程安全的,Session和一级缓存相关 hibernate核心接口: 1.JNDI Java名称和目录接口,统一管理,不依赖具体实现,解决了耦合 2.JDBC Java数据库连接,它处理本地事务,单一数据库,能保证原子性,但是跨数据库,跨资源,JDBC就不能保证了, 3.JTA Java事务API,保证跨数据库,跨资源的事务处理,他是两阶段数据处理,先是日志再更新,JTA是个容器, 4.Query 查询接口,支持hql和sql 5.Interceptor 拦截器,没有浸入性,他能将我们对实体类进行保存,删除前后的事件能侦听到, 6.UserType 转换器的概念,用户可自定义类, 持久化对象的生命周期:Transient(瞬时的),Persistent(持久的),Detached(离线的) 1.Transient *在数据库中没有与之匹配的数据 *没有纳入Session的管理 2.Persistent *在数据库中有与之匹配的数据 *纳入了Session的管理 *在清理缓存(脏数据检查)的时候,会和数据库同步 3.Detached *在数据库中有与之匹配的数据---------->只有数据库中有了才能update处理 *没有纳入Session管理 Session的load()方法 实现了lazy,懒加载或延迟加载,按OID检索,只有正真使用这个对象时才加载(发出sql语句),hibernate延迟加载实现原理是代理方式, 正真使用时对象就是persistent状态了,hibernate会自动和数据库同步,采用load在加载数据时,如果数据库中没有相应的数据,那么抛ObectNotFoundException异常, Session的get()方法 在加载时马上发出sql语句,加载对象,不会有延迟,当查询数据不存在的数据时,返回null,并不抛出异常 一般是先加载在修改,删除,也就是不要手动构造detached状态, 有许多的批量的处理就不太试用hibernate域对象之间的关系 1.关联:类之间的引用关系,以属性申明体现 ------>一对一,一对多,多对一,多对多 2.依赖:类之间访问关系,类中的方法 3.聚集:生命周期(逻辑上的约束) 4.一般化(泛化)继承 主键生成策略: assigned 自然主键:手动赋值 native 动态的选择合适的标示符生成器,OREACL用到的序列hibernate_sequence sequence identity SQLServer,MYSQL hilo 加一取走 increment:拿来加一 access=“property|filed”(访问级别,默认property) inverse 让缓存忽略set集合的变化,只关心one方,在双向关联时通常都会更新两次,inverse=true 在映射一对多的双向关联关系时,应该在one方把inverse属性设为true,one方有集合,这可以提高性能。在建立两个对象的关联时, 应该同时修改关联两端的相应属性: Customer.getOrders().add(order); Order.setCustomer(customer);这样才会使程序更加健壮,提高业务逻辑层的独立性,使业务逻辑层的程序代码不受Hibernate实现类的影响。 同理,当删除双向关联的关系时,也应该修改关联两端的对象的相应属性: Customer.getOrders().remove(order); Order.setCustomer(null); 级联关系 cascade="save-update" 关联关系的级联程度,主体改变后客体按照级联程度也进行保存更新, 双向关联时两方同时进行,防止数据的不一致,关联关系的维护hibernate自动做了,所以在进行保存更新时只保存一方就行了,而和她关联的hibernate 机动保存更新了,这就是级联,级联操作在开发中慎用, 级联删除,利用jdbc删除有外键约束,利用程序删除就会被级联一起删除(更新),hibernate执行update语句将外键置为null来解除关联, 如想删除不再关联的对象,就将cascade="all-delete-orphan" 父子关系:cascade="all-delete-orphan" 子代不能删除父代,只能删除和父代关联的子代;更强的约束,将非法数据删除,关联关系的级别就不是更新了,就直接删除操作就是没有对应的客户的订单也删除,对应的是删除操作,但原来是null的,他不会删除 多对一关联关系: 1.cascade属性为save-update的话,可实现自动持久化所关联的对象。 2.<many-to-one> 一对多关联关系: 1.<set name=“orders” cascade=“save-update”> <key column=“CUSTOMER_ID” /> <one-to-many class=“..Order” /> </set> name:设定待映射持久化类的属性名。 cascade:设定级联操作的程度。 key子属性:设定与所关联的持久化类对应的标的外键。one-to-many子属性:设定所关联的持久化类。 hibernate数据操作,面向对象: 1.插入 save() 对象加入缓存,成为持久化对象 2.更新 update() 将游离对象转变为持久化对象。不论对象属性是否发生变化,该方法都会执行update操作。如果希望仅当属性变化时才执行update语句的话可进行如下配置:(还要看具体业务了,不一定打开就好) <class name=“…” table=“…” select-before-update=“true”> ----------------------更新之前先查询,只更新改变了的, Session的update操作方法盲目的激活触发器, 如果游离状态的对象的属性和数据库一致,则更新操作是多余的。为避免这种情况:<class name=“” table=“” select-before-update=“true”> ……</class> 3.查询 load(Class,id) 根据OID在缓存中查询,类型,OID 4.删除 delete() 如果参数是持久化对象,就执行一个delete语句,若为游离对象,先使游离对象被session关联,使他变为持久化对象,然后计划执行一个delete语句。 5.批量删除 **hibernate 3.0支持批量删除 //只是创建除了删除条件,还没有执行 Query c=s.createQuery("delete from Customer c where c.id < 4");-------->用到Hql //执行 c.executeUpdate(); 6. Transaction.commit(); //提交 先清理缓存,然后向数据库提交事务, 在提交前Session有个清理缓存的模式setFluseMode(FlushMode.AUTO/COMMIT/NEVER), 模式设置为NEVER时,只有再调用flush()方法时才会提交到数据库中, 7. Session.flush(); //清理 缓存,让数据库和缓存同步,将缓存的变化反应到数据库中,但不提交,不提交就可以回滚, 8. Session.refresh(); //刷新 缓存,让缓存和数据库同步,取数据库中变化来更新缓存,执行查询操作, 9. Session.clear() //清空 缓存,将缓存中的引用全销毁,但引用的对象不一定被销毁,要看对象是否还有其他的引用, 10. Session.delete(d):将对象从Session中和记录中删除,将对象变为临时态,11. Session.evict(c):将持久态对象转变成游离的状态,将对象单纯的从缓存中删除,并不对应删除记录的操作,12. Session.saveOrUpdate():调用此方法时oid为null时肯定是save操作,如果oid类型定义为基本数据类型,那默认值为0,就不能是save操作,那怎么让oid是基本数据类的数据有插入操作,在配置文件中将id有个属性unsaved-value=“0”,这样就将oid为基本数据类型的记录调用saveOrUpdate方法时可以是save操作。 Session的save,update,saveOrUpdate方法都是将非持久化对象与Session关联让他们变成持久化对象, 缓存里的对象根据快照来查看数据是否有变化,只有来自数据库时才做快照(load),触发器:在服务器执行,(数据库中执行)Session.save(c);Session.flush(); //执行后,进行更新数据库操作,触发了触发器,在application端并不知道,Session.refresh(c); //缓存与数据库同步触发器的行为导致缓存与数据库中的数据不一致。解决办法是执行完操作后,立即调用session的flush方法和refresh方法,迫使缓存与数据库同步。Session的update操作方法盲目的激活触发器,如果游离状态的对象的属性和数据库一致,则更新操作是多余的。为避免这种情况:<class name=“” table=“” select-before-update=“true”> ……</class>select-before-update的作用 1.更新没有修改的数据2.盲目更新激活触发器映射组成关系:<compont name=“homeaddress” class=“mypack.Address”> 他是值类型, component可以嵌套, 持久化类的属性分为两种:值(value)类型和实体类型(entity)类型。值类型没有OID,不能被单独持久化,他的生命周期依赖于所属的持久化类的对象的生命周期,组件类型就是一种值类型;实体类型有OID,可单独持久化。 在组合类型中save时没有赋值,在数据库中将会存入null,当查询时就会报空指针异常,因此要判断如果null就new一个然后添加上 类级别的检索:当查询对象的时候hibernate什么时候查询对象所对应的表,load受影响 立即检索:查询表,也就是在缓存里没有,他马上就查询库 延迟检索:只有正真访问对象,在内存里创建代理对象, 他先检查缓存里,缓存里没有,他并不立即查询库 <class name="cn.itcast.hibernate.domain.Customer" table="hib_customers" lazy="true"> 代理类是用反射技术动态生成的一个新类,他继承了客户类,代理对象他能够监控Session是否关闭,在Session关闭之前你访问代理对象的有效属性时,就会触发代理对象去访问数据库的事件,进行查询操作,将结果赋给代理对象的属性,这个过程就是初始化代理对象,只有延迟检索才会有代理对象的概念,代理对象在Session持久化时并没有赋初值,Session关闭后再去初始化,去查库,然而连接已关闭了,报 延迟初始化异常,可以通过下面方法进行初始化: 两边都是外连接,理论是打印出一条里面有两次外连接的语句,这在2.0是符合的,但这样会降低性能,但在3.0打印出两条语句,目的优化,忽略了第二次迫切左外连接检索,采用和lazy保持一致的检索,lazy=flase就立即,lazy=true就延迟。Hql语句忽略了迫切左外检索,他与lazy保持一致set批量立即检索 批量的检索用batch-size,和lazy来设置,Hql语句忽略了迫切左外检索,他与lazy保持一致,降低和数据库的交互次数:<set batch-size=“ 条数”>设置一次检索的条数,一般在3-10之间批量延迟检索: 用Hql语句查询,只要将lazy=true,就是延迟检索了Many-to-one的批量检索,orders集合对应几个客户,一次查一个客户,要查询多次,设置一次可以查询多个客户,应该在orders对端(客户)的类级别进行设置: One-to-one: 外键关联一端:用多对一模拟一对多, 一对一要加上unique=“true”属性另一端: property-ref属性的参考,参考对端类的映射属性主键关联:一端: 另一端: Many-to-many:; 两边关系对等,映射多对多关联关系时一定要将一端的inverse属性打开,避免都对关联表进行维护,只有一方来维护:inverse=TRUE 解除关系 Hibernate.properties配置文件 access:设置hibernate访问级别,默认是propertyhibernate访问机制: 代理主键, increment 从数据库中拿开加一;因此在多进程,集群环境下就不能使用incrementhilo 在数据库加一带走,Oracle:hibernate¬_sequence(native) ;自然主键:class=“assigned”; 联合主键: 可以定义一个联合主键类 Cascade=”delete” :级联删除 ,当只打开inverse时就会让缓存忽略集合的变化, delete方法,将持久对象,将对象的引用从Session缓存中删除,并且对应sql删除语句将db中的记录也删除,让对象成为临时态evict方法,将Session缓存中的对象清除,但没有将DB中的数据删除的sql语句,是对象进入游离态 已经在Session中的记录就没有意义调用save,updat。Saveorupda方法 HQL和QBC 排序 分页 父类 子类 继承关系,可以将子类存入一个表中,这样要有区分符 乐观所 在javabean中设置一个version的字段,配置文件配置如下: 悲观锁二级缓: 配置二级缓存,一般在hibernate.cfg.xml中配置,可以为每个配置 使用二级缓存插件EHCache ehcache.xml配置: 找个青蛙研究,问它是怎么hibernate的 只有搞清楚了JDBC,才知道HIBERNATE的好处,建议楼主从JDBC开始,这样才能更好的理解Hibernate. 什么事都是一步一步来 ,我刚开始学JDBC的时候,觉得挺好的 ,已至于转到Hibernate觉得不如JDBC,后来用多了Hibernate,觉得它太强大了,一般都是只学HQL,只对实体对象进行操作,而不用理会数据库。配置好就OK了!加油 hibernate,用什么就学了什么。。 页面input框的name传到后台,通过request获取name时,有时出现name丢失问题 帮我看看这个动画程序!! 用spring做队列 高手来~~~~ LOG4J的问题 关于在java实现 发送xml的功能,有点像soap??? jquery ajax不是很理解 HTML中文件控件file WebLogic+JBuliderX怎么配置?不会一直要手动吧! 利用jbuilder 开发jsp程序 谁可以告诉我怎样把弹出菜单加到树控件中去吗? 请问,如何在tomcat启动时把数据加载到内存中?具体代码要怎么实现? struts2 时间类型,页面表单传值到action的接收问题
HIBERNATE //冬眠
要学找一本在下一个和书上所说的工具
慢慢的就应该会拉(数据库要回,Jdbc要回)。
缓存等基本的功能提高效率
另外 Hibernate 是jdbc的进一步封装
并提供了hbm2java hmb2ddl java2hbm 等基本的工具供开发者使用
然后你再去看看hibernate就明白了。不要动不动就使命的翻书。关键在于思维
2.使开发更对象化了,只要操纵session对象save方法就保存数据了
3.移植性好,也就是方言的配置,适配器的配置,
4.支持透明持久化,实体没有侵入性,可以复用,
试用hibernate先建立对象模型,也就是领域模型,再建立映射关系,都是一对象为中心
注意:这里是斜杠啊<mapping resource="com/landy/hibernate/User.hbm.xml"/>
hibernate的映射工具:
1.Configuration(根启动) cfg=new Configuration.configure();------>读取hibernate的配置文件hibernate.cfg.xml,加入内存
2.SessionFactory factory=cfg.bulidSessionFactory();存储sql语句和映射源数据(连接池) ,SessionFactory适合数据库绑定的,一个数据库对应一个Sessionfactory,他是重量级的对象,就是创建比较耗时,消耗资源,最好只创建一次,他是线程安全的,可以对个线程用它,SessionFactory和二级缓存相关,
3.Session 存放当前工作单元所加载的对象,他不同于Connection,是有SessionFactory创建出来的,他对Connection进行了封装,Session他管理了缓存,对实体对象生命周期管理,一般是一个业务对应一个Session, Session用完后必须关闭,是非线程安全的,Session和一级缓存相关
hibernate核心接口:
1.JNDI Java名称和目录接口,统一管理,不依赖具体实现,解决了耦合
2.JDBC Java数据库连接,它处理本地事务,单一数据库,能保证原子性,但是跨数据库,跨资源,JDBC就不能保证了,
3.JTA Java事务API,保证跨数据库,跨资源的事务处理,他是两阶段数据处理,先是日志再更新,JTA是个容器,
4.Query 查询接口,支持hql和sql
5.Interceptor 拦截器,没有浸入性,他能将我们对实体类进行保存,删除前后的事件能侦听到,
6.UserType 转换器的概念,用户可自定义类,
持久化对象的生命周期:Transient(瞬时的),Persistent(持久的),Detached(离线的)
1.Transient *在数据库中没有与之匹配的数据
*没有纳入Session的管理
2.Persistent *在数据库中有与之匹配的数据
*纳入了Session的管理
*在清理缓存(脏数据检查)的时候,会和数据库同步
3.Detached *在数据库中有与之匹配的数据---------->只有数据库中有了才能update处理
*没有纳入Session管理
Session的load()方法 实现了lazy,懒加载或延迟加载,按OID检索,只有正真使用这个对象时才加载(发出sql语句),hibernate延迟加载实现原理是代理方式,
正真使用时对象就是persistent状态了,hibernate会自动和数据库同步,采用load在加载数据时,如果数据库中没有相应的数据,那么抛ObectNotFoundException异常, Session的get()方法 在加载时马上发出sql语句,加载对象,不会有延迟,当查询数据不存在的数据时,返回null,并不抛出异常
一般是先加载在修改,删除,也就是不要手动构造detached状态, 有许多的批量的处理就不太试用hibernate
域对象之间的关系
1.关联:类之间的引用关系,以属性申明体现 ------>一对一,一对多,多对一,多对多
2.依赖:类之间访问关系,类中的方法
3.聚集:生命周期(逻辑上的约束)
4.一般化(泛化)继承
主键生成策略:
assigned 自然主键:手动赋值
native 动态的选择合适的标示符生成器,OREACL用到的序列hibernate_sequence
sequence
identity SQLServer,MYSQL
hilo 加一取走
increment:拿来加一
access=“property|filed”(访问级别,默认property)
inverse 让缓存忽略set集合的变化,只关心one方,在双向关联时通常都会更新两次,inverse=true
在映射一对多的双向关联关系时,应该在one方把inverse属性设为true,one方有集合,这可以提高性能。在建立两个对象的关联时,
应该同时修改关联两端的相应属性:
Customer.getOrders().add(order);
Order.setCustomer(customer);这样才会使程序更加健壮,提高业务逻辑层的独立性,使业务逻辑层的程序代码不受Hibernate实现类的影响。
同理,当删除双向关联的关系时,也应该修改关联两端的对象的相应属性:
Customer.getOrders().remove(order);
Order.setCustomer(null);
级联关系 cascade="save-update" 关联关系的级联程度,主体改变后客体按照级联程度也进行保存更新,
双向关联时两方同时进行,防止数据的不一致,关联关系的维护hibernate自动做了,所以在进行保存更新时只保存一方就行了,而和她关联的hibernate
机动保存更新了,这就是级联,级联操作在开发中慎用,
级联删除,利用jdbc删除有外键约束,利用程序删除就会被级联一起删除(更新),hibernate执行update语句将外键置为null来解除关联,
如想删除不再关联的对象,就将cascade="all-delete-orphan"
父子关系:cascade="all-delete-orphan" 子代不能删除父代,只能删除和父代关联的子代;更强的约束,将非法数据删除,关联关系的级别就不是更新了,就直接删除操作
就是没有对应的客户的订单也删除,对应的是删除操作,但原来是null的,他不会删除
多对一关联关系:
1.cascade属性为save-update的话,可实现自动持久化所关联的对象。
2.<many-to-one>
一对多关联关系:
1.<set name=“orders” cascade=“save-update”>
<key column=“CUSTOMER_ID” />
<one-to-many class=“..Order” />
</set>
name:设定待映射持久化类的属性名。
cascade:设定级联操作的程度。
key子属性:设定与所关联的持久化类对应的标的外键。one-to-many子属性:设定所关联的持久化类。
1.插入 save()
对象加入缓存,成为持久化对象
2.更新 update() 将游离对象转变为持久化对象。不论对象属性是否发生变化,该方法都会执行update操作。如果希望仅当属性变化时才执行update语句的话可进行如下配置:(还要看具体业务了,不一定打开就好)
<class name=“…”
table=“…”
select-before-update=“true”> ----------------------更新之前先查询,只更新改变了的,
Session的update操作方法盲目的激活触发器, 如果游离状态的对象的属性和数据库一致,则更新操作是多余的。为避免这种情况:
<class name=“” table=“” select-before-update=“true”>
……
</class> 3.查询 load(Class,id)
根据OID在缓存中查询,类型,OID 4.删除 delete()
如果参数是持久化对象,就执行一个delete语句,若为游离对象,先使游离对象被session关联,使他变为持久化对象,然后计划执行一个delete语句。 5.批量删除 **hibernate 3.0支持批量删除
//只是创建除了删除条件,还没有执行
Query c=s.createQuery("delete from Customer c where c.id < 4");-------->用到Hql
//执行
c.executeUpdate();
6. Transaction.commit(); //提交 先清理缓存,然后向数据库提交事务, 在提交前Session有个清理缓存的模式setFluseMode(FlushMode.AUTO/COMMIT/NEVER),
模式设置为NEVER时,只有再调用flush()方法时才会提交到数据库中, 7. Session.flush(); //清理 缓存,让数据库和缓存同步,将缓存的变化反应到数据库中,但不提交,不提交就可以回滚, 8. Session.refresh(); //刷新 缓存,让缓存和数据库同步,取数据库中变化来更新缓存,执行查询操作, 9. Session.clear() //清空 缓存,将缓存中的引用全销毁,但引用的对象不一定被销毁,要看对象是否还有其他的引用,
10. Session.delete(d):将对象从Session中和记录中删除,将对象变为临时态,
11. Session.evict(c):将持久态对象转变成游离的状态,将对象单纯的从缓存中删除,并不对应删除记录的操作,
12. Session.saveOrUpdate():调用此方法时oid为null时肯定是save操作,如果oid类型定义为基本数据类型,那默认值为0,就不能是save操作,那怎么让oid是基本数据类的数据有插入操作,在配置文件中将id有个属性unsaved-value=“0”,这样就将oid为基本数据类型的记录调用saveOrUpdate方法时可以是save操作。
Session的save,update,saveOrUpdate方法都是将非持久化对象与Session关联让他们变成持久化对象, 缓存里的对象根据快照来查看数据是否有变化,只有来自数据库时才做快照(load),触发器:在服务器执行,(数据库中执行)
Session.save(c);
Session.flush(); //执行后,进行更新数据库操作,触发了触发器,在application端并不知道,
Session.refresh(c); //缓存与数据库同步
触发器的行为导致缓存与数据库中的数据不一致。解决办法是执行完操作后,立即调用session的flush方法和refresh方法,迫使缓存与数据库同步。Session的update操作方法盲目的激活触发器,如果游离状态的对象的属性和数据库一致,则更新操作是多余的。为避免这种情况:
<class name=“” table=“” select-before-update=“true”>
……
</class>select-before-update的作用 1.更新没有修改的数据
2.盲目更新激活触发器映射组成关系:<compont name=“homeaddress” class=“mypack.Address”> 他是值类型, component可以嵌套,
持久化类的属性分为两种:值(value)类型和实体类型(entity)类型。值类型没有OID,不能被单独持久化,他的生命周期依赖于所属的持久化类的对象的生命周期,组件类型就是一种值类型;实体类型有OID,可单独持久化。 在组合类型中save时没有赋值,在数据库中将会存入null,当查询时就会报空指针异常,因此要判断如果null就new一个然后添加上
类级别的检索:当查询对象的时候hibernate什么时候查询对象所对应的表,load受影响
立即检索:查询表,也就是在缓存里没有,他马上就查询库 延迟检索:只有正真访问对象,在内存里创建代理对象, 他先检查缓存里,缓存里没有,他并不立即查询库
<class name="cn.itcast.hibernate.domain.Customer" table="hib_customers" lazy="true"> 代理类是用反射技术动态生成的一个新类,他继承了客户类,代理对象他能够监控Session是否关闭,在Session关闭之前你访问代理对象的有效属性时,就会触发代理对象去访问数据库的事件,进行查询操作,将结果赋给代理对象的属性,这个过程就是初始化代理对象,只有延迟检索才会有代理对象的概念,
代理对象在Session持久化时并没有赋初值,Session关闭后再去初始化,去查库,然而连接已关闭了,报 延迟初始化异常,可以通过下面方法进行初始化:
Hql语句忽略了迫切左外检索,他与lazy保持一致
set批量立即检索 批量的检索用batch-size,和lazy来设置,Hql语句忽略了迫切左外检索,他与lazy保持一致,降低和数据库的交互次数:<set batch-size=“ 条数”>设置一次检索的条数,一般在3-10之间批量延迟检索: 用Hql语句查询,只要将lazy=true,就是延迟检索了
Many-to-one的批量检索,orders集合对应几个客户,一次查一个客户,要查询多次,设置一次可以查询多个客户,应该在orders对端(客户)的类级别进行设置:
One-to-one: 外键关联
一端:用多对一模拟一对多, 一对一要加上unique=“true”属性
另一端: property-ref属性的参考,参考对端类的映射属性
主键关联:
一端:
另一端:
Many-to-many:; 两边关系对等,映射多对多关联关系时一定要将一端的inverse属性打开,避免都对关联表进行维护,只有一方来维护:inverse=TRUE
解除关系
Hibernate.properties配置文件
access:设置hibernate访问级别,默认是propertyhibernate访问机制:
代理主键,
increment 从数据库中拿开加一;因此在多进程,集群环境下就不能使用increment
hilo 在数据库加一带走,
Oracle:hibernate¬_sequence(native) ;自然主键:class=“assigned”; 联合主键: 可以定义一个联合主键类
Cascade=”delete” :级联删除 ,当只打开inverse时就会让缓存忽略集合的变化,
delete方法,将持久对象,将对象的引用从Session缓存中删除,并且对应sql删除语句将db中的记录也删除,让对象成为临时态evict方法,将Session缓存中的对象清除,但没有将DB中的数据删除的sql语句,是对象进入游离态
已经在Session中的记录就没有意义调用save,updat。Saveorupda方法
HQL和QBC
排序 分页
父类 子类 继承关系,可以将子类存入一个表中,这样要有区分符
乐观所
在javabean中设置一个version的字段,配置文件配置如下:
悲观锁
二级缓:
配置二级缓存,一般在hibernate.cfg.xml中配置,可以为每个配置
使用二级缓存插件EHCache
ehcache.xml配置: