@Entity
@Table(name = "my_table")
@FilterDef(name = "MyTable.current")
@Filter(name = "MyTable.current", condition = """
revision_number = (select max(v.revision_number) from {h-schema}my_table as v where id = v.id)
""")
public class MyRevisioneEntity extends PanacheEntityBase {
@Id
/* This is NOT autogenerated */
UUID id;
@Id
@Column(name = "revision_number")
long revision;
@Basic(fetch = FetchType.LAZY)
@Formula("(revision_number = (select max(v.revision_number) from {h-schema}my_table as v where id = v.id))")
boolean latestRevision;
// ... metadata, target of revision!
}
Над моим доменом простая сущность, идентифицируемая UUID, может иметь несколько ревизий.
Обычно мне нужна только самая последняя версия, поэтому я решил создать фильтр MyTable.current
, но у меня возникла проблема: заполнитель {h-schema}
не разрешен, поэтому мне приходится создавать схему в состоянии фильтра.
То же условие, что и @Formula
к свойству latestRevision
, работает безупречно (заполнитель разрешается, как и ожидалось).
Это задумано или условие @Filter
должно разрешать заполнитель, как это делает @Formula
?
Я не думаю, что {h-schema}
здесь поддерживается... Хотя, возможно, так и должно быть; не стесняйтесь создать запрос на функцию: https://hibernate.atlassian.net/browse/HHH
А пока вы можете попробовать просто использовать @SqlFragmentAlias
:
@Filter(name = "MyTable.current", condition = """
revision_number = (select max(v.revision_number) from {mytable} as v where id = v.id)
""",
aliases = @SqlFragmentAlias(alias = "mytable", table = "my_table"))
public class MyRevisioneEntity extends PanacheEntityBase {
Кстати, вы можете рассмотреть возможность использования Envers вместо внедрения собственного решения.
Обновлено: предложение ниже не работает, см. https://hibernate.atlassian.net/browse/HHH-18152
@Filter(name = "MyTable.current", condition = """
revision_number = (select max(v.revision_number) from {mytable} as v where id = v.id)
""",
aliases = @SqlFragmentAlias(alias = "mytable", entity = MyRevisioneEntity.class))
public class MyRevisioneEntity extends PanacheEntityBase {
См. также https://docs.jboss.org/hibernate/orm/6.5/userguide/html_single/Hibernate_User_Guide.html#pc-filter-sql-fragment-alias (хотя в этом разделе, похоже, не упоминается entity =
, так что, возможно, оно устарело).
Хм, цифры. Значит, недокументированный и сломанный. Может @SqlFragmentAlias(alias = "mytable", table = "my_table")
?
Выдает неверный SQL, поскольку таблица в подзапросе должна быть my_table, а не ее псевдоним в основном запросе. выберите mre1_0.id, mre1_0.revision_number из my_table mre1_0, где номер_версии = (выберите max(v.revision_number) из mre1_0 как v, где id = v.id)
Что касается проблемы jira: не только ссылка на самого себя не работает, но и ссылка на любые другие объекты, не созданные на этапе начальной загрузки (например, 2 объекта с @filterdef и один объект ссылается на другой)
Использование аннотации объекта приводит к этому исключению во время загрузки фабрики сеанса: org.hibernate.UnknownEntityTypeException: невозможно найти персистент: MyRevisioneEntity в MappingMetamodelImpl.getEntityDescriptor(MappingMetamodelImpl.java:394) в FilterConfiguration.mergeAliasMaps(FilterConfiguration.java:81) в FilterConfiguration.getAliasTableMap(FilterConfiguration.java:56) в FilterHelper.<init>(FilterHelper.java:76)