6.Hibernate检索及抓取策略

本次示例使用的实体类

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();
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值