冬眠。引用 SINGLE_TABLE 继承类的集合字段在 fething 时忽略 DiscriminatorValue
问题:一对多集合字段忽略鉴别器列并获取所有条目而不是专用子类。
我有带有继承策略 SINGLE_TABLE 的基超类。
@DiscriminatorColumn(name = "state")
@Data
@Table(name = "named_entity", indexes = @Index(columnList = "state"))
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@Entity
public class BaseNamedEntity {
@Id
private UUID id = UUID.randomUUID();
@Column(insertable = false, updatable = false)
@Setter(AccessLevel.PROTECTED)
@Enumerated(EnumType.STRING)
private EntityState state; // declared for jpql purposes
private String name;
@ManyToOne
@JoinColumn(name = "collection_holder_id", referencedColumnName = "id")
private CollectionHolderEntity otmCollection; // field will be important later
}
状态“活动”和“已删除”的两个子类:
@Entity
@DiscriminatorValue("active")
public class ActiveNamedEntity extends BaseNamedEntity {
}
@Entity
@DiscriminatorValue("deleted")
public class DeletedNamedEntity extends BaseNamedEntity {
}
基本功能(如 spring 数据 CRUD 存储库)按预期工作:
((CrudRepository<ActiveNamedEntity, UUID>) activeDao).existsById(UUID.randomUUID());
// -> Hibernate: select count(*) as col_0_0_ from named_entity activename0_ where activename0_.state='active' and activename0_.id=?
// Discriminator column is checked as expected
我尝试引入与子类之一保持一对多关系的实体:
@Entity
@Table(name = "collection_holder")
@Data
public class CollectionHolderEntity {
@Id
private UUID id = UUID.randomUUID();
@EqualsAndHashCode.Exclude
@ToString.Exclude
@OneToMany(mappedBy = "otmCollection", fetch = FetchType.EAGER) // Eager to avoid transactions in tests
private List<ActiveNamedEntity> oneToManyCollection = new ArrayList<>(); // ActiveNamedEntity is subclass with corelated state = "active"
}
collectionHolderDao.findById(collectionHolderEntity.getId()) // reloading entity
.orElseGet(() -> Assertions.fail("Expected to find holder " + collectionHolderEntity));
// -> Hibernate: select collection0_.id as id1_0_0_, onetomanyc1_.collection_holder_id as collecti4_1_1_, onetomanyc1_.id as id2_1_1_, onetomanyc1_.id as id2_1_2_, onetomanyc1_.name as name3_1_2_, onetomanyc1_.collection_holder_id as collecti4_1_2_, onetomanyc1_.state as state1_1_2_ from collection_holder collection0_ left outer join named_entity onetomanyc1_ on collection0_.id=onetomanyc1_.collection_holder_id where collection0_.id=?
// join contains only id reference, but not state check:
// left outer join named_entity onetomanyc1_ on collection0_.id=onetomanyc1_.collection_holder_id
其中将请求预期行为,其中包含连接的状态检查:左外连接named_entity onetomanyc1_ on collection0_.id=onetomanyc1_.collection_holder_id 和 onetomanyc1_.state="active"
我是否缺少规范的某些部分?
也许我应该在某个地方明确指定它应该向生成的请求引入鉴别器列。如果是这样 - 预计如何处理多对多关系?
到目前为止,我尝试:
- 将拥有子类关系的字段(本例中的
ActiveNamedEntity
)移动,但似乎没有任何变化。 - 切换获取类型也得到相同的结果
在这个例子中我使用了org.springframework.boot:spring-boot-starter-data-jpa:2.4.6
with 与 org.hibernate:hibernate-core:5.4.31.Final 相关联
Problem: one-to-many collection field ignores discriminator column and fetches all entries instead of dedicated subclass.
I am having base super-class with inheritance strategy SINGLE_TABLE.
@DiscriminatorColumn(name = "state")
@Data
@Table(name = "named_entity", indexes = @Index(columnList = "state"))
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@Entity
public class BaseNamedEntity {
@Id
private UUID id = UUID.randomUUID();
@Column(insertable = false, updatable = false)
@Setter(AccessLevel.PROTECTED)
@Enumerated(EnumType.STRING)
private EntityState state; // declared for jpql purposes
private String name;
@ManyToOne
@JoinColumn(name = "collection_holder_id", referencedColumnName = "id")
private CollectionHolderEntity otmCollection; // field will be important later
}
And two sub-classes for states 'active' and 'deleted':
@Entity
@DiscriminatorValue("active")
public class ActiveNamedEntity extends BaseNamedEntity {
}
@Entity
@DiscriminatorValue("deleted")
public class DeletedNamedEntity extends BaseNamedEntity {
}
Base functionality (like spring data crud repository) works as expected:
((CrudRepository<ActiveNamedEntity, UUID>) activeDao).existsById(UUID.randomUUID());
// -> Hibernate: select count(*) as col_0_0_ from named_entity activename0_ where activename0_.state='active' and activename0_.id=?
// Discriminator column is checked as expected
I tried to introduce entity that holds one-to-many relationship to one of the sub-classes:
@Entity
@Table(name = "collection_holder")
@Data
public class CollectionHolderEntity {
@Id
private UUID id = UUID.randomUUID();
@EqualsAndHashCode.Exclude
@ToString.Exclude
@OneToMany(mappedBy = "otmCollection", fetch = FetchType.EAGER) // Eager to avoid transactions in tests
private List<ActiveNamedEntity> oneToManyCollection = new ArrayList<>(); // ActiveNamedEntity is subclass with corelated state = "active"
}
And it is seems like generated statements ignores discriminator columns once it tries to fetch collection field:
collectionHolderDao.findById(collectionHolderEntity.getId()) // reloading entity
.orElseGet(() -> Assertions.fail("Expected to find holder " + collectionHolderEntity));
// -> Hibernate: select collection0_.id as id1_0_0_, onetomanyc1_.collection_holder_id as collecti4_1_1_, onetomanyc1_.id as id2_1_1_, onetomanyc1_.id as id2_1_2_, onetomanyc1_.name as name3_1_2_, onetomanyc1_.collection_holder_id as collecti4_1_2_, onetomanyc1_.state as state1_1_2_ from collection_holder collection0_ left outer join named_entity onetomanyc1_ on collection0_.id=onetomanyc1_.collection_holder_id where collection0_.id=?
// join contains only id reference, but not state check:
// left outer join named_entity onetomanyc1_ on collection0_.id=onetomanyc1_.collection_holder_id
Where expected behavior would be request, that contains state check for join: left outer join named_entity onetomanyc1_ on collection0_.id=onetomanyc1_.collection_holder_id and onetomanyc1_.state="active"
Am I missing some part of specification?
Maybe I should specify somewhere explicitly that it should introduce discriminator column to generated request. If so - what expected to do with many-to-many relationships?
So far I tried:
- to move field that owns a relationship to sub-class (
ActiveNamedEntity
in this example) but doesn't seems like anything changes. - Switching fetch type with also gets same results
In this example I used org.springframework.boot:spring-boot-starter-data-jpa:2.4.6
with correlates to org.hibernate:hibernate-core:5.4.31.Final
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我仍然不认为这是预期的行为,但这里有一些东西可以让它开箱即用:
@org.hibernate.annotations.Where(clause)
对于具有相关查询的每个子类:或者直接对于集合属性:
第一个似乎更可取,因为它将普遍工作。
我对这种方法没有任何运气,但理论上它应该有效。
I still don't think it is a expected behavior but here is few things to get it out of the box:
@org.hibernate.annotations.Where(clause)
to each sub-class with correlated query:Or to collection attribute directly:
First one is seems more preferable since will be work universally.
@org.hibernate.annotations.Filter
(and corresponding filterDef) and enable it for each session. More of that in this discussion.I didn't have any luck with this method but theoretically it should work.