zoukankan      html  css  js  c++  java
  • SSH 学习笔记

    Hibernater Hql

    Hibernater分页查询失败,查询结果为所有,原因:

    package com.tenni.test;
    
    import java.util.List;
    
    import org.hibernate.Query;
    import org.hibernate.Session;
    import org.hibernate.Transaction;
    import org.junit.Test;
    
    import com.tenni.entity.Account;
    import com.tenni.entity.Service;
    import com.tenni.util.HibernateUtil;
    
    public class testHql {
        private Session session = HibernateUtil.getSession();
        private Transaction ts = session.getTransaction();
        
        @Test
        //分页查询
        public void testPaging(){
            int page=1, pageSize = 3,totalRows,from;
            String hql = "select count(*) from Service";
            Query qry = session.createQuery(hql);
            totalRows =Integer.valueOf(qry.uniqueResult().toString());
            System.err.println("所有的 数量 totalRows==="+totalRows);
            
            hql = "from Service order by id";
            qry = session.createQuery(hql);//必须在设置起始和容量之前
            from = (page-1)*pageSize;
            qry.setFirstResult(from);//设置起点,从0开始
            qry.setMaxResults(pageSize);// 设置页容量
            List<Service> list = qry.list();
            for(Service a:list){
                System.out.println(a.getId()+" "+a.getOsUserName()+" "+a.getLoginPassword());
            }
        }
    }

     Hibernate 二级缓存管理异常情况及原因

    再用ThreadLocal线程方式管理session的时候,HibernateUtil中静态获取session的方法以次线程为key,放入ThreadLocal的map中。(自己的理解不知道对否)

    1. 如果想要close掉session必须用HibernateUtil.close();否则提示异常:Session is closed!(如下代码)
    2. HibernateUtil.close()关闭session,必须在HibernateUtil.clearSessionFactory(e1<你从session中get的实体对象>) 清理二级缓存实体类之前。否则执行清理二级缓存之后,Hibernate依然不执行查询语句,从二级缓存中获取共享的查询实例对象结果。

    附:HibernateUtil.getSessionFactory().getAllClassMetadata() 可以查看sessionFactory中的一些实体类信息

     测试代码如下:

    @Test
    //    二级缓存是SessionFactory级缓存,由它负责管理,因此需要获取到SessionFactory才能管理二级缓存,
    //    我们先在HibernateUtil中增加获取SessionFactory的方法
        public void test2() {
            Session session1 = HibernateUtil.getSession();
            Emp e1 = (Emp) session1.get(Emp.class, 1708);
            System.out.println(e1.getEname());
            System.out.println("-----------session1-----"+session1);
    //        session1.close();
           HibernateUtil.close();//前
            HibernateUtil.clearSessionFactory(e1);//后
            System.out.println("-----------session1-----"+session1);
            Session session2 = HibernateUtil.getSession();
            Emp e2 = (Emp) session2.get(Emp.class, 1708);
            System.out.println("-----------session2-----"+session2);
            System.out.println(e2.getEname());
    
        }

    控制台输出:session1已经成功关闭

    -----------session1-----SessionImpl(PersistenceContext[entityKeys=[EntityKey[com.tenni.entity.Emp#1708]],collectionKeys=[]];ActionQueue[insertions=[] updates=[] deletions=[] collectionCreations=[] collectionRemovals=[] collectionUpdates=[]])
    -----------要close()====连接--SessionImpl(PersistenceContext[entityKeys=[EntityKey[com.tenni.entity.Emp#1708]],collectionKeys=[]];ActionQueue[insertions=[] updates=[] deletions=[] collectionCreations=[] collectionRemovals=[] collectionUpdates=[]])
    -----------清理二级缓存中----实体类查询缓存
    -----------session1-----SessionImpl(<closed>)

    HibernateUtil.java

    package com.tenni.util;
    
    import org.hibernate.Session;
    import org.hibernate.SessionFactory;
    import org.hibernate.cfg.Configuration;
    
    public class HibernateUtil {
        private static SessionFactory sessionFactory;
        /* 使用ThreadLocal管理Session,可以保证一个线程中只有唯一的一个连接。
         * * 并且我们在获取连接时,它会自动的给我们返回当前线程对应的连接。
        */
        private static ThreadLocal<Session> tl = new  ThreadLocal<Session>();
        static{
    //        加载Hibernate配置文件
            Configuration conf = new Configuration();
            conf.configure("/hibernate.cfg.xml");
            sessionFactory = conf.buildSessionFactory();
        }
        /**
         * 创建session
         */
        public static Session getSession(){
    //        ThreadLocal会以当前线程名为key获取连接
            Session session = tl.get();
    //        如果取到的当前的连接为空
            if(session == null){
    //            使用工厂方法创建连接
                System.out.println("-----------getSession===使用工厂方法创建连接");
                session = sessionFactory.openSession();
    //            ThreadLocal会以当前线程名为key保存session
                tl.set(session);
            }
            System.out.println("-----------getSession===使用tl.get() 获取连接--"+session);
            return session;
        }
        /**
         * 清理二级缓存中清理掉 实体类查询缓存
         */
        public static void clearSessionFactory(Object o){
            try {
                sessionFactory.evict(o.getClass());
                System.out.println("-----------清理二级缓存中----实体类查询缓存");
            } catch (Exception e) {
                System.out.println("xxxxxxxxxxx清理二级缓存中 实体类查询缓存 !!失败!!----"+e);
            }
        }
        /**
         * @return the sessionFactory
         */
        public static SessionFactory getSessionFactory() {
            return sessionFactory;
        }
        /**
         *关闭session
         */
        public static void close(){
    //        ThreadLocal会以当前线程名为key获取session
            Session session = tl.get();
            if(session != null){
                System.out.println("-----------要close()====连接--"+session);
                session.close();
    //            将当前线程对应的连接从ThreadLocal移除
                tl.remove();
            }
        }
        public static void main(String[] args) {
            System.out.println("-----------"+getSession());
            System.out.println("-----------"+tl);
            close();
            }
        
    }
    HibernateUtil
     
    Session is closed!
    org.hibernate.SessionException: Session is closed!
        at org.hibernate.impl.AbstractSessionImpl.errorIfClosed(AbstractSessionImpl.java:49)
        at org.hibernate.impl.SessionImpl.fireLoad(SessionImpl.java:874)
        at org.hibernate.impl.SessionImpl.get(SessionImpl.java:815)
        at org.hibernate.impl.SessionImpl.get(SessionImpl.java:808)
        at com.tenni.test.TestSecondCache.test2(TestSecondCache.java:48)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
        at java.lang.reflect.Method.invoke(Unknown Source)
        at org.junit.internal.runners.TestMethod.invoke(TestMethod.java:59)
        at org.junit.internal.runners.MethodRoadie.runTestMethod(MethodRoadie.java:98)
        at org.junit.internal.runners.MethodRoadie$2.run(MethodRoadie.java:79)
        at org.junit.internal.runners.MethodRoadie.runBeforesThenTestThenAfters(MethodRoadie.java:87)
        at org.junit.internal.runners.MethodRoadie.runTest(MethodRoadie.java:77)
        at org.junit.internal.runners.MethodRoadie.run(MethodRoadie.java:42)
        at org.junit.internal.runners.JUnit4ClassRunner.invokeTestMethod(JUnit4ClassRunner.java:88)
        at org.junit.internal.runners.JUnit4ClassRunner.runMethods(JUnit4ClassRunner.java:51)
        at org.junit.internal.runners.JUnit4ClassRunner$1.run(JUnit4ClassRunner.java:44)
        at org.junit.internal.runners.ClassRoadie.runUnprotected(ClassRoadie.java:27)
        at org.junit.internal.runners.ClassRoadie.runProtected(ClassRoadie.java:37)
        at org.junit.internal.runners.JUnit4ClassRunner.run(JUnit4ClassRunner.java:42)
        at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
        at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
        at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
        at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
        at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
        at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
    Session is closed!

     Hibernate 的动态update语句,实现部分字段更新

    使用Hibernate修改时,它会根据映射关系文件,自动拼出一个update语句,然后执行修改,其中映射关系文件中往往配置表中全部的 字段,而很多时候,页面上不需要修改表中全部的字段,只需要修改其中的一部分,因此页面上的字段少于表中字段,在提交保存时,缺少的字段就成了空值,那么 再按照完整的update语句来执行更新,就会把这些不需要更新的字段更新为空。

    这个问题如果使用JDBC或者MyBatis是不会存在的,因为SQL是自己写的。而Hibernate自动生成SQL,就出现了这个问题。

    本案例中,我们采用动态更新的方式来解决这个问题,即在映射关系文件中通过dynamic-update=”true”来声明更新方式为动态 更新,届时Hibernate在自动生成update语句时会判断属性值是否发生改变,若改变则将属性拼入SQL,否则忽略掉这个属性。

    这种方式要求传给Hibernate的对象必须是持久态的,而通过页面传入的对象是Struts2自动初始化的,是临时态的。我们可以通过 ID查询出持久态对象,然后通过Spring中的BeanUtils工具类,将临时态对象的属性值复制给持久态对象,然后用这个持久态对象进行更新即可。

    <class name="com.tarena.entity.Cost" table="cost" dynamic update="true">
        <id name="id" type="integer" column="id">
        <!-- 用来指明主键的生成方式 -->
        <generator class="sequence">
        <param name="sequence">cost_seq</param>
        </generator>
        </id>
        .........

    Struts2 重定向同一个namespace的action可以简写

    如:重定向至、/cost/findByPage

    <action name="saveCost" class="costAction“ method="saveCost">
        <result name="success" type="redirectAction">
            <param name="namespace">/cost</param>
            <param name="actionName">findByPage</param>
        </result>
    </action>
    改为:
    <action name="saveCost" class="costAction" method="saveCost">
        <result name="success" type="redirectAction">
            findByPage
        </result>
    </action>       
  • 相关阅读:
    智能家居——安全信息收集(一)
    PMP软件管理之路——站在巨人的肩膀上(一)
    Linux——信息收集(二)Nikto网页服务器扫描器
    XML约束(3)
    xml基本语法(2)
    xml概述(1)
    ajax接受json响应
    ajax接受json响应(讲义)
    json与xml的比较
    零碎小技能
  • 原文地址:https://www.cnblogs.com/gcjava/p/6574378.html
Copyright © 2011-2022 走看看