[JIRA] (HHH-13988) Entity which refers to itself: invalid update statement created
by Kenny Moens (JIRA)
Kenny Moens ( https://hibernate.atlassian.net/secure/ViewProfile.jspa?accountId=5ea94bd... ) *created* an issue
Hibernate ORM ( https://hibernate.atlassian.net/browse/HHH?atlOrigin=eyJpIjoiNmVhZGM2MTFh... ) / Bug ( https://hibernate.atlassian.net/browse/HHH-13988?atlOrigin=eyJpIjoiNmVhZG... ) HHH-13988 ( https://hibernate.atlassian.net/browse/HHH-13988?atlOrigin=eyJpIjoiNmVhZG... ) Entity which refers to itself: invalid update statement created ( https://hibernate.atlassian.net/browse/HHH-13988?atlOrigin=eyJpIjoiNmVhZG... )
Issue Type: Bug Affects Versions: 5.4.0, 5.4.14 Assignee: Unassigned Attachments: hibernate-test-case-templates.zip, hql ast - HB5.3.txt, hql ast - HB5.4.txt, hql to sql - HB5.3.txt, hql to sql - HB5.4.txt, sql ast - HB5.3.txt, sql ast - HB5.4.txt, sql statement - HB5.3.txt, sql statement - HB5.4.txt Created: 29/Apr/2020 02:58 AM Environment: Hibernate 5.4.14, AdoptOpenJDK 8u252, Windows, H2 + HSQLDB Priority: Major Reporter: Kenny Moens ( https://hibernate.atlassian.net/secure/ViewProfile.jspa?accountId=5ea94bd... )
We recently did an upgrade from Hibernate 5.3.16 to Hibernate 5.4.14 inside one of our applications.
One of our enitity has a foreign key relationship inside its own table, and additionally uses discriminators for that table.
Basically we execute the following update statement:
update OpdrachtPlan o set o.plan.id = :newPlanId where o.plan.id = :planId and o.isProCalc = false and o.maand >= :datum
Hibernate 5.4.14 generates the following (invalid) SQL statement for this query:
update
SDOPDR cross
join
set
PKSDOPDRREF=?
where
(
SDOPDRPROCALC = 0
)
and PKSDOPDRREF=?
and SDOPDRPROCALC= false
and SDOPDRMND>=?
In the previous Hibernate 5.3.16, we got the following SQL statement, which works correctly:
update
SDOPDR
set
FKSDOPDR_OPDRREF_MASTER=?
where
(
SDOPDRPROCALC = 0
)
and FKSDOPDR_OPDRREF_MASTER=?
and SDOPDRPROCALC= false
and SDOPDRMND>=?
Based on my investigation, this issue appears to be introduced by multiple changes:
HHH-13875: the addition of the isNull check inside dereferenceEntity causes that we don't get inside the isPropertyEmbeddedInJoinProperties method anymore, which is necessary. This would have been sufficient if we named our primary keys id instead of objectId. As part of our investigation we then downgraded to 5.4.12 which didn't contain this patch.
The combination of HHH-12842 ( https://hibernate.atlassian.net/browse/HHH-12842 ) Closed and HHH-12775 ( https://hibernate.atlassian.net/browse/HHH-12775 ) Closed prevents that the objectId path is properly registered inside AbstractPropertyMapping.initIdentifierPropertyPaths().
As an attachment, you can find a number of traces of the AST of SQL, HBM, loggings of the mapping and the SQL statement itself.
I don't know what would be the best solution to solve this bug, I did however make a stripped down test case to reproduce this: hibernate-test-case-templates.zip ( https://hibernate.atlassian.net/secure/attachment/49661/49661_hibernate-t... )
( https://hibernate.atlassian.net/browse/HHH-13988#add-comment?atlOrigin=ey... ) Add Comment ( https://hibernate.atlassian.net/browse/HHH-13988#add-comment?atlOrigin=ey... )
Get Jira notifications on your phone! Download the Jira Cloud app for Android ( https://play.google.com/store/apps/details?id=com.atlassian.android.jira.... ) or iOS ( https://itunes.apple.com/app/apple-store/id1006972087?pt=696495&ct=EmailN... ) This message was sent by Atlassian Jira (v1001.0.0-SNAPSHOT#100125- sha1:e06514a )
4 years, 8 months
[JIRA] (HSEARCH-3903) Filters based exclusively on mapper metadata for @IndexedEmbedded
by Yoann Rodière (JIRA)
Yoann Rodière ( https://hibernate.atlassian.net/secure/ViewProfile.jspa?accountId=557058%... ) *created* an issue
Hibernate Search ( https://hibernate.atlassian.net/browse/HSEARCH?atlOrigin=eyJpIjoiMTA3YThk... ) / New Feature ( https://hibernate.atlassian.net/browse/HSEARCH-3903?atlOrigin=eyJpIjoiMTA... ) HSEARCH-3903 ( https://hibernate.atlassian.net/browse/HSEARCH-3903?atlOrigin=eyJpIjoiMTA... ) Filters based exclusively on mapper metadata for @IndexedEmbedded ( https://hibernate.atlassian.net/browse/HSEARCH-3903?atlOrigin=eyJpIjoiMTA... )
Issue Type: New Feature Assignee: Unassigned Components: engine, mapper-pojo Created: 29/Apr/2020 01:18 AM Fix Versions: 6.0.0.Beta-backlog-low-priority Priority: Major Reporter: Yoann Rodière ( https://hibernate.atlassian.net/secure/ViewProfile.jspa?accountId=557058%... )
The includePaths filter in @IndexedEmbedded refers to index field paths. This has several drawbacks:
* Part of the implementation has to be in the backend, which feels quite dirty.
* This is not very consistent with the maxDepth filter, which applied to the @IndexedEmbedded only (depth of fields created within an included bridge is unlimited).
* The filters cannot easily be applied to dynamic fields, so dynamic fields are always included as soon as their nearest static parent is included.
* The filter can end up including some fields declared by a custom field bridge, but not others.
* This does not make sense performance-wise as the fields will still be populated by the bridge, but ignored by the backend.
* Worse, when we introduce support for bridge-defined predicates ( HSEARCH-3320 ( https://hibernate.atlassian.net/browse/HSEARCH-3320 ) Reopened ), we may end up with dysfunctional predicates because only some fields are present, while the bridge expects all fields to be present.
* We are forced to use inference to detect which bridges should be included or excluded, based on the fields they declared.
* This code is unnecessarily complex.
* This code does not work correctly with field templates, since we cannot know in advance whether dynamic fields will be included. In particular:
* Bridges that declare field templates, but only ever add dynamic fields that would not match the includePaths , are included nonetheless.
* Bridges that do not declare anything and rely on field templates declared by a parent (which is legal) are excluded.
We could get rid of most of the complexity by implementing filters differently, based on mapper metadata exclusively (mapping annotations and/or entity model).
Solution 1: property paths
We could rely on property paths instead of field paths. Only bridges applied to included properties are themselves included.
The major drawback is that there wouldn't be any way to filter out type bridges.
Solution 2: groups
We could rely on "groups", similarly to the @LazyGroup support in Hibernate ORM, or to the group support in Hibernate Validator.
One assigns groups to every @Field / @IndexedEmbedded , then references the groups in @IncludedEmbedded(includeGroups = ...).
The main problem with this solution is its complexity; Validator is using groups and I know they can be pretty complex to handle. We should definitely see what makes them so complex in Validator to avoid the same problems in Search.
For example:
@Indexed
public class Level1Entity {
// Will include id only
@IndexedEmbedded
private Level2Entity level2_1;
// Will include id, name
@IndexedEmbedded(includeGroups = {BuiltinGroups.DEFAULT, "base" })
private Level2Entity level2_2;
// Will include id, name, category
@IndexedEmbedded(includeGroups = {BuiltinGroups.DEFAULT, "base" , "advanced" })
private Level2Entity level2_3;
}
public class Level2Entity {
@GenericField // Default group
private String id;
@GenericField(groups = "base" )
private String name;
@GenericField(groups = "advanced" )
private String category;
}
It would prevent us from supporting the use case mentioned in HSEARCH-1112 ( https://hibernate.atlassian.net/browse/HSEARCH-1112 ) Open directly, but I believe the same effect could be achieved if we defined group filters as "overriding" instead of "composable": an @IndexedEmbedded(includeGroups = "a") that includes an @IndexedEmbedded(includeGroups = "b") would just act as if the contained @IndexedEmbedded included group "a", and only group "a".
For example:
@Indexed
public class Level1Entity {
// Will include level2.level3.a only
@IndexedEmbedded(includeGroups = "a" )
private Level2Entity level2;
}
public class Level2Entity {
@GenericField(groups = "b" )
private String name;
@IndexedEmbedded(includeGroups = "b" ) // includeGroups is overridden in Level1Entity
private String id;
}
public class Level3Entity {
@GenericField(group = "a" )
private String a;
@GenericField(group = "b" )
private String b;
}
There are pros and cons:
* Pro: Groups would be much easier to implement and understand: the various filters defined in indexed-embedded entities would no longer be relevant.
* Con: it would become harder to manage cycles through group filtering: you would no longer be able to rely on indexed-embedded entities to filter out cycles through groups (since their group filters are ignored).
* Con: the behavior would not be consistent with that of maxDepth.
Next
As a second step, we should probably deprecate includePaths and mark it for removal in a later major version (7+).
( https://hibernate.atlassian.net/browse/HSEARCH-3903#add-comment?atlOrigin... ) Add Comment ( https://hibernate.atlassian.net/browse/HSEARCH-3903#add-comment?atlOrigin... )
Get Jira notifications on your phone! Download the Jira Cloud app for Android ( https://play.google.com/store/apps/details?id=com.atlassian.android.jira.... ) or iOS ( https://itunes.apple.com/app/apple-store/id1006972087?pt=696495&ct=EmailN... ) This message was sent by Atlassian Jira (v1001.0.0-SNAPSHOT#100125- sha1:e06514a )
4 years, 8 months