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无法实现插入操作。
转载请于明显处标明出处: