2HQL及自增主键

1HQL

Hibernate Query Language是一种面向对象的查询语言,HQL的操作对象时类,实例,属性;与EJB3 QL很接近。

HQL的功能非常丰富,where子句后支持的运算符异常丰富,不仅包括SQL的运算符,还包括EJB-QL的运算符等。

除了Java类与属性的名称外,查询语句对大小些并不敏感。

HQL 不支持union联合查询。

select子句

select子句用于确定选择出的属性,当然select选择的属性必须是from后持久化类包含的属性。例如:

select p.name from Person as p

这个select子句与EJB3 QL一样。

from子句

Hibernate中最简单的查询语句的形式如下:

from Cat

大多数情况下, 你需要指定一个别名, 原因是你可能需要 在查询语句的其它部分引用到Cat:from Cat as cat

where子句

where子句中允许使用大部分SQL支持的表达式:

数学运算符+、–、*、/?等。

比较运算符=、>、>=、<、<=、<>、!=、like等。

逻辑运算符and、or、not等。

in、not in、between、is null、is not null、is empty、is not empty、member of和not member of等。

简单的case、case ... when ... then ... else ... end和case、case when ... then ... else ...       end等。

字符串连接符value1 || value2或使用字符串连接函数concat(value1 , value2)。

时间操作函数current_date()、current_time()、current_timestamp()、second()、minute()、hour()、day()、month()、year()等。

HQL还支持EJB-QL 3.0所支持的函数或操作substring()、trim()、lower()、upper()、length()、locate()、abs()、sqrt()、bit_length()、coalesce()和nullif()等。

还支持数据库的类型转换函数,如cast(... as ...),第二个参数是Hibernate的类型名,或者extract(... from ...),前提是底层数据库支持ANSI cast()?和extract()。

例如:

cast(arg1 as arg2);arg1是要转换的数据,arg2是目标类型(不是数据库类型名,是hibernate类型名:比如目标类型是varchar,必须写string)

SELECT CAST( ’2012-12-24′ AS DATE ) 把字符串转换成date类型

SELECT CAST( 2012 AS string ) 把数字转化成字符串

SELECT CAST( ‘baiduzhidao’ AS char(3) ) 取指定长度的字符

在HQL中子查询一般出现在where子句中,不能像sql语句那样在from后嵌套子查询,通过子查询来查询某个字段等。如:

List list=session.createQuery(“from Customer c where 1>(select count(o) from c.orders o)”).list();

下面这种子查询是正确的:

Query query=em.createQuery("select g.ginID as ginID,(select x.name from Gstorage x where x.gstorageID=g.glocationID) as gstorageN from Gin g ");

下面这种子查询是错误的:

Query query=em.createQuery("select o.ginID as ginID from ( select g.ginID as ginID from Gin g ) o");

如果底层数据库支持如下单行函数sign()、trunc()、rtrim()、sin()。则HQL语句也完全可以支持。

HQL语句支持使用?作为参数占位符,这与JDBC的参数占位符一致,也可使用命名参数占位符号,方法是在参数名前加冒号:,例如 :start_date和:x1等。

当然,也可在where子句中使用SQL常量,例如‘foo‘、69、‘1970-01-01 10:00:01.0‘等。

还可以在HQL语句中使用Java public static final 类型的常量,例如eg.Color.TABBY。

除此之外,where子句还支持如下的特殊关键字用法。

in与between...and可按如下方法使用:

from DomesticCat cat where cat.name between ‘A‘ and ‘B‘

from DomesticCat cat where cat.name in ( ‘Foo‘,‘Bar‘,‘Baz‘)

当然,也支持not in和not between...and的使用,例如:

from DomesticCat cat where cat.name not between ‘A‘ and ‘B‘

from DomesticCat cat where cat.name not in ( ‘Foo‘,‘Bar‘,‘Baz‘ )

子句is null与is not null可以被用来测试空值,例如:

from DomesticCat cat where cat.name is null;

from Person as p where p.address is not null;

size关键字用于返回一个集合的大小,例如:

from Cat cat where cat.kittens.size > 0

from Cat cat where size(cat.kittens) > 0

对于有序集合,还可使用minindex与maxindex函数代表最小与最大的索引序数。同理,可以使用minelement与maxelement函数代表集合中最小与最大的元素。例如:

from Calendar cal where maxelement(cal.holidays) > current date

from Order order where maxindex(order.items) > 100

from Order order where minelement(order.items) > 10000

where子句中,有序集合的元素(arrays, lists, maps)可以通过[ ]运算符访问。例如:

//items是有序集合属性,items[0]代表第一个元素

from Order order where order.items[0].id = 1234

//holidays是map集合属性,holidays[national day]代表其中一个元素

select person from Person person, Calendar calendar

where calendar.holidays[‘national day‘] = person.birthDay

and person.nationality.calendar = calendar

//下面同时使用list 集合和map集合属性

select item from Item item, Order order

where order.items[ order.deliveredItemIndices[0] ] = item and order.id = 11

select item from Item item, Order order

where order.items[ maxindex(order.items) ] = item and order.id = 11

在[]中的表达式甚至可以是一个算术表达式,例如:

select item from Item item, Order order

where order.items[ size(order.items) - 1 ] = item

连接查询

迫切左外连接

from User u left join fetch u.student s where u.name like ‘%java%‘

左外连接

左连接就是要把左边这个表里面的所有的数据显示出来。

from User u left join u.student s where u.name like ‘%java%‘

迫切内连接

from User u inner join fetch u.student where u.name like ‘%java%‘

内连接

内连接是把所有的相等的,完全符合条件的列出来。

内连(join).可以将inner 关键字省略,默认就是内连接。

from User u inner join u.student where u.name like ‘%java%‘

右外连接

from User u right join u.student where u.name like ‘%java%‘

HQL中的条件用with即:left join ... with...

SQL中的条件用on即:left join ... on...

Fetch:

在我们查询User对象的时候,默认只有User的内容,并不包含student的信息,如果在User.hbm.xml里设置lazy="true"的话同时又想取出关联的所有student内容,那么可以使用fetch。

order by子句

排序order by

HQL和SQL的使用方法很类似,"ASC"和"DESC"分别为升序和降序,如果不显式注明,HQL中默认为asc升序。

//先按照年龄降序排序,然后再按出生日期升序排序

Query query = sessionFactory.getCurrentSession().createQuery("select p from Person p order by p.age desc, p.birthday asc");

group by子句

分组查询,大部分标准的SQL聚集函数都可以在HQL语句中使用,比如:

count(),sum(),max(),min(),avg()等。

select cat.color, sum(cat.weight), count(cat) from Cat cat group by cat.color

Query query=sessionFactory.getCurrentSession().createQuery("select p.sex,count(*) from Person p group by p.sex");

HQL和可以使用和SQL那样的grouping,group by rollup(...)

如:

select g.belongOrganID,g.customerN,g.vtype,(case when grouping(g.belongOrganID)=0 then 1 when grouping(g.belongOrganID)=1 then 0 end )+(case when grouping(g.customerN)=0 then 1 when grouping(g.customerN)=1 then 0 end )+(case when grouping(g.vtype)=0 then 1
when grouping(g.vtype)=1 then 0 end ),uuid() as ID,count(*) as count, sum(g.totoalPrice) as totoalPrice from Gin o where 1=1  group by rollup(g.belongOrganID,g.customerN,g.vtype)

聚合查询

HQL也支持查询中的聚合函数,目前HQL支持的聚合函数包括:

avg(),count(),max(),min(),sum()

distinct

有时查询结果集中有相同的数据,关键词distinct用于返回唯一不同的数据。

select [distinct] object(variable) from abstractschemaname [as] variable [where value comparison value]

子查询

如果底层数据库支持子查询,则可以在HQL语句中使用子查询。与SQL中子查询相似的是,HQL中的子查询也需要使用()括起来。如:

from Cat as fatcat

where fatcat.weight > ( select avg(cat.weight) from DomesticCat cat )

如果select中包含多个属性,则应该使用元组构造符:

from Cat as cat

where not ( cat.name, cat.color ) in (

select cat.name, cat.color from DomesticCat cat

)

命名查询

命名查询也和EJB3 QL一样使用@NamedQuery注解。

@NamedQuery

我们可以使用@NamedQuery注释来定义命名查询,这个注释可以放在任何实体Bean的上方,但为了便于管理,最好放在相关的实体Bean上方。

@NamedQuery(name="MyQuery",query="select p from PersonFlight p where name like ?1")

@NamedQueries( {

@NamedQuery(name = "person.query", query = "from Person p  where p.id=? "),

@NamedQuery(name = "person.query1", query = "from Person p  where p.id=? ") })

也可以在hbm.xml文件中配置命名查询:

<query name="findGroupsByUser">

<![CDATA[

select distinct g

from org.jbpm.pvm.internal.identity.impl.MembershipImpl m

join m.user u

join m.group g

where u.id = :userId

]]>

</query>

Query query = session.getNamedQuery("findGroupsByUser");

query.setInteger("userId", 25);

List result= query.list();

Hibernate org.hibernate.Query类

setParameter()方法:

在Hibernate的HQL查询中可以通过setParameter()方法邦定任意类型的参数,如下代码:

String hql="from User user where user.name=:customername";//注意=:后不要有空格

Query query=session.createQuery(hql);

query.setParameter("customername",name,Hibernate.STRING);

如上面代码所示,setParameter()方法包含三个参数,分别是命名参数名称,命名参数实际值,以及命名参数映射类型。对于某些参数类型 setParameter()方法可

以更具参数值的Java类型,猜测出对应的映射类型,因此这时不需要显示写出映射类型,像上面的例子,可以直接这样写:

query.setParameter("customername",name); 但是对于一些类型就必须写明映射类型,比如java.util.Date类型,因为它会对应Hibernate的多种映射类型,比如

Hibernate.DATA或者Hibernate.TIMESTAMP。

setProperties()方法:

在Hibernate中可以使用setProperties()方法,将命名参数与一个对象的属性值绑定在一起,如下程序代码:

Customer customer=new Customer();

customer.setName("pansl");

customer.setAge(80);

Query query=session.createQuery("from Customer c where c.name=:name and c.age=:age");

query.setProperties(customer);

setProperties()方法会自动将customer对象实例的属性值匹配到命名参数上,但是要求命名参数名称必须要与实体对象相应的属性同名。

查询单个字段

String hql = " select name from Users";

Query query = session.createQuery(hql);

List<String> list = query.list();

for(String str : list){

System.out.println(str);

}

输出结果为:

name1

name2

name3

查询其中几个字段

String hql = " select name,passwd from Users";

Query query = session.createQuery(hql);

//默认查询出来的list里存放的是一个Object数组

List<Object[]> list = query.list();

for(Object[] object : list){

String name = (String)object[0];

String passwd = (String)object[1];

System.out.println(name + " : " + passwd);

}

输出结果为:

name1 : password1

name2 : password2

name3 : password3

修改默认查询结果(query.list())不以Object[]数组形式返回,以List形式返回

添加new list(),注意list里的l是小写的。也不需要导入包,这样通过query.list()出来的list里存放的不再是默认的Object数组了,而是List集合了

String hql = " select new list(name,passwd) from Users";

Query query = session.createQuery(hql);

//默认查询出来的list里存放的是一个Object数组,但是在这里list里存放的不再是默认的Object数组了,而是List集合了

List<List> list = query.list();

for(List user : list){

String name = (String)user.get(0);

String passwd = (String)user.get(1);

System.out.println(name + " : " + passwd);

}

/**

输出结果为:

name1 : password1

name2 : password2

name3 : password3

*/

修改默认查询结果(query.list())不以Object[]数组形式返回,以Map形式返回

添加new map(),注意map里的m是小写的。也不需要导入包,这样通过query.list()出来的list里存放的不再是默认的Object数组了,而是 map集合了

String hql = " select new map(name,passwd) from Users";

Query query = session.createQuery(hql);

//默认查询出来的list里存放的是一个Object数组,但是在这里list里存放的不再是默认的Object数组了,而是Map集合了

List<Map> list = query.list();

for(Map user : list){

//一条记录里所有的字段值都是map里的一个元素,key是字符串0,1,2,3....,value是字段值

//如果将hql改为:String hql = " select new map(name as username,passwd as password) from Users";,那么key将不是字符串0,1,2...了,而是"username","password"了

String name = (String)user.get("0");//get("0");是get(key),注意:0,1,2...是字符串,而不是整形

String passwd = (String)user.get("1");

System.out.println(name + " : " + passwd);

}

/**

输出结果为:

name1 : password1

name2 : password2

name3 : password3

*/

修改默认查询结果(query.list())不以Object[]数组形式返回,以自定义类型形式返回

public class MyUser {

private String username;

private String password;

//因为:String hql = " select new  com.domain.MyUser(name,passwd) from Users";所以必须要有接受2个参数的构造函数

public MyUser(String username,String password){

this.username = username;

this.password = password;

}

public String getUsername() {

return username;

}

public void setUsername(String username) {

this.username = username;

}

public String getPassword() {

return password;

}

public void setPassword(String password) {

this.password = password;

}

}

2使用HibernateCallBack

HibernateTemplate还提供了一种更加灵活的方式来操作数据库,通过这种方式可以完全使用Hibernate的操作方式。HibernateTemplate的灵活访问方式可通过如下两个方法完成

Object execute(HibernateCallback action)

List executeFind(HibernateCallback action)

这两个方法都需要一个HibernateCallback的实例,HibernateCallback实例可在任何有效的Hibernate数据访问中使用。程序开发者通过HibernateCallback,可以完全使用Hibernate灵活的方式来访问数据库,解决Spring封装 Hibernate后灵活性不足的缺陷。

HibernateCallback 是一个接口,该接口包含一个方法doInHibernate(org.hibernate. Session session),该方法只有一个参数Session。在开发中提供HibernateCallback实现类时,必须实现接口里包含的 doInHibernate方法,在该方法体内即可获得Hibernate Session的引用,一旦获得了Hibernate Session的引用,就可以完全以Hibernate的方式进行数据库访问。

注意:doInHibernate方法内可以访问Session,该Session对象是绑定在该线程的Session实例。该方法内的持久层操作,与不使用Spring时的持久层操作完全相同。这保证了对于复杂的持久层访问,依然可以使用Hibernate的访问方式。

下面的代码对HibernateDaoSupport类进行扩展(虽然Spring 2.0的HibernateTemplate提供了一个分页方法setMaxResults,但仅此一个方法依然不能实现分页查询),这种扩展主要是为该类增加了3个分页查询的方法,分页查询时必须直接调用Hibernate的Session完成,因此,必须借助于HibernateCallBack的帮助。

public class YeekuHibernateDaoSupport extends HibernateDaoSupport

{

/**

* 使用hql 语句进行分页查询操作

* @param hql 需要查询的hql语句

* @param offset 第一条记录索引

* @param pageSize 每页需要显示的记录数

* @return 当前页的所有记录

*/

public List findByPage(final String hql,

final int offset, final int pageSize)

{

//HibernateDaoSupport已经包含了getHibernateTemplate()方法

List list = getHibernateTemplate().executeFind(new

HibernateCallback()

{

public Object doInHibernate(Session session)

throws HibernateException, SQLException

//该方法体内以Hibernate方法进行持久层访问

{

//注意setFirstResult是从0开始的,0就是第一页的数据

List result = session.createQuery(hql)

.setFirstResult(offset)

.setMaxResults(pageSize)

.list();

return result;

}

});

return list;

}

/**

* 使用hql 语句进行分页查询操作

* @param hql 需要查询的hql语句

* @param value 如果hql有一个参数需要传入,value就是传入的参数

* @param offset 第一条记录索引

* @param pageSize 每页需要显示的记录数

* @return 当前页的所有记录

*/

public List findByPage(final String hql , final Object value ,

final int offset, final int pageSize)

{

List list = getHibernateTemplate().executeFind(new

HibernateCallback()

{

public Object doInHibernate(Session session)

throws HibernateException, SQLException

{

//下面查询的是最简单的Hiberante HQL查询

List result = session.createQuery(hql)

.setParameter(0, value)

.setFirstResult(offset)

.setMaxResults(pageSize)

.list();

return result;

}

});

return list;

}

/**

* 使用hql 语句进行分页查询操作

* @param hql 需要查询的hql语句

* @param values 如果hql有多个参数需要传入,values就是传入的参数数组

* @param offset 第一条记录索引

* @param pageSize 每页需要显示的记录数

* @return 当前页的所有记录

*/

public List findByPage(final String hql, final Object[] values,

final int offset, final int pageSize)

{

List list = getHibernateTemplate().executeFind(new

HibernateCallback()

{

public Object doInHibernate(Session session)

throws HibernateException, SQLException

{

Query query = session.createQuery(hql);

for (int i = 0 ; i < values.length ; i++)

{

query.setParameter( i, values[i]);

}

List result = query.setFirstResult(offset)

.setMaxResults(pageSize)

.list();

return result;

}

});

return list;

}

}

在上面的代码实现中,直接使用了getHibernateTemplate()方法,这个方法由Hibernate- DaoSupport提供。而YeekuHibernateDaoSupport是HibernateDaoSupport的子类,因此,可以直接使用该方法。

当实现doInHibernate(Session session)方法时,完全以Hibernate的方式进行数据库访问,这样保证了Hibernate进行数据库访问的灵活性。

注意:Spring提供的XxxTemplate和XxxCallBack互为补充,二者体现了Spring框架设计的用心良苦:XxxTemplate对通用操作进行封装,而XxxCallBack解决了封装后灵活性不足的缺陷。

3Hibernate产生的自增主键

使用@GeneratedValue和@GenericGenerator

针对不同的数据库可以同时使用

@Id

@GeneratedValue(strategy = GenerationType.AUTO)

针对mysql

@Id

@GeneratedValue(strategy = GenerationType.IDENTITY)

针对oracle

@Id

@GeneratedValue(strategy = GenerationType.SEQUENCE,generator="s_gen")

@SequenceGenerator(name="s_gen",sequenceName="s_seq")

说明:@GeneratedValue()的strategy属性支持5中id生成器:除上面3中外还有GenerationType.TABLE。

@GeneratedValue:主键的产生策略,通过strategy属性指定。

主键产生策略通过GenerationType来指定。GenerationType是一个枚举,它定义了主键产生策略的类型。

  AUTO 自动选择一个最适合底层数据库的主键生成策略。如MySQL会自动对应auto increment。这个是默认选项,即如果只写@GeneratedValue,等价于@GeneratedValue(strategy=GenerationType.AUTO)。

  IDENTITY 表自增长字段,Oracle不支持这种方式。

  SEQUENCE 通过序列产生主键,MySQL不支持这种方式。

  TABLE 通过表产生主键,框架借由表模拟序列产生主键,使用该策略可以使应用更易于数据库移植。

不同的JPA实现商生成的表名是不同的,如 OpenJPA生成openjpa_sequence_table表,Hibernate生成一个hibernate_sequences表,而TopLink则生成sequence表。这些表都具有一个序列名和对应值两个字段,如SEQ_NAME和SEQ_COUNT。

在我们的应用中,一般选用@GeneratedValue(strategy=GenerationType.AUTO)这种方式,自动选择主键生成策略,以适应不同的数据库移植。

@GenericGenerator

自定义主键生成策略,由@GenericGenerator实现。

hibernate在JPA的基础上进行了扩展,可以用一下方式引入hibernate独有的主键生成策略,就是通过@GenericGenerator加入的。例如:

@Id

@Column(name="id",length=32)

@GeneratedValue(generator = "paymentableGenerator")

@GenericGenerator(name = "paymentableGenerator", strategy = "uuid")

private String roleID;

name属性指定生成器名称。

strategy属性指定具体生成器的类名。

parameters得到strategy指定的具体生成器所用到的参数。

对于这些hibernate主键生成策略和各自的具体生成器之间的关系,在org.hibernate.id.IdentifierGeneratorFactory中指定了

static {

GENERATORS.put("uuid", UUIDHexGenerator.class);

GENERATORS.put("hilo", TableHiLoGenerator.class);

GENERATORS.put("assigned", Assigned.class);

GENERATORS.put("identity", IdentityGenerator.class);

GENERATORS.put("select", SelectGenerator.class);

GENERATORS.put("sequence", SequenceGenerator.class);

GENERATORS.put("seqhilo", SequenceHiLoGenerator.class);

GENERATORS.put("increment", IncrementGenerator.class);

GENERATORS.put("foreign", ForeignGenerator.class);

GENERATORS.put("guid", GUIDGenerator.class);

GENERATORS.put("uuid.hex", UUIDHexGenerator.class); //uuid.hex is deprecated

GENERATORS.put("sequence-identity", SequenceIdentityGenerator.class);

}

native

根据地层数据库的能力选择identity,sequence或hilo中的一个。

@GeneratedValue(generator = "paymentableGenerator")

@GenericGenerator(name = "paymentableGenerator", strategy = "native")

uuid

用一个128-bit的UUID算法生成字符串类型的标识符,这在一个网络中是唯一的。UUID被编码为一个32为16进制数字的字符串。

@GeneratedValue(generator = "paymentableGenerator")

@GenericGenerator(name = "paymentableGenerator", strategy = "uuid")

hilo

使用一个高/低位算法高效的生成long,short或int类型的标识符。给定一个表和字段(默认分别是hibernate_unique_key和next_hi)作为高位值的来源。高/低位算法生成的标识符只在一个特定的数据库中是唯一的。

@GeneratedValue(generator = "paymentableGenerator")

@GenericGenerator(name = "paymentableGenerator", strategy = "hilo")

assigned

让应用升序在save()之前为对象分配一个标识符。这是<gengerator>元素没有指定时的默认生成策略。

@GeneratedValue(generator = "paymentableGenerator")

@GenericGenerator(name = "paymentableGenerator", strategy = "assigned")

identity

对于DB2,MySQL,MS SQL Server,Sybase和HypersonicSQL的内置标识字段提供支持,返回的标示符是long,short或int类型的。整数递增。

@GeneratedValue(generator = "paymentableGenerator")

@GenericGenerator(name = "paymentableGenerator", strategy = "identity")

select

通过数据库触发器选择一些唯一主键的行返回主键值分配一个主键。

@GeneratedValue(generator = "paymentableGenerator"

@GenericGenerator(name="select", strategy="select", parameters = { @Parameter(name = "key", value = "idstoerung") })

sequence

在DB2,PostgreSQL,Oracle,SAP DB,McKoi中使用序列(sequence),而在Interbase中使用生成器(generator)。返回的标示符是long,short或int类型的。

@GeneratedValue(generator = "paymentableGenerator")

@GenericGenerator(name = "paymentableGenerator", strategy = "sequence", parameters = { @Parameter(name = "sequence", value = "seq_payablemoney") })

seqhilo

使用一个高/低位算法高效的生成long,short或int类型的标识符,给定一个数据库序列(sequence)的名字。

@GeneratedValue(generator = "paymentableGenerator")

@GenericGenerator(name = "paymentableGenerator", strategy = "seqhilo", parameters = { @Parameter(name = "max_lo", value = "5") })

increment

用于为long,short或int类型生成唯一标识,只有在没有其他进程往同一张表中插入数据时才能使用,在集群下不要使用。

@GeneratedValue(generator = "paymentableGenerator")

@GenericGenerator(name = "paymentableGenerator", strategy = "increment")

foreign

使用另一个相关联的对象的标识符。通常和<one-to-one>联合起来使用。

@GeneratedValue(generator = "idGenerator")

@GenericGenerator(name = "idGenerator", strategy = "foreign",

parameters = { @Parameter(name = "property", value = "employee") })

例如:

@Entity

public class Employee {

@Id

@GeneratedValue(generator = "idGenerator")

@GenericGenerator(name = "idGenerator", strategy = "foreign",

parameters = { @Parameter(name = "property", value = "info") })

Integer id;

@OneToOne

EmployeeInfo info;

...

}

guid

在MS SQL Server和MySQL中使用数据库生成GUID字符串。

@GeneratedValue(generator = "paymentableGenerator")

@GenericGenerator(name = "paymentableGenerator", strategy = "guid")

uuid.hex

@GeneratedValue(generator = "paymentableGenerator")

@GenericGenerator(name = "paymentableGenerator", strategy = "uuid.hex")

sequence-identity

一种特别的序列生成策略,使用数据库序列来生成实际值,但将它和jdbc3的getGeneratedKeys结合在一起,使的在插入语句执行的时候就返回生成的值,目前只面向JDK1.4的oracle10g开放这一策略。

@GeneratedValue(generator = "paymentableGenerator")

@GenericGenerator(name = "paymentableGenerator", strategy = "sequence-identity",

parameters = { @Parameter(name = "sequence", value = "seq_payablemoney") })

在hbm.xml映射文件中,使用id生成策略

<id name="codeID" type="String">

<column name="CODEID" length="32"/>

<generator class="uuid.hex"/>

</id>

*******************

在hibernate的保存或更新完实体对象后,就可以通过实体对象得到其对应的id。

*********************

createSQLQuery(String str)

例如,Object obj=session.createSQLQuery("select o.name from organ o where o.id=1");

如果只查询一列并只有一个结果则返回Object,如果有多个结果则返回List<Object>。如果查询多列且有多个结果则返回List<Object[]>。

List<Object[]> listobj=session.createSQLQuery("select o.name,o.id from organ o");

******************

hql中+号的另一中作用:

createQuery("select new Vcolor(c.vcolorID,c.name) from Vconfig o,Vcolor c where o.vconfigID=:vconfigId and o.outterColor like ‘%‘+c.vcolorID+‘%‘ ");

表示从Vcolor中找出VcolorID在指定的Vconfig对象的outterColor属性中的vcolor对象。不能写成

like ‘%c.vcolorID%‘ 。这种写法其实和sql写法一样。

http://www.redsaga.com/hibernate-ref/3.x/zh-cn/html/queryhql.html

****************

case when:

1. select   sum(case when  otype=‘A‘ then price  when otype=‘B‘ then -price  end )  from  Entity  (sql中支持,但hql查询时,控制台查询语句缺少 ‘when otype=‘B‘ then -price ’,也就是只有otype=‘A‘ 的情况)

2.select sum(case when otype=‘A‘  then  price  else -price end ) from Entity  (支持)

3. select sum(case when otype=‘A‘  then  price  else  case when otype=‘B‘ then -price end end ) from Entity (支持)

*********************

inner join(内连接)

left outer join(左外连接)

right outer join(右外连接)

full join (全连接,并不常用)

HQL中的条件用with即:left join ... with...

SQL中的条件用on即:left join ... on...

语句inner join, left outer join 以及 right outer join 可以简写。

from Cat as cat     join cat.mate as mate    left join cat.kittens as kitten

通过HQL的with关键字,你可以提供额外的join条件。

from Cat as cat     left join cat.kittens as kitten         with kitten.bodyWeight > 10.0

还有,一个"fetch"连接允许仅仅使用一个选择语句就将相关联的对象或一组值的集合随着他们的父对象的初始化而被初始化,这种方法在使用到集合的情况下尤其有用,对于关联和集合来说,它有效的代替了映射文件中的外联接 与延迟声明(lazy declarations).

from Cat as cat     inner join fetch cat.mate    left join fetch cat.kittens

一个fetch连接通常不需要被指定别名, 因为相关联的对象不应当被用在 where 子句 (或其它任何子句)中。同时,相关联的对象 并不在查询的结果中直接返回,但可以通过他们的父对象来访问到他们。

from Cat as cat     inner join fetch cat.mate    left join fetch cat.kittens child    left join fetch child.kittens

假若使用iterate()来调用查询,请注意fetch构造是不能使用的(scroll() 可以使用)。fetch也不应该与setMaxResults() 或setFirstResult()共用,这是因为这些操作是基于结果集的,而在预先抓取集合类时可能包含重复的数据,也就是说无法预先知道精确的行数。fetch还不能与独立的 with条件一起使用。通过在一次查询中fetch多个集合,可以制造出笛卡尔积,因此请多加注意。对bag映射来说,同时join fetch多个集合角色可能在某些情况下给出并非预期的结果,也请小心。最后注意,使用full
join fetch 与 right join fetch是没有意义的。

如果你使用属性级别的延迟获取(lazy fetching)(这是通过重新编写字节码实现的),可以使用 fetch all properties 来强制Hibernate立即取得那些原本需要延迟加载的属性(在第一个查询中)。

from Document fetch all properties order by name

from Document doc fetch all properties where lower(doc.name) like ‘%cats%‘

************************

query.setResultTransformer方法

我们如果查询出实体类部分属性,hibernate会自动帮你封装成为object对象[].可是,我们想直接用对象怎么办?难道还要一个一个的setter循环赋值给VO。

例如:

public SureOrder getSureOrderVO(Integer productId) {

String hql = "select pd.id as prodid,pd.cuxiaoPrice as cuxiaoPrice,pd.types as types,pd.price as price,pd.newprice as newprice,p.nodeId,p.imgurl as imgurl,p.types as types,p.factId as factId,p.qianYueId as qianyueId,p.guiGe as guiGe,p.name as name,p.pinPai
as pinPai from Product pd,Prod p where p.id=pd.prodId and pd.id =?";

Query query = productDao.getProductDetail(productId,hql);

//主要起作用的就是下面的这个方法:SureOrder是我要封装的VO类.这样hibernate在执行hql查询的时候,会直接将结果封装为SureOrder对象.

List list = query.setResultTransformer(Transformers.aliasToBean(SureOrder.class)).list();

if(!list.isEmpty()){

return (SureOrder) list.get(0);

}

return null;

}

**************************

select中的new map前面也可以使用distinct :

select distinct new map(...)

时间: 2024-07-30 19:01:20

2HQL及自增主键的相关文章

数据库自增主键可能产生的问题

在MySQL中经常会配置自增长属性的字段作为主键,特别是使用InnoDB存储引擎,因为InnoDB的聚集索引的特性,使用自增长属性的字段当主键性能更好,但是使用自增主键也可能会带来一些问题.   举个例子,使用自增主键对数据库做分库分表,可能出现一些诸如主键重复等的问题,或者在数据库导入的时候,可能会因为主键出现一些问题.主要业务表的主键应该配置一个合理的策略,尽量避免自增AUTO_INCREMENT. 针对主键自增可能产生的问题,下面这两篇文章有相关的讨论:     INNODB自增主键的一些

mybatis自增主键返回

自增主键的返回: mysql自增主键,执行insert提交之前自动生成一个自增主键. 通过mysql函数获取到刚插入记录的自增主键: LAST_INSERT_ID() 是insert之后调用此函数. 修改insertUser定义: 非自增主键返回: 使用mysql的uuid()函数生成主键,需要修改表中id字段类型为string,长度设置成35位. 执行思路: 先通过uuid()查询到主键,将主键输入 到sql语句中. 执行uuid()语句顺序相对于insert语句之前执行. 通过oracle的

关于mybatis用mysql时,插入返回自增主键的问题

公司决定新项目用mybatis,虽然这个以前学过但是一直没用过都忘得差不多了,而且项目比较紧,也没时间去系统点的学一学,只好很粗略的百度达到能用的程度就行了. 其中涉及到插入实体要求返回主键id的问题,以前用ssh配合oracle很容易实现,因为有sequence,而且mysql也基本没用过,所以只好去百度了. 这个内容还是比较好查的,如下: <?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE mapp

MyBatis:获取插入记录的自增主键

我们知道MySql中主键可以设成auto_increment,也就是自增主键,每当新增一条记录,主键值自动加1. 在MyBatis中,执行insert,返回值为受影响的语句行数,此操作跟JDBC一致. 但是如果应用中需要将插入的值的主键返回时,这时有两种方式: 第一种方式:在mapper的insert节点中添加useGeneratedKey和keyProperty属性 第二种方式:在mapper的insert节点下添加selectKey子节点的方式 下面是具体的使用方式举例: 一.MySql中m

mybatis 添加事物后 无法获取自增主键的问题

检查代码后没发现mapper文件设置自增主键返回的问题,后来检查到,关闭事务后,执行完是可以获取返回的主键的, 我在mysql的客户端里关闭自动提交,发现使用select last_insert_id() 也是可以正确获取最新主键的, 我意识到可能是mybatis配置的问题. 问同事后发现了问题,将 defaultExecutorType 从 BATCH 改为 SIMPLE 即可. 1 <?xml version="1.0" encoding="UTF-8"

主键、自增主键、主键索引、唯一索引概念区别与性能区别

概念区别: 主键:指字段唯一不为空值的列. 主键索引:指的就是主键,主键没有明确的概念定义,主键既是约束,也是索引,主键是索引的一种,是唯一索引的特殊类型.创建主键的时候,数据库默认会为主键创建一个唯一索引. 自增主键:字段类型为数字.自增.并且是主键. 唯一索引:索引列的值必须唯一,但允许有空值.主键是唯一索引,这样说没错.但反火来说唯一索引也是主键就错误了,因为唯一索引允许空值,主键不允许有空值,所以不能说唯一索引也是主键. 性能区别: 通过测试,发现主键.自增主键.唯一索引的查询效率不一样

SpringJDBC jdbcTemplate获取自增主键

String sql = "insert into notice_type(typeName,configType,state,creatorID,corpID,createTime) values (?,?,?,?,?,?)"; Object[] objs = new Object[]{ noticeType.getTypename(), noticeType.getConfigtype(), noticeType.getState(), noticeType.getCreatori

08Mybatis_入门程序——增加用户的操作以及返回自增主键的功能以及返回非自增主键的功能

本文要实现的功能是:给user表增加一个用户. 建表如下: 案例整体结构如下: 第一步:编写po包下面的User.java代码对应上面的数据库 package cn.itcast.mybatis.po; import java.util.Date; public class User { private int id;//主键 private String username;//用户的名称 private Date birthday;//生日 private String sex;//性别 pr

MySQL 插入与自增主键值相等的字段 与 高并发下保证数据准确的实验

场景描述: 表t2 中 有 自增主键 id  和 字段v  当插入记录的时候 要求 v与id 的值相等(按理来说这样的字段是需要拆表的,但是业务场景是 只有某些行相等 ) 在网上搜的一种办法是 先获取自增ID SELECT max(id)+1 from t2 然后给v字段插入获取到的值 但是这样的做法在有删除行+调整过自增值的表中是不准确的 于是换个思路 从 information_schema 下手 读取表的信息 INSERT INTO `t2` VALUES ( NULL, ( SELECT