Hibernate 与聚合的关系
Hibernate relation with aggregation
@Entity
public class Device {
private long id;
private String deviceName; //column D_NAME
private Set<LoginDate> loginDates;
}
/**
Audit table being filled by some other processes on the network
*/
@Entity
public class LoginDate {
private long id; //pk
private String deviceName; //column D_NAME
private Date loginDate;
}
我的目标是在报告屏幕上显示设备的最后登录日期;我在 Device
和 LoginDate
表之间实现了 OneToMany 关系,其中它使用 OrderBy 对 loginDates 进行降序排序,以便我可以选择要在屏幕上显示的第一项。但是当登录数量越来越大时,这是一个有点昂贵的操作。我应该怎么做才能达到 select 仅上次登录日期;
我可以使用 Hibernate 的 @Formula
通过它生成 Pojo
具有相关参数的构造函数。但这会触发一些
报告屏幕中每个项目 select 秒。
我可以在业务层实现另一种方法,一旦
列表已加载;我可以用相关 D_NAMES 启动另一个 HQL 来获取
D_NAME、loginDate 组合并循环遍历它们。哪个是
一个来自数据库的 select 但映射在应用程序上工作
边.
那么,您是否还有其他一些建议可以建议我使用查询连接 select 设备并且它是最后一次登录日期(不是日期)?我认为这应该以某种方式要求加入站点上的 where 子句,但后来我碰壁了,不知道该怎么做。
你有什么建议?
顺便说一句,我没有 post 设备的所有属性,但你可能会意识到那里的很多属性和大多数其他属性都是通过 select 获取的,并连接到其他相关 tables/entites 使用 HQL 和 LEFT OUTER JOINS。
我通常创建一个数据库视图,比如 device_summary_data,然后使用 @SecondaryTable
注释将其映射到设备(或使用 @OneToOne
作为另一个实体)。
https://docs.oracle.com/javaee/7/api/javax/persistence/SecondaryTable.html
查看:
create view device_summary_data as
select d.id as device_id, max(l.login_date), count(l.device_name)
from logins l
inner join devices d on d.D_NAME = l.D_NAME
group by d.id
实体:
@Entity
@SecondaryTable(name = "device_summary_data",
pkJoinColumns=@PrimaryKeyJoinColumn(name="device_id", referencedColumnName = "id"))
public class Device {
private long id;
private String deviceName;
private Set<LoginDate> loginDates;
@Column(table="device_summary_data", insertable=false, updateable = false)
private Date lastLogin;
@Column(table="device_summary_data", insertable=false, updateable = false)
private Integer numberOfLogins;
}
相对于 Hibernate 的优势 @Formula
:
- 适用于任何 JPA 实现
- 过滤、排序和分页可以按照任何其他 属性.
在数据库级别应用
我会通过反转映射并制作一些 JPQL 可分页/HQL 查询来实现。
所以你的 LoginDate
会是这样的:
@Entity
public class LoginDate {
private long id; //pk
@ManyToOne
private Device device;
private Date loginDate;
}
自定义查询 (JPQL) 类似于
SELECT ld FROM LoginDate ld WHERE device=:device ORDER BY ld.loginDate DESC
根据您的其他库/框架,您需要将 JPQL 查询限制为一个结果,除非您能够使用简单的 native 查询如:
SELECT ld.logindate
FROM logindate ld
WHERE ld.device_id=:device_id
ORDER BY ld.logindate DESC
LIMIT 1
您可能仍将 Set<LoginDate>
保留在您的 Device
中,但添加 fetch=FetchType.LAZY
用于其他目的。
@Entity
public class Device {
private long id;
private String deviceName; //column D_NAME
private Set<LoginDate> loginDates;
}
/**
Audit table being filled by some other processes on the network
*/
@Entity
public class LoginDate {
private long id; //pk
private String deviceName; //column D_NAME
private Date loginDate;
}
我的目标是在报告屏幕上显示设备的最后登录日期;我在 Device
和 LoginDate
表之间实现了 OneToMany 关系,其中它使用 OrderBy 对 loginDates 进行降序排序,以便我可以选择要在屏幕上显示的第一项。但是当登录数量越来越大时,这是一个有点昂贵的操作。我应该怎么做才能达到 select 仅上次登录日期;
我可以使用 Hibernate 的
@Formula
通过它生成 Pojo 具有相关参数的构造函数。但这会触发一些 报告屏幕中每个项目 select 秒。我可以在业务层实现另一种方法,一旦 列表已加载;我可以用相关 D_NAMES 启动另一个 HQL 来获取 D_NAME、loginDate 组合并循环遍历它们。哪个是 一个来自数据库的 select 但映射在应用程序上工作 边.
那么,您是否还有其他一些建议可以建议我使用查询连接 select 设备并且它是最后一次登录日期(不是日期)?我认为这应该以某种方式要求加入站点上的 where 子句,但后来我碰壁了,不知道该怎么做。
你有什么建议?
顺便说一句,我没有 post 设备的所有属性,但你可能会意识到那里的很多属性和大多数其他属性都是通过 select 获取的,并连接到其他相关 tables/entites 使用 HQL 和 LEFT OUTER JOINS。
我通常创建一个数据库视图,比如 device_summary_data,然后使用 @SecondaryTable
注释将其映射到设备(或使用 @OneToOne
作为另一个实体)。
https://docs.oracle.com/javaee/7/api/javax/persistence/SecondaryTable.html
查看:
create view device_summary_data as
select d.id as device_id, max(l.login_date), count(l.device_name)
from logins l
inner join devices d on d.D_NAME = l.D_NAME
group by d.id
实体:
@Entity
@SecondaryTable(name = "device_summary_data",
pkJoinColumns=@PrimaryKeyJoinColumn(name="device_id", referencedColumnName = "id"))
public class Device {
private long id;
private String deviceName;
private Set<LoginDate> loginDates;
@Column(table="device_summary_data", insertable=false, updateable = false)
private Date lastLogin;
@Column(table="device_summary_data", insertable=false, updateable = false)
private Integer numberOfLogins;
}
相对于 Hibernate 的优势 @Formula
:
- 适用于任何 JPA 实现
- 过滤、排序和分页可以按照任何其他 属性. 在数据库级别应用
我会通过反转映射并制作一些 JPQL 可分页/HQL 查询来实现。
所以你的 LoginDate
会是这样的:
@Entity
public class LoginDate {
private long id; //pk
@ManyToOne
private Device device;
private Date loginDate;
}
自定义查询 (JPQL) 类似于
SELECT ld FROM LoginDate ld WHERE device=:device ORDER BY ld.loginDate DESC
根据您的其他库/框架,您需要将 JPQL 查询限制为一个结果,除非您能够使用简单的 native 查询如:
SELECT ld.logindate
FROM logindate ld
WHERE ld.device_id=:device_id
ORDER BY ld.logindate DESC
LIMIT 1
您可能仍将 Set<LoginDate>
保留在您的 Device
中,但添加 fetch=FetchType.LAZY
用于其他目的。