hibernate----懒加载,原生 sql查询及多种hql查询,表连接查询

来源:互联网 发布:history.js下载 编辑:程序博客网 时间:2024/06/07 01:03

创建实体类:

package com.xiangshuai.hibernate;

 

import java.util.HashSet;

import java.util.Set;

 

/**

 * 顾客类

 * */

public class Customer {

         privateInteger id;

         privateString cname;

         privateSet<Order> orders=new HashSet<Order>();

         publicInteger getId() {

                  returnid;

         }

         publicvoid setId(Integer id) {

                  this.id= id;

         }

         publicString getCname() {

                  returncname;

         }

         publicvoid setCname(String cname) {

                  this.cname= cname;

         }

         publicSet<Order> getOrders() {

                  returnorders;

         }

         publicvoid setOrders(Set<Order> orders) {

                  this.orders= orders;

         }

         @Override

         publicString toString() {

                  return"Customer [id=" + id + ", cname=" + cname + ",orders=" + orders + "]";

         }

        

}

 

package com.xiangshuai.hibernate;

/**

 * 订单类

 * */

public classOrder {

    private Integerid;

   privateStringoname;

   privateCustomercustomer;

    public Integer getId() {

        returnid;

    }

    public void setId(Integer id) {

        this.id =id;

    }

    public String getOname() {

        returnoname;

    }

    public void setOname(String oname) {

        this.oname =oname;

    }

    public Customer getCustomer(){

        returncustomer;

    }

    public void setCustomer(Customer customer) {

        this.customer =customer;

    }

    @Override

    public String toString() {

        return"Order [id="+ id +", oname="+ oname+"]";

    }

 

   

}

package com.xiangshuai.hibernate;

/**

 *   //投影查询查出的数据映射的POJO类,将查询出来的记录直接封装成对象,如果new的这个POJO非本身要映射Customer类那么必须写全类名

       POJO pojo = (POJO)session.createQuery("select newcom.xiangshuai.hibernate.POJO(c.id,c.cname) from Customer c wherec.id=?").setInteger(0, 8).uniqueResult();

 * */

public classPOJO {

    privateStringpname;

    privateIntegerpid;

    public POJO() {

        super();

        // TODO Auto-generated constructor stub

    }

    public POJO( Integerpid,String pname) {

        super();

        this.pname =pname;

        this.pid =pid;

    }

    public String getPname() {

        returnpname;

    }

    public void setPname(String pname) {

        this.pname =pname;

    }

    public Integer getPid() {

        returnpid;

    }

    public void setPid(Integer pid) {

        this.pid =pid;

    }

    @Override

    public String toString() {

        return"POJO [pname="+ pname+", pid="+ pid+"]";

    }

}

实体类对应的xml文件

Customer.hbm.xml

<?xmlversion="1.0"encoding="UTF-8"?>

<!DOCTYPEhibernate-mapping PUBLIC

    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"

    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">

   <!-- ORM元数据 表对象关系映射文件

    package : 配置该配置文件中类所在的包.  -->

 <hibernate-mappingpackage="com.xiangshuai.hibernate">

    <classname="Customer"table="t_customer" >

        <!-- 如果类属性 namecolumn一致可以只定name -->

        <idname="id"column="id"length="255">

            <generatorclass="native"></generator>

        </id>  

        <propertyname="cname"></property>

        <!-- 一对多关系用 set配置set标签中将inverse设为ture则此xml对应的类放弃维护外键,

        Customer放弃维护外键,实际开发也一般是一的一方放弃维护外键关系

        默认是flase,如果一的一方经常要维护cid外键,那么这里就不要设置,默认就好

        <keycolumn="cid"> column类名这里表示Order对应的表中的列名(表外键字段cid)cid

        <one-to-manyclass="Order"/>cid表对应的类

        如果inverse设为true也就是一的一方不负责维护外键cid的创建等等,那么在用session.sava(customer)

        虽然因为设置了cascade="save-update,delete"但也只会保存order对象中已有属性,而不会保存order对象中

        没有的属性cid,因此在执行session.sava(customer)前必须执行 order1.set(customer),order1.set(customer),

        order这个多的一方维护外键,先将customer保存到对象中以生成cid这样 session.sava(customer)执行后t_order给的

        cid值才不会为null

        delete却可以直接 session.delete(customer)在删除customer的同时删除customer所拥有的所有订单-->

        <!-- set 里面有个属性默认 lazy="true"默认是lazy 也就是查询customer对象时暂时不发sqlSet<Order>

        只有在用到order时才查,注意此时session不能关闭的,要不会报错-->

        <setname="orders"inverse="true"cascade="save-update,delete"lazy="false">

            <keycolumn="cid"></key>

            <one-to-manyclass="Order"/>

        </set>

    </class>

 </hibernate-mapping>

 

Order.hbm.xml

<?xmlversion="1.0"encoding="UTF-8"?>

<!DOCTYPEhibernate-mapping PUBLIC

    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"

    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">

   <!-- ORM元数据 表对象关系映射文件

    package : 配置该配置文件中类所在的包.  -->

 <hibernate-mappingpackage="com.xiangshuai.hibernate">

    <classname="Order"table="t_order" >

           <idname="id"column="id"length="255">

            <generatorclass="native"></generator>

        </id>  

        <propertyname="oname"></property>

        <!-- 多的一方直接用<many-to-one标签配置与一的一方的关系即可

        nameOrder的属性名customet,class="Customer" 这个name"customer"对应的类  ,column对应的外键名即多

        的一方的外键名和一一方set中的<key column="cid"></key>一致-->

        <many-to-onename="customer"class="Customer"column="cid"></many-to-one>

    </class>

 </hibernate-mapping>

 

将实体类对应的XML文件mapperhibernate.cfg.xml中去

hibernate.cfg.xml

<?xmlversion="1.0"encoding="UTF-8"?>

<!DOCTYPEhibernate-configuration PUBLIC

    "-//Hibernate/Hibernate Configuration DTD 3.0//EN"

    "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">

 

<hibernate-configuration>

    <session-factory>

        <!-- property 元素用于配置Hibernate中的属性

            :

          -->

          <!--hibernate.connection.driver_class :连接数据库的驱动  -->

        <propertyname="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>

          <!--hibernate.connection.username :连接数据库的用户名 -->

        <propertyname="hibernate.connection.username">root</property>

          <!--hibernate.connection.password :连接数据库的密码 -->

        <propertyname="hibernate.connection.password">root</property>

          <!--hibernate.connection.url :连接数据库的地址,路径 -->

        <propertyname="hibernate.connection.url">jdbc:mysql://localhost:3306/demo</property>

       

        <!-- show_sql: 操作数据库时,向控制台打印sql语句 -->

        <propertyname="show_sql">true</property>

        <!-- format_sql: 打印sql语句前,会将sql语句先格式化  -->

        <propertyname="format_sql">true</property>

        <!-- hbm2ddl.auto: 生成表结构的策略配置

             update(最常用的取值):如果当前数据库中不存在表结构,那么自动创建表结构.

                    如果存在表结构,并且表结构与实体一致,那么不做修改

                    如果存在表结构,并且表结构与实体不一致,那么会修改表结构.会保留原有列.

             create(很少):无论是否存在表结构.每次启动Hibernate都会重新创建表结构.(数据会丢失)

            create-drop(极少):无论是否存在表结构.每次启动Hibernate都会重新创建表结构.每次Hibernate运行结束时,删除表结构.

             validate(很少):不会自动创建表结构.也不会自动维护表结构.Hibernate只校验表结构.如果表结构不一致将会抛出异常.

          -->

        <propertyname="hbm2ddl.auto">update</property>

       

        <!-- 数据库方言配置

         org.hibernate.dialect.MySQLDialect (选择最短的)

         -->

        <propertyname="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>

       

       

       

        <!-- hibernate.connection.autocommit:事务自动提交  -->

        <propertyname="hibernate.connection.autocommit">true</property>

        <!-- Session与线程绑定=>只有配置了该配置,才能使用getCurrentSession-->

        <propertyname="hibernate.current_session_context_class">thread</property>

        <!-- 引入ORM映射文件

            填写src之后的路径

         -->

        <mappingresource="com/xiangshuai/hibernate/Customer.hbm.xml"/>

        <mappingresource="com/xiangshuai/hibernate/Order.hbm.xml"/>

       

    </session-factory>

</hibernate-configuration>

 

测试test

package com.xiangshuai.hibernate;

 

import java.util.List;

 

import org.hibernate.Query;

import org.hibernate.SessionFactory;

import org.hibernate.cfg.Configuration;

import org.hibernate.classic.Session;

import org.junit.Test;

 

public class Demo1 {

         privateConfiguration conf = null;

         SessionFactorysessionFactory = null;

         Sessionsession = null;

         /*

          * 在lazy="true"的情况下,如果用 get方法会直接从数据库中查出数据放入快照和session

          * 中,而load只会由hibernate生成代理对象, 只有当用到其它 属性时才会去数据 库select出来

          * ,并快照和更新session中存在的数据

          */

  @Test

         publicvoid lazytrue1() {

            /*lazy="ture"的情况 get 会马上从数据库中将id为5的customer记录查出并封装但不会马上查

             * customer的属性即关联的order

             * 如下执行session.get(Customer.class,5)发的sql如下:

             * Hibernate:

   select  customer0_.id asid0_0_,customer0_.cname as cname0_0_

   from t_customer customer0_ where customer0_.id=?

             * 而只有执行了customer.getOrders()才会发查询orders的sql如下:

             * Hibernate:

   select  orders0_.cid as cid0_1_,orders0_.id as id1_,orders0_.id as id1_0_,orders0_.oname as oname1_0_,

       orders0_.cid as cid1_0_  from   t_order orders0_   where

       orders0_.cid=?

        syso执行结果-- [Order [id=10, oname=订单1], Order [id=9, oname=订单2]]

             * */

          session=getSession();

          Customer customer = (Customer) session.get(Customer.class, 5);

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

          closeStream(sessionFactory, session);

         }

   //原生 sql查询及多种hql查询

  @Test

  public void testR(){

            session=getSession();

          //hql条件查询1 --setInteger(0, 5):0表示占位符的位置,从0开始,5表示此占位符set进的值

            Customer c1 = (Customer)session.createQuery("from Customer where id=?").setInteger(0,5).uniqueResult();

            //hql条件查询2--加select 则必须使用类别名并且slect c(别名)这种格式

            Customer c2 = (Customer)session.createQuery("select c from Customer c whereid=?").setInteger(0, 6).uniqueResult();

            //hql条件查询2

            Customer c3 = (Customer)session.createQuery("select c from Customer c where c.id=?").setInteger(0,7).uniqueResult();

      

    //投影查询(部分),将查询出来的记录直接封装成对象,如果new 的这个POJO非本身要映射的Customer类那么必须 写全类名

      POJO pojo = (POJO) session.createQuery("select newcom.xiangshuai.hibernate.POJO(c.id,c.cname) from Customer c wherec.id=?").setInteger(0, 8).uniqueResult();

           

      //投影查询查询出的customer对象记录封装成List<POJO>集合

      List<POJO> list = session.createQuery("select newcom.xiangshuai.hibernate.POJO(c.id,c.cname) from Customer c").list();

      System.out.println(list);

      //排序查询出 按id倒序的两条customer记录,先按id查询反序再分页即可

      List<Customer> list2 = session.createQuery("from Customerorder by id desc").setFirstResult(0).setMaxResults(2).list();

      //mysql 聚合函数的使用如查询 t_customer共有几条记录,注意uniqueResult() 返回的只能先强转为long值

      Long sum = (Long) session.createQuery("select sum(c.id) fromCustomer c").uniqueResult();

            closeStream(sessionFactory, session);

   }

  @Test

  public void ljdemo(){

            /*

             * 表连接查询 -- 内连接   迫切内连接   左外连接   迫切左外内连接   右连接   迫切右连接

             * 区别  普通连接与迫切连接的区别在于,普通是将连接查出的一条记录封装成表对象的对象

             *  再将所有的对象  放入Object[]中(其中像orders单独再封装成一个对象放入此数组中),

             *  而迫切是将一条记录直接封装到Customer看(其中像orders单独再封装成一个对象放入此数组中)

             *  左,右连接和mysql一样,左连接左边的会全查出的,而右边的只有满足条件才查出来

             *  普通内连接查询出来的结果 如list1为:

             *      Customer.hbm.xml中set lazy="false"的情况 下 sql为:

             *     

          list1.get(0)获得的object[]为         [Customer [id=5,cname=小明, orders=[Order [id=10, oname=订单1], Order [id=9,oname=订单2]]], Order [id=9, oname=订单2]]

                   即 object[]中放的是查出的封装成customer,和 order两个对象

             list1.get(1)获得的object[]为          

          [Customer [id=5, cname=小明, orders=[Order [id=10, oname=订单1], Order [id=9,oname=订单2]]], Order [id=10, oname=订单1]]       

                  普通内连接查询出来的结果 如list2为:

                  Customer.hbm.xml中setlazy="false"的情况下 sql为:

                  Hibernate:

   select customer0_.id as id0_0_,  orders1_.id as id1_1_, customer0_.cname as cname0_0_, orders1_.oname as oname1_1_,

       orders1_.cid as cid1_1_,orders1_.cid as cid0_0__,orders1_.id as id0__

   from t_customer customer0_ inner join t_order orders1_  on customer0_.id=orders1_.cid

         object[0]即为 Customer [id=5, cname=小明, orders=[Order[id=10, oname=订单1], Order [id=9, oname=订单2]]]即

         Customer一个对象,此对象customer的属性,其中set<Order>单独封装成一个数组。

         迫切与非迫切就是看 join 后有没有加 fetch,那么生成的 Oject[] 迫切一个只放一个对象,非迫切放两个对象

            [Customer [id=5, cname=小明, orders=[Order [id=10, oname=订单1], Order [id=9,oname=订单2]]],

            Customer [id=5, cname=小明, orders=[Order [id=10, oname=订单1], Order [id=9,oname=订单2]]],

             Customer [id=6, cname=小明,orders=[Order [id=11, oname=订单1], Order [id=12, oname=订单2]]],

              Customer [id=6, cname=小明,orders=[Order [id=11, oname=订单1], Order [id=12, oname=订单2]]],

              Customer [id=7, cname=小明,orders=[Order [id=13, oname=订单1], Order [id=14, oname=订单2]]],

              Customer [id=7, cname=小明,orders=[Order [id=13, oname=订单1], Order [id=14, oname=订单2]]],

               Customer [id=8, cname=小明,orders=[Order [id=15, oname=订单8], Order [id=16, oname=订单9]]],

               Customer [id=8, cname=小明,orders=[Order [id=15, oname=订单8], Order [id=16, oname=订单9]]],

                 Customer [id=9, cname=小明,orders=[Order [id=17, oname=订单10], Order [id=18, oname=订单11]]],

                 Customer [id=9, cname=小明, orders=[Order[id=17, oname=订单10], Order [id=18, oname=订单11]]]]

        * */

            //内连接操作(部分)

      //普通内连接放入Object[]中(其中像orders单独再封装成一个对象放入此数组中)

            session=getSession();

           // List<Object[]> list1 =session.createQuery("from Customer c,Order o where o.customer=c").list();

            //方法2List<Object[]> list1 = session.createQuery("from Customer c  join c.orders").list();

          //迫切内连接加 fetch关键字- 不会像普通 内连接一样 放入Object[]中(其中像orders单独再封装成一个对象放入此数组中),而是是直接将记录封装成一个Customer对象(其中像orders单独再封装成一个对象放入此数组中)        

           // List<Object[]> list2 =session.createQuery("from Customer c join fetch c.orders").list();

           

            //左外连接

            List<Object[]> llist =session.createQuery("from Customer c join c.orders").list();

            //左迫切外连接

            List lflist = session.createQuery("fromCustomer c join fetch c.orders").list();

            closeStream(sessionFactory, session);

   }

 

  

         publicSession getSession() {

                  //1 读取配置文件

                  conf= new Configuration().configure();

                  //2 根据配置 创建Factory

                  sessionFactory= conf.buildSessionFactory();

                  //3 通过获得操作数据库的session对象

                  session= sessionFactory.openSession();

                  returnsession;

         }

 

         publicvoid closeStream(SessionFactory sessionFactory, Session session) {

                  if(session != null) {

                          session.close();

                  }

                  if(sessionFactory != null) {

                          sessionFactory.close();

                  }

         }

}

原创粉丝点击