Спящая связь с агрегацией - PullRequest
0 голосов
/ 06 ноября 2018
@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;
}

Моя цель - отобразить дату последнего входа в систему устройства на экранах отчетов; Я реализовал связь OneToMany между Device и LoginDate таблицами, где он использует OrderBy для упорядочения по убыванию loginDates, чтобы я мог выбрать первый элемент для отображения на экране. Но это немного дорогая операция, когда дело доходит до того, что количество логинов становится все больше и больше. Что я должен сделать, чтобы выбрать только последнюю дату входа в систему;

  • Я могу использовать @Formula Hibernate для генерации Pojo через его конструктор со связанными параметрами. Но это вызовет количество выбирает каждый элемент на экране отчета.

  • Я могу реализовать другой метод на бизнес-уровне, чтобы после список загружен; Я могу инициировать другой HQL с соответствующими D_NAMES для получения D_NAME, loginDate соединяются и проходят через них. Который один единственный выбор из БД, но отображение приложения для приложения сторона.

Итак, у вас есть еще какие-нибудь вещи, чтобы я мог предложить что-то вроде запроса с объединениями для выбора Устройства и его последней даты входа в систему (не даты) сразу? Я думаю, что это должно как-то потребовать пункт where на сайте присоединения, но потом я врезался в стену и не мог понять, как это сделать.

Что вы предлагаете?

Кстати, я не опубликовал все свойства устройства, но, как вы могли понять, многие свойства там и большинство других свойств выбираются с помощью выбора с объединениями с другими связанными таблицами / объектами, используя HQL и LEFT OUTER. JOINS.

Ответы [ 2 ]

0 голосов
/ 06 ноября 2018

Я бы сделал это, перевернув отображение и сделав какой-нибудь 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 , чтобы ограничить его только одним результатом, если вы не можете использовать простой собственный запрос, подобный:

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 к нему для других целей.

0 голосов
/ 06 ноября 2018

Обычно я создаю представление базы данных, скажем, 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
  • Фильтрация, сортировка и разбиение на страницы могут применяться на уровне БД, как и любое другое свойство.
...