静态元模型JPA中的多态关联

时间:2015-09-24 07:36:05

标签: java hibernate jpa criteria-api

我有一个实体,它包含与少数实体的多态关联。它定义:

@Entity
@Table(name = "notifications")
public class Notification implements java.io.Serializable {

//some fields ...

//Polymorphic association
@Any (metaColumn = @Column(name = "target_type"), fetch = FetchType.LAZY)
@AnyMetaDef(idType = "integer", metaType = "string",
        metaValues = {
        @MetaValue(targetEntity = Task.class, value = "Task"),
        @MetaValue(targetEntity = AdminNote.class, value = "AdminNote"),
        @MetaValue(targetEntity = UserCancelRequest.class, value = "UserCancelRequest"),
        //@MetaValue(targetEntity = TransferInfo.class, value = "TransferInfo"),
        //@MetaValue(targetEntity = NoteSubscription.class, value = "NoteSubscription")
})
@JoinColumn(name = "target_id")
@Getter
@Setter
private NotificationAssociation target;

我的多态关联由接口NotificationAssociation表示:

public interface NotificationAssociation {
/**
 * Return actual type of associated entity
 * @return one of {@link NotificationTargetType}
 */
String getTargetType();

/**
 * Return associated entity id. Used in queries
 * @return target entity id
 */
Integer getTargetId();
}

这很有效。但我需要通过静态元模型API从条件中的 Notification 类访问目标。我的元模型:

@StaticMetamodel(Notification.class)
public class Notification_ {
public static volatile SingularAttribute<Notification, Integer> id;
public static volatile SingularAttribute<Notification, Integer>   postedById;
public static volatile SingularAttribute<Notification, Integer> adminId;
public static volatile SingularAttribute<Notification, NotificationAssociation> target;
public static volatile SingularAttribute<Notification, Date> hiddenAt;
public static volatile SingularAttribute<Notification, Date> createdAt;

}

在HQL / JPQL中我可以访问它, 但是在元模​​型 target 中为null,当我通过Root#getModel()获取模型时, target 不会出现在属性列表中。 我的问题是我可以这样做还是有任何其他解决方案。谢谢你的帮助

2 个答案:

答案 0 :(得分:1)

我很确定您已经解决了您的问题,但是我最近也遇到了同样的问题。 就我而言,我确实需要使用CriteriaAPI,因为我已经进行了一些用于创建规范的通用处理。 由于HQL不是我的选择,因此我们无法将HQL与规格混合使用。 我通过两次映射该列来解决此问题。以您的示例为例:

@Any (metaColumn = @Column(name = "target_type"), fetch = FetchType.LAZY)
@AnyMetaDef(idType = "integer", metaType = "string",
        metaValues = {
        @MetaValue(targetEntity = Task.class, value = "Task"),
        @MetaValue(targetEntity = AdminNote.class, value = "AdminNote"),
        @MetaValue(targetEntity = UserCancelRequest.class, value = "UserCancelRequest")
})
@JoinColumn(name = "target_id")
@Getter
@Setter
private NotificationAssociation target;

@Column(name = "target_id", insertable = false, updatable = false)
private Integer targetId;

进行一些小的调整,就为targetId字段生成了元数据,并且该元数据在Criteria API上可用。因此,您可以执行以下操作:

notificationService.getAll((root, query, cb) -> cb.and(cb.equals(root.get("targetId"), someId), ...))

我希望这对面临相同问题的所有人有所帮助。

答案 1 :(得分:0)

想想我弄明白了。 @Any注释与它相关(@AnyMetadef和其他)由Hibernate提供,而不是JPA。因此,我们无法使用JPA Criteria API来管理此类关系,但我们可以使用Hibernate Criteria API。