本文主要探讨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. 查询
10.4.1. 执行查询
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());
10.4.1.1. 迭代式获取结果(Iterating results)
// 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)结果
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. 绑定参数
//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. 分页
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)
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()
10.4.1.7. 外置命名查询(Externalizing named queries)
<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();
10.4.2. 过滤集合
Collection blackKittens = session.createFilter( pk.getKittens(), "where this.color = ?") .setParameter( Color.BLACK, Hibernate.custom(ColorUserType.class) ) .list() );
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)
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的查询
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进行查询的情况,需要在具体的使用中仔细体会。