Hibernate(2)

Criter查询(单表条件查询)

Ctiter是Hibernate无语句面向对象查询

  1. 条件查询

public  void getVoid(){

         Configuration configure = new Configuration().configure();

         SessionFactory sessionFactory = configure.buildSessionFactory();

          Session session = sessionFactory.openSession();

          Transaction tx = session.beginTransaction();

            //====编写实体对象===============

          /**

           * 查询所有的查询对象

           */

          Criteria createCriteria = session.createCriteria(User.class);

          List<User> list = createCriteria.list();

          System.out.println("list:"+list);

            //查询单个对象

          //User uniqueResult = (User)createCriteria.uniqueResult();

          //===================

          tx.commit();

          session.close();

    }

 

  1. 条件查询

/***

     * Restrictions 条件参数的设置

     * >       -->     gt

     * >=      -->     ge

     * <       -->      lt

     * <=      -->      le

     * ==       -->     eq

     * !=       -->     ne

     * in        -->      in

     * between and -->   between

     * like          -->     like

     * is not null    -->    isNotNull

     * is null       -->     inNull

     * or          -->       or

     * and         -->       and

     */

 //====编写实体对象===============

          /**

           * 查询所有的查询对象

           */

          Criteria createCriteria = session.createCriteria(User.class);

            //添加查询的参数

         createCriteria.add(Restrictions.eq("id", 1l));

         List list = createCriteria.list()

  1. 分页查询

/**

           * 设置分页的信息

           */

          Criteria createCriteria = session.createCriteria(User.class);

          createCriteria.setFirstResult(1);//开始

          createCriteria.setMaxResults(3);//多少条数据

         List list = createCriteria.list();

  1. 设置查询聚合函数

 * 设查询聚合行数==》总行数

           */

          Criteria createCriteria = session.createCriteria(User.class);

           //

          createCriteria.setProjection(Projections.rowCount());

          Long uniqueResult = (Long)createCriteria.uniqueResult();

  1. 排序查询

    Criteria createCriteria = openSession.createCriteria(User.class);

        createCriteria.addOrder(Order.desc("id"));

        List<User> list = createCriteria.list();

        for (User user : list) {

            System.out.println(user);

        }

  1. 离线查询对象
  1. 传统的离线查询

  1. 离线的Criteria查询

  1. 测试

 public void getVoid04(){

        //创建离线的查询

        DetachedCriteria forClass = DetachedCriteria.forClass(User.class);

        //拼装条件进行查询

        forClass.add(Restrictions.idEq(3l));

        //创建Session

        Configuration configure = new Configuration().configure();

        SessionFactory sessionFactory = configure.buildSessionFactory();

        Session openSession = sessionFactory.openSession();

        Transaction beginTransaction = openSession.beginTransaction();

        //------------------

        //进行组装session条件

        Criteria executableCriteria = forClass.getExecutableCriteria(openSession);

        List list = executableCriteria.list();

         for (Object object : list) {

               System.out.println(object);          

        }

        //------------------

        beginTransaction.commit();

        openSession.close();

    }

  1. 原生态SQL查询(复杂的业务的查询)
  1. 基本查询:
    1. 返回数据list

 //===原生的SQL语句查询===============

          String sql="select * from  user";

              //创建SQL的查询对象

          SQLQuery createSQLQuery = session.createSQLQuery(sql);

          List<Object[]> list = createSQLQuery.list();

           for (Object[] objects : list) {

            System.out.println(Arrays.toString(objects));

        }

          /* 查询单个

          * createSQLQuery.uniqueResult();*/

          //===================

    1. 返回对象list

 //===原生的SQL语句查询===============

          String sql="select * from  user";

              //创建SQL的查询对象

          SQLQuery createSQLQuery = session.createSQLQuery(sql);

               //  将结果集封装到结果对象中

          createSQLQuery.addEntity(User.class);

            //得到结果

          List<User> list = createSQLQuery.list();

           System.out.println(list);

  1. 条件查询

  //===原生的SQL语句查询===============

          String sql="select * from  user where id =?";

              //创建SQL的查询对象

          SQLQuery createSQLQuery = session.createSQLQuery(sql);

              //设置参数

          createSQLQuery.setParameter(0,1l);

          createSQLQuery.addEntity(User.class);

            //得到结果

          List<User> list = createSQLQuery.list();

           System.out.println(list);

  1. 分页查询

//===原生的SQL语句查询===============

          String sql="select * from  user limit ?,?";

              //创建SQL的查询对象

          SQLQuery createSQLQuery = session.createSQLQuery(sql);

              //设置参数

          createSQLQuery.setParameter(0, 1);

          createSQLQuery.setParameter(1, 3);

          createSQLQuery.addEntity(User.class);

            //得到结果

          List<User> list = createSQLQuery.list();

  1. 一对多&多对一关系表达
  1. 数据库中的表的表达关系

  1. 实体类对象的表示

1.客户实体类

public class Customer {

  private  Long c_id;

  private  String c_name;

  //使用Set集合表达一对多的关系

  private Set<Orders> orders=new HashSet<Orders>();

  //对应的get set 方法

  }

2.订单实体类

public class Orders {

      private  Long o_id;

      private  String o_name;

      //表达多对一的的关系

      private  Customer  customer;

        //对应的get set 方法

      }

  1. ORM数据配置
  1. 主配置文件hibernate.cfg.cml要加入

        <mapping resource="com/hibernate01/dem02/bean/Customer.hbm.xml" />

        <mapping resource="com/hibernate01/dem02/bean/Orders.hbm.xml" />

  1. 一对多

<hibernate-mapping >

   <class name="com.hibernate01.dem02.bean.Customer" >

      <id name="c_id" column="c_id">

         <generator class="native"></generator>

      </id>

       <property name="c_name" column="c_name" > </property>

       <!--集合;一对多关系的配置  -->

       <!--name 集合的属性名  

         cascade:级联操作如(保存客户把客户的订单也同时保存)

              save-update:级联保存更新    

              delete:级联删除

              all:(save-update+delete)

           级联操作:本质,就是简化操作   

         inverse:配置关联维护关系(反转)

                   true:当前配置的类不维护关系

                   false:默认值  当前配置类维护    

               关联维护本质:提高关系维护的性能     

       -->

       <set name="orders"  cascade=""  inverse="" >

          <!--column:对应的是外键关系  (必须一致)

          -->

          <key column="o_c_id"  ></key>

          <!--one-to-many  指向的一对多

              class:与本类关联的对象完整类名

              -->

          <one-to-many class="com.hibernate01.dem02.bean.Orders" />

       </set>

   </class>

</hibernate-mapping>

  1. 多对一

<hibernate-mapping>

   <class name="com.hibernate01.dem02.bean.Orders">

      <id name="o_id" column="o_id">

         <generator class="native" ></generator>

      </id>

       <property name="o_name" column="o_name" ></property>

       <!-- 多对一的配置

           name:配置对象的属性名

           column:对应的是外键关系(必须一致)

           class:与本类关联的对象完整类名

           cascade:级联操作如(保存客户是把客户的订单也同时保存)

              save-update:级联保存更新    

              delete:级联删除

              all:(save-update+delete)

         -->

       <many-to-one  cascade="" name="customer" column="o_c_id" class="com.hibernate01.dem02.bean.Customer" ></many-to-one>

   </class>

</hibernate-mapping>

测试

  1. 保存 客户意见客户下的订单

**

     * 多对一| 一对多

     * 保存 客户意见客户下的订单

     */

    @Test

    public void getVoid(){

        Session openSession = HibernateUtils.openSession();

        Transaction beginTransaction = openSession.beginTransaction();

        //-------操作----------

          Customer customer = new Customer();

          customer.setC_name("小张");

          Orders order = new Orders();

          order.setO_name("西瓜");

          Orders order1 = new Orders();

          order1.setO_name("苹果");

          /**

           * 表示一对多,客户下有多个订单

           */

          customer.getOrders().add(order);

          customer.getOrders().add(order1);

          /**

           * 表示多对的多,订单属于那个客户

           */

          order1.setCustomer(customer);

          order.setCustomer(customer);

          openSession.save(customer);

    /*

     * 如这两行代码不写,需要配置级联操作

     *   save-update:级联保存更新         

     * openSession.save(order);

          openSession.save(order1);*/

          //---------------------

 

        beginTransaction.commit();

        openSession.close();

    }

  1. 只为客户添加订单

 //-------操作----------

        Customer customer = openSession.get(Customer.class, 1L);

          Orders order = new Orders();

          order.setO_name("葡萄");

          Orders order1 = new Orders();

          order1.setO_name("香蕉");

          /**

           * 表示一对多,客户下有多个订单

           */

          customer.getOrders().add(order);

          customer.getOrders().add(order1);

          /**

           * 表示多对的多,订单属于那个客户

           */

          order1.setCustomer(customer);

          order.setCustomer(customer);

          openSession.save(order);

          openSession.save(order1);

  1. 只为客户删除订单数据

 Customer customer = openSession.get(Customer.class, 1L);

         Orders orders = openSession.get(Orders.class, 1L);

         customer.getOrders().remove(orders);

         orders.setCustomer(null)

  1. 级联操作
  1. 多对一/一对多中的属性一样的配置
  2. 级联造作:本质,就是简化操作

多对一配置

Name:配置对象的属性名

Column:对应的是外建关系(必须一致)

Class:与本类关联的对象完整类名

Cascade:级联操作(保存客户时把客户的订单同时保存)

save-update:级联保存更新

delete:级联删除

all:(save-update+delete)

   <many-to-one cascade=""    name="customer" column="o_c_id" class="com.hibernate01.dem02.bean.Customer" ></many-to-one>

  1. 关系-维护
  1. 在没有进行关系维护是Sql语句执行多次操作
  2. 先执行添加在执行修改语句
  3. 早保存时,都会维护外键关系。关系维护两次
  4. 关系维护本质:提高关系维护性能

/**

     * 多对一| 一对多

     * 保存 客户意见客户下的订单

     */

    @Test

    public void getVoid(){

        Session openSession = HibernateUtils.openSession();

        Transaction beginTransaction = openSession.beginTransaction();

        //-------操作----------

          Customer customer = new Customer();

          customer.setC_name("小张");

          Orders order = new Orders();

          order.setO_name("西瓜");

          Orders order1 = new Orders();

          order1.setO_name("苹果");

          /**

           * 表示一对多,客户下有多个订单

           * 如果客户放弃维护,代码可以不用写

           */

          customer.getOrders().add(order);

          customer.getOrders().add(order1);

          /**

           * 表示多对的多,订单属于那个客户

           */

          order1.setCustomer(customer);

          order.setCustomer(customer);

          openSession.save(customer);

          openSession.save(order);

          openSession.save(order1);

          //---------------------

        openSession.close();

}

  1. 配置关系维护
  1. sql语句不会执行Update语句
  2. 在有外键的一方是不能放弃维护,只能有一的一方可以放弃维护

inverse:配置关联维护关系(反转)

true:当前配置的类不维护关系

false:默认值  当前配置类维护

  <set name="orders" inverse="true" >

          <!--column:对应的是外键关系  (必须一致)

          -->

          <key column="o_c_id"  ></key>

          <!--one-to-many  指向的一对多

              class:与本类关联的对象完整类名

              -->

          <one-to-many class="com.hibernate01.dem02.bean.Orders" />

       </set>

2.注意—放弃维护方

1.添加:

   /**

           * 表示一对多,客户下有多个订单

           * 如果客户放弃维护,代码可以不用写

           */

          customer.getOrders().add(order);

          customer.getOrders().add(order1);

2.删除

  /**

         * 如:Customer设置了,不进行维护关系

         *  在这里是不能删除的

         * 如需要删除:

         *    方式一: 开启 cascade="delete"

         *    方式二: 开始维护  inverse="false"

         * */

        Customer customer = openSession.get(Customer.class, 1L);

         openSession.delete(customer);

删除的配置

 <set name="orders" inverse="true" cascade="delete" >

    <!--    <set name="orders" inverse="false"  > -->

          <!--column:对应的是外键关系  (必须一致)

          -->

          <key column="o_c_id"  ></key>

          <!--one-to-many  指向的一对多

              class:与本类关联的对象完整类名

              -->

          <one-to-many class="com.hibernate01.dem02.bean.Orders" />

       </set>

  1. 多对多关系的表达
  1. 数据库表关系表达

  1. 实体类关系表达

  1. ORM映射文件的配置

多对多的表达关系

name:集合对应的属性名

table:中间表名

   <set name="student" table="student_teacher">

         <!--column:外键  指定别人<引用我>的ID名  -->

        <key column="t_id"></key>

        <!--class:指定那个类是多对多的关系

           column:外键<我引用>别人的外键

          -->

        <many-to-many class="com.hibernate01.dem02.bean.Student" column="s_id"></many-to-many>

     </set>

  1. 操作关联属性
  1. 维护关系
  1. 在多对多的是一定要配置维护关系
  2. Inverse属性:如果遇到多对多关系,一定要选择一方放弃维护关系
  3. 一般谁来放弃要看业务方向,有业务方维护业务方,非业务方放弃维护

1.1非业务方不进行保存

   public void getVoid(){

        Session openSession = HibernateUtils.openSession();

        Transaction beginTransaction = openSession.beginTransaction();

        //-------操作----------

            Teacher teacher = new Teacher();

            teacher.setT_name("陈老师");

            Teacher teacher1 = new Teacher();

            teacher1.setT_name("张老师");

            Student student = new Student();

             student.setS_name("张三同学");

             Student student2 = new Student();

             student2.setS_name("张三同学");

             /**

              * 对象的关系设置

              */

             //teacet的对应关系

           /* 非业务方不进行保存

            * teacher1.getStudent().add(student);

             teacher1.getStudent().add(student2);

             teacher.getStudent().add(student);

             teacher.getStudent().add(student2);*/

             //student的对应关系

             student.getTeacher().add(teacher);

             student.getTeacher().add(teacher1);

             student2.getTeacher().add(teacher);

             student2.getTeacher().add(teacher1);

             /**

              * 保存

              */

             openSession.save(teacher);

             openSession.save(teacher1);

             openSession.save(student);

             openSession.save(student2);

        //---------------------

        beginTransaction.commit();

        openSession.close();

}

1.2.非业务方放弃维护关系

<!-- 使用inverse属性

            true: 放弃维护外键关系

            false(默认值):维护关系

        结论: 将来在开发中,如果遇到多对多关系.一定要选择一方放弃维护关系.

             一般谁来放弃要看业务方向.

             业务方向维护角色. 非业务方向不需要维护关系.放弃维护

         -->

     <set name="student" table="student_teacher" inverse="true">

         <!--column:外键  指定别人<引用我>的ID名  -->

        <key column="t_id"></key>

        <!--class:指定那个类是多对多的关系

           column:外键<我引用>别人的外键

          -->

        <many-to-many class="com.hibernate01.dem02.bean.Student" column="s_id"></many-to-many>

     </set>

  1. 级联属性
  1. ascade=“save-update”配置了就少写openSession.save()代码

/**

     * 给学生添加老师

     */

    @Test

    public void getVoid1(){

        Session openSession = HibernateUtils.openSession();

        Transaction beginTransaction = openSession.beginTransaction();

        //-------操作----------

        //获取到学生

        Student student = openSession.get(Student.class, 1l);

           //创建老师

          Teacher teacher = new Teacher();

          teacher.setT_name("王老师");

           //添加老师

          student.getTeacher().add(teacher);

           //将瞬时状态转换为持久状态       

          openSession.save(teacher);

        //---------------------

        beginTransaction.commit();

        openSession.close();

}

<!--多对多的表达关系  

       name:集合对应的属性名

       table:中间表名

            cascade:级联操作如

              save-update:级联保存更新   

              delete:级联删除(风险大特别是多对多的时,不建议使用)

              all:(save-update+delete)

              结论: cascade简化代码书写.该属性使不使用无所谓. 建议要用只用save-update.

      -->

     <set name="teacher" table="student_teacher" cascade="save-update">

         <!--column:外键  指定别人<引用我>的ID名  -->

        <key column="s_id"></key>

        <!--class:指定那个类是多对多的关系

           column:外键<我引用>别人的外键

          -->

        <many-to-many class="com.hibernate01.dem02.bean.Teacher" column="t_id"></many-to-many>

     </set>

public void getVoid1(){

        Session openSession = HibernateUtils.openSession();

        Transaction beginTransaction = openSession.beginTransaction();

        Student student = openSession.get(Student.class, 1l);

          Teacher teacher = new Teacher();

          teacher.setT_name("王老师");

          student.getTeacher().add(teacher);

        //---------------------

        beginTransaction.commit();

        openSession.close();

    }

  1. 解除

 /**

     * 为学生,解除老师

     */

    @Test

    public void getVoid2(){

        Session openSession = HibernateUtils.openSession();

        Transaction beginTransaction = openSession.beginTransaction();

        Student student = openSession.get(Student.class, 1l);

        Teacher teacher = openSession.get(Teacher.class, 1l);

        Teacher teacher2 = openSession.get(Teacher.class, 2l);

        student.getTeacher().remove(teacher);

        student.getTeacher().remove(teacher2);

        //---------------------

        beginTransaction.commit();

        openSession.close();

}

  1. HQL多表语法详解
  1. 数据表||实体类
  1. 数据库表数据
  1. Orders

  1. Custoner

2.实体类

public class Orders {

      private  Long o_id;

      private  String o_name;

      //表达多对一的的关系

      private  Customer  customer;

      //对应的 get set方法

      }

public class Customer {

  private  Long c_id;

  private  String c_name;

  //使用Set集合表达一对多的关系

  private Set<Orders> orders=new HashSet<Orders>();

  //对应的get set 方法

  }

2.回顾原生SQL语句多表查询

1.交叉连接-笛卡尔乘积

Select * from 表名1,表名2

2.内连接

1.隐士连接

Select * from 表名1,表名2 where 表名1.id=表名2.id

2.显示内连接

Select * from 表名1 inner join 表名2 on 表名.id=表名2.id

  1. 外连接
  1. 左外连接

Select * from 表名1 left jion 表名2 表名2 on 表名.id=表名2.id

 

  1. 右连接

Select * from 表名1 right jion 表名2 表名2 on 表名.id=表名2.id

3.HSQL的多表查询

1.内连接

1.平常内连接:将连接的两端对象分别返回放置数组中

public void getVoid01(){

        Configuration configure = new Configuration().configure();

        SessionFactory sessionFactory = configure.buildSessionFactory();

        Session openSession = sessionFactory.openSession();

        Transaction beginTransaction = openSession.beginTransaction();

          //------------

           String hql="from Customer  c inner join c.orders";

           Query createQuery = openSession.createQuery(hql);

           List<Object[]> list = createQuery.list();

            for (Object[] object : list) {

                 System.out.println(Arrays.toString(object));

            }

        //------------

        beginTransaction.commit();

        openSession.close();

    }

  1. 迫切内连接:进行封装,返回一个对象

    String hql="from Customer  c inner join fetch c.orders";

               Query createQuery = openSession.createQuery(hql);

               List<Customer> list = createQuery.list();

                for (Customer object : list) {

                     System.out.println(object);

                }

  1. 左外连接

String hql="from Customer  c left join   c.orders";

                   Query createQuery = openSession.createQuery(hql);

                   List<Object[]> list = createQuery.list();

                    for (Object[] object : list) {

                         System.out.println(Arrays.toString(object));

                    }

  1. 右外连接

  String hql="from Customer  c right join   c.orders";

           Query createQuery = openSession.createQuery(hql);

           List<Object[]> list = createQuery.list();

            for (Object[] object : list) {

                 System.out.println(Arrays.toString(object));

            }}

  1. 类级加载策略(赖加载|延迟加载)
  1. load(延迟加载)|| get(不同加载)
  1. 使用get方法进行查询:open.session()加载时立即查询则会打印SQL语句

 Customer customer = openSession.get(Customer.class,1l);

        System.out.println(customer);

2.使用load方法加载

1.(默认)是执行时,不发生SQL语句,返回一个对象,使用该对象时才执行SQL查询

2.延迟加载:只是获得对象没有使用不会查询,在使用的时候进行查询

           Customer customer = openSession.load(Customer.class,1l);

            System.out.println(customer);

2.1延迟加载策略

  1. 可以通过配置文件中的class元素上的lazy进行配置
  1. lazy:true加载时,不查询使用时候查询(默认)
  2. lazy:false:加载时立即查询
  3. get方法没有 延迟加载策略

<hibernate-mapping >

   <class name="com.hibernate01.dem02.bean.Customer" lazy="true" >

     </class>

   </hibernate-mapping >

3.赖加载流程

3.1lazy=true

查询时,会返回一个代理对象,会在使用属性时,根据关联session查询数据库,加载数据

3.2 lazy=false(和get没区别,调用立即加载数据)

直接返回对象

3.3注意:使用懒加载时,调用数据加载数据必须保证session的开启

  1. 关联级别
  1. 集合关联策略

 Customer customer = openSession.get(Customer.class,1l);

            //关联级别

            Set<Orders> orders = customer.getOrders();

1.0:加载的策略

<hibernate-mapping >

   <class name="com.hibernate01.dem02.bean.Customer" lazy="true" >

       <!--

           lazy:延迟加载

                |-true:(默认)延迟加载

                |-false:立即加载

                |-extra:极其懒惰

          fetch:抓取策略.使用什么样的SQL语句加载集合数据

                |-select:(默认)单表查询加载

                |-join:使用多表查询加载集合

                |-subselect:使用子查询加载集合            

        -->

      <set name="orders" lazy="true" fetch="select">

          <key column="o_c_id"  ></key>

          <one-to-many class="com.hibernate01.dem02.bean.Orders" />

       </set>

   </class>

</hibernate-mapping>

1.1:lazy=true && fetch=select(默认)

  1. 执行44行时(不执行查询集合)
  2. 执行47行使用时(加载集合数据)

1.2:lazy=false && fetch=select

执行44行时,还没有使用集合就会加载集合数据

1.3:lazy=extra && fetch=select

极其懒惰与懒加载基本一致,如获得集合的size,只查询集合的size

1.4:fetch=select

  1. 执行44行代码,则会使用多表查询出所有的数据,44行执行之后不会再执行SQL语句
  2. 当fetch=select时lazy无论是true|false|extra都失效,则都是立即加载

 

1.5:lazy=true && fetch=subselect

String Hsql="FROM Customer";

        Query createQuery = openSession.createQuery(Hsql);

        List<Customer> list = createQuery.list();

        for (Customer customer : list) {

            System.out.println(customer);

            System.out.println(customer.getOrders().size());

            System.out.println(customer.getOrders());

        }

注意:执行45行代码则使用的子查询,与懒加载

1.6:lazy=false  && fetch=subselect

  1. 执行到43行则执行2行sql查询
  2. 执行之后的查询则不会再执行sql语句

1.7;lazy=extra && fetch=subselect

  1. 极其懒惰与懒加载类型

2.属性关联策略

<hibernate-mapping>

   <class name="com.hibernate01.dem02.bean.Orders">

         <!--

             lazy:延迟加载

                    |-false:立即加载

                    |-proxy:由该类属性类级别的加载策略 (lazy)进行决定

              fetch:抓取策略.使用什么样的SQL语句加载数据

                    |-select:(默认)单表查询加载

                    |-join:使用多表查询加载集合

           -->

       <many-to-one  lazy="proxy" fetch="join"    name="customer" column="o_c_id" class="com.hibernate01.dem02.bean.Customer" ></many-to-one>

   </class>

</hibernate-mapping>

 2.0:加载策略

Orders orders = openSession.get(Orders.class, 1l);

            Customer customer = orders.getCustomer();

            System.out.println(customer);

2.1:fetch=jion

  1. lazy属性值无论是false|peoxy都会失效
  2. 在执行40行代码时,会执行多表查询,后面的不会执行sql语句

3.总结

1.为了提高fetch应当选择select:lazy应当选择true(使用默认值)

2.no-session(session关闭)

1.过大session的作用使用Filter拦截器进行扩展

4.使用批量加载

<hibernate-mapping >

   <class name="com.hibernate01.dem02.bean.Customer"  >

   <!--batch-size:表示每次加载多少条数据-->

      <set name="orders"  batch-size="3">

          <key column="o_c_id"  ></key>

          <one-to-many class="com.hibernate01.dem02.bean.Orders" />

       </set>

   </class>

</hibernate-mapping>

在执行44行代码时,不会执行多个sql语句

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值