本文主要探讨hibernate的简单查询,主要是使用Query进行的查询。
1.首先看下annotation的API中关于查询的描述
使用注解还可以映射EJBQL/HQL查询. @NamedQuery 和@NamedQueries是可使用在类和包上的注解. 但是它们的定义在session factory/entity manager factory范围中是都可见的. 命名式查询通过它的名字和实际的查询字符串来定义.
javax.persistence.NamedQueries( @javax.persistence.NamedQuery(name="plane.getAll", query="select p from Plane p") ) package org.hibernate.test.annotations.query; ... @Entity @NamedQuery(name="night.moreRecentThan", query="select n from Night n where n.date >= :date") public class Night { ... } public class MyDao { doStuff() { Query q = s.getNamedQuery("night.moreRecentThan"); q.setDate( "date", aMonthAgo ); List results = q.list(); ... } ... }
还可以通过定义 QueryHint 数组的hints 属性为查询提供一些hint信息.
下面是目前可以使用的一些Hibernate hint:
表 2.2. Query hints
hint | description |
---|---|
org.hibernate.cacheable | 查询是否与二级缓存交互(默认值为false) |
org.hibernate.cacheRegion | 设置缓存区名称 (默认为otherwise) |
org.hibernate.timeout | 查询超时设定 |
org.hibernate.fetchSize | 所获取的结果集(resultset)大小 |
org.hibernate.flushMode | 本次查询所用的刷新模式 |
org.hibernate.cacheMode | 本次查询所用的缓存模式 |
org.hibernate.readOnly | 是否将本次查询所加载的实体设为只读(默认为false) |
org.hibernate.comment | 将查询注释添加入所生成的SQL |
你还可以映射本地化查询(也就是普通SQL查询). 不过这需要你使用@SqlResultSetMapping注解来描述SQL的resultset的结构 (如果你打算定义多个结果集映射,可是使用@SqlResultSetMappings). @SqlResultSetMapping和@NamedQuery, @SqlResultSetMapping一样,可以定义在类和包一级. 但是@SqlResultSetMapping的作用域为应用级. 下面我们会看到,@NamedNativeQuery 注解中 resultSetMapping参数值为@SqlResultSetMapping的名字. 结果集映射定义了通过本地化查询返回值和实体的映射. 该实体中的每一个字段都绑定到SQL结果集中的某个列上. 该实体的所有字段包括子类的所有字段以及 关联实体的外键列都必须在SQL查询中有对应的定义. 如果实体中的属性和SQL查询中的列名相同,这种情况下可以不进行定义字段映射.
@NamedNativeQuery(name="night&area", query="select night.id nid, night.night_duration, "
+ " night.night_date, area.id aid, night.area_id, area.name "
+ "from Night night, Area area where night.area_id = area.id", resultSetMapping="joinMapping")
@SqlResultSetMapping(name="joinMapping", entities={
@EntityResult(entityClass=org.hibernate.test.annotations.query.Night.class, fields = {
@FieldResult(name="id", column="nid"),
@FieldResult(name="duration", column="night_duration"),
@FieldResult(name="date", column="night_date"),
@FieldResult(name="area", column="area_id"),
discriminatorColumn="disc"
}),
@EntityResult(entityClass=org.hibernate.test.annotations.query.Area.class, fields = {
@FieldResult(name="id", column="aid"),
@FieldResult(name="name", column="name")
})
}
)
在上面这个例子中,名为night&area的查询 和joinMapping结果集映射对应. 该映射返回两个实体,分别为Night 和Area,其中每个属性都和一个列关联, 列名通过查询获取.下面我们看一个隐式声明属性和列映射关系的例子.
@Entity
@SqlResultSetMapping(name="implicit", entities=@EntityResult(entityClass=org.hibernate.test.annotations.query.SpaceShip.class))
@NamedNativeQuery(name="implicitSample", query="select * from SpaceShip", resultSetMapping="implicit")
public class SpaceShip {
private String name;
private String model;
private double speed;
@Id
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Column(name="model_txt")
public String getModel() {
return model;
}
public void setModel(String model) {
this.model = model;
}
public double getSpeed() {
return speed;
}
public void setSpeed(double speed) {
this.speed = speed;
}
}
在这个例子中,我们只需要定义结果集映射中的实体成员. 属性和列名之间的映射借助实体中包含映射信息来完成. 在这个例子中,model属性绑定到model_txt列. 如果和相关实体的关联设计到组合主键, 那么应该使用@FieldResult注解来定义每个外键列. @FieldResult的名字由以下几部分组成: 定义这种关系的属性名字+"."+主键名或主键列或主键属性.
@Entity
@SqlResultSetMapping(name="compositekey",
entities=@EntityResult(entityClass=org.hibernate.test.annotations.query.SpaceShip.class,
fields = {
@FieldResult(name="name", column = "name"),
@FieldResult(name="model", column = "model"),
@FieldResult(name="speed", column = "speed"),
@FieldResult(name="captain.firstname", column = "firstn"),
@FieldResult(name="captain.lastname", column = "lastn"),
@FieldResult(name="dimensions.length", column = "length"),
@FieldResult(name="dimensions.width", column = "width")
}),
columns = { @ColumnResult(name = "surface"),
@ColumnResult(name = "volume") } )
@NamedNativeQuery(name="compositekey",
query="select name, model, speed, lname as lastn, fname as firstn, length, width, length * width as surface from SpaceShip",
resultSetMapping="compositekey")
} )
public class SpaceShip {
private String name;
private String model;
private double speed;
private Captain captain;
private Dimensions dimensions;
@Id
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@ManyToOne(fetch= FetchType.LAZY)
@JoinColumns( {
@JoinColumn(name="fname", referencedColumnName = "firstname"),
@JoinColumn(name="lname", referencedColumnName = "lastname")
} )
public Captain getCaptain() {
return captain;
}
public void setCaptain(Captain captain) {
this.captain = captain;
}
public String getModel() {
return model;
}
public void setModel(String model) {
this.model = model;
}
public double getSpeed() {
return speed;
}
public void setSpeed(double speed) {
this.speed = speed;
}
public Dimensions getDimensions() {
return dimensions;
}
public void setDimensions(Dimensions dimensions) {
this.dimensions = dimensions;
}
}
@Entity
@IdClass(Identity.class)
public class Captain implements Serializable {
private String firstname;
private String lastname;
@Id
public String getFirstname() {
return firstname;
}
public void setFirstname(String firstname) {
this.firstname = firstname;
}
@Id
public String getLastname() {
return lastname;
}
public void setLastname(String lastname) {
this.lastname = lastname;
}
}
观察dimension属性你会发现Hibernate支持用"."符号来表示嵌入式对象. EJB3实现不必支持这个特征,但是我们做到了:-)
如果查询返回的是单个实体,或者你打算使用系统默认的映射, 这种情况下可以不使用resultSetMapping 而是使用resultClass属性:
@NamedNativeQuery(name="implicitSample", query="select * from SpaceShip",
resultClass=SpaceShip.class)
public class SpaceShip {
某些本地查询返回的是scalar值,例如报表查询. 你可以通过@ColumnResult将其映射到 @SqlResultsetMapping上. 甚至还可以在同一个本地查询的结果中混合实体和scalar类型(不过这种情况比较少见).
@SqlResultSetMapping(name="scalar", columns=@ColumnResult(name="dimension"))
@NamedNativeQuery(name="scalar", query="select length*width as dimension from SpaceShip", resultSetMapping="scalar")
本地查询中还有另外一个hint属性: org.hibernate.callable. 这个属性的布尔变量值表明这个查询是否是一个存储过程.
If you do not know the identifiers of the objects you are looking for, you need a query. Hibernate supports an easy-to-use but powerful object oriented query language (HQL). For programmatic query creation, Hibernate supports a sophisticated Criteria and Example query feature (QBC and QBE). You can also express your query in the native SQL of your database, with optional support from Hibernate for result set conversion into objects.
HQL和原生SQL(native SQL)查询要通过为org.hibernate.Query
的实例来表达。 这个接口提供了参数绑定、结果集处理以及运行实际查询的方法。 你总是可以通过当前Session
获取一个Query
对象:
List cats = session.createQuery( "from Cat as cat where cat.birthdate < ?") .setDate(0, date) .list(); List mothers = session.createQuery( "select mother from Cat as cat join cat.mother as mother where cat.name = ?") .setString(0, name) .list(); List kittens = session.createQuery( "from Cat as cat where cat.mother = ?") .setEntity(0, pk) .list(); Cat mother = (Cat) session.createQuery( "select cat.mother from Cat as cat where cat = ?") .setEntity(0, izi) .uniqueResult();]] Query mothersWithKittens = (Cat) session.createQuery( "select mother from Cat as mother left join fetch mother.kittens"); Set uniqueMothers = new HashSet(mothersWithKittens.list());
A query is usually executed by invoking list()
. The result of the query will be loaded completely into a collection in memory. Entity instances retrieved by a query are in a persistent state. The uniqueResult()
method offers a shortcut if you know your query will only return a single object. Queries that make use of eager fetching of collections usually return duplicates of the root objects, but with their collections initialized. You can filter these duplicates through a Set
.
Occasionally, you might be able to achieve better performance by executing the query using the iterate()
method. This will usually be the case if you expect that the actual entity instances returned by the query will already be in the session or second-level cache. If they are not already cached, iterate()
will be slower thanlist()
and might require many database hits for a simple query, usually 1 for the initial select which only returns identifiers, and n additional selects to initialize the actual instances.
// fetch ids Iterator iter = sess.createQuery("from eg.Qux q order by q.likeliness").iterate(); while ( iter.hasNext() ) { Qux qux = (Qux) iter.next(); // fetch the object // something we couldnt express in the query if ( qux.calculateComplicatedAlgorithm() ) { // delete the current instance iter.remove(); // dont need to process the rest break; } }
Hibernate queries sometimes return tuples of objects. Each tuple is returned as an array:
Iterator kittensAndMothers = sess.createQuery( "select kitten, mother from Cat kitten join kitten.mother mother") .list() .iterator(); while ( kittensAndMothers.hasNext() ) { Object[] tuple = (Object[]) kittensAndMothers.next(); Cat kitten = (Cat) tuple[0]; Cat mother = (Cat) tuple[1]; .... }
Queries can specify a property of a class in the select
clause. They can even call SQL aggregate functions. Properties or aggregates are considered "scalar" results and not entities in persistent state.
Iterator results = sess.createQuery( "select cat.color, min(cat.birthdate), count(cat) from Cat cat " + "group by cat.color") .list() .iterator(); while ( results.hasNext() ) { Object[] row = (Object[]) results.next(); Color type = (Color) row[0]; Date oldest = (Date) row[1]; Integer count = (Integer) row[2]; ..... }
Methods on Query
are provided for binding values to named parameters or JDBC-style ?
parameters. Contrary to JDBC, Hibernate numbers parameters from zero. Named parameters are identifiers of the form :name
in the query string. The advantages of named parameters are as follows:
命名参数(named parameters)与其在查询串中出现的顺序无关
they can occur multiple times in the same query
它们本身是自我说明的
//named parameter (preferred) Query q = sess.createQuery("from DomesticCat cat where cat.name = :name"); q.setString("name", "Fritz"); Iterator cats = q.iterate();
//positional parameter Query q = sess.createQuery("from DomesticCat cat where cat.name = ?"); q.setString(0, "Izi"); Iterator cats = q.iterate();
//named parameter list List names = new ArrayList(); names.add("Izi"); names.add("Fritz"); Query q = sess.createQuery("from DomesticCat cat where cat.name in (:namesList)"); q.setParameterList("namesList", names); List cats = q.list();
If you need to specify bounds upon your result set, that is, the maximum number of rows you want to retrieve and/or the first row you want to retrieve, you can use methods of the Query
interface:
Query q = sess.createQuery("from DomesticCat cat"); q.setFirstResult(20); q.setMaxResults(10); List cats = q.list();
Hibernate 知道如何将这个有限定条件的查询转换成你的数据库的原生SQL(native SQL)。
If your JDBC driver supports scrollable ResultSet
s, the Query
interface can be used to obtain aScrollableResults
object that allows flexible navigation of the query results.
Query q = sess.createQuery("select cat.name, cat from DomesticCat cat " + "order by cat.name"); ScrollableResults cats = q.scroll(); if ( cats.first() ) { // find the first name on each page of an alphabetical list of cats by name firstNamesOfPages = new ArrayList(); do { String name = cats.getString(0); firstNamesOfPages.add(name); } while ( cats.scroll(PAGE_SIZE) ); // Now get the first page of cats pageOfCats = new ArrayList(); cats.beforeFirst(); int i=0; while( ( PAGE_SIZE > i++ ) && cats.next() ) pageOfCats.add( cats.get(1) ); } cats.close()
Note that an open database connection and cursor is required for this functionality. UsesetMaxResult()
/setFirstResult()
if you need offline pagination functionality.
You can also define named queries in the mapping document. Remember to use a CDATA
section if your query contains characters that could be interpreted as markup.
? ] ]>
参数绑定及执行以编程方式(programatically)完成:
Query q = sess.getNamedQuery("ByNameAndMaximumWeight"); q.setString(0, name); q.setInt(1, minWeight); List cats = q.list();
The actual program code is independent of the query language that is used. You can also define native SQL queries in metadata, or migrate existing queries to Hibernate by placing them in mapping files.
Also note that a query declaration inside a
element requires a global unique name for the query, while a query declaration inside a
element is made unique automatically by prepending the fully qualified name of the class. For example eg.Cat.ByNameAndMaximumWeight
.
A collection filter is a special type of query that can be applied to a persistent collection or array. The query string can refer to this
, meaning the current collection element.
Collection blackKittens = session.createFilter( pk.getKittens(), "where this.color = ?") .setParameter( Color.BLACK, Hibernate.custom(ColorUserType.class) ) .list() );
The returned collection is considered a bag that is a copy of the given collection. The original collection is not modified. This is contrary to the implication of the name "filter", but consistent with expected behavior.
Observe that filters do not require a from
clause, although they can have one if required. Filters are not limited to returning the collection elements themselves.
Collection blackKittenMates = session.createFilter( pk.getKittens(), "select this.mate where this.color = eg.Color.BLACK.intValue") .list();
Even an empty filter query is useful, e.g. to load a subset of elements in a large collection:
Collection tenKittens = session.createFilter( mother.getKittens(), "") .setFirstResult(0).setMaxResults(10) .list();
HQL is extremely powerful, but some developers prefer to build queries dynamically using an object-oriented API, rather than building query strings. Hibernate provides an intuitive Criteria
query API for these cases:
Criteria crit = session.createCriteria(Cat.class); crit.add( Restrictions.eq( "color", eg.Color.BLACK ) ); crit.setMaxResults(10); List cats = crit.list();
Criteria
以及相关的样例(Example)
API将会再第 15 章 条件查询(Criteria Queries)中详细讨论。
You can express a query in SQL, using createSQLQuery()
and let Hibernate manage the mapping from result sets to objects. You can at any time call session.connection()
and use the JDBC Connection
directly. If you choose to use the Hibernate API, you must enclose SQL aliases in braces:
List cats = session.createSQLQuery("SELECT {cat.*} FROM CAT {cat} WHERE ROWNUM<10") .addEntity("cat", Cat.class) .list();
List cats = session.createSQLQuery( "SELECT {cat}.ID AS {cat.id}, {cat}.SEX AS {cat.sex}, " + "{cat}.MATE AS {cat.mate}, {cat}.SUBCLASS AS {cat.class}, ... " + "FROM CAT {cat} WHERE ROWNUM<10") .addEntity("cat", Cat.class) .list()
SQL queries can contain named and positional parameters, just like Hibernate queries. More information about native SQL queries in Hibernate can be found in 第 16 章 Native SQL查询.
新建3个类,Category、Topic和Msg,其中Category和Topic是1对多,Topic和Msg是1对多
另外还有1个查询辅助类MsgInfo,注意此类不适用注解
Category
package com.baosight.model;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
@Entity
public class Category {
private String id;
private String name;
@Id
@GeneratedValue
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Topic
package com.baosight.model;
import java.util.Date;
import java.util.List;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.OneToMany;
@Entity
@NamedQueries({ @NamedQuery(name = "topic.selectCertainTopic", query = "from Topic t where t.id=:id") })
public class Topic {
private String id;
private String title;
private Category category;
private Date createDate;
private List msgs;
@ManyToOne
public Category getCategory() {
return category;
}
public void setCategory(Category category) {
this.category = category;
}
@Id
@GeneratedValue
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public Date getCreateDate() {
return createDate;
}
public void setCreateDate(Date createDate) {
this.createDate = createDate;
}
@OneToMany(mappedBy="topic")
public List getMsgs() {
return msgs;
}
public void setMsgs(List msgs) {
this.msgs = msgs;
}
}
Msg
package com.baosight.model;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
@Entity
public class Msg {
private String id;
private String cont;
private Topic topic;
@Id
@GeneratedValue
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getCont() {
return cont;
}
public void setCont(String cont) {
this.cont = cont;
}
@ManyToOne
public Topic getTopic() {
return topic;
}
public void setTopic(Topic topic) {
this.topic = topic;
}
}
MsgInfo
package com.baosight.model;
public class MsgInfo {
private String id;
private String cont;
private String topicName;
private String categoryName;
public MsgInfo(String id, String cont, String topicName, String categoryName) {
super();
this.id = id;
this.cont = cont;
this.topicName = topicName;
this.categoryName = categoryName;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getCont() {
return cont;
}
public void setCont(String cont) {
this.cont = cont;
}
public String getTopicName() {
return topicName;
}
public void setTopicName(String topicName) {
this.topicName = topicName;
}
public String getCategoryName() {
return categoryName;
}
public void setCategoryName(String categoryName) {
this.categoryName = categoryName;
}
}
hibernate.cfg.xml
oracle.jdbc.driver.OracleDriver
jdbc:oracle:thin:@127.0.0.1:1521:orcl
scott
tiger
org.hibernate.dialect.Oracle9iDialect
thread
org.hibernate.cache.NoCacheProvider
true
true
package com.baosight.model;
import java.util.Date;
import java.util.List;
import java.util.Map;
import org.hibernate.Query;
import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.AnnotationConfiguration;
import org.hibernate.tool.hbm2ddl.SchemaExport;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
public class OrMappingTest {
private static SessionFactory sessionFactory;
@BeforeClass
public static void beforeClass() {
//new SchemaExport(new AnnotationConfiguration().configure()).create(false, true);
sessionFactory = new AnnotationConfiguration().configure().buildSessionFactory();
}
@AfterClass
public static void afterClass() {
sessionFactory.close();
}
@Test
public void testSave() {
//插入数据
Session session = sessionFactory.getCurrentSession();
session.beginTransaction();
for(int i=0;i<10;i++){
Category c = new Category();
c.setName("c"+i);
session.save(c);
}
for(int i=0;i<10;i++){
Category c = new Category();
c.setId("1");
Topic t = new Topic();
t.setTitle("t"+i);
t.setCreateDate(new Date());
t.setCategory(c);
session.save(t);
}
for(int i=0;i<10;i++){
Topic t = new Topic();
t.setId("11");
Msg m = new Msg();
m.setCont("m"+i);
m.setTopic(t);
session.save(m);
}
session.getTransaction().commit();
}
@Test
public void testHQL01() {
Session session = sessionFactory.getCurrentSession();
session.beginTransaction();
//查询
List list = (List)session.createQuery("from Category").list();
for(Category c : list) {
System.out.println(c.getName());
}
session.getTransaction().commit();
}
@Test
public void testHQL02() {
Session session = sessionFactory.getCurrentSession();
session.beginTransaction();
//条件查询
List list = (List)session.createQuery("from Category c where c.name>'c5'").list();
for(Category c : list) {
System.out.println(c.getName());
}
session.getTransaction().commit();
}
@Test
public void testHQL03() {
//排序等
String sql = "";
// sql = "from Category c order by c.name desc";
sql = "select distinct c from Category c order by c.name desc";
Session session = sessionFactory.getCurrentSession();
session.beginTransaction();
List list = (List)session.createQuery(sql).list();
for(Category c : list) {
System.out.println(c.getName());
}
session.getTransaction().commit();
}
@Test
public void testHQL04() {
//传参查询
String sql = "";
sql = "from Category c where c.id>:min and c.id<:max order by c.name desc";
Session session = sessionFactory.getCurrentSession();
session.beginTransaction();
Query q = session.createQuery(sql);
q.setParameter("min", "2");
q.setParameter("max", "8");
List list = (List)q.list();
for(Category c : list) {
System.out.println(c.getId()+"--"+c.getName());
}
session.getTransaction().commit();
}
@Test
public void testHQL05() {
//分页查询
String sql = "";
sql = "from Category c order by c.name desc";
Session session = sessionFactory.getCurrentSession();
session.beginTransaction();
Query q = session.createQuery(sql);
q.setMaxResults(4);//每页条数
q.setFirstResult(2);//开始行号
List list = (List)q.list();
for(Category c : list) {
System.out.println(c.getId()+"--"+c.getName());
}
session.getTransaction().commit();
}
@Test
public void testHQL06() {
//查询字段
String sql = "";
sql = "select c.id,c.name from Category c order by c.name desc";
Session session = sessionFactory.getCurrentSession();
session.beginTransaction();
Query q = session.createQuery(sql);
List
4.首先执行测试类的testSchemaExport进行建表
4.1注意Topic中的private List
5.首先进行简单查询
5.1执行testHQL01进行单表查询
通过List
查询出结果集并进行遍历
List
5.3执行testHQL03进行单表查询排序和使用distinct
sql = "from Category c order by c.name desc";
sql = "select distinct c from Category c order by c.name desc";
5.4执行testHQL04进行单表查询传入查询参数
使用:xx定义传入参数,使用q.setParameter("xx", Obj);传入参数
sql = "from Category c where c.id>:min and c.id<:max order by c.name desc";
q.setParameter("min", "2");
q.setParameter("max", "8");
5.5执行testHQL05进行单表分页查询
使用q.setMaxResults(xx);设置每页条数;使用q.setFirstResult(xx);设置开始行号
sql = "from Category c order by c.name desc";
q.setMaxResults(4);//每页条数
q.setFirstResult(2);//开始行号
5.6执行testHQL06进行单表字段查询
注意此时查询的结果是Object[]组成的list
sql = "select c.id,c.name from Category c order by c.name desc";
List
6.进行关联查询
6.1多对一关联查询,使用testHQL07
查询语句为sql = "from Topic t where t.category.id=1";这体现了hibernate对象查询的本质,直接通过对象进行关联查询
6.2使用testHQL08进行多级关联
sql = "from Msg m where m.topic.category.id=1";
6.3使用辅助类进行查询,此查询和ibatis里面的查询辅助类相似
sql = "select new com.baosight.model.MsgInfo(m.id,m.cont,m.topic.title,m.topic.category.name) from Msg m";
运行testHQL09
6.4进行连接查询,运行testHQL10
sql = "select m.cont,t.title from Msg m join m.topic t";
注意使用m.topic就指明了二者之间的连接字段
6.5使用uniqueResult,运行testHQL11
查询结果只有1条记录时可以使用类似于Msg msg = (Msg) q.uniqueResult();进行查询
一般适用于通过id进行查询,或者是使用聚合函数查询出单条记录等
6.6使用count查询统计,运行testHQL12
sql = "select count(*) from Msg m";
Long count = (Long) q.uniqueResult();
查询结果是Long
6.7使用聚合函数查询统计,运行testHQL13
sql = "select max(m.id),min(m.id),avg(m.id),sum(m.id) from Msg m";
7.条件查询
7.1使用between and/in/is not null查询,运行testHQL14
sql = "from Msg m where m.id between 21 and 24";
sql = "from Msg m where m.id in(22,23,24)";
sql = "from Msg m where m.topic is not null";
7.2使用is empty/like查询,运行testHQL15
上面6.7中is null是在多的一方查询1,如果想要在1的一方查询多,需要在1中配置@OneToMany(mappedBy="topic")
public List
查询时可以使用sql = "from Topic t where t.msgs is empty";
sql = "from Topic t where t.title like '%5'";
sql = "from Topic t where t.title like '_5'";
8.使用常用函数进行查询
8.1使用字符串函数查询,运行testHQL16
sql = "select lower(m.cont),upper(m.cont),trim(m.cont),concat(m.cont,'***'),length(m.cont) from Msg m";
8.2使用数学运算函数查询,运行testHQL17
sql = "select abs(m.id),sqrt(m.id),mod(m.id,2) from Msg m";
8.3使用日期函数查询,运行testHQL18
sql = "select current_date,sysdate,current_timestamp,m.id from Msg m";
8.4使用日期函数传参查询,运行testHQL19
sql = "from Topic t where t.createDate<:date";q.setParameter("date", new Date());
9.复杂查询
9.1使用group by和having进行分组查询,运行testHQL20
sql = "select t.title,count(*) from Topic t group by t.title";
sql = "select t.title,count(*) from Topic t group by t.title having count(*)>1";
9.2使用子查询和exists,运行testHQL21
sql = "from Topic t where t.id<(select avg(t1.id) from Topic t1)";
sql = "from Topic t where t.id< all(select t1.id from Topic t1 where mod(t1.id,2)=0)";
sql = "from Topic t where not exists(select m.id from Msg m where m.topic.id=t.id)";
sql = "from Topic t where exists(select m.id from Msg m where m.topic.id=t.id)";
9.3使用executeUpdate进行修改和删除操作等,运行testHQL22
sql = "update Topic t set t.title=upper(t.title)";
q.executeUpdate();
10.其它查询形式
10.1使用NamedQuery进行查询,运行testHQL23
需要先使用annotation进行声明
@NamedQueries({ @NamedQuery(name = "topic.selectCertainTopic", query = "from Topic t where t.id=:id") })
Query q = session.getNamedQuery("topic.selectCertainTopic");
10.2使用NativeSQL进行查询,运行testHQL24
注意,此时使用的不是hibernate的对象查询,二是使用sql进行查询,类似于JDBC
SQLQuery q = session.createSQLQuery("select * from category").addEntity(Category.class);
以上主要探讨了hibernate使用Query进行查询的情况,需要在具体的使用中仔细体会。