hibernate 基本操作

一、创建SessionFactory的两种方式:(将下面其中一种封装成getSessionFactory方法)
1、通过进行创建Configuration:

        //创建配置对象
        Configuration cfg=new Configuration();
        cfg.configure("hibernate.cfg.xml");

        //创建session工厂
        return cfg.buildSessionFactory();
        
2、通过服务注册类实现

        StandardServiceRegistry registry = new StandardServiceRegistryBuilder()
                                                                        .configure("hibernate.cfg.xml")
                                                                        .build();
        SessionFactory sessionFactory = new MetadataSources(registry).buildMetadata().buildSessionFactory();

 

二、创建一个Main测试类:

public static void main(String[] args) {
    //获取session工厂
    SessionFactory factory = getSessionFactory();
    //打开一个新的session
    Session session=factory.openSession();
    //开始事务
    Transaction t=session.beginTransaction();

    //这里写操作数据库的代码(下面的测试代码均在此处写)

    //提交事务
    t.commit();
    //关闭session
    session.close();
    //关闭session工厂
    factory.close();
}

三、测试保存或更新api

   Integer index = (Integer)session.save(employee);//返回数据库中的主键Id
   session.persist(employee);//没有返回值
   Object o = session.merge(employee);//返回整个对象

       session.saveOrUpdate(employee);//没有返回值,如果有主键那么更新,没有则插入新纪录

注意上述的各种方法都会将对象存入到一级缓存session中(其实就是一个Map结构"EntityKey[domain.Employee#112]" -> obj,在变量persistenceContext中),此时的对象都是持久态的

四、各种查询

   Employee employee = session.find(Employee.class,101);//直接跟进id查询
   employee.setLastName("xtz");持久化的对象在提交事务后会主动把结果更新的到数据库
   Employee employee = session.load(Employee.class,101);//通过id查询,通过懒加载的方式
   employee.setLastName("jeff");//使用到这个对象的时候,才发送查询sql,同样的,在关闭事务也会刷线到数据库中       HQL
      Query<Employee> query = session.createQuery("from domain.Employee");//创建查询,可以加where order by 等,但是不能加limit      query.setMaxResults(10);//记录数,用于分页
    query.setFirstResult(11);//记录开始的下标,从0开始,用于分页
    List<Employee> list = query.list();//查询

         使用具名参数: (我的hinernate 版本hibernate-core-5.4.5.Final.jar

   from domain.Employee where id = :id

         query.setString("id","101");//这个版本已经不推荐使用了,代替的方案如下:

         query.setParameter("id",101, IntegerType.INSTANCE);//什么类型就用xxxType.INSTANCE

         使用Criteria对象  

    Criteria criteria = session.createCriteria(Employee.class);
    criteria.add(Restrictions.eq("id",101));
    List<Employee> list = criteria.list();//不够这个版本已经不这样使用了,在后续的版本中会被移除

         替代方式:  https://stackoverflow.com/questions/40720799/deprecated-createcriteria-method-in-hibernate-5

   //首先获取CriteriaBuilder
   CriteriaBuilder criteriaBuilder = session.getCriteriaBuilder();
   //获取CriteriaQuery对象
   CriteriaQuery<Employee> criteriaQuery = criteriaBuilder.createQuery(Employee.class);
   //用于条件查询
   Root<Employee> root = criteriaQuery.from(Employee.class);
   //拿id=101的记录
   criteriaQuery.select(root).where(root.get("id").in(101));
   //创建query对象
   Query<Employee> query1 = session.createQuery(criteriaQuery);
   List<Employee> employees = query1.list();

       使用本地sql

      Query<Employee> query = session.createSQLQuery("select * from tb_employee where id = :id");     

      query.setParameter("id",101, IntegerType.INSTANCE);//设置具名参数

      List<Employee> list = query.list();

五、hibernate的三种对象状态

      1、瞬时态,(new 出来的对象处于瞬时态)

      2、游离态,(数据库中存在,但是session中不存在的对象)

      3、持久态,(数据库中存在,同时session中也存在的对象)

      这里我提出一个问题,就是瞬时态和游离态的区分,感觉界限不太明显。持久态的最好区分,就是数据库中和都存在的实体,比如你save、find、load、list等等都是会把实体存在session中,此时就是持久态了。但是比如持久态的对象调用session的clear、evict、close等方法,都会将实体移除session,那么此时的实体,跟数据库是对应的,比如他们的主键是一样。那么这个对应就是游离态的话。存在一种情况,我new一个对象(将游离态的实体传入赋值),那么这个新new的对象是瞬时态的还是游离态的呢?(这个是我一直不太理解的地方,知道的大神麻烦指点一下)(其实可不可这样理解,就针对实体的主键而言,如果session的有一个实体和数据库实体主键一致,那么这个session的实体就是持久态;如果一个实体不存在session中,同时它的的主键在数据库中有一条记录跟它对应,那么这个就是游离态的实体;如果一个实体不存在主键或者主键在数据库中找不和它相对的记录,那么这个就是瞬时态)

六、在工作记得,在一个会话中,如果如果操作多张表,比如A表和B表。A表呢,你需要返回一些数据,然后你通过find的方式找到entity,然后你在entity中某个字段的值改了,比如image="www.xxxx.jpg",你要加水印,改了image="www.xxxx.jpg-image_big"

然后你返回给前端,就可以展示有水印的图片。一开始你发现没啥问题的,但是突然又有一个需求,说是要对这个请求进行记录,比如要保存这个请求的访问时间啥的,那么就需要往B表插入一条数据。此时你会发现A表中,数据库image的值也被改了。

这是因为,当持久态的实体,被修改后,执行flush、session.close等操作,会将数据更新到数据库中(工作中被坑过几次)。

 

 

 


 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章