HQL查询——关联和连接
为了便于理解有关的使用关联和连接进行HQL查询,首先提供两个具有关联关系的持久化类:Person类和MyEvent类
Person类:
import javax.persistence.CollectionTable; import javax.persistence.Column; import javax.persistence.ElementCollection; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.ManyToOne; import javax.persistence.Table; @Entity //标识这是一个持久化类 @Table(name="person_info") // 指定此持久化类对应的表名 public class Person { @Id @Column(name="p_id") //标识主键 指定主键列的列名 @GeneratedValue(strategy=GenerationType.IDENTITY) //定义主键的生车策略为自增长 private Integer id; @Column(name="p_name") private String name; @Column(name="p_age") private int age; //定义该实体对应的MyEvent实体 @ManyToOne(targetEntity=MyEvent.class) //设置外键 @JoinColumn(name="event_id",referencedColumnName="event_id") private MyEvent myEvent; //定义一个集合属性 @ElementCollection(targetClass=String.class) //设置关联表 @CollectionTable( name="person_email_info", joinColumns=@JoinColumn(name="person_id",nullable=false) ) @Column(name="email_detail",nullable=false) private Set<String> emails = new HashSet<>(); public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public MyEvent getMyEvent() { return myEvent; } public void setMyEvent(MyEvent myEvent) { this.myEvent = myEvent; } public Set<String> getEmails() { return emails; } public void setEmails(Set<String> emails) { this.emails = emails; } }
Myevent类:
import java.util.Date; import java.util.HashSet; import java.util.Set; import javax.persistence.Column; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.ManyToMany; public class MyEvent { @Id @Column(name="event_id") @GeneratedValue(strategy=GenerationType.IDENTITY) private Integer id; @Column(name="event_title") private String title; @Column(name="event_happenDate") private Date happenDate; @ManyToMany(targetEntity=Person.class,mappedBy="myEvent") private Set<Person> actors = new HashSet<>(); public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public Date getHappenDate() { return happenDate; } public void setHappenDate(Date happenDate) { this.happenDate = happenDate; } public Set<Person> getActors() { return actors; } public void setActors(Set<Person> actors) { this.actors = actors; } }
1.HQL支持两种关联连接(join)形式:隐式和显式。
2.隐式连接形式不使用join关键字,而是使用“.”来隐式连接关联的实体,在Hibernate底层自动实现关联查询。
from Person p where p.myEvent.title >: title
3.显式连接则需要使用xxx join关键字。
from Person p
inner join p.myEvent event
where event.happenDate <: endDate
在使用显示链接时可以为相关联的实体或关联集合中的全部元素指定一个别名。
4.Hibernate支持的HQL连接类型直接借鉴了SQL99多表查询的关键字,可使用如下几种连接方式:
(1)inner join(内连接),可简写成join。
(2)left outer join(左外连接),可简写成left join。
(3)right outer join(右外连接),可简写成right join。
(4)full join(全连接),不常使用。
5.使用显式连接时,还可以通过HQL的with关键字来提供额外的连接条件。如:
from Person p
inner join p.myEvent event
with p.id > event.id
where event.happenDate <: endDate;
Hibernate会将这种显式连接转换成SQL99的多表连接语句,HQL中为with关键字基本等同于SQL99中的关键字on也是用于指定额连接外条件的。
6.对于HQL的显式连接和隐式连接有如下两种区别:
(1)隐式连接底层将转换成SQL99的交叉连接,显式连接将转化成SQL99的inner join、left join和right join等连接;
(2)隐式连接和显式连接查询后返回的结果不同:
使用隐式连接查询返回的结果是多个被查询实体组成的集合。
当使用显式连接查询的HQL语句中省略select关键字是,返回的结果也是集合,但集合元素是被查询的持久化对象、所有被关联的持久化对象所组成的数组。