• hibernate操纵数据库常用方法 及 hibernate对象的三种状态


        在dao层使用hibernate语言来与数据库进行访问,hibernate作为面向对象思想开发的dao层框架其理解也需要以面向对象的思想来看待 使用。hibernate不仅支持使用者使用他提供的对象来操作 还支持使用者使用HQL语言访问数据库。

    下面介绍简单的增删改:

    public class test {
            Configuration conf = new Configuration().configure();
            // 根据配置信息,创建 SessionFactory对象
            SessionFactory sessionFactory = conf.buildSessionFactory();
            Session session=sessionFactory.openSession();
            //2开启事务
            Transaction tx = session.beginTransaction();
            User u=new User();
            user.setUser_id(2);
            tx.commit();
            session.close();
        }

    上述代码创建sessionFactory很麻烦而且代码重复  所以可以使用hibernateSessionFactory 提供的getSession()方法

     1 public class testUpdate {
     2          Session session = HibernateSessionFactory.getSession();
     3         //设置主键指定update
     4             user.setId(2);  
     5             user.setUser_name("dabai");
     6             Transaction trans = session.beginTransaction();
     7             session.update(news);
     8             trans.commit();
     9             HibernateSessionFactory.closeSession();
    10     }

    这里要说一下  hibernate的update方法比较效率低  先查在更新  因为它提供一个方法叫saveorupdate 如名所示  当存在它更新不存在它创建一条记录,怎么实现?先查在做后续操作,查到了主键就更新否则就添加,那如果不设置主键,再使用saveorupdate()呢,这里就牵扯到hibernate的持久化对象了,稍后会作解答。先看删除操作

     1 public class testUpdate {
     2          Session session = HibernateSessionFactory.getSession();
     3         //设置主键指定delete
     4             user.setId(2);  
     5             user.setUser_name("dabai");
     6             Transaction trans = session.beginTransaction();
     7             session.delete(user);
     8             trans.commit();
     9             HibernateSessionFactory.closeSession();
    10     }

    查询:查询方法很多很多很多

     1 public class testUpdate {
     2          Session session = HibernateSessionFactory.getSession();
     3         // 此处from的不是table名  是实体类 
     4             Query query = session.createQuery("from User");
     5             //2 调用query的方法得到结果
     6             List<User> list = query.list();
     7 
     8             for (User user : list) {
     9                 System.out.println(user);
    10             }
    11             trans.commit();
    12             HibernateSessionFactory.closeSession();
    13     }

    上述query不是from表名是实体名  虽然hibernate官方说要from实体名 但是!!我试过表名同样有效

    接下来介绍下hql  和使用jdbcConnection比较类似  什么模糊查询啊 limit查询啊都能用 order by  count  sum  avg  min  max 查询啊 就写sql就完事了 同样不能from表名 我也试了下还是能用  不过尽量不要写表名  编码规范

     1 public class testHql {
     2          Session session = HibernateSessionFactory.getSession();
     3         // 此处from的不是table名  是实体类 
     4          String hql = "from User u where u.username = ?";
     5             Query query = session.createQuery(hql);
     6 
     7             // 参数设置方法可以参照jdbc的写法  hibernate从0开始 jdbc的参数从一开始 可以设置多个参数 嫌麻烦的话后面有简单的
     8             query.setParameter(0,"dabai");
     9 
    10             //3 调用方法得到结果
    11             List<User> list = query.list(); 
    12 
    13             for (User user : list) {
    14                 System.out.println(user);
    15             }
    16             trans.commit();
    17             HibernateSessionFactory.closeSession();
    18     }

    可以看出来query返回的都是list形式的 而且都经过封装成对象返回过来,于是就牵扯到一个问题,当只需要查询某个字段或几个字段时 且字段组合无法构成Java实体怎么操作?也很简单 返回的东西给它成object就完事了不过遍历要麻烦一些,因为返回结果写成List<Object[]> 形式遍历时一个object就是查询出来的一个元组 用Arrarys.toString可以看到打印的内容是查询的字段的一行(题外话  实体类最好覆写一下toString方法 这有助于调试 测试 反正写了不吃亏

    下面是个很重要的内容Criteria 和DetachedCriteria  放在最后那就注定了Criteria一家的不平凡。其中后者是离线的 前者是在线的  DetachedCriteria可以在web层创建 当作参数传到dao层 ,这意味着你使用DetachedCriteria可以没有session。两个Criteria都提供方法.forClass().以求保证查询对象是哪一个。Criteria 和 DetachedCriteria 都能使用 Criterion 和 Projection 设置查询条件。 

    上面是Criteria的一个方法  getHibernateTemplate是hibernate提供的一个方便abstract类中的一个对象具体看下图

    通常我们会这样写  这样就能在BaseDaoImpl中使用提供的各种方法了

    1 public class BaseDaoImpl extends HibernateDaoSupport  {
    2 
    3     @Resource
    4     public void setmySessionFactory(SessionFactory sessionFactory){
    5         super.setSessionFactory(sessionFactory);
    6     }
    7 }

     总而言之就是getHibernateTemplate很好用 你可以用  我们继续谈Criteria 和DetachedCriteria 两个我只讲DetachedCriteria 因为Criteria能做的Detached Criteria也能 然后我主要说一下我认为比较重要的方法

    关于创建:通过forClass和entityname讲道理没什么不同不稀奇

    关于setProjection:这里是service层的一个方法

    dc是web层传来的一个DetachedCriteria  这里dc.setProjection(Projections.rowCount());是告诉hibernate不要查字段值查这个Class对应的table中有多少条记录,否则hibernate会查所有的字段然后再统计count给你,很影响性能。最后dc.setProjection(null);是清除前面设置的rowCount()否则你后续使用这个DetachedCriteria查询所有的结果都是空,当然你可以选择再创建一个DetachedCriteria dcc;

     关于Criteria的混合使用

    1 DetachedCriteria dc =DetachedCriteria.forClass(User.class);  
    2 dc.setProjection(Projections.rowCount());  
    3 dc.setProjection(Projections.groupProperty("name"));  
    4 List results = dc.list();

    上述代码可以计算各name的user的个数 我也是从别的老哥那里看到的。hibernate方法使用很灵活  有时候多到我想写hql,徘徊于用哪个方法。

    还想提一点的就是前面介绍的getHibernateTemplate还能写hql  太好用了!具体参照代码  注意参数变成了final类  否则会报错   uniqueResult顾名思义就是告诉hibernate就一个返回值强转就完事了  ,当不知道返回的会是几个值时建议用query.list()不然会报错的;

    query.list()只限于使用查询,当hql语句是update  insert  delete之类的有关事务的操作时  使用query.executeUpdate()

     1 public User checkUser(final User u) {
     2         //hql 查询
     3         return    getHibernateTemplate().execute(new HibernateCallback<User>() {
     4 
     5             @Override
     6             public User doInHibernate(Session session) throws HibernateException {
     7                 String hql="from User where username=? and password=?";
     8                 Query query=session.createQuery(hql);
     9                 query.setParameter(0, u.getUsername());
    10                 query.setParameter(1, u.getPassword());
    11                 User returnu = (User)query.uniqueResult();
    12                 return returnu;
    13             }
    14             
    15         });
    16      
    17     }

     还有getHibernateTemplate.find()方法,参数可以设置两个  一个时hql语句,后一个接参数

    如getHibernateTemplate().find(" from Institution"); 及查询Institution对应的表中所有数据 返回值是list 可以指定list的数据类型List<Institution>,需要强转

     最后说 hibernate中对象的三种状态:

    临时状态  (Transient)、持久状态(Persistent)、游离状态(Detached)。持久状态对象也叫PO (PersistentObject)   临时状态和游离状态的对象也叫VO(ValueObject)

     

    一、临时状态

           临时状态对象是通过实例化的方式注入到内存中,也就是通过New的方式来开辟内存。

           临时对象是孤立在内存上的,它不与数据库中的数据有任何关系。比如:

           UserEntity userEntity=new UserEntity();

           这个时候,userEntity对象就称之为临时对象。如果没有任何引用,jvm将其进行GC回收。

    二、持久状态

           持久状态的对象是该对象和数据库中的数据存在关联关系,并且拥有持久化的标识。

           通过session.get()或者session.load()等获取的数据对象,就是持久化状态的对象。

           值得注意的是:如果对持久化对象进行了修改,并没有执行事务提交,这时持久化对象的数据不会同步到数据库中的。

    三、游离状态

            当某个持久化对象与session断开之后,那么此时,该持久化对象就称之为游离对象。

            通常通过session.get()或者session.load()等方式获取的数据后,执行了  session.close()等操作,那么此时获取的持久化对象就转换为游离对象了。 

    上述是文字解释不形象这样说:对于一个User对象,user对象由new关键字创建,此时还未与Session进行关联,它的状态称为瞬时态;在执行了session save(user)操作后,book 对象纳入了Session 的管理范围,这时的user对象变成了持久态对象,此时Session的事务还没有被提交:程序执行完commit()操作并关闭了Session 后,customer对象与Session的关联被关闭,此时customer对象就变成了脱管态。

    关于hibernate给对象设置主键在瞬时还是持久 我看了下有的觉得是这个过程中赋予id的我比较认同,因为在添加到数据库时必须给出id,所以瞬时到持久态间转换赋予id比较合适

  • 相关阅读:
    洛谷P2577 午餐【贪心】【线性dp】
    洛谷P1169 棋盘制作【悬线法】【区间dp】
    洛谷1546 最短网络Agri-Net【最小生成树】【prim】
    洛谷P1144 最短路计数【堆优化dijkstra】
    洛谷P1339 热浪【最短路】
    洛谷P1273 有线电视网【树形dp】
    洛谷P2279 消防局的设立【树形dp】
    洛谷P1220 关路灯【区间dp】
    洛谷P1341 无序字母对【欧拉路】【dfs】
    洛谷P1330 封锁阳光大学【dfs】
  • 原文地址:https://www.cnblogs.com/notably/p/10507239.html
Copyright © 2020-2023  润新知