hibernate使用Query进行查询

本文主要探讨hibernate的简单查询,主要是使用Query进行的查询。

1.首先看下annotation的API中关于查询的描述

2.3. 映射查询

2.3.1. 映射EJBQL/HQL查询

使用注解还可以映射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

2.3.2. 映射本地化查询

你还可以映射本地化查询(也就是普通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", [email protected](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",
        [email protected](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", [email protected](name="dimension"))
@NamedNativeQuery(name="scalar", query="select length*width as dimension from SpaceShip", resultSetMapping="scalar")

本地查询中还有另外一个hint属性: org.hibernate.callable. 这个属性的布尔变量值表明这个查询是否是一个存储过程.

2.再来看下xml的API中关于查询的描述

10.4. 查询

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.

10.4.1. 执行查询

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
Set.

10.4.1.1. 迭代式获取结果(Iterating results)

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;
    }
}

10.4.1.2. 返回元组(tuples)的查询

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];
    ....
}

10.4.1.3. 标量(Scalar)结果

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];
    .....
}

10.4.1.4. 绑定参数

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 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();

10.4.1.5. 分页

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)。

10.4.1.6. 可滚动遍历(Scrollable iteration)

If your JDBC driver supports scrollable ResultSets, 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.

10.4.1.7. 外置命名查询(Externalizing named queries)

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.

<query name="ByNameAndMaximumWeight"><![CDATA[
    from eg.DomesticCat as cat
        where cat.name = ?
        and cat.weight > ?
] ]></query>

参数绑定及执行以编程方式(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 <hibernate-mapping> element
requires a global unique name for the query, while a query declaration inside a <class> element is made unique automatically by prepending the
fully qualified name of the class. For example eg.Cat.ByNameAndMaximumWeight.

10.4.2. 过滤集合

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();

10.4.3. 条件查询(Criteria queries)

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)
中详细讨论。

10.4.4. 使用原生SQL的查询

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.查询练习

新建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<Msg> 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<Msg> getMsgs() {
		return msgs;
	}
	public void setMsgs(List<Msg> 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

<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">

<hibernate-configuration>

    <session-factory>

        <!-- Database connection settings -->
        <property name="connection.driver_class">oracle.jdbc.driver.OracleDriver</property>
        <property name="connection.url">jdbc:oracle:thin:@127.0.0.1:1521:orcl</property>
        <property name="connection.username">scott</property>
        <property name="connection.password">tiger</property>

        <!-- JDBC connection pool (use the built-in) -->
        <!-- <property name="connection.pool_size">1</property> -->

        <!-- SQL dialect -->
        <property name="dialect">org.hibernate.dialect.Oracle9iDialect</property>

        <!-- Enable Hibernate's automatic session context management -->
        <property name="current_session_context_class">thread</property>

        <!-- Disable the second-level cache  -->
        <property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property>

        <!-- Echo all executed SQL to stdout -->
        <property name="show_sql">true</property>
        <property name="format_sql">true</property>

        <!-- Drop and re-create the database schema on startup -->
     <!--    <property name="hbm2ddl.auto">update</property> -->

		<mapping class="com.baosight.model.Category"/>
		<mapping class="com.baosight.model.Topic"/>
		<mapping class="com.baosight.model.Msg"/>
    </session-factory>

</hibernate-configuration>

JUnit测试类

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<Category> list = (List<Category>)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<Category> list = (List<Category>)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<Category> list = (List<Category>)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<Category> list = (List<Category>)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<Category> list = (List<Category>)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<Object[]> list = (List<Object[]>)q.list();
		for(Object[] c : list) {
			System.out.println(c[0]+"--"+c[1]);
		}
		session.getTransaction().commit();
	}
	@Test
	public void testHQL07() {
		//关联查询
		String sql = "";
		sql = "from Topic t where t.category.id=1";
		Session session = sessionFactory.getCurrentSession();
		session.beginTransaction();
		Query q = session.createQuery(sql);
		List<Topic> list = (List<Topic>)q.list();
		for(Topic c : list) {
			System.out.println(c.getId()+"--"+c.getTitle());
//			System.out.println(c.getCategory().getId()+"--"+c.getCategory().getName());
		}
		session.getTransaction().commit();
	}
	@Test
	public void testHQL08() {
		//多级关联查询
		String sql = "";
		sql = "from Msg m where m.topic.category.id=1";
		Session session = sessionFactory.getCurrentSession();
		session.beginTransaction();
		Query q = session.createQuery(sql);
		List<Msg> list = (List<Msg>)q.list();
		for(Msg c : list) {
			System.out.println(c.getId()+"--"+c.getCont());
//			System.out.println(c.getTopic().getTitle()+"--"+c.getTopic().getCategory().getName());
		}
		session.getTransaction().commit();
	}
	@Test
	public void testHQL09() {
		//通过辅助类查询
		String sql = "";
		sql = "select new com.baosight.model.MsgInfo(m.id,m.cont,m.topic.title,m.topic.category.name) from Msg m";
		Session session = sessionFactory.getCurrentSession();
		session.beginTransaction();
		Query q = session.createQuery(sql);
		List list = q.list();
		for(Object c : list) {
			MsgInfo m = (MsgInfo)c;
			System.out.println(m.getId()+"--"+m.getCont());
			System.out.println(m.getTopicName()+"--"+m.getCategoryName());
		}
		session.getTransaction().commit();
	}
	@Test
	public void testHQL10() {
		//连接查询个别字段
		String sql = "";
		sql = "select m.cont,t.title from Msg m join m.topic t";
		Session session = sessionFactory.getCurrentSession();
		session.beginTransaction();
		Query q = session.createQuery(sql);
		List<Object[]> list = (List<Object[]>)q.list();
		for(Object[] c : list) {
			System.out.println(c[0]+"--"+c[1]);
		}
		session.getTransaction().commit();
	}
	@Test
	public void testHQL11() {
		//使用uniqueResult
		String sql = "";
		sql = "from Msg m where m=:msgToSearch";
		Session session = sessionFactory.getCurrentSession();
		session.beginTransaction();
		Query q = session.createQuery(sql);
		Msg m = new Msg();
		m.setId("21");
		q.setParameter("msgToSearch", m);
		Msg msg = (Msg) q.uniqueResult();
		System.out.println(msg.getId()+"--"+msg.getCont());
		session.getTransaction().commit();
	}
	@Test
	public void testHQL12() {
		//使用uniqueResult
		String sql = "";
		sql = "select count(*) from Msg m";
		Session session = sessionFactory.getCurrentSession();
		session.beginTransaction();
		Query q = session.createQuery(sql);
		Long count = (Long) q.uniqueResult();
		System.out.println(count);
		session.getTransaction().commit();
	}
	@Test
	public void testHQL13() {
		//使用聚合函数
		String sql = "";
		sql = "select max(m.id),min(m.id),avg(m.id),sum(m.id) from Msg m";
		Session session = sessionFactory.getCurrentSession();
		session.beginTransaction();
		Query q = session.createQuery(sql);
		Object[] o = (Object[]) q.uniqueResult();
		System.out.println(o[0]+"--"+o[1]+"--"+o[2]+"--"+o[3]);
		session.getTransaction().commit();
	}
	@Test
	public void testHQL14() {
		//between and
		//in
		String sql = "";
//		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";
		Session session = sessionFactory.getCurrentSession();
		session.beginTransaction();
		Query q = session.createQuery(sql);
		List<Msg> list = (List<Msg>)q.list();
		for(Msg c : list) {
			System.out.println(c.getId()+"--"+c.getCont());
//			System.out.println(c.getTopic().getTitle()+"--"+c.getTopic().getCategory().getName());
		}
		session.getTransaction().commit();
	}
	@Test
	public void testHQL15() {
		//is empty
		//like
		String sql = "";
//		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'";
		Session session = sessionFactory.getCurrentSession();
		session.beginTransaction();
		Query q = session.createQuery(sql);
		List<Topic> list = (List<Topic>)q.list();
		for(Topic c : list) {
			System.out.println(c.getId()+"--"+c.getTitle());
//			System.out.println(c.getTopic().getTitle()+"--"+c.getTopic().getCategory().getName());
		}
		session.getTransaction().commit();
	}
	@Test
	public void testHQL16() {
		//字段函数
		String sql = "";
		sql = "select lower(m.cont),upper(m.cont),trim(m.cont),concat(m.cont,'***'),length(m.cont) from Msg m";
		Session session = sessionFactory.getCurrentSession();
		session.beginTransaction();
		Query q = session.createQuery(sql);
		List<Object[]> list = (List<Object[]>)q.list();
		for(Object[] c : list) {
			System.out.println(c[0]+"--"+c[1]+"--"+c[2]+"--"+c[3]+"--"+c[4]);
		}
		session.getTransaction().commit();
	}
	@Test
	public void testHQL17() {
		//运算函数
		String sql = "";
		sql = "select abs(m.id),sqrt(m.id),mod(m.id,2) from Msg m";
		Session session = sessionFactory.getCurrentSession();
		session.beginTransaction();
		Query q = session.createQuery(sql);
		List<Object[]> list = (List<Object[]>)q.list();
		for(Object[] c : list) {
			System.out.println(c[0]+"--"+c[1]+"--"+c[2]);
		}
		session.getTransaction().commit();
	}
	@Test
	public void testHQL18() {
		//日期函数
		String sql = "";
		sql = "select current_date,sysdate,current_timestamp,m.id from Msg m";
		Session session = sessionFactory.getCurrentSession();
		session.beginTransaction();
		Query q = session.createQuery(sql);
		List<Object[]> list = (List<Object[]>)q.list();
		for(Object[] c : list) {
			System.out.println(c[0]+"--"+c[1]+"--"+c[2]+"--"+c[3]);
		}
		session.getTransaction().commit();
	}
	@Test
	public void testHQL19() {
		//日期参数
		String sql = "";
		sql = "from Topic t where t.createDate<:date";
		Session session = sessionFactory.getCurrentSession();
		session.beginTransaction();
		Query q = session.createQuery(sql);
		q.setParameter("date", new Date());
		List<Topic> list = (List<Topic>)q.list();
		for(Topic c : list) {
			System.out.println(c.getId()+"--"+c.getTitle());
//			System.out.println(c.getTopic().getTitle()+"--"+c.getTopic().getCategory().getName());
		}
		session.getTransaction().commit();
	}
	@Test
	public void testHQL20() {
		//分组查询
		String sql = "";
//		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";
		Session session = sessionFactory.getCurrentSession();
		session.beginTransaction();
		Query q = session.createQuery(sql);
		List<Object[]> list = (List<Object[]>)q.list();
		for(Object[] c : list) {
			System.out.println(c[0]+"--"+c[1]);
		}
		session.getTransaction().commit();
	}
	@Test
	public void testHQL21() {
		//子查询
		//exists的使用
		String sql = "";
//		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)";
		Session session = sessionFactory.getCurrentSession();
		session.beginTransaction();
		Query q = session.createQuery(sql);
		List<Topic> list = (List<Topic>)q.list();
		for(Topic c : list) {
			System.out.println(c.getId()+"--"+c.getTitle());
//			System.out.println(c.getTopic().getTitle()+"--"+c.getTopic().getCategory().getName());
		}
		session.getTransaction().commit();
	}
	@Test
	public void testHQL22() {
		//update
		String sql = "";
		sql = "update Topic t set t.title=upper(t.title)";
		Session session = sessionFactory.getCurrentSession();
		session.beginTransaction();
		Query q = session.createQuery(sql);
		q.executeUpdate();
		q = session.createQuery("from Topic");
		List<Topic> list = (List<Topic>)q.list();
		for(Topic c : list) {
			System.out.println(c.getId()+"--"+c.getTitle());
//			System.out.println(c.getTopic().getTitle()+"--"+c.getTopic().getCategory().getName());
		}
		session.createQuery("update Topic t set t.title=lower(t.title)").executeUpdate();
		session.getTransaction().commit();
	}
	@Test
	public void testHQL23() {
		//NamedQuery
		Session session = sessionFactory.getCurrentSession();
		session.beginTransaction();
		Query q = session.getNamedQuery("topic.selectCertainTopic");
		q.setParameter("id", "15");
		Topic t = (Topic) q.uniqueResult();
		System.out.println(t.getId()+"--"+t.getTitle());
		session.getTransaction().commit();
	}
	@Test
	public void testHQL24() {
		//update
		Session session = sessionFactory.getCurrentSession();
		session.beginTransaction();
		SQLQuery q = session.createSQLQuery("select * from category").addEntity(Category.class);
		List<Category> list = (List<Category>)q.list();
		for(Category c : list) {
			System.out.println(c.getId()+"--"+c.getName());
//			System.out.println(c.getTopic().getTitle()+"--"+c.getTopic().getCategory().getName());
		}
		session.getTransaction().commit();
	}
	@Test
	public void testSchemaExport() {
		//建表
		new SchemaExport(new AnnotationConfiguration().configure()).create(false, true);
	}

	public static void main(String[] args) {
		beforeClass();
	}
}

4.首先执行测试类的testSchemaExport进行建表

4.1注意Topic中的private List<Msg> msgs;是后来测试is empty时添加的,刚开始并没有

4.2执行测试类的testSave插入测试数据

5.首先进行简单查询

5.1执行testHQL01进行单表查询

通过List<Category> list = (List<Category>)session.createQuery("from Category").list();

查询出结果集并进行遍历

5.2执行testHQL02进行单表条件查询

List<Category> list = (List<Category>)session.createQuery("from Category c where c.name>‘c5‘").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<Object[]> list = (List<Object[]>)q.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<Msg> getMsgs() {

查询时可以使用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进行查询的情况,需要在具体的使用中仔细体会。

时间: 2024-10-10 15:28:44

hibernate使用Query进行查询的相关文章

Hibernate Query Language查询:

Hibernate Query Language查询: Criteria查询对查询条件进行了面向对象封装,符合编程人员的思维方式,不过HQL(Hibernate Query Language)查询提供了更加丰富的和灵活的查询特性,因此Hibernate将HQL查询方式立为官方推荐的标准查询方式,HQL查询在涵盖Criteria查询的所有功能的前提下,提供了类似标准SQL语句的查询方式,同时也提供了更加面向对象的封装.完整的HQL语句形势如下: Select/update/delete-- fro

Hibernate 关于执行sql查询语句(转)

原文  http://www.yshjava.cn/post/543.html 主题 SQLHibernate Hibernate对原生SQL查询的支持和控制是通过SQLQuery接口实现的.通过Session接口,我们能够很方便的创建一个SQLQuery(SQLQuery是一个接口,在Hibernate4.2.2之前,默认返回的是SQLQuery的实现类--SQLQueryImpl对象,在下文中出现的SQLQuery如非注明,都是指该子类)对象来进行原生SQL查询: session.creat

Hibernate 插入,修改,删除,查询语句

/* *具体操作hibernate的类 *增加,删除,修改,按ID查询,模糊查询,查询全部 **/ public class PersonOperate { //在hibernate中所有操作都是由Session完成 public Session session = null; //在构造方法中实例化Session对象 public PersonOperate(){ //找出hibernate的配置 Configuration config = new Configuration().confi

Hibernate 之HQL数据查询

1. HQL简介 HQL是面向对象的查询语言,与SQL查询语言相比,虽然在语法上类似,都是运行时进行解析,但HQL并不像SQL那样操作的是数据表,列等数据库对象,HQL所操作的对象是类,对象,属性等.它也可以支持继承和多态等特征,在Hibernate 提供的各种检索方式中,HQL是使用最广泛的. 2. Query接口 Hibernate框架负责解析HQL语句,根据映射配置信息,把HQL查询语句解析成相应的SQL语句来执行数据库的查询操作.这一过程依赖的就是Query接口.Query的实例由Ses

Hibernate的检索方式--查询数据的方式

Hibernate 提供了以下几种检索对象的方式1导航对象图检索方式: 根据已经加载的对象导航到其他对象(根据已经加载的对象,导航到其他对象-例如一对多的查询)2OID 检索方式: 按照对象的 OID 来检索对象(更具ID查询---find(Id).get(),load())3HQL 检索方式: 使用面向对象的 HQL 查询语言4QBC 检索方式: 使用 QBC(Query By Criteria) API 来检索对象. 这种 API 封装了基于字符串形式的查询语句, 提供了更加面向对象的查询接

Hibernate 的原生 SQL 查询

Hibernate除了支持HQL查询外,还支持原生SQL查询.         对原生SQL查询执行的控制是通过SQLQuery接口进行的,通过执行Session.createSQLQuery()获取这个接口.该接口是Query接口的子接口.         执行SQL查询步骤如下:         1.获取Hibernate Session对象         2.编写SQL语句         3.通过Session的createSQLQuery方法创建查询对象         4.调用SQ

hibernate使用原生SQL查询返回结果集的处理

今天没事的时候,看到公司框架里有一个用原生SQL写的函数,说实在以前自己也干过这事,但好久都没有用,都忘得差不多了,现在基本都是用的hql语句来查询结果.hibernate中使用createSQLQuery拉来来实现SQL语句的查询,具体用法:session.createSQLQuery(sql),对于用SQL返回的结果集是一个什么样的结果集都毫无记忆.自己查了下,才知道,原来是返回一个Object类型数组的list集合,而其中Object类型的数组里的值则与sql语句中的查询项相对应,如果是s

Hibernate笔记——11.HQL查询

HQL是Hibernate的面向对象的查询语句.使用HQL,首先要得到session对象,然后编写HQL,以HQL语句为参数调用session的createQuery方法创建查询对象.如果HQL包含参数,则调用Query的set方法为参数赋值.调用Query对象的list或者uniqueResult方法返回查询结果列表(持久化实体集).

[Hibernate Search] (3) 基础查询

基础查询 眼下我们仅仅用到了基于keyword的查询,实际上Hibenrate Search DSL还提供了其他的查询方式,以下我们就来一探到底. 映射API和查询API 对于映射API.我们能够通过使用Hibernate提供的注解来完毕映射工作.同一时候我们也能够使用JPA提供的注解来完毕.类似的,对于查询API,我们也能够从Hibernate和JPA提供的查询API中进行选择. 每种方式都有它的长处和缺点,比方当我们使用Hibernate提供的查询API时,意味着能够使用很多其它的特性,毕竟