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>       
  • 相关阅读:
    Coursera机器学习week11 单元测试
    关于 TypeReference 的解释
    getModifiers 方法解释。
    instanceof isInstance isAssignableFrom 比较
    elasticsearch 基础 语法总结
    kibana 启动 关闭 和进程查找
    MD5 SHA1 SHA256 SHA512 SHA1WithRSA 的区别
    spring boot 项目 热启动
    java zip 压缩文件
    Packet for query is too large (1660 > 1024). You can change this value on the server by setting the max_allowed_packet' variable.
  • 原文地址:https://www.cnblogs.com/gcjava/p/6574378.html
Copyright © 2011-2022 走看看