本次示例使用的实体类
public class Subscriber implements Serializable {
private static final long serialVersionUID = -4245745407349030869L;
@Id
@Column(length = 36)
@GeneratedValue(generator = "userID")
@GenericGenerator(name = "userID", strategy = "uuid2")
private String userID;
private String username;
private String password;
private String description;
@Column(columnDefinition = "TIMESTAMP", insertable = false)
@Temporal(TemporalType.TIMESTAMP)
private Date lastUpdate;
@OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
@JoinColumn(name = "personID")
private Person person;
@ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
@JoinColumn(name = "roleID")
private Role role;
}
public class Person implements Serializable {
private static final long serialVersionUID = 2423758408277291361L;
@Id
@GeneratedValue(generator = "personID")
@GenericGenerator(name = "personID", strategy = "uuid2")
private String personID;
private String personName;
private String email;
@Enumerated(EnumType.STRING)
private Sex male;
private String address;
private LocalDate birthday;
@Column(columnDefinition = "TIMESTAMP", insertable = false)
@Temporal(TemporalType.TIMESTAMP)
private Date lastUpdate;
}
public class Role implements Serializable {
private static final long serialVersionUID = -4090771109134214449L;
@Id
@Column(length = 36)
@GeneratedValue(generator = "roleID")
@GenericGenerator(name = "roleID", strategy = "uuid2")
private String roleID;
private String roleName;
private String description;
@Column(columnDefinition = "TIMESTAMP", insertable = false)
@Temporal(TemporalType.TIMESTAMP)
private Date lastUpdate;
@OneToMany(mappedBy = "role", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@Fetch(FetchMode.SUBSELECT)
private Set<Subscriber> subscribers;
}
Subscriber和Person表单向一对一外键关联,Subscribe方维护外键关联。
Subscribe和Role表双向一堆多关联,Subscribe方维护外键关联。
FetchType
在一对多/多对多/一对一关联的注解上设置fetch = FetchType.LAZY(EAGER)。(并不是所有关联关系注解的FetchType值是LAZY)
FetchType.EAGER表示立即抓取。在检索某个对象的数据时立即抓取相关联的对象
FetchType.LAZY表示延迟抓取。在检索某个对象时并不会立即抓取相关联的对象,只有在使用中才会发出SQL抓取具体对象的属性值。
Hibernate的推荐是全部使用延迟加载,然后在特定的事务中使用特定的抓取策略对其进行重载。
但是,并不是设置了LAZY之后都是延迟加载了。在双向(单向)一对一主键关联或者双向一对一外键关联的非外键持有方,延迟加载并不会有效。
Hibernate使用代理(Proxy)来实现在访问实体类的关联对象的属性时去加载数据,对实体类的操作会被代理类接受和处理,从而实现延迟加载。也就是说,Hibernate在延迟加载时,需要知道关联关系是否存在,以此来确定建立代理类或者设置为null。在一对一中,Hibernate无法直接通过外键知道关联关系是否存在,所以每次都需要发送额外的SQL,以此来设置关联关系的代理类或者null。
在其他关联关系中,所有的实体都很容易的检查到自己的外键以此来确定关联对象的填充(在一对多的情况下,最初会创建空集合代理,并且按需填充)。
FetchMode
FetchMode.SELECT:1+n 条select语句,第一条查主表,第n条查第n条主表记录对应的子表记录。
// 每次都会发送一条SQL
SELECT
subscriber0_.roleID AS roleID8_5_0_,
......
FROM
t_user subscriber0_
WHERE
subscriber0_.roleID =?;
FetchMode.SUBSELECT:以 id in(…)的方式做第二条查询,(如果查询主表的是返回单条记录,subselect和select没有区别,如果查询主表的是返回多条记录的话,对子表查询会以id in 的方式)。
SELECT
subscriber0_.roleID AS roleID8_5_1_,
......
FROM
t_user subscriber0_
WHERE
subscriber0_.roleID IN (
SELECT
role0_.roleID
FROM
t_role role0_
)
FetchMode.JOIN:使用外链接查询对象及关联对象,但是在设置该属性后,延迟加载将无效,会采用立即加载方式查询。
SELECT
subscriber0_.userID AS userID1_5_0_,
......
FROM
t_user subscriber0_
LEFT OUTER JOIN t_role role1_ ON subscriber0_.roleID = role1_.roleID
WHERE
subscriber0_.userID =?
Hibernate查询
HQL查询
import org.hibernate.query.Query
Query<Subscriber> query = session.createQuery("from Subscriber u where userID = :userID", Subscriber.class);
query.setParameter("userID", "params");
List<Subscriber> subscribers = query.getResultList();
Query<Object[]> query = session.createQuery("from Subscriber as user left join Person as person on user.userID = person.personID", Object[].class);
query.setParameter("username", "params");
query.setParameter("userID", "params");
Criteria对象化查询
Session session = this.sessionFactory.getCurrentSession();
Criteria criteria = session.createCriteria(Subscriber.class);
criteria.setProjection(Projections.rowCount());
// criteria.setProjection(Projections.avg("username"));
// criteria.setProjection(Projections.groupProperty("username"));
criteria.createAlias("role", "r");
Criterion criterion = Restrictions.or(Restrictions.like("username", "username"), Restrictions.eq("r.roleName", "roleName"));
criteria.add(criterion);
criteria.addOrder(Order.asc("username"));
List subscribers = criteria.list();