zoukankan      html  css  js  c++  java
  • hibernate深度学习 游离状态 HQL

    当我学完这个之后 我仿佛都懂了 = =或许这就是 hibernate的力量吧.

    操纵持久化对象(Session)

    1.1. 在hibernate中java对象的状态

    Hibernate 把对象分为 4 种状态:

    ¨       持久化状态,

    ¨       临时状态,

    ¨       游离状态,

    ¨       删除状态.

    Session 的特定方法能使对象从一个状态转换到另一个状态

    1.2. 临时对象(transient)

    ¨       在使用代理主键的情况下, OID 通常为 null

    ¨       不处于 Session 的缓存中

    ¨       在数据库中没有对应的记录

    1.2.1.  删除对象(Removed)

    ¨       OID 不为 null

    ¨       从一个 Session实例的缓存中删除

    ¨       Session 已经计划将其从数据库删除, Session 在清理缓存时, 会执行 SQL delete 语句, 删除数据库中的对应记录

    ¨       一般情况下, 应用程序不该再使用被删除的对象

    1.2.2.  持久化对象(也叫”托管”)(Persist)

    1.2.3.   

    ¨       OID 不为 null

    ¨       位于 Session 缓存中

    ¨       持久化对象和数据库中的相关记录对应

    ¨       Session 在清理缓存时, 会根据持久化对象的属性变化, 来同步更新数据库

    ¨       在同一个 Session 实例的缓存中, 数据库表中的每条记录只对应唯一的持久化对象

    1.2.4.  游离对象(也叫”脱管”)(Detached)

    ¨       OID 不为 null

    ¨       不再处于 Session 的缓存中

    ¨       一般情况需下, 游离对象是由持久化对象转变过来的, 因此在数据库中可能还存在与它对应的记录

    1.2.5.  对象的状态转换说明(图)

    对象的状态转换图

    测试hibernatejava对象的状态

    程序代码

    生命周期

    状态

    tx = session.beginTransaction();

    Customer c = new Customer);

    开始生命周期

    临时状态

    Session.save(c)

    处于生命周期中

    转变为持久化状态

    Long id=c.getId();

    c = null;

    Customer c2 = (Customer)session.load(Customer.class,id);

    tx.commit();

    处于生命周期中

    处于持久化状态

    session.close();

    处于生命周期中

    转变为游离态

    c2.getName();

    处于生命周期中

    处于游离态

    c2 = null;

    结束生命周期

    结束生命周期

     

    1.2.6.  对象的状态总结

     

     

    Session缓存存在对应的记录

    数据中存在对应的记录

    临时态

    no

    no

    持久态

    yes

    可能有也可能没有

    游离态

    no

    可能有(数据没有删除)也可能没有

     

    1.2.7.  操纵持久化对象的方法(Session中)

    1.2.8.  save()

    Session 的 save() 方法使一个临时对象转变为持久化对象。

    ¨       Session 的 save() 方法完成以下操作:

    • 把 News 对象加入到 Session 缓存中, 使它进入持久化状态
    • 选用映射文件指定的标识符生成器, 为持久化对象分配唯一的 OID. 在使用代理主键的情况下, setId() 方法为 News 对象设置 OID 使无效的.
    • 计划执行一条 insert 语句,把Customer对象当前的属性值组装到insert语句中

    ¨       Hibernate 通过持久化对象的 OID 来维持它和数据库相关记录的对应关系. 当 News 对象处于持久化状态时, 不允许程序随意修改它的 ID

    @Test
    
        public void save() throws Exception{
    
          
    
           Session session = sessionFactory.openSession();
    
       
    
           Transaction tc = null;
    
           User user = null;
    
           try {
    
               tc = session.beginTransaction();
    
               user = new User();//临时状态
    
               user.setName("张张");
    
               session.save(user);//持久化状态
    
               tc.commit();
    
           } catch (Exception e) {
    
               tc.rollback();
    
               throw e;
    
           }finally{
    
               session.close();
    
           }
    
           user.setName("王王");//游离状态
    
           System.out.println(user.getName());
    
          
    
        }

    1.2.9.      update()

    Session 的 update() 方法使一个游离对象转变为持久化对象, 并且计划执行一条 update 语句。

     

    @Test
    
        public void update() throws Exception{
    
          
    
           Session session = sessionFactory.openSession();
    
       
    
           Transaction tc = null;
    
           User user = null;
    
           try {
    
               tc = session.beginTransaction();
    
               user = (User) session.get(User.class, 1);
    
               //session.clear();
    
               //session.evict(user);//清楚某一个对象。
    
               user.setName("冯芬1");
    
     
    
               //session.update(user);//执行完才提交给数据库
    
               session.flush();//一执行立即提交
    
               System.out.println("执行");
    
               tc.commit();
    
           } catch (Exception e) {
    
               tc.rollback();
    
               throw e;
    
           }finally{
    
               session.close();
    
           }
    
        
    
      }Session 的 update() 方法使一个游离对象转变为持久化对象, 并且计划执行一条 update 语句。

    若希望 Session 仅当修改了 News 对象的属性时, 才执行 update() 语句, 可以把映射文件中 <class> 元素的 select-before-update(更新之前先查询) 设为 true. 该属性的默认值为 false

    当 update() 方法关联一个游离对象时, 如果在 Session 的缓存中已经存在相同 OID 的持久化对象, 会抛出异常

    原因是:两个不同的对象拥有相同的OID

    当 update() 方法关联一个游离对象时, 如果在数据库中不存在相应的记录, 也会抛出异常

    1.2.10.     saveOrUpdate()

    该方法同时包含save和update方法,如果参数是临时对象就用save方法,如果是游离对象就用update方法,如果是持久化对象就直接返回。

    判定对象为临时对象的标准

    ¨       Java 象的 OID 为 null

    ¨       映射文件中为 <id> 设置了 unsaved-value 属性, 并且 Java 对象的 OID 取值与这个 unsaved-value 属性值匹配(在hbn3中基本用不到了)

    @Test
    
        public void saveOrUpdate() throws Exception {
    
           Session session = sessionFactory.openSession();
    
          
    
           Transaction tc = null;
    
           User user = null;
    
           try {
    
               tc = session.beginTransaction();
    
               //临时对象执行插入
    
    //        user = new User();
    
    //        user.setName("洋洋");
    
    //        session.saveOrUpdate(user);
    
               //游离对象执行修改
    
    //        user  = (User) session.get(User.class,1);
    
    //        session.evict(user);
    
    //        session.saveOrUpdate(user);
    
               //如果是持久化对象就直接返回,不执行操作
    
               user  = (User) session.get(User.class,1);
    
               session.saveOrUpdate(user);
    
              
    
               tc.commit();
    
           } catch (Exception e) {
    
               tc.rollback();
    
               throw e;
    
           }finally{
    
               session.close();
    
           }
    
          
    
        }

    如果参数是临时对象就会用save方法

    如果是游离对象就用update方法

    如果是持久化对象就直接返回,不执行操作

    判定对象为临时对象的标准

    ¨       Java 对象的 OID 为 null

    ¨       映射文件中为 <id> 设置了 unsaved-value 属性, 并且 Java 对象的 OID 取值与这个 unsaved-value 属性值匹配,执行插入操作

    根据以上判断临时对象的标准id=null是临时对象。但可以定义属性为int  id

    * 此时id默认值是0而不是null,应该执行更新操作

    * 但实际我们要执行的插入操作。这时,可以在id中设置unsaved-value=0(默认值)

    1.2.11.     get()、load()

    都可以根据给定的 OID 从数据库中加载一个持久化对象

    @Test
    
        public void getOrLoad() throws Exception {
    
           Session session = sessionFactory.openSession();
    
          
    
           Transaction tc = null;
    
           User user = null;
    
           try {
    
               tc = session.beginTransaction();
    
               //get方式会马上执行sql语句
    
               user  = (User) session.get(User.class,1);
    
               System.out.println("aaaaa");
    
               System.out.println(user.getName());
    
               //load方式不会马上执行sql语句
    
               user  = (User) session.load(User.class,2);
    
               System.out.println("bbbbbbbbbbbb");
    
               System.out.println(user.getName());
    
               tc.commit();
    
           } catch (Exception e) {
    
               tc.rollback();
    
               throw e;
    
           }finally{
    
               session.close();
    
           }
    
          
    
                }

    区别:

    ¨       当数据库中不存在与 OID 对应的记录时, load() 方法抛出 ObjectNotFoundException 异常, 而 get() 方法返回 null

    ¨       两者采用不同的延迟检索策略

    get():获取数据,是持久化状态

        1. 会生成:select ... where id=?

        2. 会马上执行sql语句

        3. 如果数据不存在,就返回null

    load():获取数据,是持久化状态

        1.会生成:select ... where id=?

        2. load()后返回的是一个代理对象,要求类不能是final的,否则不能生成子类代理,就不能使用懒加载功能了。

        3.让懒加载失效的方式:一、把实体写成final的;二、在hbm.xml中写<class ... lazy="false">

        4. 不会马上执行sql语句,而是在第1次使用非id或class属性时执行sql

        5. 如果数据不存在,就抛异常:ObjectNotFoundException

    1.2.12.     delete()

    Session 的 delete() 方法既可以删除一个游离对象, 也可以删除一个持久化对象。

    ¨       如果参数是持久化对象,就执行一个delete语句,若为游离对象,先使游离对象被session关联,使他变为持久化对象

    ¨       计划执行一条 delete 语句

    ¨       把对象从 Session 缓存中删除, 该对象进入删除状态.

    1.2.13.     与触发器协同工作

    Session.save(c);

    Session.flush();

    Session.refresh(c);

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

    触发器的行为导致缓存与数据库中的数据不一致。解决办法是执行完

    操作后,立即调用session的flush方法和refresh方法,迫使缓存与

    数据库同步。

    Session的update操作方法盲目的激活触发器

    如果游离状态的对象的属性和数据库一致,则更新操作是多余的。

    为避免这种情况:

    <class name=“” table=“” select-before-update=“true”>

       ……

    </class>

    1.2.14.     DML(数据操作语言)风格的操作

    ,Hibernate 提供通过 Hibernate 查询语言(HQL)来执行大

    批量 SQL 风格的 DML 语句的方法。

    UPDATE 和 DELETE 语句的伪语法为:( UPDATE | DELETE ) FROM? EntityName (WHERE

    where_conditions)?。

    要注意的事项:

    •在 FROM 子句(from-clause)中,FROM 关键字是可选的

    •在 FROM 子句(from-clause)中只能有一个实体名,它可以是别名。如果实体名是别名,那么

    任何被引用的属性都必须加上此别名的前缀;如果不是别名,那么任何有前缀的属性引用都是

    非法的。

    •不能在大批量 HQL 语句中使用 joins 连接(显式或者隐式的都不行)。不过在 WHERE 子句中

    可以使用子查询。可以在 where 子句中使用子查询,子查询本身可以包含 join。

    •整个 WHERE 子句是可选的。

    使用 Query.executeUpdate() 方法执行一个 HQL UPDATE语句

    由 Query.executeUpdate() 方法返回的整型值表明了受此操作影响的记录数量

    Session session = sessionFactory.openSession();

    Transaction tx = session.beginTransaction();

    String hqlDelete = "delete Customer c where c.name = :oldName";

    // or String hqlDelete = "delete Customer where name = :oldName";

    int deletedEntities = s.createQuery( hqlDelete )

    .setString( "oldName", oldName )

    .executeUpdate();

    tx.commit();

    session.close();

     

    6.HQL介绍

     SQL(表和字段)  HQL(对象和属性)

    使用HQL查询

             HQL: Hibernate Query Language.

             特点:

     1,与SQL相似,SQL中的语法基本上都可以直接使用。

     2,SQL查询的是表和表中的列;HQL查询的是对象与对象中的属性。

     3,HQL的关键字不区分大小写,类名与属性名是区分大小写的。

     4,SELECT可以省略.

    案例:

      1,简单的查询

                         hql = "FROM Employee";

                         hql = "FROM Employee AS e";   使用别名

                         hql = "FROM Employee e";   使用别名,as关键字可省略

     执行查询

    List list = session.createQuery(hql).list();

    显示结果

                       

    while(itr.hasNext()){
    
                                         //System.out.println(itr.next().getName());
    
                                         Object[] object =  (Object[]) itr.next();
    
                                         System.out.println(object[0]+":"+object[1]);
    
                                }

     2,带上过滤条件的(可以使用别名):Where

                        

     hql = "FROM Employee WHERE id<10";
    
                         hql = "FROM Employee e WHERE e.id<10";
    
                         hql = "FROM Employee e WHERE e.id<10 AND e.id>5";

     

    3,带上排序条件的:Order By

                 

            hql = "FROM Employee e WHERE e.id<10 ORDER BY e.name";
    
                         hql = "FROM Employee e WHERE e.id<10 ORDER BY e.name DESC";
    
                         hql = "FROM Employee e WHERE e.id<10 ORDER BY e.name DESC, id ASC";

     

    4,指定select子句(不可以使用select *)

                      

       hql = "SELECT e FROM Employee e";   相当于"FROM Employee e"
    
                         hql = "SELECT e.name FROM Employee e";   只查询一个列,返回的集合的元素类型就是这个属性的类型
    
                         hql = "SELECT e.id,e.name FROM Employee e";   查询多个列,返回的集合的元素类型是Object数组
    
                         hql = "SELECT new Employee(e.id,e.name) FROM Employee e";   可以使用new语法,指定把查询出的部分属性封装到对象中

     

    5,执行查询,获得结果(list、uniqueResult、分页 )

                         

    Query query = session.createQuery("FROM Employee e WHERE id<3");
    
                         query.setFirstResult(0);
    
                         query.setMaxResults(10);
    
                         List list = query.list();   查询的结果是一个List集合
    
                         Employee employee = (Employee) query.uniqueResult();  查询的结果是唯一的一个结果,当结果有多个,就会抛异常
    
                         System.out.println(employee);

     

    6,函数的使用

    hql = "select count(id) from Department";
    
                                Number num =  (Number) session.createQuery(hql).uniqueResult();
    
                                System.out.println(num);

    7,分组查询

    hql = "select d.name,count(d.name) from Department d group by d.name";
    
    hql = "select d.name,count(d.name) from Department d group by d.name having count(d.name)>5";
    
     

     

    8,参数查询

    第一种:使用“?”

    hql = "from Department d where d.id between ? and ? ";
    
    List list = session.createQuery(hql)
    
                                .setParameter(0, 2)
    
                                .setParameter(1, 8)
    
                                .list();

    第二种:使用变量名

        

        hql = "FROM Employee e WHERE id BETWEEN :idMin AND :idMax";
    
                       List list = session.createQuery(hql)//
    
                       .setParameter("idMax", 15)//
    
                       .setParameter("idMin", 5)//
    
             .list();

    第三种:当参数是集合时,使用setParameterList()设置参数值

                 

          hql = "FROM Employee e WHERE id IN (:ids)";
    
                       List list = session.createQuery(hql)//
    
                       .setParameterList("ids", new Object[] { 1, 2, 3, 5, 8, 100 })//
    
                       .list();

     

    9在映射文件配置HQL语句

    为了使程序具有更大的灵活性,Hibernate可以在映射文件中配置HQL语句。如下所示为在Student.hbm.xml中的配置。

    <hibernate-mapping>
    
         <class name="hibernate.ch06.Student" table="student" catalog="joblog">
    
              <!--此处省略了配置-->
    
         </class>
    
         <query name="searchStudent"><![CDATA[
    
         from Student s where s.sage>22
    
         ]]><![CDATA[  ]]>表示一些特殊字符不需要转义)
    
         </query>
    
    </hibernate-mapping>

    可以用如下代码访问配置文件中的HQL语句。

            

    Session session=HibernateSessionFactory.currentSession();//创建Session
    
            Query query=session.getNamedQuery("searchStudent");                   //用getNamedQuery得到查询
    
            List list=query.list();                                                   //执行查询
    
            Iterator it=list.iterator();
    
           
    
            while(it.hasNext()){
    
                   Student stu=(Student)it.next();
    
                   System.out.println(stu.getSname());
    
            }

    其中,getNamedQuery()函数用来访问映射文件Student.hbm.xml中配置的HQL语句,参数为配置的名称。

    Select s.id,s.name, c.name from t_student s,t_classes c where c.id = s.classId

    Select s.id,s.name, c.name from t_student s right join t_classes c on s.classtId = c.id;

    10.连接查询

                             

       //第一种:(内连接)
    
                                //hql = "select s.id,s.name,c.name from Student s join s.classes c";
    
                                //第二种:
    
                                //hql = "select s.id,s.name,s.classes.name from Student s";
    
                                //外连接:
    
    hql = "select s.id,s.name,c.name from Student s right join s.classes c";
    
    hql = "select s.id,s.name,c.name from Student s left join s.classes c";

    11.更新

                   

                 //更新前:
    
                                Student student = (Student)session.get(Student.class, 2);
    
                                System.out.println(student.getName());
    
                                int num = session.createQuery("update Student s set s.name=? where s.id=2")
    
                                .setParameter(0,"好人1")
    
                                .executeUpdate();
    
                                System.out.println(num);
    
                                //更新后:
    
                                session.refresh(student);
    
                                System.out.println(student.getName());

    12.删除

                                

    /*int num1 = session.createQuery("delete Student s  where s.id=1")
    
                                .executeUpdate();
    
                                System.out.println(num1);*/ 

     

    Criteria查询方式

    // 创建Criteria对象
    
             Criteria criteria = session.createCriteria(Student.class);
    
                                // 增加过滤条件
    
                                criteria.add(Restrictions.ge("id", 2));
    
                                criteria.add(Restrictions.le("id", 5));
    
     
    
                                // 增加排序条件
    
    criteria.addOrder(Order.desc("id"));
    
                                criteria.addOrder(Order.desc("name"));
    
                                                            // 执行查询
    
                                // criteria.setFirstResult(0);
    
                                // criteria.setMaxResults(100);
    
                                // criteria.uniqueResult();
    
                                // criteria.list()
    
                                List list = criteria.list();
    
                                Iterator  itr = list.iterator();
    
                                while(itr.hasNext()){
    
                                        
    
                                         Student student = (Student)itr.next();
    
                                         System.out.println(student.getName()+":"+student.getScore());
    
                                }

     写完了 今天落枕了 起床也是在床底睁开眼  歪着脖子写了折磨一一篇, 真难受啊 不过这质量算是我写过最棒的一篇了吧.

  • 相关阅读:
    2017-3-13 SQL server 表连接
    2017-3-13 SQL server 函数(聚合函数,数学函数,字符串函数,转换函数,时间日期函数)
    2017-3-10 SQL server T-sql语句 高级查询
    2017-3-10 SQL server 数据库 T--SQL语句
    layer框架使用的问题汇总
    pulic——功能性(自己写完测试的)list转树
    bootstrap的datetimepicker使用(1.将默认的英文设置为中文2.选择日月年的时候记录之前的操作)
    临时笔记0318
    最简单的多线程代码,一句话就可以使用
    scrollview滑动到某区域执行某种方法
  • 原文地址:https://www.cnblogs.com/hwcs/p/7462981.html
Copyright © 2011-2022 走看看