Hibernate学习(六)

Hibernate的三种查询方式

1、Criteria 查询 ,Query  By Criteria ( QBC )JPA 规范中定义的一种查询方法,但是不推荐使用

2、HQL : Hibernate Query Language , Hibernate 查询语言 ( 建议使用 )

3、Native SQL : Native SQL Query , 使用原生 SQL 语句进行查询

4、OID:根据id查询某一条记录

  • <T> T get(Class<T> entityType,Serializable id) 从数据库汇总查询一条记录并封装成一个相应类型的Java对象

              默认不支持延迟加载,当id对应的数据不存在时返回null

  • <T> T load(Class<T> theClass,Serializable id)  从数据库汇总查询一条记录并封装成一个相应类型的Java对象

              默认支持延迟加载,当id对应的数据不存在时抛出ObjectNotFoundException

  • <T> T find(Class<T> entityClass, Object primaryKey)  从数据库汇总查询一条记录并封装成一个相应类型的Java对象    javax.persistence.EntityManager中的

              默认不支持延迟加载,当id对应的数据不存在时返回null

5、对象导航方式查询:一个对象关联一个集合(一对多),hibernate会自动检索关联集合的数据

  • 比如一个班级中有多个学生,在班级的持久类中定义了private Set<Student> students属性,可以通过班级持久化类可以获取students。

Hibernate Query Language

1、查询所有

package ecut.query.test.hql;

import java.lang.reflect.Array;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.query.Query;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import ecut.query.entity.Clazz;

public class TestHibernateQuery1 {
    private SessionFactory factory ;
    private Session session ; 
    
    public @Before void init() {
        // 创建一个 Configuration 对象,用来读取配置文件 ( 默认位置、默认名称 )
        Configuration config = new Configuration();
        // 读取配置文件
        config.configure("ecut/query/hibernate.cfg.xml");
        //config.configure(); // 读取 默认位置 ( 当前 classpath ) 的 默认名称 ( hibernate.cfg.xml ) 的配置文件

        // 使用 Configuration 创建 SessionFactory
        factory = config.buildSessionFactory();
        
        // 创建 Session 对象 ( 这里的 Session 是 Java 程序 跟 数据库 之间的 会话 )
        session = factory.openSession();
    }
    
    /** 查询  Clazz 类 对应的表中的所有数据并 封装成  Clazz 对象 组成的 集合 */
    public @Test void query1(){
        
        String HQL = "FROM  Clazz" ; // 建议 所有的 SQL 关键字 一律大写
        
        // 通过 session 对象 来创建一个 查询器
        // session.createQuery( HQL ); // 如果类型不明确,可以采用该方法
        Query<Clazz>  queryer = session.createQuery( HQL , Clazz.class ) ; // 如果类型能够确定,建议指定类型
        System.out.println( "~~~~~~~~~~~~~~~~~~~" );
        List<Clazz> list = queryer.list() ; // 执行查询操作 ( 与 queryer.getResultList() 功能 相似 )
        System.out.println( list.size() );
        
        for( Clazz c : list ){
            System.out.println( c.getName() );
        }
        
    }
    
    /** 查询  Clazz 类 对应的表中的所有数据并 封装成  Clazz 对象 组成的 集合 */
    public @Test void query2(){
        
        String HQL = "SELECT c FROM  Clazz AS c" ; // 建议 所有的 SQL 关键字 一律大写
        
        Query<Clazz>  queryer = session.createQuery( HQL , Clazz.class ) ; 
        System.out.println( "~~~~~~~~~~~~~~~~~~~" );
        List<Clazz> list = queryer.list() ; // 执行查询操作
        
        for( Clazz c : list ){
            System.out.println( c.getName() );
        }
        
    }
    
    /** N + 1 问题  */
    @SuppressWarnings("deprecation")
    public @Test void query3(){
        
        String HQL = "SELECT c FROM  Clazz AS c" ; // 建议 所有的 SQL 关键字 一律大写
        
        Query<Clazz>  queryer = session.createQuery( HQL , Clazz.class ) ;
        
        System.out.println( "~~~~~~~~~~~~~~~~~~~" );
        
        // 第一次查询 ( 查询所有的对象标识符 )
        Iterator<Clazz> it = queryer.iterate(); // 执行查询操作 ( 但是 只获取 每个对象对应的 对象标识符 )
        
        // 每循环一次 就查询一条记录 ( N )
        while( it.hasNext() ){
            Clazz c = it.next();
            System.out.println( c.getId() + " : " + c.getName() );
        }
        
    }
    public @After void destory(){
        session.close();
        factory.close();
    }

}

HQL语句可以是SELECT c FROM  Clazz AS c 也可以将SELECT省略,除了可以使用list方法,也可以使用iterate方法(已过时)获取,每循环一次就查询一次记录,有N条记录就查询N次,调用iterate方法时也会调用一次查询获取所有对象的标识符,一共查询了N+1次即是N+1问题。

2、条件查询和排序查询

package ecut.query.test.hql;

import java.lang.reflect.Array;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.query.Query;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import ecut.query.entity.Clazz;

public class TestHibernateQuery1 {
    private SessionFactory factory ;
    private Session session ; 
    
    public @Before void init() {
        // 创建一个 Configuration 对象,用来读取配置文件 ( 默认位置、默认名称 )
        Configuration config = new Configuration();
        // 读取配置文件
        config.configure("ecut/query/hibernate.cfg.xml");
        //config.configure(); // 读取 默认位置 ( 当前 classpath ) 的 默认名称 ( hibernate.cfg.xml ) 的配置文件

        // 使用 Configuration 创建 SessionFactory
        factory = config.buildSessionFactory();
        
        // 创建 Session 对象 ( 这里的 Session 是 Java 程序 跟 数据库 之间的 会话 )
        session = factory.openSession();
    }

    /** 使用 条件过滤 和 排序 */
    public @Test void query4(){
        
        String HQL = "FROM  Clazz AS c WHERE c.id > 4 ORDER BY c.id DESC" ;
        
        Query<Clazz>  queryer = session.createQuery( HQL , Clazz.class ) ; 

        List<Clazz> list = queryer.list() ; // 执行查询操作
        
        for( Clazz c : list ){
            System.out.println( c.getId() + " : " + c.getName() );
        }
        
    }

    
    public @After void destory(){
        session.close();
        factory.close();
    }

}

3、标量查询(投影查询)

package ecut.query.test.hql;

import java.lang.reflect.Array;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.query.Query;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import ecut.query.entity.Clazz;

public class TestHibernateQuery1 {
    private SessionFactory factory ;
    private Session session ; 
    
    public @Before void init() {
        // 创建一个 Configuration 对象,用来读取配置文件 ( 默认位置、默认名称 )
        Configuration config = new Configuration();
        // 读取配置文件
        config.configure("ecut/query/hibernate.cfg.xml");
        //config.configure(); // 读取 默认位置 ( 当前 classpath ) 的 默认名称 ( hibernate.cfg.xml ) 的配置文件

        // 使用 Configuration 创建 SessionFactory
        factory = config.buildSessionFactory();
        
        // 创建 Session 对象 ( 这里的 Session 是 Java 程序 跟 数据库 之间的 会话 )
        session = factory.openSession();
    }
   /** 标量查询: 查询单个属性 */
    public @Test void query5(){
        
        String HQL = "SELECT c.name FROM  Clazz AS c" ;
        
        Query<String>  queryer = session.createQuery( HQL , String.class) ; 

        List<String> list = queryer.list() ; // 执行查询操作
        
        for( String o : list ){
            System.out.println( o );
        }
        
    }
    
    /** 标量查询: 查询多个属性 */
    public @Test void query6(){
        
        String HQL = "SELECT c.id , c.name FROM  Clazz AS c" ;
        
        Query<?>  queryer = session.createQuery( HQL ) ; 

        List<?> list = queryer.list() ; // 执行查询操作
        
        for( Object o : list ){
            Class<?> c = o.getClass(); // 获得当前元素的类型
            if( c.isArray() ) {
                int length = Array.getLength( o ); // 用  java.lang.reflect.Array 中的方法获取数组长度
                // 用反射的方式遍历数组
                for( int i = 0 ; i < length ; i ++ ){
                    Object e = Array.get( o ,  i ) ; // Object e = o[ i ] ;
                    System.out.print( e );
                    System.out.print( "	");
                }
                System.out.println();
            }
        }
        
    }
    
    /** 标量查询: 查询多个属性 */
    public @Test void query7(){
        
        String HQL = "SELECT c.id , c.name FROM  Clazz AS c" ;
        
        Query<Object[]>  queryer = session.createQuery( HQL , Object[].class ) ; 

        List<Object[]> list = queryer.list() ; // 执行查询操作
        
        for( Object[] array : list ){
            if( array == null || array.length == 0 ){
                System.out.println( "没有数据" );
            } else {
                for( int i = 0 , n = array.length ; i < n ; i++ ){
                    Object e = array[ i ] ; 
                    System.out.print( e + "	" );
                }
                System.out.println();
            }
        }
        
    }
    
    /** 查询多个属性返回实体类型的对象 */
    public @Test void query8(){
        
        // String HQL = "SELECT new Clazz( c.id , c.name ) FROM  Clazz AS c" ;
        
        String HQL = "SELECT new Clazz( c.name , c.id ) FROM  Clazz AS c" ;
        
        Query<Clazz>  queryer = session.createQuery( HQL ,Clazz.class ) ; 

        List<Clazz> list = queryer.list() ; // 执行查询操作
        
        for( Clazz c : list ){
            if( c != null ) {
                System.out.println( c.getId() + " : " + c.getName() );
            }
        }
        
    }
    
    /** 查询单个或多个属性,并返回 map 组成的 List 集合 */
    @SuppressWarnings("rawtypes")
    public @Test void query9(){
        
        // 如果没有通过 AS 关键字指定 属性的 别名,
        // 那么将来的 Map 集合中 key 是按照 属性出现的顺序对应的索引 ( 不是数字类型而是 String 类型 )
        // String HQL = "SELECT new map( c.id , c.name ) FROM  Clazz AS c WHERE c.id = 1 " ;
        
        // 使用 AS 关键字指定  属性的 别名 ,将的 Map 集合中 key 的名称就是这里的 别名
        String HQL = "SELECT new map( c.id AS id , c.name AS name ) FROM  Clazz AS c" ;
        
        Query<Map>  queryer = session.createQuery( HQL ,Map.class ) ; 

        List<Map> list = queryer.list() ; // 执行查询操作
        
        for( Map map : list ){
            System.out.println( map.get( "id" ) + " : " + map.get( "name" ) );
        }
        
        /*
        for( Map map : list ){
            Set<Entry> entrySet =  map.entrySet();
            for ( Entry e : entrySet ){
                //System.out.println( e.getKey() + " : " + e.getKey().getClass().getName() );
                // System.out.println( e.getValue() + " : " + e.getValue().getClass().getName() );
                 System.out.println( e.getKey() + " : " + e.getValue() );
                
            }
        }
        */
        
    }
    
    public @After void destory(){
        session.close();
        factory.close();
    }

}

标量查询返回的是由Object数组组成的List集合,可以利用反射去进行遍历。也可以将字段封装到对象中,使用SELECT new Clazz( c.id , c.name ) FROM Clazz AS c这种格式的HQL,并需要在持久化类中指定与之对应的有参构造,才可以完成封装。或者将对象封装到一个map(本质是HashMap,但是HQL中只能写Map)中。

4、多表查询

package ecut.query.test.hql;

import java.lang.reflect.Array;
import java.util.List;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.query.Query;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import ecut.query.entity.Clazz;
import ecut.query.entity.Student;

public class TestHibernateQuery2 {
    private SessionFactory factory ;
    private Session session ; 
    
    public @Before void init() {
        // 创建一个 Configuration 对象,用来读取配置文件 ( 默认位置、默认名称 )
        Configuration config = new Configuration();
        // 读取配置文件
        config.configure("ecut/query/hibernate.cfg.xml");
        //config.configure(); // 读取 默认位置 ( 当前 classpath ) 的 默认名称 ( hibernate.cfg.xml ) 的配置文件

        // 使用 Configuration 创建 SessionFactory
        factory = config.buildSessionFactory();
        
        // 创建 Session 对象 ( 这里的 Session 是 Java 程序 跟 数据库 之间的 会话 )
        session = factory.openSession();
    }
    
    /** 使用 表连接进行查询 ( 内连接 ) */
    public @Test void query10(){
        
        // select * from t_class c , t_student s where c.id = s.class_id ;
        // select * from t_class c inner join t_student s on c.id = s.class_id ;
        // select * from t_class c cross join t_student s where c.id = s.class_id ;
        String HQL = "FROM Clazz AS c , Student AS s WHERE c.id = s.clazz.id" ;
        
        Query<?> queryer = session.createQuery( HQL );
        
        List<?> list = queryer.list();
        
        System.out.println( list.size() );
        
        for( Object o : list ){
            Class<?> c = o.getClass();
            if( c.isArray() ){
                final int length = Array.getLength( o ) ;
                for( int i = 0 ; i < length ; i ++ ){
                    Object e = Array.get( o ,  i ) ; // Object e = o[ i ] ;
                    System.out.print( e + "	" );
                }
                System.out.println();
            }
        }
        
    }
    
    /** 连接查询 ( Clazz 对应表 跟  Clazz 中 students 对应的表 进行连接 ) */
    public @Test void query11(){
        
        // select * from t_class c inner join t_student s on c.id = s.class_id ;
        String HQL = "FROM Clazz AS c JOIN c.students" ;
        
        Query<?> queryer = session.createQuery( HQL );
        
        List<?> list = queryer.list();
        
        System.out.println( list.size() );

        for( Object o : list ){
            Class<?> c = o.getClass();
            if( c.isArray() ){
                final int length = Array.getLength( o ) ;
                for( int i = 0 ; i < length ; i ++ ){
                    Object e = Array.get( o ,  i ) ; // Object e = o[ i ] ;
                    System.out.print( e + "	" );
                }
                System.out.println();
            }
        }
        
    }
    
    /** 连接查询 ( 使用 fetch 关键字 ) */
    public @Test void query12(){
        
        // 使用 fetch 关键字后,下面的 HQL 语句执行后返回 由 Clazz 对象组成的 List 集合
        // Student 对象被自动添加到 相应 的班级对象的 students 集合中
        String HQL = "FROM Clazz AS c JOIN fetch c.students" ;
        
        Query<Clazz> queryer = session.createQuery( HQL , Clazz.class );
        
        List<Clazz> list = queryer.list();
        
        System.out.println( list.size() );
        
        for( Clazz c : list ){
            System.out.println( c.getName() + " : " + c.getStudents().size() );
        }
        
    }
    
    /** 使用 DISTINCT 剔除重复数据 */
    public @Test void query13(){
        
        String HQL = "SELECT DISTINCT c FROM Clazz AS c JOIN fetch c.students" ;
        
        Query<Clazz> queryer = session.createQuery( HQL , Clazz.class );
        
        List<Clazz> list = queryer.list();
        
        System.out.println( list.size() );
        
        for( Clazz c : list ){
            System.out.println( c.getName() + " : " + c.getStudents().size() );
        }
        
    }
    
    /** 使用左外连接: 查询所有班级 及 各班级的学生 ( 暂时没有学生的班级也列出来 ) */
    public @Test void query14(){
        //SELECT * FROM t_class c LEFT JOIN  t_student AS s ON  s.class_id = c.id
        String HQL = "SELECT DISTINCT c FROM Clazz AS c LEFT JOIN fetch c.students" ;
        
        Query<Clazz> queryer = session.createQuery( HQL , Clazz.class );
        
        List<Clazz> list = queryer.list();
        
        System.out.println( list.size() );
        
        for( Clazz c : list ){
            System.out.println( c.getName() + " : " + c.getStudents().size() );
        }
        
    }
    
    /** 使用左外连接: 查询每个学生及其班级信息,如果某个学生没有明确班级,也列出来 */
    public @Test void query15(){
        
        String HQL = "FROM Student AS s  LEFT  OUTER  JOIN fetch s.clazz" ;
        
        Query<Student> queryer = session.createQuery( HQL , Student.class );
        
        List<Student> list = queryer.list();
        
        System.out.println( list.size() );
        
        for( Student c : list ){
            System.out.println( c.getName() + " : " + c.getClazz() );
        }
        
    }
    
    public @After void destory(){
        session.close();
        factory.close();
    }

}

 使用迫切内连接(fetch 关键字)后,执行返回 由 Clazz 对象组成的 List 集合,Student 对象被自动添加到 相应 的班级对象的 students 集合中,而不是默认返回的object[]。另外可以使用DISTINCT 删除重复数据。HQL中使用LEFT OUTER JOIN来实现左连接。

5、HQL参数传递

  • 使用 ? 做参数占位符
    package ecut.query.test.hql;
    
    import java.util.List;
    
    import org.hibernate.Session;
    import org.hibernate.SessionFactory;
    import org.hibernate.cfg.Configuration;
    import org.hibernate.query.Query;
    import org.junit.After;
    import org.junit.Before;
    import org.junit.Test;
    import ecut.query.entity.Student;
    
    public class TestHibernateQuery3 {
        private SessionFactory factory ;
        private Session session ; 
        
        public @Before void init() {
            // 创建一个 Configuration 对象,用来读取配置文件 ( 默认位置、默认名称 )
            Configuration config = new Configuration();
            // 读取配置文件
            config.configure("ecut/query/hibernate.cfg.xml");
    
            //config.configure(); // 读取 默认位置 ( 当前 classpath ) 的 默认名称 ( hibernate.cfg.xml ) 的配置文件
    
            // 使用 Configuration 创建 SessionFactory
            factory = config.buildSessionFactory();
            
            // 创建 Session 对象 ( 这里的 Session 是 Java 程序 跟 数据库 之间的 会话 )
            session = factory.openSession();
        }
        
        /** 使用 ? 做参数占位符 */
        public @Test void query16(){
            
            String HQL = "FROM Student AS s  WHERE s.id BETWEEN ? AND ? " ;
            
            Query<Student> queryer = session.createQuery( HQL , Student.class );
            
            queryer.setParameter( 0 , 5 ); // JDBC是从1开始,HQL的参数占位符的索引从 0 开始
            queryer.setParameter( 1 , 10 );
            
            List<Student> list = queryer.list();
            
            System.out.println( list.size() );
            
            for( Student c : list ){
                System.out.println( c.getId() + " : " + c.getName()  );
            }
            
        }
    public @After void destory(){ session.close(); factory.close(); } }

    JDBC是从1开始,HQL的参数占位符的索引从 0 开始。

  • 使用 命名 参数占位符
    package ecut.query.test.hql;
    
    import java.util.List;
    
    import org.hibernate.Session;
    import org.hibernate.SessionFactory;
    import org.hibernate.cfg.Configuration;
    import org.hibernate.query.Query;
    import org.junit.After;
    import org.junit.Before;
    import org.junit.Test;
    import ecut.query.entity.Student;
    
    public class TestHibernateQuery3 {
        private SessionFactory factory ;
        private Session session ; 
        
        public @Before void init() {
            // 创建一个 Configuration 对象,用来读取配置文件 ( 默认位置、默认名称 )
            Configuration config = new Configuration();
            // 读取配置文件
            config.configure("ecut/query/hibernate.cfg.xml");
    
            //config.configure(); // 读取 默认位置 ( 当前 classpath ) 的 默认名称 ( hibernate.cfg.xml ) 的配置文件
    
            // 使用 Configuration 创建 SessionFactory
            factory = config.buildSessionFactory();
            
            // 创建 Session 对象 ( 这里的 Session 是 Java 程序 跟 数据库 之间的 会话 )
            session = factory.openSession();
        }
    /** 使用 命名 参数占位符 */
        public @Test void query17(){
            
            String HQL = "FROM Student AS s  WHERE s.id BETWEEN :start AND :end " ;
            
            Query<Student> queryer = session.createQuery( HQL , Student.class );
            
            queryer.setParameter( "start" , 5 ); // 参数占位符的索引从 0 开始
            queryer.setParameter( "end" , 10 );
            
            List<Student> list = queryer.list();
            
            System.out.println( list.size() );
            
            for( Student c : list ){
                System.out.println( c.getId() + " : " + c.getName()  );
            }
            
        }
        
        public @After void destory(){
            session.close();
            factory.close();
        }
    
    }

6、HQL实现更新和删除

package ecut.query.test.hql;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.query.Query;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import ecut.query.entity.Student;

public class TestHibernateQuery4 {
    private SessionFactory factory ;
    private Session session ; 
    
    public @Before void init() {
        // 创建一个 Configuration 对象,用来读取配置文件 ( 默认位置、默认名称 )
        Configuration config = new Configuration();
        // 读取配置文件
        config.configure("ecut/query/hibernate.cfg.xml");

        //config.configure(); // 读取 默认位置 ( 当前 classpath ) 的 默认名称 ( hibernate.cfg.xml ) 的配置文件

        // 使用 Configuration 创建 SessionFactory
        factory = config.buildSessionFactory();
        
        // 创建 Session 对象 ( 这里的 Session 是 Java 程序 跟 数据库 之间的 会话 )
        session = factory.openSession();
    }
    
    /** 使用 HQL 方式支持 update */
    public @Test void update(){
        
        //String HQL = "UPDATE Student AS s SET s.name = ? WHERE id = ? " ;
        String HQL = "UPDATE Student AS s SET s.name = :name WHERE s.id = :id " ;
        
        Query<?> queryer = session.createQuery( HQL );
        
        queryer.setParameter( "name" , "张无忌" );
        queryer.setParameter( "id" , 2 );
        
        session.getTransaction().begin();
        
        int count = queryer.executeUpdate();
        
        session.getTransaction().commit();
        
        System.out.println( "受影响的记录数: " +  count );
        
    }

    /** 使用 HQL 方式支持 delete */
    public @Test void delete(){
        
        String HQL = "DELETE  FROM Student AS s WHERE s.id = :id " ;
        
        Query<?> queryer = session.createQuery( HQL );
        
        queryer.setParameter( "id" , 8 );
        
        session.getTransaction().begin();
        
        int count = queryer.executeUpdate();
        
        session.getTransaction().commit();
        
        System.out.println( "受影响的记录数: " +  count );
        
    }
    
    /** 使用 HQL 方式不支持 insert into */
    public @Test void insert(){
        
        // 错误: String HQL = "INSERT INTO Student ( id , name ) VALUES ( ? , ? )" ;
        
        Student s = new Student();
        s.setName( "林平之" );
        
        session.getTransaction().begin();
        session.save( s );
        session.getTransaction().commit();
        
    }
    
    public @After void destory(){
        session.close();
        factory.close();
    }

}

HQL 支持更新和删除,但是不支持插入。

Native SQL Query

1、标量查询(投影查询)

package ecut.query.test.sql;

import java.util.List;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.query.NativeQuery;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import ecut.query.entity.Clazz;

public class TestNativeSQLQuery {

    private SessionFactory factory ;
    private Session session ;

    public @Before void init() {
        
        Configuration config = new Configuration();
        config.configure("ecut/query/hibernate.cfg.xml");

        //config.configure(); 
    
        factory = config.buildSessionFactory();
        
        session = factory.openSession();
    }
    //标量查询
    public @Test void query1(){
        
        String SQL = "SELECT id , name FROM t_class" ;
        
        // SQLQuery queryer = session.createSQLQuery( SQL ); // 过时
        // NativeQuery<?> queryer = session.createNativeQuery( SQL );
        NativeQuery<Object[]> queryer = session.createNativeQuery( SQL , Object[].class );
        
        List<Object[]> list = queryer.list();
        
        for( Object[] o : list ){
            System.out.println( o[ 0 ] + " : " + o[ 1 ]);
        }
        
    }
    
    public @Test void query2(){
        
        String SQL = "SELECT name FROM t_class" ;
        
        NativeQuery<?> queryer = session.createNativeQuery( SQL );
        
        List<?> list = queryer.list();
        
        for( Object o : list ){
            System.out.println( o + " : " + o.getClass().getName() );
        }
        
    }
    
    /** 执行 SQL 语句并将结果集中的数据 封装到 指定的实体类型的对象中 */
    public @Test void query3(){
        
        String SQL = "SELECT id , name FROM t_class" ;
        
        NativeQuery<Clazz> queryer = session.createNativeQuery( SQL , Clazz.class );
        
        List<Clazz> list = queryer.list();
        
        for( Clazz c : list ){
            System.out.println( c.getId() + " : " + c.getName() ) ;
        }
        
    }
   public @After void destory(){
        session.close();
        factory.close();
    }

}

可以在List中指定具体的类型实现对字段的封装,不再是保存为Object数组。

2、排序查询

package ecut.query.test.sql;

import java.util.List;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.query.NativeQuery;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import ecut.query.entity.Clazz;

public class TestNativeSQLQuery {

    private SessionFactory factory ;
    private Session session ;

    public @Before void init() {
        
        Configuration config = new Configuration();
        config.configure("ecut/query/hibernate.cfg.xml");

        //config.configure(); 
    
        factory = config.buildSessionFactory();
        
        session = factory.openSession();
    }
   /** 使用 ? 做参数占位符 */
    public @Test void query4(){
        
        String SQL = "SELECT id , name FROM t_class WHERE id > ? ORDER BY id DESC" ;
        
        NativeQuery<Clazz> queryer = session.createNativeQuery( SQL , Clazz.class );
        
        queryer.setParameter( 1 , 5 ); // 执行 SQL 语句跟 执行 HQL 语句不同,这里的索引跟JDBC一致,从 1 开始
        
        List<Clazz> list = queryer.list();
        
        for( Clazz c : list ){
            System.out.println( c.getId() + " : " + c.getName() ) ;
        }
        
    }

    /** 使用 命名 参数占位符 */
    public @Test void query5(){
        
        String SQL = "SELECT id , name FROM t_class WHERE id > :id ORDER BY id DESC" ;
        
        NativeQuery<Clazz> queryer = session.createNativeQuery( SQL , Clazz.class );
        
        queryer.setParameter( "id" , 5 ); 
        
        List<Clazz> list = queryer.list();
        
        for( Clazz c : list ){
            System.out.println( c.getId() + " : " + c.getName() ) ;
        }
        
    }
public @After void destory(){
        session.close();
        factory.close();
    }

}

SQL中也可以通过使用?做参数占位符和使用命名参数占位符,但是与HQL不同的是SQL和JDBC一样参数占位符的索引从 1 开始。

3、SQL实现更新、插入和删除操作

package ecut.query.test.sql;

import java.util.List;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.query.NativeQuery;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import ecut.query.entity.Clazz;

public class TestNativeSQLQuery {

    private SessionFactory factory ;
    private Session session ;

    public @Before void init() {
        
        Configuration config = new Configuration();
        config.configure("ecut/query/hibernate.cfg.xml");

        //config.configure(); 
    
        factory = config.buildSessionFactory();
        
        session = factory.openSession();
    }
 public @Test void insert(){
        
        String SQL = "INSERT INTO t_class ( id , name ) VALUES ( :id , :name )" ;
        
        NativeQuery<?> queryer = session.createNativeQuery( SQL );
        
        queryer.setParameter( "id" , 8 ); 
        queryer.setParameter( "name" ,  "计算机科学技术" );
        
        session.getTransaction().begin();
        int count = queryer.executeUpdate();
        System.out.println( count );
        session.getTransaction().commit();
        
    }
    
    public @Test void update(){
        
        String SQL = "UPDATE t_class SET name = :name WHERE id = :id" ;
        
        NativeQuery<?> queryer = session.createNativeQuery( SQL );
        
        queryer.setParameter( "id" , 8 ); 
        queryer.setParameter( "name" ,  "大数据与云计算" );
        
        session.getTransaction().begin();
        int count = queryer.executeUpdate();
        System.out.println( count );
        session.getTransaction().commit();
        
    }
    
    public @Test void delete(){
        
        String SQL = "DELETE FROM t_class WHERE id = :id" ;
        
        NativeQuery<?> queryer = session.createNativeQuery( SQL );
        
        queryer.setParameter( "id" , 8 ); 
        
        session.getTransaction().begin();
        int count = queryer.executeUpdate();
        System.out.println( count );
        session.getTransaction().commit();
        
    }
    
    public @After void destory(){
        session.close();
        factory.close();
    }

}

SQL可以实现插入操作但是HQL无法实现插入操作。

转载请于明显处标明出处:

https://www.cnblogs.com/AmyZheng/p/9324192.html

原文地址:https://www.cnblogs.com/AmyZheng/p/9324192.html