Hibernate(03)

作者: 71150ce14a00 | 来源:发表于2017-09-14 20:12 被阅读24次
    对象导航检索方式: 主要针对关联集合对象的
    查询(针对多表)   查找目标表数据再访问其关联的集合对象属性的时候,自动发送sql语句
     注意:导航检索必须是持久态对象,否则不能导航, 解决办法 : 在session关闭之前,对对象中集合或者对象初始化
    默认情况下,关联属性是延迟加载的,只有在访问其关联属性的时候才发出SQL从数据库查询,导致查询两张表数据时,至少发出两部分SQL语句,一个是主对象查询语句,一个是关联属性的语句。
    

    OID检索方式:

     session.get(entity.class,id),session.load(entity.class,id)(单表 byid)
    HQL检索方式:session.createQuery(hql).list(),uniqu…// 面向对象
    SQL检索方式(Native Query):session.createSQLQuery(sql).addEntity().list(),
    QBC检索方式:(Query by Criteria):session.createCriteria(Entity.class).list()// 面向对象
    

    HQL\QBC和SQL的区别?

    HQL\QBC 面向类和属性,由hibernate自动生成sql语句,效率低
    SQL 面向表和字段, 不会去组建sql语句,效率高
    

    条件查找

    public void testQueryByCondition(){
             Session session = HibernateUtil. openSession();
              session.beginTransaction();
       
              /**HQL*/
              Customer c1 = (Customer) session.createQuery( "from Customer where name=?")
          // .setParameter(0, "tom");
             .setString(0, "tom")
             .uniqueResult();
             System. out.println(c1 );
             
              /**SQL*/
              Customer c2 = (Customer) session.createSQLQuery( "select * from t_customer where name=:name").addEntity(Customer. class)
    //  .setParameter("name", "tom")
             .setString( "name", "tom" )
             .uniqueResult();
             System. out.println(c2 );
             
              /**QBC*/
             Criteria criteria = session.createCriteria(Customer. class);
             List<Customer> list = criteria.add(Restrictions.like("name" , "%o%" )).list();
             System. out.println(list );
    
              session.getTransaction().commit();
              session.close();
       }
    
    1
              :name   .setString("name","db");
    HQL检索: session.createQuery("from 实体 where name=?").setParameter(0,"name").uniqueResult();  
    SQL检索 : session.createSQLQuery("select * from 表 where name=?").addEntity(实体.class).setParameter(0,"name").uniqueResult();  
    QBC检索:  criteriy=  session.createCriteria(实体.class);
                        criteriy.add(Restricions.eq("name","db"));
                        criteriy.uniqueResult();
    

    排序

     Session session = HibernateUtil. openSession();
              session.beginTransaction();
             
              /**HQL*/
             List<Customer> list = session.createQuery("from Customer order by id desc").list(); // 此id为实体类中的对象id
             System. out.println(list );
             
              /**SQL*/
             List<Customer> list2 = session.createSQLQuery("select * from t_customer order by id desc").addEntity(Customer. class).list();// 此id为数据库属性
             System. out.println(list2 );
             
              /**QBC*/
             List<Customer> list3 = session.createCriteria(Customer.class).addOrder(org.hibernate.criterion.Order. desc("id")).list() ;
             System. out.println(list3 );
             
              session.getTransaction().commit();
              session.close();
    

    分页查询:

              // 当前页
              int pageNo = 2;
              // 每页显示的数量
              int pageCount = 10;
              // 下标计算公式
              int index = (pageNo -1)*pageCount ;
             
             Session session = HibernateUtil. openSession();
              session.beginTransaction();
              /**HQL*/
             List<Order> list = session.createQuery("from Order")
             .setFirstResult( index)
             .setMaxResults( pageCount).list();
             System. out.println(list );
             
              /**之前的SQL*/
             List<Order> list2 = session.createSQLQuery("select * from t_order limit ?,?").addEntity(Order. class).setParameter(0, index).setParameter(1, pageCount).list();
             System. out.println("old" +list2 );
             
              /**SQL*/
             List<Order> list3 = session.createSQLQuery("select * from t_order").addEntity(Order. class).setFirstResult(index).setMaxResults(pageCount).list() ;
             System. out.println("new" +list3 );
             
             
              /**QBC*/
             List<Order> list4 = session.createCriteria(Order.class).setFirstResult( index).setMaxResults(pageCount).list();   
             System. out.println(list4 );
    
     //oracle:写的技巧:先在 sql编辑器中写好,再复制进来改一改就行了。
     List<Order> list2 = session.createSQLQuery("SELECT * FROM (SELECT t.*,ROWNUM r FROM t_order t WHERE ROWNUM<="+(firstResult+maxResults)+") t2 WHERE t2.r>="+(firstResult+1)).addEntity(Order.class).list();
        System.out.println(list2);
    
    投影查询: 查询结果仅包含实体的部分属性, 即只查询表中的部分指定字段的值,不查询全部
     用List<Object[]> 接收    , 非受管对象,不受session管理,不会在一级缓存中存在,一般不用, 一般都查所有的
    经过投影查询的结果,默认 都不会封装到实体类型中, 而是根据实际查询的结果自动封装(object[]),如查询id和name,返回的object[]的list集合。
    最大的坏处:一级缓存不存放该对象。无法使用hibernate的一些特性,比如快照等等。
    【注意】查询之后封装到Object[]数组中的这些数据,称之为散装数据,不会存放于一级缓存,所以未来需要用的时候,还要查询,尽量少用
             Session session = HibernateUtil. openSession();
              session.beginTransaction();
             
              /**HQL*/
              //此时不再封装成实体对象,而是返回Object[]的散装数据
              List<Object[]> list = session.createQuery("select c.name,c.city from Customer c where c.id=?").setParameter(0, 1).list() ;
              for (Object[] object : list ) {
                    System. out.println(object [0]+":" +object [1]);
                    
             }
             
              /**SQL*/
              //此时不再封装成实体对象,而是返回Object[]的散装数据
             List<Object[]> list2 = session.createSQLQuery("select c.name,c.city from t_customer c where c.id=:id").setParameter("id" , 1).list();
              for (Object[] o : list2 ) {
                    System. out.println(o [0]+":" +o [1]);
             }
             
              /**QBC*/
              //此时不再封装成实体对象,而是返回Object[]的散装数据
             List<Object[]> list3 = session.createCriteria(Customer.class)
             .setProjection(Projections. projectionList()
             .add(Property. forName("name"))
             .add(Property. forName("city")))
             .add(Restrictions. eq("id", 1)).list() ;
              for (Object[] o : list3 ) {
                    System. out.println(o [0]+":" +o [1]);
             }
    
              session.getTransaction().commit();
              session.close();
    投影查询也可以封装成对象, 但是对象必须要有对应参数的构造方法
    

    HQL:

    List<Customer> list4 = session.createQuery( "select new Customer(c.id,c.name) from Customer c").list() ;
    

    QBC

             Criteria criteria = session.createCriteria(Customer. class);
              criteria.setProjection(Projections. projectionList()
                           .add(Property. forName("name").as( "name"))
                           .add(Property. forName("city").as( "city")));
              criteria.setResultTransformer( new AliasToBeanResultTransformer(Customer.class ));
             List<Customer> list = criteria .list();
    

    或者

    criteria.setResultTransformer(Transformers.aliasToBean(Customer.class))
    

    聚合函数count查询

             Session session = HibernateUtil. openSession();
              session.beginTransaction();
             
              /**HQL*/
               Long obj = (Long) session.createQuery( "select count(*) from Customer c").uniqueResult();
               System. out.println(obj );
              
              /**SQL*/
             BigInteger count = (BigInteger) session.createSQLQuery( "select count(*) from t_customer").uniqueResult();
             System. out.println(count );
             
              /**QBC*/
             Long num = (Long) session.createCriteria(Customer. class)
             .setProjection(Projections. rowCount())//相当于 count(*)
             .setProjection(Projections. count("name")) // 相当于 count(name)
             .uniqueResult();
             System. out.println(num );
             
              session.getTransaction().commit();
              session.close();
    

    命名查询:是将sql或hql语句写入配置文件中,为该语句起个名字,在程序中通过名字来访问sql或hql语句

    第一步:在hbm中配置命名查询的名字和语句(支持HQL或Sql)
     第二步:在程序中通过session.getNamedQuery(命名查询的名字)来直接获取Query或SQLQuery对象,进行操作
              <!-- 命名查询 --> 在class中命名
              <query name= "query1">
                    from Customer where name=? and city=?
              </query>
       </class >    // class外命名 
                     <sql-query name= "cn.itcast.a_oneToMany.Customer.query2" >
                    select * from t_customer where name = ? and city = ?
              </sql-query>
             
    
              /**HQL*/
             Customer c = (Customer) session.getNamedQuery("cn.itcast.a_oneToMany.Customer.query1" ).setParameter(0, "tom")
             .setParameter(1, "上海").uniqueResult();
             System. out.println(c );
             
              /**SQL*/
             SQLQuery query  = (SQLQuery) session.getNamedQuery("cn.itcast.a_oneToMany.Customer.query2" );
              query.addEntity(Customer. class);
              query.setParameter(0, "tom");
              query.setParameter(1, "上海");
             Customer c2 = (Customer) query.uniqueResult();
             System. out.println(c2 );
    
    离线查询: DetachedCriteria   脱离离session,在service层拼接条件,传到dao层, dao层只需一个方法
    Criteria:在线查询方式:依赖session,有了session之后,才能去创建Criteria对象,然后才可以添加条件
    DetachedCriteria:离线查询方式:不依赖session创建,自身内部含有创建方式,可以在没有session的情况下,自由的组装各种条件,然后在发送给session执行
    通过静态方法 DetachedCriteria.forClass(PO.class)来实例化
    通过detachedCriteria.getExecutableCriteria(session)方法与session关联
              /**Service层*/
              //离线查询(先拼装查询条件,然后再用Session去查询数据库)
              DetachedCriteria criteria = DetachedCriteria.forClass(Customer.class);
              criteria.add(Restrictions. like("name", "%o%"));
              criteria.add(Restrictions. eq("city", "上海"));
             
             
              /**传递Dao层*/
             Session session = HibernateUtil. openSession();
              session.beginTransaction();
             
             Customer  c = (Customer) criteria.getExecutableCriteria(session ).uniqueResult();
             System. out.println(c );
             
              session.getTransaction().commit();
              session.close()
    

    内连接和迫切连接fetch

    相同点:都是只需要发出一条SQL就可以将两个表的数据一次性查询出来。
    不同点:返回的结果的默认封装方式不同:
    内连接将结果封装为List<Object[]>,Object[]中再封装了实体对象。非受管对象。
    迫切内连接将结果封装为List<主表的实体>,这里是List<Customer>,其从表数据  被封装到主表实体中的关联属性中了。而且是受管对象
    

    HQL

       List list15 = session .createQuery("from Customer c left join c.orders").list();
       List list15 = session.createQuery( "select distinct c from Customer c left join fetch c.orders").list();
    

    SQL:

    List<Object[]> list = session.createSQLQuery("select c.id as cid,c.name as cname,c.city,o.id as oid,o.name as oname,o.price from t_customer c inner join t_order o on c.id=o.cid").list();
    

    QBC:

    criteria. createCriteria("orders",CriteriaSpecification. LEFT_JOIN);
     criteria.createCriteria( "orders",org.hibernate.sql.JoinType.LEFT_OUTER_JOIN);//表示左外连接,默认是内连接
    

    Query功能扩展: 也可以完成增删改

    int rows = session.createQuery("update Customer set name = ' Jattt' where id = ?").setParameter(0, 2) .executeUpdate()
    

    JPA注解:
    注解要么都放属性上,要么都放getter上,不能混着用

    @Entity // 将当前类标识为一个实体类,表名默认是类名
    @Table(catalog="user" ,name="t_book" ) //catalog数据库名   name为表名
    public class Book {
        @Id // 指定该字段是主键, 注解也可以写在getter方法上
        @GeneratedValue(strategy=GenerationType.AUTO) // 默认是自动增长,主键生成策略  auto相当于native
    // @GenericGenerator(name="myidGenerator",strategy="assigned")// HIbernate的主键策略生成器,name主键生成器名字, strategy:生成策略
    // @GeneratedValue(generator="myidGenerator") // 使用自定义扩展主键生成器
        private Integer id ;
        @Column(name= "name",length=30,nullable=false,unique=true)
        private String name ;
        @Column(name= "price",unique=false )
        @Basic // 表示该字段有效,数据库会生成队列(默认)  不写则默认为@Basic
        private Double price ;
        @Transient // 控制数据库不生成队列
        private String stat ;
    

    一对多

    @Entity  
    @Table(name="t_customer" ) 
    public class Customer {
        @Id
        @GeneratedValue(strategy=GenerationType.AUTO)
        private Integer id;
        private String name ;
        private String city ;
        @OneToMany(mappedBy="customer" ,// 相当于inverse=true放弃外键维护权,配置当前Customer对象在Order实体中的名称
                    fetch=FetchType. LAZY, // 设置是否延迟加载
                    cascade=CascadeType. ALL, // 设置级联
                    targetEntity=Order. class // 设置集合中放入的目前实体的类型,基本上可以忽略
                    )
        private Set<Order> orders = new HashSet<Order>();
    
    @Entity
    @Table(name="t_order" )
    public class Order {
        @Id
        @GeneratedValue(strategy=GenerationType.AUTO)
        private Integer id ;
        private String name ;
        private Double price ;
       
        @ManyToOne
        @JoinColumn(name="cid" )// 设置外键
        private Customer customer ;
         // 配置映射文件
          <mapping class= "cn.jpa.oneToMany.Customer" />
       <mapping class= "cn.jpa.oneToMany.Order" />
    

    多对多:

    @Entity
    @Table(name="t_course" )
    public class Course {
        @Id
        @GeneratedValue (strategy=GenerationType.AUTO)
        private Integer id ;
        private String name ;
        @ManyToMany(mappedBy="courses" )// 放弃外键维护权
        private Set<Student> students = new HashSet<Student>();
    
    @Entity
    @Table(name="t_student" )
    public class Student {
        @Id
        @GeneratedValue(strategy=GenerationType.AUTO)
        private Integer id ;
        private String name ;
        @ManyToMany(cascade=CascadeType.ALL)
        @JoinTable(name="t_s_c" ,
       joinColumns= @JoinColumn(name="sid" ),// 配置Student对象在关系表中的外键名
       inverseJoinColumns= @JoinColumn(name="cid" ))// 配置放弃外键维护权一方在关系表中的外键名
        private Set<Course> courses = new HashSet<Course>();
    

    测试:

     Session session = HibernateUtil. openSession();
             Transaction tran = session.beginTransaction();
             
             Student s = new Student();
              s.setName( "杨过");
             
             Course c = new Course();
              c.setName("java" );
             
              s.getCourses().add( c);
    //c.getStudents().add(s);
              session.save( s);
    //session.save(c);
              tran.commit();
              session.close();
    

    注解命名查询:
    HQL:

    @NamedQuery(name="Student.findAll" ,query="from Student" )
    @NamedQueries(value={
              @NamedQuery(name="query1" ,query="from Student" ),
              @NamedQuery(name="query2" ,query="from Student" ),
              @NamedQuery(name="query3" ,query="from Student" )
    })
    
    @Entity
    @Table(name="t_student" )
    public class Student {}
    
    List<Student> list = session.getNamedQuery( "Student.findAll").list();
     System. out.println(list .get(0).getCourses());
    
    List<Student> list = session.getNamedQuery( "query1").list();
     System. out.println(list .get(0).getCourses());
    

    SQL

    //sql
    @NamedNativeQuery(name="Customer.findcount" ,query="select count(*) from t_customer")//配置一个
    @NamedNativeQueries({@NamedNativeQuery (name="Customer.findcount" ,query="select count(*) from t_customer"),@NamedNativeQuery(name= "Customer.findcount2",query="select count(*) from t_customer" )})
    

    相关文章

      网友评论

        本文标题:Hibernate(03)

        本文链接:https://www.haomeiwen.com/subject/dxtjsxtx.html