延迟加载:是在真实需要数据才执行SQL语句进行查询,避免无谓的性能开销。
类级可选:立即检索,延迟检索,默认为延迟检索
立即检索:立即加载对指定的对象,立即发送SQL
延迟检索:延迟加载指定检索的属性,才发送SQL
无论<class>元素的lazy的属性是true或false , session的get( )方法及Query( )方法在类级别总是立即检索策略
简单来说就是,get( )或list( ),lazy无效
lazy:决定关联对象初始化时机
Fetch:决定SQL语句构建形式
proxy(默认) 延迟加载 no-proxy:无法代理延迟加载 false:立即加载
No-Session的场景构建:在Session关闭了dao层的会话对象,在Ui层使用的时候,发现代理对象而非真实的对象,获取属性上网时候,想走别的,但是走不了。。。
NO-Session 的解决方案:
(1)将dao中的load( )方法改成get( )
/*第一种解决 no Session 的方法*/ Object result= HibernateUtil.getSession().get(clazz,id);
(2)在biz中加入
/*第二种解决 no Session 的方案*/ if (!Hibernate.isInitialized(obj)){ Hibernate.initialize(obj); }
(3)改变小配置
<!--第三种解决 no Session 的方案 在<class> 中加入 lazy="false" 如下所示--> <class name="Emp" table="Emp" lazy="false" schema="happyy2165">
(4)先在biz层读取信息,不得已方案
/*第四种解决方法,不得已方案*/
Emp emp= (Emp) obj;
emp.getEname();
(5)OpenSessionInview (javaweb中使用) :在用户的每一次请求过程始终保持一个Session对象打开看。
public class OpenSessionInviewFilter implements Filter { public void init(FilterConfig filterConfig) throws ServletException { } public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { //请求达到时,打开Session并启动事务 Transaction tx=null; try { tx= HibernateUtil.getSession().beginTransaction(); filterChain.doFilter(servletRequest,servletResponse);//执行 找xxxServlet 或 index.jsp tx.commit(); }catch (Exception ex){ ex.printStackTrace(); tx.rollback(); }finally { HibernateUtil.closeSession(); } } public void destroy() { } }
web.xml
<filter> <filter-name>OpenSessionInviewFilter</filter-name> <filter-class>cn.happy.Session.filter.OpenSessionInviewFilter</filter-class> </filter> <filter-mapping> <filter-name>OpenSessionInviewFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>----------------------------------
biz层:public class HibernateBiz { HibernateDAo dAo=new HibernateDAo(); public Object get(Class clazz, Serializable id){ Transaction tx= HibernateUtil.getSession().beginTransaction(); Object obj=dAo.get(clazz,id); /*第四种解决方法,不得已方案*//* /* Emp emp= (Emp) obj; emp.getEname();*/ /*第二种解决 no Session 的方案*/ /* if (!Hibernate.isInitialized(obj)){ Hibernate.initialize(obj); }*/ tx.commit(); HibernateUtil.closeSession(); System.out.println("========"); /*obj:代理对象. 不走数据库,根据原始对象的模板,将属性copy一遍。*/ return obj; } }dao层:在Dapt中写上属性,并将其进行封装,并使用Set将emp植入进来public class HibernateDAo { public Object get(Class clazz, Serializable id){ /*第一种解决 no Session 的方法*/ /* Object result= HibernateUtil.getSession().get(clazz,id);*/ Object result= HibernateUtil.getSession().load(clazz,id); return result; } }
private Integer pid;
private String pname; private Set<Emp> emps=new HashSet<Emp>();Dapt.hbm.xml
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="cn.happy.Session"> <class name="Dapt" table="Dapt" lazy="false" schema="happyy2165"> <id name="pid" column="pid"> <generator class="native"></generator> </id> <property name="pname"/> <set name="emps" cascade="save-update" inverse="true" lazy="false" fetch="join" order-by="pid"> <!--一对多--> <key column="pid"></key> <one-to-many class="cn.happy.Session.Emp"></one-to-many> </set> </class> </hibernate-mapping>创建Emp类,写上属性值,并将其进行封装
private Integer eid; private String ename; private Dapt dapt=new Dapt();
Emp.hbm.xml
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="cn.happy.Session"> <!--第三种解决 no Session 的方案 在<class> 中加入 lazy="false" 如下所示--> <!-- <class name="Emp" table="Emp" lazy="false" schema="happyy2165">--> <class name="Emp" table="Emp" schema="happyy2165"> <id name="eid" column="eid"> <generator class="native"></generator> </id> <property name="ename"/> <!--多对一 name:Emp中植入的一方过的属性名称 column:数据库中的外键列的名称 --> <many-to-one name="dapt" column="pid" lazy="proxy" class="Dapt"></many-to-one> </class> </hibernate-mapping>
测试类:
public class SessionTest { @Test public void loadGetTest(){ HibernateBiz biz=new HibernateBiz(); //获取单个员工对象 Emp emp= (Emp) biz.get(Emp.class,1); //获取员工实体中员工姓名 System.out.println(emp.getEname()); } }